]> git.mxchange.org Git - flightgear.git/blob - src/Autopilot/auto_gui.cxx
Oliver Schroeder:
[flightgear.git] / src / Autopilot / auto_gui.cxx
1 // auto_gui.cxx -- autopilot gui interface
2 //
3 // Written by Norman Vine <nhv@cape.com>
4 // Arranged by Curt Olson <http://www.flightgear.org/~curt>
5 //
6 // Copyright (C) 1998 - 2000
7 //
8 // This program is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU General Public License as
10 // published by the Free Software Foundation; either version 2 of the
11 // License, or (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful, but
14 // WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 // General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 //
22 // $Id$
23
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #include <simgear/compiler.h>
30
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include STL_STRING
36
37 #include <Aircraft/aircraft.hxx>
38 #include <FDM/flight.hxx>
39 #include <Controls/controls.hxx>
40 #include <Scenery/scenery.hxx>
41
42 #include <simgear/constants.h>
43 #include <simgear/sg_inlines.h>
44 #include <simgear/debug/logstream.hxx>
45 #include <simgear/math/sg_geodesy.hxx>
46 #include <simgear/misc/sg_path.hxx>
47
48 #include <Airports/simple.hxx>
49 #include <GUI/gui.h>
50 #include <Main/fg_init.hxx>
51 #include <Main/globals.hxx>
52 #include <Main/fg_props.hxx>
53 #include <Navaids/fixlist.hxx>
54 #include <Navaids/navlist.hxx>
55 #include <Navaids/navrecord.hxx>
56
57 #include "auto_gui.hxx"
58 #include "route_mgr.hxx"
59 #include "xmlauto.hxx"
60
61 SG_USING_STD(string);
62
63
64 #define mySlider puSlider
65
66 // Climb speed constants
67 // const double min_climb = 70.0;       // kts
68 // const double best_climb = 75.0;      // kts
69 // const double ideal_climb_rate = 500.0; // fpm
70
71 /// These statics will eventually go into the class
72 /// they are just here while I am experimenting -- NHV :-)
73 // AutoPilot Gain Adjuster members
74 // static double MaxRollAdjust;        // MaxRollAdjust       = 2 * APData->MaxRoll;
75 // static double RollOutAdjust;        // RollOutAdjust       = 2 * APData->RollOut;
76 // static double MaxAileronAdjust;     // MaxAileronAdjust    = 2 * APData->MaxAileron;
77 // static double RollOutSmoothAdjust;  // RollOutSmoothAdjust = 2 * APData->RollOutSmooth;
78
79 // static float MaxRollValue;          // 0.1 -> 1.0
80 // static float RollOutValue;
81 // static float MaxAileronValue;
82 // static float RollOutSmoothValue;
83
84 // static float TmpMaxRollValue;       // for cancel operation
85 // static float TmpRollOutValue;
86 // static float TmpMaxAileronValue;
87 // static float TmpRollOutSmoothValue;
88
89 // static puDialogBox *APAdjustDialog;
90 // static puFrame     *APAdjustFrame;
91 // static puText      *APAdjustDialogMessage;
92 // static puFont      APAdjustLegendFont;
93 // static puFont      APAdjustLabelFont;
94
95 // static puOneShot *APAdjustOkButton;
96 // static puOneShot *APAdjustResetButton;
97 // static puOneShot *APAdjustCancelButton;
98
99 // static puButton        *APAdjustDragButton;
100
101 // static puText *APAdjustMaxRollTitle;
102 // static puText *APAdjustRollOutTitle;
103 // static puText *APAdjustMaxAileronTitle;
104 // static puText *APAdjustRollOutSmoothTitle;
105
106 // static puText *APAdjustMaxAileronText;
107 // static puText *APAdjustMaxRollText;
108 // static puText *APAdjustRollOutText;
109 // static puText *APAdjustRollOutSmoothText;
110
111 // static mySlider *APAdjustHS0;
112 // static mySlider *APAdjustHS1;
113 // static mySlider *APAdjustHS2;
114 // static mySlider *APAdjustHS3;
115
116 // static char SliderText[ 4 ][ 8 ];
117
118 ///////// AutoPilot New Heading Dialog
119
120 static puDialogBox     *ApHeadingDialog;
121 static puFrame         *ApHeadingDialogFrame;
122 static puText          *ApHeadingDialogMessage;
123 static puInput         *ApHeadingDialogInput;
124 static puOneShot       *ApHeadingDialogOkButton;
125 static puOneShot       *ApHeadingDialogCancelButton;
126
127
128 ///////// AutoPilot New Altitude Dialog
129
130 static puDialogBox     *ApAltitudeDialog = 0;
131 static puFrame         *ApAltitudeDialogFrame = 0;
132 static puText          *ApAltitudeDialogMessage = 0;
133 static puInput         *ApAltitudeDialogInput = 0;
134
135 static puOneShot       *ApAltitudeDialogOkButton = 0;
136 static puOneShot       *ApAltitudeDialogCancelButton = 0;
137
138
139 /// The beginnings of Lock AutoPilot to target location :-)
140 //  Needs cleaning up but works
141 //  These statics should disapear when this is a class
142 static puDialogBox     *TgtAptDialog = 0;
143 static puFrame         *TgtAptDialogFrame = 0;
144 // static puText          *TgtAptDialogMessage = 0;
145 static puInput         *TgtAptDialogInput = 0;
146 static puListBox       *TgtAptDialogWPList = 0;
147 static puSlider        *TgtAptDialogSlider = 0;
148 static puArrowButton   *TgtAptDialogUPArrow = 0;
149 static puArrowButton   *TgtAptDialogDNArrow = 0;
150 static char**          WPList;
151 static int             WPListsize;
152
153 static char NewTgtAirportId[16];
154 static char NewTgtAirportLabel[] = "New Apt/Fix ID";
155
156 static puOneShot       *TgtAptDialogOkButton = 0;
157 static puOneShot       *TgtAptDialogCancelButton = 0;
158 static puOneShot       *TgtAptDialogResetButton = 0;
159
160
161 // extern char *coord_format_lat(float);
162 // extern char *coord_format_lon(float);
163
164 // THIS NEEDS IMPROVEMENT !!!!!!!!!!!!!
165 static int scan_number(char *s, double *new_value)
166 {
167     int ret = 0;
168     char WordBuf[64];
169     char *cptr = s;
170     char *WordBufPtr = WordBuf;
171     if (*cptr == '+')
172         cptr++;
173     if (*cptr == '-') {
174         *WordBufPtr++ = *cptr++;
175     }
176     while (isdigit(*cptr) ) {
177         *WordBufPtr++ = *cptr++;
178         ret = 1;
179     }
180     if (*cptr == '.') 
181         *WordBufPtr++ = *cptr++;  // put the '.' into the string
182     while (isdigit(*cptr)) {
183         *WordBufPtr++ = *cptr++;
184         ret = 1;
185     }
186     if( ret == 1 ) {
187         *WordBufPtr = '\0';
188         sscanf(WordBuf, "%lf", new_value);
189     }
190
191     return(ret);
192 } // scan_number
193
194
195 void ApHeadingDialog_Cancel(puObject *)
196 {
197     ApHeadingDialogInput->rejectInput();
198     FG_POP_PUI_DIALOG( ApHeadingDialog );
199 }
200
201 void ApHeadingDialog_OK (puObject *me)
202 {
203     int error = 0;
204     char *c;
205     string s;
206     ApHeadingDialogInput -> getValue( &c );
207
208     if( strlen(c) ) {
209         double NewHeading;
210         if( scan_number( c, &NewHeading ) ) {
211             fgSetString( "/autopilot/locks/heading", "dg-heading-hold" );
212             fgSetDouble( "/autopilot/settings/heading-bug-deg", 
213                          NewHeading );
214         } else {
215             error = 1;
216             s = c;
217             s += " is not a valid number.";
218         }
219     }
220     ApHeadingDialog_Cancel(me);
221     if ( error ) mkDialog(s.c_str());
222 }
223
224 void NewHeading(puObject *cb)
225 {
226     //  string ApHeadingLabel( "Enter New Heading" );
227     //  ApHeadingDialogMessage  -> setLabel(ApHeadingLabel.c_str());
228     float heading = fgGetDouble( "/autopilot/settings/heading-bug-deg" );
229     while ( heading < 0.0 ) { heading += 360.0; }
230     ApHeadingDialogInput   ->    setValue ( heading );
231     ApHeadingDialogInput    -> acceptInput();
232     FG_PUSH_PUI_DIALOG( ApHeadingDialog );
233 }
234
235 void NewHeadingInit()
236 {
237     //  printf("NewHeadingInit\n");
238     char NewHeadingLabel[] = "Enter New Heading";
239     char *s;
240
241     float heading = fgGetDouble("/orientation/heading-deg");
242     int len = 260/2 -
243         (puGetDefaultLabelFont().getStringWidth( NewHeadingLabel ) / 2 );
244
245     ApHeadingDialog = new puDialogBox (150, 50);
246     {
247         ApHeadingDialogFrame   = new puFrame (0, 0, 260, 150);
248
249         ApHeadingDialogMessage = new puText   (len, 110);
250         ApHeadingDialogMessage    -> setDefaultValue (NewHeadingLabel);
251         ApHeadingDialogMessage    -> getDefaultValue (&s);
252         ApHeadingDialogMessage    -> setLabel        (s);
253
254         ApHeadingDialogInput   = new puInput  ( 50, 70, 210, 100 );
255         ApHeadingDialogInput   ->    setValue ( heading );
256
257         ApHeadingDialogOkButton     =  new puOneShot         (50, 10, 110, 50);
258         ApHeadingDialogOkButton     ->     setLegend         (gui_msg_OK);
259         ApHeadingDialogOkButton     ->     makeReturnDefault (TRUE);
260         ApHeadingDialogOkButton     ->     setCallback       (ApHeadingDialog_OK);
261
262         ApHeadingDialogCancelButton =  new puOneShot         (140, 10, 210, 50);
263         ApHeadingDialogCancelButton ->     setLegend         (gui_msg_CANCEL);
264         ApHeadingDialogCancelButton ->     setCallback       (ApHeadingDialog_Cancel);
265
266     }
267     FG_FINALIZE_PUI_DIALOG( ApHeadingDialog );
268 }
269
270 void ApAltitudeDialog_Cancel(puObject *)
271 {
272     ApAltitudeDialogInput -> rejectInput();
273     FG_POP_PUI_DIALOG( ApAltitudeDialog );
274 }
275
276 void ApAltitudeDialog_OK (puObject *me)
277 {
278     int error = 0;
279     string s;
280     char *c;
281     ApAltitudeDialogInput->getValue( &c );
282
283     if ( strlen( c ) ) {
284         double NewAltitude;
285         if ( scan_number( c, &NewAltitude) ) {
286             fgSetString( "/autopilot/locks/altitude", "altitude-hold" );
287             fgSetDouble( "/autopilot/settings/altitude-ft", NewAltitude );
288         } else {
289             error = 1;
290             s = c;
291             s += " is not a valid number.";
292         }
293     }
294     ApAltitudeDialog_Cancel(me);
295     if( error )  mkDialog(s.c_str());
296 }
297
298 void NewAltitude(puObject *cb)
299 {
300     float altitude = fgGetDouble("/autopilot/settings/altitude-ft")
301         * SG_METER_TO_FEET;
302     ApAltitudeDialogInput -> setValue( altitude );
303     ApAltitudeDialogInput -> acceptInput();
304     FG_PUSH_PUI_DIALOG( ApAltitudeDialog );
305 }
306
307 void NewAltitudeInit()
308 {
309     //  printf("NewAltitudeInit\n");
310     char NewAltitudeLabel[] = "Enter New Altitude";
311     char *s;
312
313     float alt = cur_fdm_state->get_Altitude();
314
315     if ( !strcmp(fgGetString("/sim/startup/units"), "meters")) {
316         alt *= SG_FEET_TO_METER;
317     }
318
319     int len = 260/2 -
320         (puGetDefaultLabelFont().getStringWidth( NewAltitudeLabel ) / 2);
321
322     //  ApAltitudeDialog = new puDialogBox (150, 50);
323     ApAltitudeDialog = new puDialogBox (150, 200);
324     {
325         ApAltitudeDialogFrame   = new puFrame  (0, 0, 260, 150);
326         ApAltitudeDialogMessage = new puText   (len, 110);
327         ApAltitudeDialogMessage    -> setDefaultValue (NewAltitudeLabel);
328         ApAltitudeDialogMessage    -> getDefaultValue (&s);
329         ApAltitudeDialogMessage    -> setLabel (s);
330
331         ApAltitudeDialogInput   = new puInput  ( 50, 70, 210, 100 );
332         ApAltitudeDialogInput      -> setValue ( alt );
333         // Uncomment the next line to have input active on startup
334         // ApAltitudeDialogInput   ->    acceptInput       ( );
335         // cursor at begining or end of line ?
336         //len = strlen(s);
337         //              len = 0;
338         //              ApAltitudeDialogInput   ->    setCursor         ( len );
339         //              ApAltitudeDialogInput   ->    setSelectRegion   ( 5, 9 );
340
341         ApAltitudeDialogOkButton     =  new puOneShot         (50, 10, 110, 50);
342         ApAltitudeDialogOkButton     ->     setLegend         (gui_msg_OK);
343         ApAltitudeDialogOkButton     ->     makeReturnDefault (TRUE);
344         ApAltitudeDialogOkButton     ->     setCallback       (ApAltitudeDialog_OK);
345
346         ApAltitudeDialogCancelButton =  new puOneShot         (140, 10, 210, 50);
347         ApAltitudeDialogCancelButton ->     setLegend         (gui_msg_CANCEL);
348         ApAltitudeDialogCancelButton ->     setCallback       (ApAltitudeDialog_Cancel);
349
350     }
351     FG_FINALIZE_PUI_DIALOG( ApAltitudeDialog );
352 }
353
354
355 #if 0
356 static void maxroll_adj( puObject *hs ) {
357     float val ;
358     
359     hs-> getValue ( &val ) ;
360     SG_CLAMP_RANGE ( val, 0.1f, 1.0f ) ;
361     //    printf ( "maxroll_adj( %p ) %f %f\n", hs, val, MaxRollAdjust * val ) ;
362     fgSetDouble( "/autopilot/config/max-roll-deg", MaxRollAdjust * val );
363     sprintf( SliderText[ 0 ], "%05.2f",
364              fgGetDouble("/autopilot/config/max-roll-deg") );
365     APAdjustMaxRollText -> setLabel ( SliderText[ 0 ] ) ;
366 }
367
368 static void rollout_adj( puObject *hs ) {
369     float val ;
370
371     hs-> getValue ( &val ) ;
372     SG_CLAMP_RANGE ( val, 0.1f, 1.0f ) ;
373     //    printf ( "rollout_adj( %p ) %f %f\n", hs, val, RollOutAdjust * val ) ;
374     fgSetDouble( "/autopilot/config/roll-out-deg", RollOutAdjust * val );
375     sprintf( SliderText[ 1 ], "%05.2f",
376              fgGetDouble("/autopilot/config/roll-out-deg") );
377     APAdjustRollOutText -> setLabel ( SliderText[ 1 ] );
378 }
379
380 static void maxaileron_adj( puObject *hs ) {
381     float val ;
382
383     hs-> getValue ( &val ) ;
384     SG_CLAMP_RANGE ( val, 0.1f, 1.0f ) ;
385     //    printf ( "maxaileron_adj( %p ) %f %f\n", hs, val, MaxAileronAdjust * val ) ;
386     fgSetDouble( "/autopilot/config/max-aileron", MaxAileronAdjust * val );
387     sprintf( SliderText[ 3 ], "%05.2f",
388              fgGetDouble("/autopilot/config/max-aileron") );
389     APAdjustMaxAileronText -> setLabel ( SliderText[ 3 ] );
390 }
391
392 static void rolloutsmooth_adj( puObject *hs ) {
393     float val ;
394
395     hs -> getValue ( &val ) ;
396     SG_CLAMP_RANGE ( val, 0.1f, 1.0f ) ;
397     //    printf ( "rolloutsmooth_adj( %p ) %f %f\n", hs, val, RollOutSmoothAdjust * val ) ;
398     fgSetDouble( "/autopilot/config/roll-out-smooth-deg",
399                  RollOutSmoothAdjust * val );
400     sprintf( SliderText[ 2 ], "%5.2f",
401              fgGetDouble("/autopilot/config/roll-out-smooth-deg") );
402     APAdjustRollOutSmoothText-> setLabel ( SliderText[ 2 ] );
403
404 }
405
406 static void goAwayAPAdjust (puObject *)
407 {
408     FG_POP_PUI_DIALOG( APAdjustDialog );
409 }
410
411 void cancelAPAdjust( puObject *self ) {
412     fgSetDouble( "/autopilot/config/max-roll-deg", TmpMaxRollValue );
413     fgSetDouble( "/autopilot/config/roll-out-deg", TmpRollOutValue );
414     fgSetDouble( "/autopilot/config/max-aileron", TmpMaxAileronValue );
415     fgSetDouble( "/autopilot/config/roll-out-smooth-deg",
416                  TmpRollOutSmoothValue );
417
418     goAwayAPAdjust(self);
419 }
420
421 void resetAPAdjust( puObject *self ) {
422     fgSetDouble( "/autopilot/config/max-roll-deg", MaxRollAdjust / 2 );
423     fgSetDouble( "/autopilot/config/roll-out-deg", RollOutAdjust / 2 );
424     fgSetDouble( "/autopilot/config/max-aileron", MaxAileronAdjust / 2 );
425     fgSetDouble( "/autopilot/config/roll-out-smooth-deg", 
426                  RollOutSmoothAdjust / 2 );
427
428     FG_POP_PUI_DIALOG( APAdjustDialog );
429
430     fgAPAdjust( self );
431 }
432
433 void fgAPAdjust( puObject *self ) {
434     TmpMaxRollValue       = fgGetDouble("/autopilot/config/max-roll-deg");
435     TmpRollOutValue       = fgGetDouble("/autopilot/config/roll-out-deg");
436     TmpMaxAileronValue    = fgGetDouble("/autopilot/config/max-aileron");
437     TmpRollOutSmoothValue = fgGetDouble("/autopilot/config/roll-out-smooth-deg");
438
439     MaxRollValue = fgGetDouble("/autopilot/config/max-roll-deg")
440         / MaxRollAdjust;
441     RollOutValue = fgGetDouble("/autopilot/config/roll-out-deg")
442         / RollOutAdjust;
443     MaxAileronValue = fgGetDouble("/autopilot/config/max-aileron")
444         / MaxAileronAdjust;
445     RollOutSmoothValue =  fgGetDouble("/autopilot/config/roll-out-smooth-deg")
446         / RollOutSmoothAdjust;
447
448     APAdjustHS0-> setValue ( MaxRollValue ) ;
449     APAdjustHS1-> setValue ( RollOutValue ) ;
450     APAdjustHS2-> setValue ( RollOutSmoothValue ) ;
451     APAdjustHS3-> setValue ( MaxAileronValue ) ;
452
453     FG_PUSH_PUI_DIALOG( APAdjustDialog );
454 }
455
456 // Done once at system initialization
457 void fgAPAdjustInit() {
458
459     //  printf("fgAPAdjustInit\n");
460 #define HORIZONTAL  FALSE
461
462     int DialogX = 40;
463     int DialogY = 100;
464     int DialogWidth = 230;
465
466     char Label[] =  "AutoPilot Adjust";
467     char *s;
468
469     int labelX = (DialogWidth / 2) -
470         (puGetDefaultLabelFont().getStringWidth( Label ) / 2);
471     labelX -= 30;  // KLUDGEY
472
473     int nSliders = 4;
474     int slider_x = 10;
475     int slider_y = 55;
476     int slider_width = 210;
477     int slider_title_x = 15;
478     int slider_value_x = 160;
479     float slider_delta = 0.1f;
480
481     TmpMaxRollValue       = fgGetDouble("/autopilot/config/max-roll-deg");
482     TmpRollOutValue       = fgGetDouble("/autopilot/config/roll-out-deg");
483     TmpMaxAileronValue    = fgGetDouble("/autopilot/config/max-aileron");
484     TmpRollOutSmoothValue = fgGetDouble("/autopilot/config/roll-out-smooth-deg");
485     MaxRollAdjust = 2 * fgGetDouble("/autopilot/config/max-roll-deg");
486     RollOutAdjust = 2 * fgGetDouble("/autopilot/config/roll-out-deg");
487     MaxAileronAdjust = 2 * fgGetDouble("/autopilot/config/max-aileron");
488     RollOutSmoothAdjust = 2 * fgGetDouble("/autopilot/config/roll-out-smooth-deg");
489
490     MaxRollValue = fgGetDouble("/autopilot/config/max-roll-deg")
491         / MaxRollAdjust;
492     RollOutValue = fgGetDouble("/autopilot/config/roll-out-deg")
493         / RollOutAdjust;
494     MaxAileronValue = fgGetDouble("/autopilot/config/max-aileron")
495         / MaxAileronAdjust;
496     RollOutSmoothValue =  fgGetDouble("/autopilot/config/roll-out-smooth-deg")
497         / RollOutSmoothAdjust;
498
499     puGetDefaultFonts (  &APAdjustLegendFont,  &APAdjustLabelFont );
500     APAdjustDialog = new puDialogBox ( DialogX, DialogY ); {
501         int horiz_slider_height = APAdjustLabelFont.getStringHeight() +
502             APAdjustLabelFont.getStringDescender() +
503             PUSTR_TGAP + PUSTR_BGAP + 5;
504
505         APAdjustFrame = new puFrame ( 0, 0,
506                                       DialogWidth,
507                                       85 + nSliders * horiz_slider_height );
508
509         APAdjustDialogMessage = new puText ( labelX,
510                                              52 + nSliders
511                                              * horiz_slider_height );
512         APAdjustDialogMessage -> setDefaultValue ( Label );
513         APAdjustDialogMessage -> getDefaultValue ( &s );
514         APAdjustDialogMessage -> setLabel        ( s );
515
516         APAdjustHS0 = new mySlider ( slider_x, slider_y,
517                                      slider_width, HORIZONTAL ) ;
518         APAdjustHS0-> setDelta ( slider_delta ) ;
519         APAdjustHS0-> setValue ( MaxRollValue ) ;
520         APAdjustHS0-> setCBMode ( PUSLIDER_DELTA ) ;
521         APAdjustHS0-> setCallback ( maxroll_adj ) ;
522
523         sprintf( SliderText[ 0 ], "%05.2f",
524                  fgGetDouble("/autopilot/config/max-roll-deg") );
525         APAdjustMaxRollTitle = new puText ( slider_title_x, slider_y ) ;
526         APAdjustMaxRollTitle-> setDefaultValue ( "MaxRoll" ) ;
527         APAdjustMaxRollTitle-> getDefaultValue ( &s ) ;
528         APAdjustMaxRollTitle-> setLabel ( s ) ;
529         APAdjustMaxRollText = new puText ( slider_value_x, slider_y ) ;
530         APAdjustMaxRollText-> setLabel ( SliderText[ 0 ] ) ;
531
532         slider_y += horiz_slider_height;
533
534         APAdjustHS1 = new mySlider ( slider_x, slider_y, slider_width,
535                                      HORIZONTAL ) ;
536         APAdjustHS1-> setDelta ( slider_delta ) ;
537         APAdjustHS1-> setValue ( RollOutValue ) ;
538         APAdjustHS1-> setCBMode ( PUSLIDER_DELTA ) ;
539         APAdjustHS1-> setCallback ( rollout_adj ) ;
540
541         sprintf( SliderText[ 1 ], "%05.2f",
542                  fgGetDouble("/autopilot/config/roll-out-deg") );
543         APAdjustRollOutTitle = new puText ( slider_title_x, slider_y ) ;
544         APAdjustRollOutTitle-> setDefaultValue ( "AdjustRollOut" ) ;
545         APAdjustRollOutTitle-> getDefaultValue ( &s ) ;
546         APAdjustRollOutTitle-> setLabel ( s ) ;
547         APAdjustRollOutText = new puText ( slider_value_x, slider_y ) ;
548         APAdjustRollOutText-> setLabel ( SliderText[ 1 ] );
549
550         slider_y += horiz_slider_height;
551
552         APAdjustHS2 = new mySlider ( slider_x, slider_y, slider_width,
553                                      HORIZONTAL ) ;
554         APAdjustHS2-> setDelta ( slider_delta ) ;
555         APAdjustHS2-> setValue ( RollOutSmoothValue ) ;
556         APAdjustHS2-> setCBMode ( PUSLIDER_DELTA ) ;
557         APAdjustHS2-> setCallback ( rolloutsmooth_adj ) ;
558
559         sprintf( SliderText[ 2 ], "%5.2f", 
560                  fgGetDouble("/autopilot/config/roll-out-smooth-deg") );
561         APAdjustRollOutSmoothTitle = new puText ( slider_title_x, slider_y ) ;
562         APAdjustRollOutSmoothTitle-> setDefaultValue ( "RollOutSmooth" ) ;
563         APAdjustRollOutSmoothTitle-> getDefaultValue ( &s ) ;
564         APAdjustRollOutSmoothTitle-> setLabel ( s ) ;
565         APAdjustRollOutSmoothText = new puText ( slider_value_x, slider_y ) ;
566         APAdjustRollOutSmoothText-> setLabel ( SliderText[ 2 ] );
567
568         slider_y += horiz_slider_height;
569
570         APAdjustHS3 = new mySlider ( slider_x, slider_y, slider_width,
571                                      HORIZONTAL ) ;
572         APAdjustHS3-> setDelta ( slider_delta ) ;
573         APAdjustHS3-> setValue ( MaxAileronValue ) ;
574         APAdjustHS3-> setCBMode ( PUSLIDER_DELTA ) ;
575         APAdjustHS3-> setCallback ( maxaileron_adj ) ;
576
577         sprintf( SliderText[ 3 ], "%05.2f", 
578                  fgGetDouble("/autopilot/config/max-aileron") );
579         APAdjustMaxAileronTitle = new puText ( slider_title_x, slider_y ) ;
580         APAdjustMaxAileronTitle-> setDefaultValue ( "MaxAileron" ) ;
581         APAdjustMaxAileronTitle-> getDefaultValue ( &s ) ;
582         APAdjustMaxAileronTitle-> setLabel ( s ) ;
583         APAdjustMaxAileronText = new puText ( slider_value_x, slider_y ) ;
584         APAdjustMaxAileronText-> setLabel ( SliderText[ 3 ] );
585
586         APAdjustOkButton = new puOneShot ( 10, 10, 60, 50 );
587         APAdjustOkButton-> setLegend ( gui_msg_OK );
588         APAdjustOkButton-> makeReturnDefault ( TRUE );
589         APAdjustOkButton-> setCallback ( goAwayAPAdjust );
590
591         APAdjustCancelButton = new puOneShot ( 70, 10, 150, 50 );
592         APAdjustCancelButton-> setLegend ( gui_msg_CANCEL );
593         APAdjustCancelButton-> setCallback ( cancelAPAdjust );
594
595         APAdjustResetButton = new puOneShot ( 160, 10, 220, 50 );
596         APAdjustResetButton-> setLegend ( gui_msg_RESET );
597         APAdjustResetButton-> setCallback ( resetAPAdjust );
598     }
599     FG_FINALIZE_PUI_DIALOG( APAdjustDialog );
600
601 #undef HORIZONTAL
602 }
603 #endif
604
605 // Simple Dialog to input Target Airport
606 void TgtAptDialog_Cancel(puObject *)
607 {
608     FG_POP_PUI_DIALOG( TgtAptDialog );
609 }
610
611 void TgtAptDialog_OK (puObject *)
612 {
613     string TgtAptId;
614     
615     //    FGTime *t = FGTime::cur_time_params;
616     //    int PauseMode = t->getPause();
617     //    if(!PauseMode)
618     //        t->togglePauseMode();
619     
620     char *s;
621     TgtAptDialogInput->getValue(&s);
622
623     string tmp = s;
624     unsigned int pos = tmp.find( "@" );
625     if ( pos != string::npos ) {
626         TgtAptId = tmp.substr( 0, pos );
627     } else {
628         TgtAptId = tmp;
629     }
630
631     TgtAptDialog_Cancel( NULL );
632     
633     /* s = input string, either 'FIX' or FIX@4000' */
634     /* TgtAptId is name of fix only; may get appended to below */
635
636     if ( NewWaypoint( TgtAptId ) == 0)
637     {
638         TgtAptId  += " not in database.";
639         mkDialog(TgtAptId.c_str());
640     }
641 }
642
643 /* add new waypoint (either from above popup window 'ok button or telnet session) */
644
645 int NewWaypoint( const string& Tgt_Alt )
646 {
647   string TgtAptId;
648   FGAirport a;
649   FGFix f;
650
651   double alt = 0.0;
652   unsigned int pos = Tgt_Alt.find( "@" );
653   if ( pos != string::npos ) {
654     TgtAptId = Tgt_Alt.substr( 0, pos );
655     string alt_str = Tgt_Alt.substr( pos + 1 );
656     alt = atof( alt_str.c_str() );
657     if ( !strcmp(fgGetString("/sim/startup/units"), "feet") ) {
658       alt *= SG_FEET_TO_METER;
659     }
660   } else {
661     TgtAptId = Tgt_Alt;
662   }
663
664   FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
665
666   if ( fgFindAirportID( TgtAptId, &a ) ) {
667
668       SG_LOG( SG_GENERAL, SG_INFO,
669               "Adding waypoint (airport) = " << TgtAptId );
670
671       sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
672
673       SGWayPoint wp( a.getLongitude(), a.getLatitude(), alt,
674                      SGWayPoint::WGS84, TgtAptId );
675       rm->add_waypoint( wp );
676
677       /* and turn on the autopilot */
678       fgSetString( "/autopilot/locks/heading", "true-heading-hold" );
679
680       return 1;
681
682   } else if ( globals->get_fixlist()->query( TgtAptId, &f ) ) {
683       SG_LOG( SG_GENERAL, SG_INFO,
684               "Adding waypoint (fix) = " << TgtAptId );
685
686       sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
687
688       SGWayPoint wp( f.get_lon(), f.get_lat(), alt,
689                      SGWayPoint::WGS84, TgtAptId );
690       rm->add_waypoint( wp );
691
692       /* and turn on the autopilot */
693       fgSetString( "/autopilot/locks/heading", "true-heading-hold" );
694       return 2;
695   } else {
696           // Try finding a nav matching the ID
697           double lat, lon;
698           // The base lon/lat are determined by the last WP,
699           // or the current pos if the WP list is empty.
700           const int wps = rm->size();
701           if (wps > 0) {
702                   SGWayPoint wp = rm->get_waypoint(wps-1);
703                   lat = wp.get_target_lat();
704                   lon = wp.get_target_lon();
705           }
706           else {
707                   lat = fgGetNode("/position/latitude-deg")->getDoubleValue();
708                   lon = fgGetNode("/position/longitude-deg")->getDoubleValue();
709           }
710
711           lat *= SGD_DEGREES_TO_RADIANS;
712           lon *= SGD_DEGREES_TO_RADIANS;
713
714           SG_LOG( SG_GENERAL, SG_INFO,
715                           "Looking for nav " << TgtAptId << " at " << lon << " " << lat);
716           if (FGNavRecord* nav =
717                           globals->get_navlist()->findByIdent(TgtAptId.c_str(), lon, lat))
718           {
719                   SG_LOG( SG_GENERAL, SG_INFO,
720                                   "Adding waypoint (nav) = " << TgtAptId );
721
722                   sprintf( NewTgtAirportId, "%s", TgtAptId.c_str() );
723
724                   SGWayPoint wp( nav->get_lon(), nav->get_lat(), alt,
725                                                  SGWayPoint::WGS84, TgtAptId );
726                   rm->add_waypoint( wp );
727
728                   /* and turn on the autopilot */
729                   fgSetString( "/autopilot/locks/heading", "true-heading-hold" );
730                   return 3;
731           }
732           else {
733                   return 0;
734           }
735   }
736 }
737
738
739 void TgtAptDialog_Reset(puObject *)
740 {
741     sprintf( NewTgtAirportId, "%s", fgGetString("/sim/presets/airport-id") );
742     TgtAptDialogInput->setValue ( NewTgtAirportId );
743     TgtAptDialogInput->setCursor( 0 ) ;
744 }
745
746 void TgtAptDialog_HandleSlider ( puObject * slider )
747 {
748   float val ;
749   slider -> getValue ( &val ) ;
750   val = 1.0f - val ;
751
752   int index = int ( TgtAptDialogWPList -> getNumItems () * val ) ;
753   TgtAptDialogWPList -> setTopItem ( index ) ;
754 }
755
756 void TgtAptDialog_HandleArrow( puObject *arrow )
757 {
758     int type = ((puArrowButton *)arrow)->getArrowType() ;
759     int inc = ( type == PUARROW_DOWN     ) ?   1 :
760             ( type == PUARROW_UP       ) ?  -1 :
761             ( type == PUARROW_FASTDOWN ) ?  10 :
762             ( type == PUARROW_FASTUP   ) ? -10 : 0 ;
763
764     float val ;
765     TgtAptDialogSlider -> getValue ( &val ) ;
766     val = 1.0f - val ;
767     int num_items = TgtAptDialogWPList->getNumItems () - 1 ;
768     if ( num_items > 0 )
769     {
770       int index = int ( num_items * val + 0.5 ) + inc ;
771       if ( index > num_items ) index = num_items ;
772       if ( index < 0 ) index = 0 ;
773
774       TgtAptDialogSlider -> setValue ( 1.0f - (float)index / num_items ) ;
775       TgtAptDialogWPList -> setTopItem ( index ) ;
776   }
777
778 }
779
780 void AddWayPoint(puObject *cb)
781 {
782     sprintf( NewTgtAirportId, "%s", fgGetString("/sim/presets/airport-id") );
783     TgtAptDialogInput->setValue( NewTgtAirportId );
784     
785     /* refresh waypoint list */
786     char WPString[100];
787
788     int i;
789     if ( WPList != NULL ) {
790         for (i = 0; i < WPListsize; i++ ) {
791           delete WPList[i];
792         }
793         delete [] WPList[i];
794     }
795     FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
796     WPListsize = rm->size();
797     if ( WPListsize > 0 ) { 
798         WPList = new char* [ WPListsize + 1 ];
799         for (i = 0; i < WPListsize; i++ ) {
800             SGWayPoint wp = rm->get_waypoint(i);
801             sprintf( WPString, "%5s %3.2flon %3.2flat",
802                      wp.get_id().c_str(),
803                      wp.get_target_lon(),
804                      wp.get_target_lat() );
805            WPList [i] = new char[ strlen(WPString)+1 ];
806            strcpy ( WPList [i], WPString );
807         }
808     } else {
809         WPListsize = 1;
810         WPList = new char* [ 2 ];
811         WPList [0] = new char[18];
812         strcpy ( WPList [0], "** List Empty **");
813     }    
814     WPList [ WPListsize ] = NULL;
815     TgtAptDialogWPList->newList( WPList );
816
817    // if non-empty list, adjust the size of the slider...
818    TgtAptDialogSlider->setSliderFraction (0.9999f) ;
819    TgtAptDialogSlider->hide();
820    TgtAptDialogUPArrow->hide();
821    TgtAptDialogDNArrow->hide();
822    if (WPListsize > 10) {
823       TgtAptDialogSlider->setSliderFraction (10.0f/(WPListsize-1)) ;
824       TgtAptDialogSlider->reveal();
825       TgtAptDialogUPArrow->reveal();
826       TgtAptDialogDNArrow->reveal();
827     }
828
829     FG_PUSH_PUI_DIALOG( TgtAptDialog );
830 }
831
832 void PopWayPoint(puObject *cb)
833 {
834     FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
835     rm->pop_waypoint();
836 }
837
838 void ClearRoute(puObject *cb)
839 {
840     FGRouteMgr *rm = (FGRouteMgr *)globals->get_subsystem("route-manager");
841     rm->init();
842 }
843
844 void NewTgtAirportInit()
845 {
846     SG_LOG( SG_AUTOPILOT, SG_INFO, " enter NewTgtAirportInit()" );
847     sprintf( NewTgtAirportId, "%s", fgGetString("/sim/presets/airport-id") );
848     SG_LOG( SG_AUTOPILOT, SG_INFO, " NewTgtAirportId " << NewTgtAirportId );
849     
850     TgtAptDialog = new puDialogBox (150, 350);
851     {
852         TgtAptDialogFrame   = new puFrame           (0,0,350, 350);
853         
854         TgtAptDialogWPList = new puListBox ( 50, 130, 300, 320 ) ;
855         TgtAptDialogWPList -> setLabel ( "Flight Plan" );
856         TgtAptDialogWPList -> setLabelPlace ( PUPLACE_ABOVE ) ;
857         TgtAptDialogWPList -> setStyle ( -PUSTYLE_SMALL_SHADED ) ;
858         TgtAptDialogWPList -> setValue ( 0 ) ;
859
860         TgtAptDialogSlider = new puSlider (300, 150, 150 ,TRUE,20);
861         TgtAptDialogSlider->setValue(1.0f);
862         TgtAptDialogSlider->setSliderFraction (0.2f) ;
863         TgtAptDialogSlider->setDelta(0.1f);
864         TgtAptDialogSlider->setCBMode( PUSLIDER_DELTA );
865         TgtAptDialogSlider->setCallback( TgtAptDialog_HandleSlider );
866
867         TgtAptDialogUPArrow = new puArrowButton ( 300, 300, 320, 320, PUARROW_UP ) ;
868         TgtAptDialogUPArrow->setCallback ( TgtAptDialog_HandleArrow ) ;
869
870         TgtAptDialogDNArrow = new puArrowButton ( 300, 130, 320, 150, PUARROW_DOWN ) ;
871         TgtAptDialogDNArrow->setCallback ( TgtAptDialog_HandleArrow ) ;
872
873
874         TgtAptDialogInput   = new puInput           (50, 70, 300, 100);
875         TgtAptDialogInput -> setLabel ( NewTgtAirportLabel );
876         TgtAptDialogInput -> setLabelPlace ( PUPLACE_ABOVE ) ;
877         TgtAptDialogInput   ->    setValue          (NewTgtAirportId);
878         TgtAptDialogInput   ->    acceptInput();
879         
880         TgtAptDialogOkButton     =  new puOneShot   (50, 10, 110, 50);
881         TgtAptDialogOkButton     ->     setLegend   (gui_msg_OK);
882         TgtAptDialogOkButton     ->     setCallback (TgtAptDialog_OK);
883         TgtAptDialogOkButton     ->     makeReturnDefault(TRUE);
884         
885         TgtAptDialogCancelButton =  new puOneShot   (140, 10, 210, 50);
886         TgtAptDialogCancelButton ->     setLegend   (gui_msg_CANCEL);
887         TgtAptDialogCancelButton ->     setCallback (TgtAptDialog_Cancel);
888         
889         TgtAptDialogResetButton  =  new puOneShot   (240, 10, 300, 50);
890         TgtAptDialogResetButton  ->     setLegend   (gui_msg_RESET);
891         TgtAptDialogResetButton  ->     setCallback (TgtAptDialog_Reset);
892
893     }
894
895     FG_FINALIZE_PUI_DIALOG( TgtAptDialog );
896     SG_LOG(SG_GENERAL, SG_DEBUG, "leave NewTgtAirportInit()");
897 }
898
899
900