1
0
Fork 0

- replace string methods with property methods The class was originally adapted

from plib's file-picker, where it made some sense to keep the current path as
  string, and to chop off elements when leaving a dir, and adding them when
  entering. But it doesn't make the least sense in SGPropertyNode space, where
  we already have everything to move in a tree.

- add R & W flags for TRACE_READ and TRACE_WRITE. Remember: lower case letters:
  disabled (rw ... reading/writing), upper case letters: enabled (RWAUT)

- remove some verbosity & further cleanup ... to make further work easier :-)
This commit is contained in:
mfranz 2006-05-20 15:25:38 +00:00
parent d6320ad76b
commit 24981fd043
2 changed files with 130 additions and 199 deletions

View file

@ -39,24 +39,16 @@
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include STL_STRING #include STL_STRING
SG_USING_STD(string);
#include <Main/fg_os.hxx> #include <Main/fg_os.hxx>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include "new_gui.hxx" #include "new_gui.hxx"
#include "prop_picker.hxx" #include "prop_picker.hxx"
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 "/"
static puObject *PP_widget = 0; static puObject *PP_widget = 0;
// widget location and size...
#define PROPPICK_X 100 #define PROPPICK_X 100
#define PROPPICK_Y 200 #define PROPPICK_Y 200
#define PROPPICK_W 500 #define PROPPICK_W 500
@ -86,9 +78,9 @@ void prop_pickerView( puObject * )
void prop_pickerInit() void prop_pickerInit()
{ {
if ( PP_widget == 0 ) { if (!PP_widget) {
fgPropPicker *PP = new fgPropPicker ( PROPPICK_X, PROPPICK_Y, PROPPICK_W, PROPPICK_H, fgPropPicker *PP = new fgPropPicker ( PROPPICK_X, PROPPICK_Y, PROPPICK_W, PROPPICK_H,
1, "/", "FG Properties"); 1, globals->get_props(), "FG Properties");
PP_widget = PP; PP_widget = PP;
} }
} }
@ -96,7 +88,7 @@ void prop_pickerInit()
void prop_pickerRefresh() void prop_pickerRefresh()
{ {
if( PP_widget == 0 ) if (!PP_widget)
prop_pickerInit(); prop_pickerInit();
fgPropPicker *me = (fgPropPicker *)PP_widget -> getUserData(); fgPropPicker *me = (fgPropPicker *)PP_widget -> getUserData();
@ -105,16 +97,18 @@ void prop_pickerRefresh()
} }
void prop_editOpen( const char * name, const char * value, char * proppath ) void prop_editOpen( SGPropertyNode *node )
{ {
if( PE_widget == 0 ) assert(node);
PE_widget = new fgPropEdit(name, value, proppath); if (!PE_widget)
PE_widget = new fgPropEdit(node);
fgPropEdit *me = (fgPropEdit *)PE_widget -> getUserData(); fgPropEdit *me = (fgPropEdit *)PE_widget -> getUserData();
me -> propname -> setLabel (name); me -> namestring = node->getDisplayName();
me -> propinput -> setValue (value); me -> propname -> setLabel (me->namestring.c_str());
strcpy(me -> propPath, proppath); me -> propinput -> setValue (node->getStringValue());
me -> propinput -> acceptInput (); me -> propinput -> acceptInput ();
me -> setEditNode(node);
FG_PUSH_PUI_DIALOG( me ); FG_PUSH_PUI_DIALOG( me );
} }
@ -147,6 +141,21 @@ static string getValueTypeString( const SGPropertyNode_ptr node ) {
} }
// 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;
// Compare name first, and then index.
int diff = strcmp(pNode1->getName(), pNode2->getName());
if (diff)
return diff;
return pNode1->getIndex() - pNode2->getIndex();
}
// property picker class ====================================================== // property picker class ======================================================
@ -199,48 +208,6 @@ void fgPropPicker::fgPropPickerHandleArrow ( puObject *arrow )
} }
void fgPropPicker::chop_file ( char *fname )
{
/* removes everything back to the last '/' */
for ( int i = strlen(fname)-1; fname[i] != SLASH[0] && i >= 0; i-- )
fname[i] = '\0';
}
void fgPropPicker::go_up_one_directory ( char *fname )
{
/* removes everything back to the last but one '/' */
chop_file ( fname );
if ( strlen ( fname ) == 0 ) {
/* Empty string! The only way to go up is to append a "../" */
strcpy ( fname, DOTDOTSLASH );
return;
}
/* If the last path element is a "../" then we'll have to add another "../" */
if ( strcmp ( & fname [ strlen(fname)-3 ], DOTDOTSLASH ) == 0 ) {
if ( strlen ( fname ) + 4 >= PUSTRING_MAX ) {
ulSetError ( UL_WARNING, "PUI: fgPropPicker - path is too long, max is %d.",
PUSTRING_MAX );
return;
}
strcat ( fname, DOTDOTSLASH );
return;
}
/* Otherwise, just delete the last element of the path. */
/* Remove the trailing slash - then remove the rest as if it was a file name */
fname [ strlen(fname)-1 ] = '\0';
chop_file ( fname );
}
void fgPropPicker::handle_select ( puObject* list_box ) void fgPropPicker::handle_select ( puObject* list_box )
{ {
fgPropPicker* prop_picker = (fgPropPicker*) list_box -> getUserData (); fgPropPicker* prop_picker = (fgPropPicker*) list_box -> getUserData ();
@ -248,20 +215,22 @@ void fgPropPicker::handle_select ( puObject* list_box )
list_box -> getValue ( &selected ); list_box -> getValue ( &selected );
if ( selected >= 0 && selected < prop_picker -> num_files ) { if ( selected >= 0 && selected < prop_picker -> num_files ) {
char *dst = prop_picker -> startDir; const char *src = prop_picker -> files [ selected ];
char *src = prop_picker -> files [ selected ];
if (prop_picker->dotFiles && (selected < 2)) { if (prop_picker->dotFiles && (selected < 2)) {
if ( strcmp ( src, "." ) == 0 ) { if ( strcmp ( src, "." ) == 0 ) {
/* Do nothing - but better refresh anyway. */ /* Do nothing - but better refresh anyway. */
prop_picker -> find_props (); prop_picker -> find_props ();
return; return;
} else if ( strcmp ( src, ".." ) == 0 ) { } else if ( strcmp ( src, ".." ) == 0 ) {
/* Do back up one level - so refresh. */ /* Do back up one level - so refresh. */
go_up_one_directory ( dst ); SGPropertyNode *parent = prop_picker->getCurrent()->getParent();
prop_picker -> find_props (); if (parent) {
prop_picker->setCurrent(parent);
prop_picker -> find_props ();
}
return; return;
} }
} }
@ -275,32 +244,17 @@ void fgPropPicker::handle_select ( puObject* list_box )
// check if it's a directory (had children) // check if it's a directory (had children)
if ( child->nChildren() ) { if ( child->nChildren() ) {
/* If this is a directory - then descend into it and refresh */ prop_picker->setCurrent(child);
if ( strlen ( dst ) + strlen ( src ) + 2 >= PUSTRING_MAX ) {
ulSetError ( UL_WARNING,
"PUI: fgPropPicker - path is too long, max is %d.", PUSTRING_MAX );
return;
}
strcat ( dst, src ); /* add path to descend to */
prop_picker -> find_props (); prop_picker -> find_props ();
return; return;
} }
/* If this is a regular file - then just append it to the string */ // it is a regular property
if ( strlen ( dst ) + strlen ( src ) + 2 >= PUSTRING_MAX ) {
ulSetError ( UL_WARNING,
"PUI: fgPropPicker - path is too long, max is %d.", PUSTRING_MAX );
return;
}
if (child->getType() == SGPropertyNode::BOOL && (fgGetKeyModifiers() & KEYMOD_CTRL)) { if (child->getType() == SGPropertyNode::BOOL && (fgGetKeyModifiers() & KEYMOD_CTRL)) {
child->setBoolValue(!child->getBoolValue()); child->setBoolValue(!child->getBoolValue());
prop_pickerRefresh(); prop_pickerRefresh();
} else } else
prop_editOpen(child->getName(), child->getStringValue(), dst); prop_editOpen(child);
} else { } else {
// The user clicked on blank screen - maybe we should // The user clicked on blank screen - maybe we should
@ -315,7 +269,7 @@ void fgPropPicker::fgPropPickerHandleOk ( puObject* b )
{ {
fgPropPicker* prop_picker = (fgPropPicker*) b -> getUserData (); fgPropPicker* prop_picker = (fgPropPicker*) b -> getUserData ();
/* nothing to do, just hide */ // nothing to do, just hide
FG_POP_PUI_DIALOG( prop_picker ); FG_POP_PUI_DIALOG( prop_picker );
} }
@ -350,8 +304,10 @@ fgPropPicker::~fgPropPicker ()
fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows, fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
const char *dir, const char *title ) : SGPropertyNode *start, const char *title ) :
fgPopup ( x,y ), fgPopup ( x,y ),
curr(start),
flags(fgGetNode("/sim/gui/dialogs/property-browser/show-flags", true)),
_gui((NewGUI *)globals->get_subsystem("gui")) _gui((NewGUI *)globals->get_subsystem("gui"))
{ {
puFont LegendFont, LabelFont; puFont LegendFont, LabelFont;
@ -363,8 +319,6 @@ fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
files = NULL; files = NULL;
num_files = 0; num_files = 0;
strcpy ( startDir, dir );
// printf ( "StartDirLEN=%i", strlen(startDir));
if ( arrows > 2 ) if ( arrows > 2 )
arrows = 2; arrows = 2;
if ( arrows < 0 ) if ( arrows < 0 )
@ -376,7 +330,7 @@ fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
setUserData( this ); setUserData( this );
proppath = new puText (10, h-30); proppath = new puText (10, h-30);
proppath -> setLabel (startDir); proppath -> setLabel (curr->getPath(true));
proppath -> setColor(PUCOL_LABEL, txtcol.red(), txtcol.green(), proppath -> setColor(PUCOL_LABEL, txtcol.red(), txtcol.green(),
txtcol.blue(), txtcol.alpha()); txtcol.blue(), txtcol.alpha());
@ -421,44 +375,24 @@ fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
} }
// Like strcmp, but for sorting property nodes into a suitable display order. // Replace list with children of current
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;
// Compare name first, and then index.
int diff = strcmp(pNode1->getName(), pNode2->getName());
if (diff)
return diff;
return pNode1->getIndex() - pNode2->getIndex();
}
// Replace the current list of properties with the children of node "startDir".
void fgPropPicker::find_props ( bool restore_pos ) void fgPropPicker::find_props ( bool restore_pos )
{ {
int pi; int pi;
int i; int i;
delete_arrays(); delete_arrays();
num_files = 0; num_files = (int)curr->nChildren();
// printf("dir begin of find_props=%s\n",startDir);
// printf("len of dir=%i",strlen(startDir));
SGPropertyNode * node = globals->get_props()->getNode(startDir);
num_files = node ? (int)node->nChildren() : 0;
// instantiate string objects and add [.] and [..] for subdirs // instantiate string objects and add [.] and [..] for subdirs
if (strcmp(startDir,"/") == 0) { if (!curr->getParent()) {
files = new char* [ num_files+1 ]; files = new char* [ num_files+1 ];
pi = 0; pi = 0;
dotFiles = false; dotFiles = false;
} else { } else {
// add two for the .. and . // add two for the .. and .
num_files = num_files + 2; num_files += 2;
// make room for .. and . // make room for .. and .
files = new char* [ num_files+1 ]; files = new char* [ num_files+1 ];
@ -474,38 +408,34 @@ void fgPropPicker::find_props ( bool restore_pos )
dotFiles = true; dotFiles = true;
} }
num_children = curr->nChildren();
children = new SGPropertyNode_ptr[num_children];
for (i = 0; i < num_children; i++)
children[i] = curr->getChild(i);
if (node) { qsort(children, num_children, sizeof(children[0]), nodeNameCompare);
num_children = node->nChildren();
children = new SGPropertyNode_ptr[num_children];
for (i = 0; i < num_children; i++)
children[i] = node->getChild(i);
qsort(children, num_children, sizeof(children[0]), nodeNameCompare); // Make lists of the children's names, values, etc.
for (i = 0; i < num_children; i++) {
SGPropertyNode * child = children[i];
// Make lists of the children's names, values, etc. if ( child->nChildren() > 0 ) {
for (i = 0; i < num_children; i++) { stdString name = stdString(child->getDisplayName(true)) + '/';
SGPropertyNode * child = children[i]; files[ pi ] = new char[ name.size() + 1 ];
stdString name = child->getDisplayName(true); strcpy ( files [ pi ], name.c_str() );
if ( child->nChildren() > 0 ) { } else {
files[ pi ] = new char[ strlen(name.c_str())+2 ]; files[pi] = NULL; // ensure it's NULL before setting intial value
strcpy ( files [ pi ], name.c_str() ); updateTextForEntry(i);
strcat ( files [ pi ], "/" ); child->addChangeListener(this);
} else {
files[pi] = NULL; // ensure it's NULL before setting intial value
updateTextForEntry(i);
// observe it
child->addChangeListener(this);
}
++pi;
} }
++pi;
} }
files [ num_files ] = NULL; files [ num_files ] = NULL;
proppath -> setLabel(startDir); proppath -> setLabel(curr->getPath(true));
int top = list_box->getTopItem(); int top = list_box->getTopItem();
list_box -> newList ( files ); list_box -> newList ( files );
@ -535,50 +465,54 @@ void fgPropPicker::updateTextForEntry(int index)
assert((index >= 0) && (index < num_children)); assert((index >= 0) && (index < num_children));
SGPropertyNode_ptr node = children[index]; SGPropertyNode_ptr node = children[index];
// take a copy of the value stdString name = node->getDisplayName(true);
stdString type = getValueTypeString(node);
stdString value = node->getStringValue(); stdString value = node->getStringValue();
stdString line = node->getDisplayName() + stdString(" = '") + value + "' " + "("; stdString line = name + " = '" + value + "' (" + type;
line += getValueTypeString( node );
if (fgGetBool("/sim/gui/dialogs/property-browser/show-flags", false)) { if (flags->getBoolValue()) {
stdString ext; stdString ext;
if (!node->getAttribute(SGPropertyNode::READ)) if (!node->getAttribute(SGPropertyNode::READ))
ext += "r"; ext += 'r';
if (!node->getAttribute(SGPropertyNode::WRITE)) if (!node->getAttribute(SGPropertyNode::WRITE))
ext += "w"; ext += 'w';
if (node->getAttribute(SGPropertyNode::TRACE_READ))
ext += 'R';
if (node->getAttribute(SGPropertyNode::TRACE_WRITE))
ext += 'W';
if (node->getAttribute(SGPropertyNode::ARCHIVE)) if (node->getAttribute(SGPropertyNode::ARCHIVE))
ext += "A"; ext += 'A';
if (node->getAttribute(SGPropertyNode::USERARCHIVE)) if (node->getAttribute(SGPropertyNode::USERARCHIVE))
ext += "U"; ext += 'U';
if (node->isTied()) if (node->isTied())
ext += "T"; ext += 'T';
if (ext.size()) if (ext.size())
line += ", " + ext; line += ", " + ext;
} }
line += ")"; line += ')';
// truncate entries to plib pui limit // truncate entries to plib pui limit
if (line.length() >= PUSTRING_MAX) if (line.length() >= PUSTRING_MAX)
line[PUSTRING_MAX-1] = '\0'; line[PUSTRING_MAX-1] = '\0';
if (dotFiles) if (dotFiles)
index +=2; index += 2;
// don't leak everywhere if we're updating // don't leak everywhere if we're updating
delete[] files[index]; delete[] files[index];
files[index] = new char[ strlen(line.c_str())+2 ]; files[index] = new char[ line.size() + 1 ];
strcpy ( files [ index ], line.c_str() ); strcpy ( files [ index ], line.c_str() );
} }
void fgPropPicker::valueChanged(SGPropertyNode *nd) void fgPropPicker::valueChanged(SGPropertyNode *nd)
{ {
for (int C=0; C<num_children; ++C) for (int i = 0; i < num_children; i++)
if (children[C] == nd) { if (children[i] == nd) {
updateTextForEntry(C); updateTextForEntry(i);
return; return;
} }
} }
@ -599,15 +533,10 @@ void fgPropEdit::fgPropEditHandleCancel ( puObject* b )
void fgPropEdit::fgPropEditHandleOK ( puObject* b ) void fgPropEdit::fgPropEditHandleOK ( puObject* b )
{ {
fgPropEdit* prop_edit = (fgPropEdit*) b -> getUserData (); fgPropEdit* prop_edit = (fgPropEdit*) b -> getUserData ();
const char* tname;
char* tvalue; char* tvalue;
// use label text for property node to be updated
tname = prop_edit -> propname -> getLabel();
prop_edit -> propinput -> getValue( &tvalue ); prop_edit -> propinput -> getValue( &tvalue );
prop_edit->getEditNode()->setStringValue(tvalue);
SGPropertyNode * node = globals->get_props()->getNode(prop_edit -> propPath);
node->getNode( prop_edit -> propname -> getLabel(), true)->setStringValue(tvalue);
// update the picker display so it shows new value // update the picker display so it shows new value
prop_pickerRefresh(); prop_pickerRefresh();
@ -616,10 +545,13 @@ void fgPropEdit::fgPropEditHandleOK ( puObject* b )
} }
fgPropEdit::fgPropEdit ( const char *name, const char *value, char *proppath ) : fgPropEdit::fgPropEdit ( SGPropertyNode *n ) :
fgPopup ( 0, 0 ), fgPopup ( 0, 0 ),
node(n),
_gui((NewGUI *)globals->get_subsystem("gui")) _gui((NewGUI *)globals->get_subsystem("gui"))
{ {
assert(n);
puFont LegendFont, LabelFont; puFont LegendFont, LabelFont;
puGetDefaultFonts ( &LegendFont, &LabelFont ); puGetDefaultFonts ( &LegendFont, &LabelFont );
FGColor txtcol(_gui->getColor("label")); FGColor txtcol(_gui->getColor("label"));
@ -631,17 +563,16 @@ fgPropEdit::fgPropEdit ( const char *name, const char *value, char *proppath ) :
int fy = PROPPICK_Y + PROPPICK_H; int fy = PROPPICK_Y + PROPPICK_H;
frame = new puFrame (fx,fy, fx+500, fy+120); frame = new puFrame (fx,fy, fx+500, fy+120);
strcpy (propPath, proppath);
setUserData( this ); setUserData( this );
namestring = node->getDisplayName();
propname = new puText (fx+10, fy+90); propname = new puText (fx+10, fy+90);
propname -> setLabel(name); propname -> setLabel(namestring.c_str());
propname -> setColor(PUCOL_LABEL, txtcol.red(), txtcol.green(), propname -> setColor(PUCOL_LABEL, txtcol.red(), txtcol.green(),
txtcol.blue(), txtcol.alpha()); txtcol.blue(), txtcol.alpha());
propinput = new puInput (fx+10, fy+50, fx+480, fy+80); propinput = new puInput (fx+10, fy+50, fx+480, fy+80);
propinput -> setValue (value); propinput -> setValue (node->getStringValue());
propinput -> acceptInput(); propinput -> acceptInput();
ok_button = new puOneShot (fx+10, fy+10, fx+80, fy+30); ok_button = new puOneShot (fx+10, fy+10, fx+80, fy+30);

View file

@ -8,17 +8,32 @@
#include "dialog.hxx" #include "dialog.hxx"
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
// A local alternative name, for use when a variable called "string"
// is in scope - e.g. in classes derived from puInput.
typedef string stdString;
void prop_pickerInit(); void prop_pickerInit();
void prop_pickerView( puObject * ); void prop_pickerView( puObject * );
void prop_pickerRefresh(); void prop_pickerRefresh();
void prop_editOpen( const char * name, const char * value ); void prop_editOpen(SGPropertyNode *);
class fgPropPicker;
class fgPropEdit;
class fgPropPicker : public fgPopup, public SGPropertyChangeListener { class fgPropPicker : public fgPopup, public SGPropertyChangeListener {
public:
fgPropPicker ( int x, int y, int w, int h, int arrows,
SGPropertyNode *, const char *title = "Pick a file" );
void find_props ( bool restore_slider_pos = false );
SGPropertyNode *getCurrent () const { return curr; }
void setCurrent(SGPropertyNode *p) { curr = p; }
// over-ride the method from SGPropertyNodeListener
virtual void valueChanged (SGPropertyNode * node);
puText *proppath;
private:
static void handle_select ( puObject *b ); static void handle_select ( puObject *b );
static void input_entered ( puObject *b ); static void input_entered ( puObject *b );
static void fgPropPickerHandleSlider ( puObject * slider ); static void fgPropPickerHandleSlider ( puObject * slider );
@ -36,12 +51,13 @@ class fgPropPicker : public fgPopup, public SGPropertyChangeListener {
char** files; char** files;
int num_files; int num_files;
int arrow_count; int arrow_count;
char startDir [ PUSTRING_MAX * 2 ];
SGPropertyNode_ptr curr;
SGPropertyNode_ptr flags;
SGPropertyNode_ptr* children; SGPropertyNode_ptr* children;
int num_children; int num_children;
// set if we're display the . and .. entries at the start of the // set if we're displaying the . and .. entries at the start of the
// list // list
bool dotFiles; bool dotFiles;
@ -55,47 +71,31 @@ protected:
puArrowButton *up_arrow; puArrowButton *up_arrow;
NewGUI * _gui; NewGUI * _gui;
public:
puText *proppath;
void find_props ( bool restore_slider_pos = false );
fgPropPicker ( int x, int y, int w, int h, int arrows,
const char *dir, const char *title = "Pick a file" );
~fgPropPicker () {}
static void go_up_one_directory ( char *fname );
static void chop_file ( char *fname );
// over-ride the method from SGPropertyNodeListener
virtual void valueChanged (SGPropertyNode * node);
}; };
class fgPropEdit : public fgPopup { class fgPropEdit : public fgPopup {
public:
fgPropEdit ( SGPropertyNode *node );
static void fgPropEditHandleCancel ( puObject *b ); SGPropertyNode *getEditNode() const { return node; }
static void fgPropEditHandleOK ( puObject* b ); void setEditNode(SGPropertyNode *p) { node = p; }
static void fgPropEditHandleCancel ( puObject *b );
static void fgPropEditHandleOK ( puObject* b );
protected: protected:
puFrame *frame; puFrame *frame;
puOneShot *cancel_button; puOneShot *cancel_button;
puOneShot *ok_button; puOneShot *ok_button;
SGPropertyNode_ptr node;
NewGUI * _gui; NewGUI * _gui;
public: public:
puText *propname; stdString namestring; // FIXME make setters/getters
puInput *propinput; puText *propname;
char propPath [ PUSTRING_MAX * 2 ]; puInput *propinput;
fgPropEdit ( const char *name, const char *value, char *proppath );
~fgPropEdit () {}
static void go_up_one_directory ( char *fname );
static void chop_file ( char *fname );
}; };
#endif // _PROP_PICKER_HXX #endif // _PROP_PICKER_HXX