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