]> git.mxchange.org Git - flightgear.git/blobdiff - src/GUI/prop_picker.cxx
Added static port system and a new altimeter model connected to it.
[flightgear.git] / src / GUI / prop_picker.cxx
index a5137946018d3cc544bca7c73085978af151a345..0f3371fe019df10d40021ad1f58fa0825124b914 100755 (executable)
 #include <Main/globals.hxx>
 
 #include <simgear/compiler.h>
+#include <simgear/misc/props.hxx>
+
+#include STL_STRING
+SG_USING_STD(string);
+
+// A local alternative name, for use when a variable called "string" is in scope - e.g. in classes derived from puInput.
+typedef string stdString;
 
 #define DOTDOTSLASH "../"
 #define SLASH       "/"
 
-string name, line, value;
-
 static puObject *PP_widget = 0;
 
 // widget location and size...
@@ -136,13 +141,17 @@ static string getValueTypeString( const SGPropertyNode *node ) {
 
 void fgPropPicker::fgPropPickerHandleSlider ( puObject * slider )
 {
+  puListBox* list_box = (puListBox*) slider -> getUserData () ;
+
   float val ;
   slider -> getValue ( &val ) ;
   val = 1.0f - val ;
-
-  puListBox* list_box = (puListBox*) slider -> getUserData () ;
-  int index = int ( list_box -> getNumItems () * val ) ;
-  list_box -> setTopItem ( index ) ;
+  int scroll_range = list_box->getNumItems () - list_box->getNumVisible() ;
+  if ( scroll_range > 0 )
+  {
+    int index = int ( scroll_range * val + 0.5 ) ;
+    list_box -> setTopItem ( index ) ;
+  }
 }
 
 void fgPropPicker::fgPropPickerHandleArrow ( puObject *arrow )
@@ -159,14 +168,18 @@ void fgPropPicker::fgPropPickerHandleArrow ( puObject *arrow )
   float val ;
   slider -> getValue ( &val ) ;
   val = 1.0f - val ;
-  int num_items = list_box->getNumItems () - 1 ;
-  if ( num_items > 0 )
+  int scroll_range = list_box->getNumItems () - list_box->getNumVisible() ;
+  if ( scroll_range > 0 )
   {
-    int index = int ( num_items * val + 0.5 ) + inc ;
-    if ( index > num_items ) index = num_items ;
+    int index = int ( scroll_range * val + 0.5 ) ;
+    index += inc ;
+    // if ( index > scroll_range ) index = scroll_range ;
+    // Allow buttons to scroll further than the slider does
+    if ( index > ( list_box->getNumItems () - 1 ) )
+      index = ( list_box->getNumItems () - 1 ) ;
     if ( index < 0 ) index = 0 ;
 
-    slider -> setValue ( 1.0f - (float)index / num_items ) ;
+    slider -> setValue ( 1.0f - (float)index / scroll_range ) ;
     list_box -> setTopItem ( index ) ;
   }
 }
@@ -239,7 +252,6 @@ void fgPropPicker::handle_select ( puObject* list_box )
       return ;
     } 
 
-    printf("select got here 2\n");
     if ( strcmp ( src, ".." ) == 0 )
     {
       /* Do back up one level - so refresh. */
@@ -296,16 +308,15 @@ void fgPropPicker::fgPropPickerHandleOk ( puObject* b )
   FG_POP_PUI_DIALOG( prop_picker );
 }
 
-/*
 
-fgPropPicker::~fgPropPicker ()
+void fgPropPicker::delete_arrays ()
 {
   if ( files )
   {
     for ( int i=0; i<num_files; i++ ) {
-      delete files[i];
-      delete names[i];
-      delete values[i];
+      delete[] files[i];
+      delete[] names[i];
+      delete[] values[i];
     }
 
     delete[] files;
@@ -313,6 +324,13 @@ fgPropPicker::~fgPropPicker ()
     delete[] values;
     delete[] dflag;
   }
+}
+
+/*
+
+fgPropPicker::~fgPropPicker ()
+{
+  delete_arrays();
 
   if ( this == puActiveWidget () )
     puDeactivateWidget () ;
@@ -333,7 +351,7 @@ fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
   num_files = 0 ;
 
   strcpy ( startDir, dir ) ;
-  printf ( "StartDirLEN=%i", strlen(startDir));
+  // printf ( "StartDirLEN=%i", strlen(startDir));
   if ( arrows > 2 ) arrows = 2 ;
   if ( arrows < 0 ) arrows = 0 ;
   arrow_count = arrows ;
@@ -346,10 +364,7 @@ fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
   proppath ->    setLabel          (startDir);
 
   slider = new puSlider (w-30,40+20*arrows,h-100-40*arrows,TRUE,20);
-  slider->setDelta(0.1f);
   slider->setValue(1.0f);
-  slider->setSliderFraction (0.2f) ;
-  slider->setCBMode( PUSLIDER_DELTA );
   
   list_box = new puListBox ( 10, 40, w-40, h-60 ) ;
   list_box -> setLabel ( title );
@@ -359,14 +374,6 @@ fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
   list_box -> setCallback ( handle_select ) ;
   list_box -> setValue ( 0 ) ;
 
-  find_props () ;
-
-//  printf("after Props files[1]=%s\n",files[1]);
-//  printf("num items %i", list_box -> getNumItems ());
-
-  slider -> setUserData ( list_box ) ;
-  slider -> setCallback ( fgPropPickerHandleSlider ) ;
-
   ok_button = new puOneShot ( 10, 10, (w<170)?(w/2-5):80, 30 ) ;
   ok_button -> setLegend ( "Ok" ) ;
   ok_button -> setUserData ( this ) ;
@@ -374,72 +381,59 @@ fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
 
   if ( arrows > 0 )
   {
-    puArrowButton *down_arrow = new puArrowButton ( w-30, 20+20*arrows, w-10, 40+20*arrows, PUARROW_DOWN ) ;
+    down_arrow = new puArrowButton ( w-30, 20+20*arrows, w-10, 40+20*arrows, PUARROW_DOWN ) ;
     down_arrow->setUserData ( slider ) ;
     down_arrow->setCallback ( fgPropPickerHandleArrow ) ;
 
-    puArrowButton *up_arrow = new puArrowButton ( w-30, h-30-20*arrows, w-10, h-10-20*arrows, PUARROW_UP ) ;
+    up_arrow = new puArrowButton ( w-30, h-60-20*arrows, w-10, h-40-20*arrows, PUARROW_UP ) ;
     up_arrow->setUserData ( slider ) ;
     up_arrow->setCallback ( fgPropPickerHandleArrow ) ;
   }
 
-  if ( arrows == 2 )
-  {
-    puArrowButton *down_arrow = new puArrowButton ( w-30, 40, w-10, 60, PUARROW_FASTDOWN ) ;
-    down_arrow->setUserData ( slider ) ;
-    down_arrow->setCallback ( fgPropPickerHandleArrow ) ;
+  // after picker is built, load the list box with data...
+  find_props () ;
 
-    puArrowButton *up_arrow = new puArrowButton ( w-30, h-50, w-10, h-30, PUARROW_FASTUP ) ;
-    up_arrow->setUserData ( slider ) ;
-    up_arrow->setCallback ( fgPropPickerHandleArrow ) ;
-  }
+//  printf("after Props files[1]=%s\n",files[1]);
+//  printf("num items %i", list_box -> getNumItems ());
+
+  slider -> setUserData ( list_box ) ;
+  slider -> setCallback ( fgPropPickerHandleSlider ) ;
 
   FG_FINALIZE_PUI_DIALOG( this );
   printf("fgPropPicker - End of Init\n");
 }
 
 
-void fgPropPicker::find_props ()
+// Like strcmp, but for sorting property nodes into a suitable display order.
+static int nodeNameCompare(const void *ppNode1, const void *ppNode2)
 {
+  const SGPropertyNode_ptr pNode1 = *(const SGPropertyNode_ptr *)ppNode1;
+  const SGPropertyNode_ptr pNode2 = *(const SGPropertyNode_ptr *)ppNode2;
 
-  int pi;
+  // Compare name first, and then index.
+  int diff = strcmp(pNode1->getName(), pNode2->getName());
+  if (diff) return diff;
+  return pNode1->getIndex() - pNode2->getIndex();
+}
 
-  if ( files != NULL )
-  {
-    for ( int i = 0 ; i < num_files ; i++ ) {
-      delete files[i] ;
-      delete names[i] ;
-      delete values[i] ;
-    }
 
-    delete [] files ;
-    delete [] names ;
-    delete [] values ;
-    delete [] dflag ;
-  }
+// Replace the current list of properties with the children of node "startDir".
+void fgPropPicker::find_props ()
+{
+  int pi;
+  int i;
 
+  delete_arrays();
   num_files = 0 ;
 
-  char dir [ PUSTRING_MAX * 2 ] ;
-
-  int  iindex = 0;
-  char sindex [ 20 ];
+//  printf("dir begin of find_props=%s\n",startDir);
+//  printf("len of dir=%i",strlen(startDir));
+  SGPropertyNode * node = globals->get_props()->getNode(startDir);
 
-  strcpy ( dir, startDir ) ;
-
-  int i = 0 ;
-//  printf("dir begin of find_props=%s\n",dir);
-//  printf("len of dir=%i",strlen(dir));
-  SGPropertyNode * node = globals->get_props()->getNode(dir);
-
-  printf("find_props: allocation of node\n");
-  num_files = (int)node->nChildren();
-
-  // take off one for the trailing "null" in each SGProperty list
-  num_files = num_files -1;
+  num_files = (node) ? (int)node->nChildren() : 0;
 
   // instantiate string objects and add [.] and [..] for subdirs
-  if (strcmp(dir,"/") == 0) {
+  if (strcmp(startDir,"/") == 0) {
     files = new char* [ num_files+1 ] ;
     names = new char* [ num_files+1 ] ;
     values = new char* [ num_files+1 ] ;
@@ -453,7 +447,7 @@ void fgPropPicker::find_props ()
     names = new char* [ num_files+1 ] ;
     values = new char* [ num_files+1 ] ;
     dflag = new char  [ num_files+1 ] ;
-    line = ".";
+    stdString line = ".";
     files [ 0 ] = new char[ strlen(line.c_str())+2 ];
     strcpy ( files [ 0 ], line.c_str() );
     names [ 0 ] = new char[ 2 ];
@@ -471,43 +465,69 @@ void fgPropPicker::find_props ()
   };
 
 
-  for (i = 0; i < (int)node->nChildren()-1; i++) {
-           SGPropertyNode * child = node->getChild(i);
-           name = child->getName();
-           line = name;
-           names[ pi ] = new char[ strlen(line.c_str())+2 ] ;
-           strcpy ( names [ pi ], line.c_str() ) ;
+  if (node) {
+    // Get the list of children
+    int nChildren = node->nChildren();
+    SGPropertyNode_ptr * children = new SGPropertyNode_ptr[nChildren];
+    for (i = 0; i < nChildren; i++) {
+      children[i] = node->getChild(i);
+    }
+
+    // Sort the children into display order
+    qsort(children, nChildren, sizeof(children[0]), nodeNameCompare);
+
+    // Make lists of the children's names, values, etc.
+    for (i = 0; i < nChildren; i++) {
+           SGPropertyNode * child = children[i];
+           stdString name = child->getDisplayName(true);
+           names[ pi ] = new char[ strlen(name.c_str())+2 ] ;
+           strcpy ( names [ pi ], name.c_str() ) ;
            if ( child->nChildren() > 0 ) {
-                iindex = child->getIndex();
-               sprintf(sindex, "%d", iindex);
                dflag[ pi ] = 1 ;
-                files[ pi ] = new char[ strlen(line.c_str())+strlen(sindex)+4 ] ;
-               strcpy ( files [ pi ], line.c_str() ) ;
-               strcat ( files [ pi ], "[" ) ;
-                strcat ( files [ pi ], sindex ) ;
-               strcat ( files [ pi ], "]/" ) ;
+                files[ pi ] = new char[ strlen(name.c_str())+2 ] ;
+               strcpy ( files [ pi ], name.c_str() ) ;
+               strcat ( files [ pi ], "/" ) ;
                values[ pi ] = new char[ 2 ] ;
            } else {
                 dflag[ pi ] = 0 ;
-               value = node->getStringValue ( name, "" );
+               stdString value = child->getStringValue();
                values[ pi ] = new char[ strlen(value.c_str())+2 ] ;
                 strcpy ( values [pi], value.c_str() );
-               line += " = '" + value + "' " + "(";
-               line += getValueTypeString( node->getNode( name ) );
+               stdString line = name + " = '" + value + "' " + "(";
+               line += getValueTypeString( child );
                 line += ")";
+                // truncate entries to plib pui limit
+                if (line.length() > (PUSTRING_MAX-1)) line[PUSTRING_MAX-1] = '\0';
                 files[ pi ] = new char[ strlen(line.c_str())+2 ] ;
                strcpy ( files [ pi ], line.c_str() ) ;
            }
-            printf("files->%i %s\n",pi, files [pi]);
+            // printf("files->%i of %i %s\n",pi, node->nChildren(), files [pi]);
             ++pi;
+    }
+
+    delete [] children;
   }
 
   files [ num_files ] = NULL ;
 
-  printf("files pointer=%i\n", files);
+  // printf("files pointer=%i/%i\n", files, num_files);
+
   proppath ->    setLabel          (startDir);
+
   list_box -> newList ( files ) ;
-  
+
+  // adjust the size of the slider...
+  if (num_files > list_box->getNumVisible()) {
+    slider->setSliderFraction((float)list_box->getNumVisible() / num_files);
+    slider->setValue(1.0f);
+    slider->reveal();
+    up_arrow->reveal();
+    down_arrow->reveal();
+  } else {
+    slider->hide();
+    up_arrow->hide();
+    down_arrow->hide();      
+  }
 }
 
 void fgPropEdit::fgPropEditHandleCancel ( puObject* b )
@@ -572,4 +592,3 @@ fgPropEdit::fgPropEdit ( char *name, char *value, char *proppath ) : puDialogBox
     FG_FINALIZE_PUI_DIALOG( this );
 }
 
-