3 Adapted by Jim Wilson, beginning Sept 2001 (FG v 0.79)
5 **** Insert FlightGear GPL here.
7 Based on puFilePicker from:
10 PLIB - A Suite of Portable Game Libraries
11 Copyright (C) 2001 Steve Baker
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Library General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Library General Public License for more details.
23 You should have received a copy of the GNU Library General Public
24 License along with this library; if not, write to the Free
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 For further information visit http://plib.sourceforge.net
38 #include "prop_picker.hxx"
39 #include <Main/globals.hxx>
41 #include <simgear/compiler.h>
43 #define DOTDOTSLASH "../"
46 string name, line, value;
48 static puObject *PP_widget = 0;
50 // widget location and size...
51 #define PROPPICK_X 100
52 #define PROPPICK_Y 200
53 #define PROPPICK_W 500
54 #define PROPPICK_H 300
56 static puObject *PE_widget = 0;
58 void prop_pickerInit()
60 if( PP_widget == 0 ) {
61 fgPropPicker *PP = new fgPropPicker ( PROPPICK_X, PROPPICK_Y, PROPPICK_W, PROPPICK_H, 1, "/", "FG Properties");
66 void prop_pickerView( puObject * )
68 if( PP_widget == 0 ) {
71 fgPropPicker *me = (fgPropPicker *)PP_widget -> getUserData();
74 FG_PUSH_PUI_DIALOG( me );
77 void prop_pickerRefresh()
79 if( PP_widget == 0 ) {
82 fgPropPicker *me = (fgPropPicker *)PP_widget -> getUserData();
86 void prop_editInit(char * name, char * value, char * proppath)
88 if( PE_widget == 0 ) {
89 fgPropEdit *PP = new fgPropEdit ( name, value, proppath );
94 void prop_editOpen( char * name, char * value, char * proppath )
96 if( PE_widget == 0 ) {
97 prop_editInit( name, value, proppath );
99 fgPropEdit *me = (fgPropEdit *)PE_widget -> getUserData();
100 me -> propname -> setLabel (name);
101 me -> propinput -> setValue (value);
102 strcpy(me -> propPath, proppath);
103 me -> propinput -> acceptInput ();
104 FG_PUSH_PUI_DIALOG( me );
107 // return a human readable form of the value "type"
108 static string getValueTypeString( const SGPropertyNode *node ) {
111 if ( node == NULL ) {
115 SGPropertyNode::Type type = node->getType();
116 if ( type == SGPropertyNode::UNSPECIFIED ) {
117 result = "unspecified";
118 } else if ( type == SGPropertyNode::NONE ) {
120 } else if ( type == SGPropertyNode::BOOL ) {
122 } else if ( type == SGPropertyNode::INT ) {
124 } else if ( type == SGPropertyNode::LONG ) {
126 } else if ( type == SGPropertyNode::FLOAT ) {
128 } else if ( type == SGPropertyNode::DOUBLE ) {
130 } else if ( type == SGPropertyNode::STRING ) {
137 void fgPropPicker::fgPropPickerHandleSlider ( puObject * slider )
140 slider -> getValue ( &val ) ;
143 puListBox* list_box = (puListBox*) slider -> getUserData () ;
144 int index = int ( list_box -> getNumItems () * val ) ;
145 list_box -> setTopItem ( index ) ;
148 void fgPropPicker::fgPropPickerHandleArrow ( puObject *arrow )
150 puSlider *slider = (puSlider *) arrow->getUserData () ;
151 puListBox* list_box = (puListBox*) slider -> getUserData () ;
153 int type = ((puArrowButton *)arrow)->getArrowType() ;
154 int inc = ( type == PUARROW_DOWN ) ? 1 :
155 ( type == PUARROW_UP ) ? -1 :
156 ( type == PUARROW_FASTDOWN ) ? 10 :
157 ( type == PUARROW_FASTUP ) ? -10 : 0 ;
160 slider -> getValue ( &val ) ;
162 int num_items = list_box->getNumItems () - 1 ;
165 int index = int ( num_items * val + 0.5 ) + inc ;
166 if ( index > num_items ) index = num_items ;
167 if ( index < 0 ) index = 0 ;
169 slider -> setValue ( 1.0f - (float)index / num_items ) ;
170 list_box -> setTopItem ( index ) ;
175 void fgPropPicker::chop_file ( char *fname )
177 /* removes everything back to the last '/' */
179 for ( int i = strlen(fname)-1 ; fname[i] != SLASH[0] && i >= 0 ; i-- )
184 void fgPropPicker::go_up_one_directory ( char *fname )
186 /* removes everything back to the last but one '/' */
188 chop_file ( fname ) ;
190 if ( strlen ( fname ) == 0 )
192 /* Empty string! The only way to go up is to append a "../" */
194 strcpy ( fname, DOTDOTSLASH ) ;
198 /* If the last path element is a "../" then we'll have to add another "../" */
200 if ( strcmp ( & fname [ strlen(fname)-3 ], DOTDOTSLASH ) == 0 )
202 if ( strlen ( fname ) + 4 >= PUSTRING_MAX )
204 ulSetError ( UL_WARNING, "PUI: fgPropPicker - path is too long, max is %d.",
209 strcat ( fname, DOTDOTSLASH ) ;
213 /* Otherwise, just delete the last element of the path. */
215 /* Remove the trailing slash - then remove the rest as if it was a file name */
217 fname [ strlen(fname)-1 ] = '\0' ;
218 chop_file ( fname ) ;
222 void fgPropPicker::handle_select ( puObject* list_box )
224 fgPropPicker* prop_picker = (fgPropPicker*) list_box -> getUserData () ;
227 list_box -> getValue ( &selected ) ;
229 if ( selected >= 0 && selected < prop_picker -> num_files )
231 char *dst = prop_picker -> startDir ;
232 char *src = prop_picker -> files [ selected ] ;
234 if ( strcmp ( src, "." ) == 0 )
236 /* Do nothing - but better refresh anyway. */
238 prop_picker -> find_props () ;
242 printf("select got here 2\n");
243 if ( strcmp ( src, ".." ) == 0 )
245 /* Do back up one level - so refresh. */
247 go_up_one_directory ( dst ) ;
248 prop_picker -> find_props () ;
252 if ( prop_picker -> dflag [ selected ] )
254 /* If this is a directory - then descend into it and refresh */
256 if ( strlen ( dst ) + strlen ( src ) + 2 >= PUSTRING_MAX )
258 ulSetError ( UL_WARNING,
259 "PUI: fgPropPicker - path is too long, max is %d.", PUSTRING_MAX ) ;
263 strcat ( dst, src ) ; /* add path to descend to */
264 prop_picker -> find_props () ;
268 /* If this is a regular file - then just append it to the string */
270 if ( strlen ( dst ) + strlen ( src ) + 2 >= PUSTRING_MAX )
272 ulSetError ( UL_WARNING,
273 "PUI: fgPropPicker - path is too long, max is %d.", PUSTRING_MAX ) ;
276 prop_editOpen( prop_picker -> names [ selected ], prop_picker -> values [ selected ], dst);
281 The user clicked on blank screen - maybe we should
282 refresh just in case some other process created the
286 prop_picker -> find_props () ;
291 void fgPropPicker::fgPropPickerHandleOk ( puObject* b )
293 fgPropPicker* prop_picker = (fgPropPicker*) b -> getUserData () ;
295 /* nothing to do, just hide */
296 FG_POP_PUI_DIALOG( prop_picker );
301 fgPropPicker::~fgPropPicker ()
305 for ( int i=0; i<num_files; i++ ) {
317 if ( this == puActiveWidget () )
318 puDeactivateWidget () ;
323 fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
324 const char *dir, const char *title ) : puDialogBox ( x,y )
326 puFont LegendFont, LabelFont;
327 puGetDefaultFonts ( &LegendFont, &LabelFont );
335 strcpy ( startDir, dir ) ;
336 printf ( "StartDirLEN=%i", strlen(startDir));
337 if ( arrows > 2 ) arrows = 2 ;
338 if ( arrows < 0 ) arrows = 0 ;
339 arrow_count = arrows ;
341 frame = new puFrame ( 0, 0, w, h );
345 proppath = new puText (10, h-30);
346 proppath -> setLabel (startDir);
348 slider = new puSlider (w-30,40+20*arrows,h-100-40*arrows,TRUE,20);
349 slider->setDelta(0.1f);
350 slider->setValue(1.0f);
351 slider->setSliderFraction (0.2f) ;
352 slider->setCBMode( PUSLIDER_DELTA );
354 list_box = new puListBox ( 10, 40, w-40, h-60 ) ;
355 list_box -> setLabel ( title );
356 list_box -> setLabelPlace ( PUPLACE_ABOVE ) ;
357 list_box -> setStyle ( -PUSTYLE_SMALL_SHADED ) ;
358 list_box -> setUserData ( this ) ;
359 list_box -> setCallback ( handle_select ) ;
360 list_box -> setValue ( 0 ) ;
364 // printf("after Props files[1]=%s\n",files[1]);
365 // printf("num items %i", list_box -> getNumItems ());
367 slider -> setUserData ( list_box ) ;
368 slider -> setCallback ( fgPropPickerHandleSlider ) ;
370 ok_button = new puOneShot ( 10, 10, (w<170)?(w/2-5):80, 30 ) ;
371 ok_button -> setLegend ( "Ok" ) ;
372 ok_button -> setUserData ( this ) ;
373 ok_button -> setCallback ( fgPropPickerHandleOk ) ;
377 puArrowButton *down_arrow = new puArrowButton ( w-30, 20+20*arrows, w-10, 40+20*arrows, PUARROW_DOWN ) ;
378 down_arrow->setUserData ( slider ) ;
379 down_arrow->setCallback ( fgPropPickerHandleArrow ) ;
381 puArrowButton *up_arrow = new puArrowButton ( w-30, h-30-20*arrows, w-10, h-10-20*arrows, PUARROW_UP ) ;
382 up_arrow->setUserData ( slider ) ;
383 up_arrow->setCallback ( fgPropPickerHandleArrow ) ;
388 puArrowButton *down_arrow = new puArrowButton ( w-30, 40, w-10, 60, PUARROW_FASTDOWN ) ;
389 down_arrow->setUserData ( slider ) ;
390 down_arrow->setCallback ( fgPropPickerHandleArrow ) ;
392 puArrowButton *up_arrow = new puArrowButton ( w-30, h-50, w-10, h-30, PUARROW_FASTUP ) ;
393 up_arrow->setUserData ( slider ) ;
394 up_arrow->setCallback ( fgPropPickerHandleArrow ) ;
397 FG_FINALIZE_PUI_DIALOG( this );
398 printf("fgPropPicker - End of Init\n");
402 void fgPropPicker::find_props ()
409 for ( int i = 0 ; i < num_files ; i++ ) {
423 char dir [ PUSTRING_MAX * 2 ] ;
428 strcpy ( dir, startDir ) ;
431 // printf("dir begin of find_props=%s\n",dir);
432 // printf("len of dir=%i",strlen(dir));
433 SGPropertyNode * node = globals->get_props()->getNode(dir);
435 printf("find_props: allocation of node\n");
436 num_files = (int)node->nChildren();
438 // take off one for the trailing "null" in each SGProperty list
439 num_files = num_files -1;
441 // instantiate string objects and add [.] and [..] for subdirs
442 if (strcmp(dir,"/") == 0) {
443 files = new char* [ num_files+1 ] ;
444 names = new char* [ num_files+1 ] ;
445 values = new char* [ num_files+1 ] ;
446 dflag = new char [ num_files+1 ] ;
449 // add two for the .. and .
450 num_files = num_files + 2;
451 // make room for .. and .
452 files = new char* [ num_files+1 ] ;
453 names = new char* [ num_files+1 ] ;
454 values = new char* [ num_files+1 ] ;
455 dflag = new char [ num_files+1 ] ;
457 files [ 0 ] = new char[ strlen(line.c_str())+2 ];
458 strcpy ( files [ 0 ], line.c_str() );
459 names [ 0 ] = new char[ 2 ];
460 values[ 0 ] = new char[ 2 ] ;
463 files [ 1 ] = new char[ strlen(line.c_str())+2 ];
464 strcpy ( files [ 1 ], line.c_str() );
465 names [ 1 ] = new char[ strlen(line.c_str())+2 ];
466 values[ 1 ] = new char[ 2 ] ;
467 strcpy ( names [ 1 ], line.c_str() );
474 for (i = 0; i < (int)node->nChildren()-1; i++) {
475 SGPropertyNode * child = node->getChild(i);
476 name = child->getName();
478 names[ pi ] = new char[ strlen(line.c_str())+2 ] ;
479 strcpy ( names [ pi ], line.c_str() ) ;
480 if ( child->nChildren() > 0 ) {
481 iindex = child->getIndex();
482 sprintf(sindex, "%d", iindex);
484 files[ pi ] = new char[ strlen(line.c_str())+strlen(sindex)+4 ] ;
485 strcpy ( files [ pi ], line.c_str() ) ;
486 strcat ( files [ pi ], "[" ) ;
487 strcat ( files [ pi ], sindex ) ;
488 strcat ( files [ pi ], "]/" ) ;
489 values[ pi ] = new char[ 2 ] ;
492 value = node->getStringValue ( name, "" );
493 values[ pi ] = new char[ strlen(value.c_str())+2 ] ;
494 strcpy ( values [pi], value.c_str() );
495 line += " = '" + value + "' " + "(";
496 line += getValueTypeString( node->getNode( name ) );
498 files[ pi ] = new char[ strlen(line.c_str())+2 ] ;
499 strcpy ( files [ pi ], line.c_str() ) ;
501 printf("files->%i %s\n",pi, files [pi]);
505 files [ num_files ] = NULL ;
507 printf("files pointer=%p\n", files);
508 proppath -> setLabel (startDir);
509 list_box -> newList ( files ) ;
513 void fgPropEdit::fgPropEditHandleCancel ( puObject* b )
515 fgPropEdit* prop_edit = (fgPropEdit*) b -> getUserData () ;
516 FG_POP_PUI_DIALOG( prop_edit );
519 void fgPropEdit::fgPropEditHandleOK ( puObject* b )
521 fgPropEdit* prop_edit = (fgPropEdit*) b -> getUserData () ;
525 // use label text for property node to be updated
526 tname = prop_edit -> propname -> getLabel();
527 prop_edit -> propinput -> getValue( &tvalue );
529 SGPropertyNode * node = globals->get_props()->getNode(prop_edit -> propPath);
530 node->getNode( prop_edit -> propname -> getLabel(), true)->setStringValue(tvalue);
532 // update the picker display so it shows new value
533 prop_pickerRefresh();
535 FG_POP_PUI_DIALOG( prop_edit );
538 fgPropEdit::fgPropEdit ( char *name, char *value, char *proppath ) : puDialogBox ( 0, 0 )
541 puFont LegendFont, LabelFont;
542 puGetDefaultFonts ( &LegendFont, &LabelFont );
544 // locate in relation to picker widget...
546 int fy = PROPPICK_Y + PROPPICK_H;
547 frame = new puFrame (fx,fy, fx+500, fy+120);
549 strcpy (propPath, proppath);
553 propname = new puText (fx+10, fy+90);
554 propname -> setLabel (name);
556 propinput = new puInput (fx+10, fy+50, fx+480, fy+80);
557 propinput -> setValue (value);
558 propinput -> acceptInput();
561 ok_button = new puOneShot (fx+10, fy+10, fx+80, fy+30);
562 ok_button -> setUserData (this);
563 ok_button -> setLegend (gui_msg_OK);
564 ok_button -> setCallback (fgPropEditHandleOK);
565 ok_button -> makeReturnDefault(TRUE);
567 cancel_button = new puOneShot (fx+100, fy+10, fx+180, fy+30);
568 cancel_button -> setUserData (this);
569 cancel_button -> setLegend (gui_msg_CANCEL);
570 cancel_button -> setCallback (fgPropEditHandleCancel);
572 FG_FINALIZE_PUI_DIALOG( this );