2001-11-12 20:57:08 +00:00
|
|
|
/*
|
|
|
|
|
|
|
|
Adapted by Jim Wilson, beginning Sept 2001 (FG v 0.79)
|
|
|
|
|
|
|
|
**** Insert FlightGear GPL here.
|
|
|
|
|
|
|
|
Based on puFilePicker from:
|
|
|
|
|
|
|
|
********
|
|
|
|
PLIB - A Suite of Portable Game Libraries
|
|
|
|
Copyright (C) 2001 Steve Baker
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-02-21 01:16:04 +00:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
For further information visit http://plib.sourceforge.net
|
|
|
|
|
|
|
|
$Id$
|
|
|
|
********
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <simgear/compiler.h>
|
2003-05-06 23:46:24 +00:00
|
|
|
#include <simgear/props/props.hxx>
|
2001-11-12 20:57:08 +00:00
|
|
|
|
Patch from Julian Foad:
When the scroll bar slider is dragged, the list scrolls only far
enough to see all items; only the arrow buttons can scroll it so far
that the last item goes to the top of the view.
Fix scroll bar proportional size: was wrong when the list was only
a little longer than the visible area.
Minor fixes such as "delete files[i];" -> "delete[] files[i];"
(where the item being deleted is an array of characters) and removal of
global variables.
Smooth scrolling when dragging the slider: one item at a time,
rather than one tenth of the list at a time.
Fix a bug that would have occurred if instantiated with arrows=2.
Sort properties primarily by name and then by numerical index
order, rather than a simple ASCII string order. E.g. "js[1]", "js[2]",
"js[10]" rather than "js[1]", "js[10]", "js[2]".
Avoid crashing if the selected property path does not exist;
display an empty list instead. This cannot happen when the property
picker is working properly, but did happen due to missing indices prior
to this patch, and could happen if the user is allowed to type a
pathname, as in the http and telnet interfaces.
Fix truncation of strings to PUSTRING_MAX: was wrong when string
length was exactly 80.
Fix: move the scroll bar to the top each time a new list is
displayed. It was left at its previous position, while the top of the
new list was displayed, not corresponding to the slider.
Use getDisplayName instead of duplicated code: gives a better
decision on whether to display the index, and avoids invalid property
paths being generated which would previously crash find_props().
Replace unnecessary node lookups by name with direct access: tidier
and more efficient. E.g. "getValueTypeString
(node->getNode(name.c_str()))" -> "getValueTypeString (child)".
2002-09-07 12:35:06 +00:00
|
|
|
#include STL_STRING
|
2006-05-20 15:25:38 +00:00
|
|
|
SG_USING_STD(string);
|
2003-05-06 23:46:24 +00:00
|
|
|
|
2006-05-18 12:12:10 +00:00
|
|
|
#include <Main/fg_os.hxx>
|
2003-05-06 23:46:24 +00:00
|
|
|
#include <Main/globals.hxx>
|
2005-07-07 21:32:33 +00:00
|
|
|
#include "new_gui.hxx"
|
2003-05-06 23:46:24 +00:00
|
|
|
#include "prop_picker.hxx"
|
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
|
|
|
|
static puObject *PP_widget = 0;
|
|
|
|
|
|
|
|
#define PROPPICK_X 100
|
|
|
|
#define PROPPICK_Y 200
|
|
|
|
#define PROPPICK_W 500
|
|
|
|
#define PROPPICK_H 300
|
|
|
|
|
|
|
|
static puObject *PE_widget = 0;
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
// entry point: called from src/GUI/menubar.cxx -- do_properties_dialog() =====
|
|
|
|
|
|
|
|
void prop_pickerView( puObject * )
|
2001-11-12 20:57:08 +00:00
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
if( PP_widget == 0 )
|
|
|
|
prop_pickerInit();
|
|
|
|
|
|
|
|
fgPropPicker *me = (fgPropPicker *)PP_widget -> getUserData();
|
|
|
|
// refresh
|
|
|
|
me -> find_props();
|
|
|
|
FG_PUSH_PUI_DIALOG( me );
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
void prop_pickerInit()
|
2001-11-12 20:57:08 +00:00
|
|
|
{
|
2006-05-20 15:25:38 +00:00
|
|
|
if (!PP_widget) {
|
2006-05-19 10:59:04 +00:00
|
|
|
fgPropPicker *PP = new fgPropPicker ( PROPPICK_X, PROPPICK_Y, PROPPICK_W, PROPPICK_H,
|
2006-05-20 15:25:38 +00:00
|
|
|
1, globals->get_props(), "FG Properties");
|
2006-05-19 10:59:04 +00:00
|
|
|
PP_widget = PP;
|
|
|
|
}
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
void prop_pickerRefresh()
|
|
|
|
{
|
2006-05-20 15:25:38 +00:00
|
|
|
if (!PP_widget)
|
2006-05-19 10:59:04 +00:00
|
|
|
prop_pickerInit();
|
|
|
|
|
|
|
|
fgPropPicker *me = (fgPropPicker *)PP_widget -> getUserData();
|
|
|
|
me -> find_props( true );
|
|
|
|
me -> clrValue();
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
void prop_editOpen( SGPropertyNode *node )
|
2001-11-12 20:57:08 +00:00
|
|
|
{
|
2006-05-20 15:25:38 +00:00
|
|
|
assert(node);
|
|
|
|
if (!PE_widget)
|
|
|
|
PE_widget = new fgPropEdit(node);
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
fgPropEdit *me = (fgPropEdit *)PE_widget -> getUserData();
|
2006-05-20 15:25:38 +00:00
|
|
|
me -> namestring = node->getDisplayName();
|
|
|
|
me -> propname -> setLabel (me->namestring.c_str());
|
|
|
|
me -> propinput -> setValue (node->getStringValue());
|
2006-05-19 10:59:04 +00:00
|
|
|
me -> propinput -> acceptInput ();
|
2006-05-20 15:25:38 +00:00
|
|
|
me -> setEditNode(node);
|
2006-05-19 10:59:04 +00:00
|
|
|
FG_PUSH_PUI_DIALOG( me );
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2003-02-04 22:27:58 +00:00
|
|
|
static string getValueTypeString( const SGPropertyNode_ptr node ) {
|
2001-11-12 20:57:08 +00:00
|
|
|
string result;
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
if ( node == NULL )
|
|
|
|
return "unknown";
|
2001-11-12 20:57:08 +00:00
|
|
|
|
|
|
|
SGPropertyNode::Type type = node->getType();
|
2006-05-19 10:59:04 +00:00
|
|
|
if ( type == SGPropertyNode::UNSPECIFIED )
|
|
|
|
result = "unspecified";
|
|
|
|
else if ( type == SGPropertyNode::NONE )
|
2001-11-12 20:57:08 +00:00
|
|
|
result = "none";
|
2006-05-19 10:59:04 +00:00
|
|
|
else if ( type == SGPropertyNode::BOOL )
|
|
|
|
result = "bool";
|
|
|
|
else if ( type == SGPropertyNode::INT )
|
|
|
|
result = "int";
|
|
|
|
else if ( type == SGPropertyNode::LONG )
|
|
|
|
result = "long";
|
|
|
|
else if ( type == SGPropertyNode::FLOAT )
|
|
|
|
result = "float";
|
|
|
|
else if ( type == SGPropertyNode::DOUBLE )
|
|
|
|
result = "double";
|
|
|
|
else if ( type == SGPropertyNode::STRING )
|
|
|
|
result = "string";
|
2001-11-12 20:57:08 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
// property picker class ======================================================
|
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
void fgPropPicker::fgPropPickerHandleSlider ( puObject * slider )
|
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
puListBox* list_box = (puListBox*) slider -> getUserData ();
|
|
|
|
|
|
|
|
float val;
|
|
|
|
slider -> getValue ( &val );
|
|
|
|
val = 1.0f - val;
|
|
|
|
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 );
|
|
|
|
}
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
void fgPropPicker::fgPropPickerHandleArrow ( puObject *arrow )
|
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
puSlider *slider = (puSlider *) arrow->getUserData ();
|
|
|
|
puListBox* list_box = (puListBox*) slider -> getUserData ();
|
|
|
|
|
|
|
|
int type = ((puArrowButton *)arrow)->getArrowType();
|
|
|
|
int inc = ( type == PUARROW_DOWN ) ? 1 :
|
|
|
|
( type == PUARROW_UP ) ? -1 :
|
|
|
|
( type == PUARROW_FASTDOWN ) ? 10 :
|
|
|
|
( type == PUARROW_FASTUP ) ? -10 : 0;
|
|
|
|
|
|
|
|
float val;
|
|
|
|
slider -> getValue ( &val );
|
|
|
|
val = 1.0f - val;
|
|
|
|
int scroll_range = list_box->getNumItems () - list_box->getNumVisible();
|
|
|
|
|
|
|
|
if ( scroll_range > 0 ) {
|
|
|
|
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 / scroll_range );
|
|
|
|
list_box -> setTopItem ( index );
|
|
|
|
}
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void fgPropPicker::handle_select ( puObject* list_box )
|
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
fgPropPicker* prop_picker = (fgPropPicker*) list_box -> getUserData ();
|
|
|
|
int selected;
|
|
|
|
list_box -> getValue ( &selected );
|
|
|
|
|
|
|
|
if ( selected >= 0 && selected < prop_picker -> num_files ) {
|
2006-05-20 15:25:38 +00:00
|
|
|
const char *src = prop_picker -> files [ selected ];
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
if (prop_picker->dotFiles && (selected < 2)) {
|
|
|
|
if ( strcmp ( src, "." ) == 0 ) {
|
|
|
|
/* Do nothing - but better refresh anyway. */
|
|
|
|
prop_picker -> find_props ();
|
|
|
|
return;
|
2006-05-20 15:25:38 +00:00
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
} else if ( strcmp ( src, ".." ) == 0 ) {
|
|
|
|
/* Do back up one level - so refresh. */
|
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
SGPropertyNode *parent = prop_picker->getCurrent()->getParent();
|
|
|
|
if (parent) {
|
|
|
|
prop_picker->setCurrent(parent);
|
|
|
|
prop_picker -> find_props ();
|
|
|
|
}
|
2006-05-19 10:59:04 +00:00
|
|
|
return;
|
|
|
|
}
|
2003-02-04 22:27:58 +00:00
|
|
|
}
|
2001-11-12 20:57:08 +00:00
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
// we know we're dealing with a regular entry, so convert
|
|
|
|
// it to an index into children[]
|
|
|
|
if (prop_picker->dotFiles)
|
|
|
|
selected -= 2;
|
|
|
|
SGPropertyNode_ptr child = prop_picker->children[selected];
|
|
|
|
assert(child != NULL);
|
|
|
|
|
|
|
|
// check if it's a directory (had children)
|
|
|
|
if ( child->nChildren() ) {
|
2006-05-20 15:25:38 +00:00
|
|
|
prop_picker->setCurrent(child);
|
2006-05-19 10:59:04 +00:00
|
|
|
prop_picker -> find_props ();
|
|
|
|
return;
|
|
|
|
}
|
2001-11-12 20:57:08 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
// it is a regular property
|
2006-05-19 10:59:04 +00:00
|
|
|
if (child->getType() == SGPropertyNode::BOOL && (fgGetKeyModifiers() & KEYMOD_CTRL)) {
|
|
|
|
child->setBoolValue(!child->getBoolValue());
|
|
|
|
prop_pickerRefresh();
|
|
|
|
} else
|
2006-05-20 15:25:38 +00:00
|
|
|
prop_editOpen(child);
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
// The user clicked on blank screen - maybe we should
|
|
|
|
// refresh just in case some other process created the file.
|
|
|
|
// Should be obsolete once we observe child add/remove on our top node
|
|
|
|
prop_picker -> find_props ();
|
|
|
|
}
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void fgPropPicker::fgPropPickerHandleOk ( puObject* b )
|
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
fgPropPicker* prop_picker = (fgPropPicker*) b -> getUserData ();
|
2001-11-12 20:57:08 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
// nothing to do, just hide
|
2006-05-19 10:59:04 +00:00
|
|
|
FG_POP_PUI_DIALOG( prop_picker );
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
Patch from Julian Foad:
When the scroll bar slider is dragged, the list scrolls only far
enough to see all items; only the arrow buttons can scroll it so far
that the last item goes to the top of the view.
Fix scroll bar proportional size: was wrong when the list was only
a little longer than the visible area.
Minor fixes such as "delete files[i];" -> "delete[] files[i];"
(where the item being deleted is an array of characters) and removal of
global variables.
Smooth scrolling when dragging the slider: one item at a time,
rather than one tenth of the list at a time.
Fix a bug that would have occurred if instantiated with arrows=2.
Sort properties primarily by name and then by numerical index
order, rather than a simple ASCII string order. E.g. "js[1]", "js[2]",
"js[10]" rather than "js[1]", "js[10]", "js[2]".
Avoid crashing if the selected property path does not exist;
display an empty list instead. This cannot happen when the property
picker is working properly, but did happen due to missing indices prior
to this patch, and could happen if the user is allowed to type a
pathname, as in the http and telnet interfaces.
Fix truncation of strings to PUSTRING_MAX: was wrong when string
length was exactly 80.
Fix: move the scroll bar to the top each time a new list is
displayed. It was left at its previous position, while the top of the
new list was displayed, not corresponding to the slider.
Use getDisplayName instead of duplicated code: gives a better
decision on whether to display the index, and avoids invalid property
paths being generated which would previously crash find_props().
Replace unnecessary node lookups by name with direct access: tidier
and more efficient. E.g. "getValueTypeString
(node->getNode(name.c_str()))" -> "getValueTypeString (child)".
2002-09-07 12:35:06 +00:00
|
|
|
void fgPropPicker::delete_arrays ()
|
2001-11-12 20:57:08 +00:00
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
if ( files ) {
|
|
|
|
for ( int i=0; i<num_files; i++ )
|
|
|
|
delete[] files[i];
|
|
|
|
|
|
|
|
for (int C=0; C<num_children; ++C) {
|
|
|
|
if (children[C]->nChildren() == 0)
|
|
|
|
children[C]->removeChangeListener(this);
|
|
|
|
}
|
2001-11-12 20:57:08 +00:00
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
delete[] files;
|
|
|
|
delete[] children;
|
2003-02-04 22:27:58 +00:00
|
|
|
}
|
Patch from Julian Foad:
When the scroll bar slider is dragged, the list scrolls only far
enough to see all items; only the arrow buttons can scroll it so far
that the last item goes to the top of the view.
Fix scroll bar proportional size: was wrong when the list was only
a little longer than the visible area.
Minor fixes such as "delete files[i];" -> "delete[] files[i];"
(where the item being deleted is an array of characters) and removal of
global variables.
Smooth scrolling when dragging the slider: one item at a time,
rather than one tenth of the list at a time.
Fix a bug that would have occurred if instantiated with arrows=2.
Sort properties primarily by name and then by numerical index
order, rather than a simple ASCII string order. E.g. "js[1]", "js[2]",
"js[10]" rather than "js[1]", "js[10]", "js[2]".
Avoid crashing if the selected property path does not exist;
display an empty list instead. This cannot happen when the property
picker is working properly, but did happen due to missing indices prior
to this patch, and could happen if the user is allowed to type a
pathname, as in the http and telnet interfaces.
Fix truncation of strings to PUSTRING_MAX: was wrong when string
length was exactly 80.
Fix: move the scroll bar to the top each time a new list is
displayed. It was left at its previous position, while the top of the
new list was displayed, not corresponding to the slider.
Use getDisplayName instead of duplicated code: gives a better
decision on whether to display the index, and avoids invalid property
paths being generated which would previously crash find_props().
Replace unnecessary node lookups by name with direct access: tidier
and more efficient. E.g. "getValueTypeString
(node->getNode(name.c_str()))" -> "getValueTypeString (child)".
2002-09-07 12:35:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
fgPropPicker::~fgPropPicker ()
|
|
|
|
{
|
|
|
|
delete_arrays();
|
2001-11-12 20:57:08 +00:00
|
|
|
|
|
|
|
if ( this == puActiveWidget () )
|
2006-05-19 10:59:04 +00:00
|
|
|
puDeactivateWidget ();
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
fgPropPicker::fgPropPicker ( int x, int y, int w, int h, int arrows,
|
2006-05-20 15:25:38 +00:00
|
|
|
SGPropertyNode *start, const char *title ) :
|
2006-05-19 10:59:04 +00:00
|
|
|
fgPopup ( x,y ),
|
2006-05-20 15:25:38 +00:00
|
|
|
curr(start),
|
|
|
|
flags(fgGetNode("/sim/gui/dialogs/property-browser/show-flags", true)),
|
2006-05-19 10:59:04 +00:00
|
|
|
_gui((NewGUI *)globals->get_subsystem("gui"))
|
2001-11-12 20:57:08 +00:00
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
puFont LegendFont, LabelFont;
|
|
|
|
puGetDefaultFonts ( &LegendFont, &LabelFont );
|
|
|
|
FGColor txtcol(_gui->getColor("label"));
|
|
|
|
txtcol.merge(_gui->getColor("text"));
|
|
|
|
txtcol.merge(_gui->getColor("text-label"));
|
|
|
|
|
|
|
|
files = NULL;
|
|
|
|
num_files = 0;
|
|
|
|
|
|
|
|
if ( arrows > 2 )
|
|
|
|
arrows = 2;
|
|
|
|
if ( arrows < 0 )
|
|
|
|
arrows = 0;
|
|
|
|
arrow_count = arrows;
|
|
|
|
|
|
|
|
frame = new puFrame ( 0, 0, w, h );
|
|
|
|
|
|
|
|
setUserData( this );
|
|
|
|
|
|
|
|
proppath = new puText (10, h-30);
|
2006-05-20 15:25:38 +00:00
|
|
|
proppath -> setLabel (curr->getPath(true));
|
2006-05-19 10:59:04 +00:00
|
|
|
proppath -> setColor(PUCOL_LABEL, txtcol.red(), txtcol.green(),
|
|
|
|
txtcol.blue(), txtcol.alpha());
|
|
|
|
|
|
|
|
slider = new puSlider (w-30,40+20*arrows,h-100-40*arrows,TRUE,20);
|
|
|
|
slider->setValue(1.0f);
|
|
|
|
|
|
|
|
list_box = new puListBox ( 10, 40, w-40, h-60 );
|
|
|
|
list_box -> setLabel ( title );
|
|
|
|
list_box -> setLabelPlace ( PUPLACE_ABOVE );
|
|
|
|
list_box -> setStyle ( -PUSTYLE_SMALL_SHADED );
|
|
|
|
list_box -> setUserData ( this );
|
|
|
|
list_box -> setCallback ( handle_select );
|
|
|
|
list_box -> setValue ( 0 );
|
|
|
|
list_box -> setColor(PUCOL_LABEL, txtcol.red(), txtcol.green(),
|
|
|
|
txtcol.blue(), txtcol.alpha());
|
|
|
|
|
|
|
|
ok_button = new puOneShot ( 10, 10, (w<170)?(w/2-5):80, 30 );
|
|
|
|
ok_button -> setLegend ( "Ok" );
|
|
|
|
ok_button -> setUserData ( this );
|
|
|
|
ok_button -> setCallback ( fgPropPickerHandleOk );
|
|
|
|
|
|
|
|
if ( arrows > 0 ) {
|
|
|
|
down_arrow = new puArrowButton ( w-30, 20+20*arrows, w-10, 40+20*arrows, PUARROW_DOWN );
|
|
|
|
down_arrow->setUserData ( slider );
|
|
|
|
down_arrow->setCallback ( fgPropPickerHandleArrow );
|
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// after picker is built, load the list box with data...
|
|
|
|
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 );
|
|
|
|
|
|
|
|
FG_FINALIZE_PUI_DIALOG( this );
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
// Replace list with children of current
|
2006-05-18 12:51:32 +00:00
|
|
|
void fgPropPicker::find_props ( bool restore_pos )
|
Patch from Julian Foad:
When the scroll bar slider is dragged, the list scrolls only far
enough to see all items; only the arrow buttons can scroll it so far
that the last item goes to the top of the view.
Fix scroll bar proportional size: was wrong when the list was only
a little longer than the visible area.
Minor fixes such as "delete files[i];" -> "delete[] files[i];"
(where the item being deleted is an array of characters) and removal of
global variables.
Smooth scrolling when dragging the slider: one item at a time,
rather than one tenth of the list at a time.
Fix a bug that would have occurred if instantiated with arrows=2.
Sort properties primarily by name and then by numerical index
order, rather than a simple ASCII string order. E.g. "js[1]", "js[2]",
"js[10]" rather than "js[1]", "js[10]", "js[2]".
Avoid crashing if the selected property path does not exist;
display an empty list instead. This cannot happen when the property
picker is working properly, but did happen due to missing indices prior
to this patch, and could happen if the user is allowed to type a
pathname, as in the http and telnet interfaces.
Fix truncation of strings to PUSTRING_MAX: was wrong when string
length was exactly 80.
Fix: move the scroll bar to the top each time a new list is
displayed. It was left at its previous position, while the top of the
new list was displayed, not corresponding to the slider.
Use getDisplayName instead of duplicated code: gives a better
decision on whether to display the index, and avoids invalid property
paths being generated which would previously crash find_props().
Replace unnecessary node lookups by name with direct access: tidier
and more efficient. E.g. "getValueTypeString
(node->getNode(name.c_str()))" -> "getValueTypeString (child)".
2002-09-07 12:35:06 +00:00
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
int pi;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
delete_arrays();
|
2006-05-20 15:25:38 +00:00
|
|
|
num_files = (int)curr->nChildren();
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
// instantiate string objects and add [.] and [..] for subdirs
|
2006-05-20 15:25:38 +00:00
|
|
|
if (!curr->getParent()) {
|
2006-05-19 10:59:04 +00:00
|
|
|
files = new char* [ num_files+1 ];
|
|
|
|
pi = 0;
|
|
|
|
dotFiles = false;
|
2006-05-20 15:25:38 +00:00
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
} else {
|
|
|
|
// add two for the .. and .
|
2006-05-20 15:25:38 +00:00
|
|
|
num_files += 2;
|
2006-05-19 10:59:04 +00:00
|
|
|
// make room for .. and .
|
|
|
|
files = new char* [ num_files+1 ];
|
|
|
|
|
|
|
|
stdString line = ".";
|
|
|
|
files [ 0 ] = new char[line.size() + 1];
|
|
|
|
strcpy ( files [ 0 ], line.c_str() );
|
|
|
|
|
|
|
|
line = "..";
|
|
|
|
files [ 1 ] = new char[line.size() + 1];
|
|
|
|
strcpy ( files [ 1 ], line.c_str() );
|
|
|
|
|
|
|
|
pi = 2;
|
|
|
|
dotFiles = true;
|
Patch from Julian Foad:
When the scroll bar slider is dragged, the list scrolls only far
enough to see all items; only the arrow buttons can scroll it so far
that the last item goes to the top of the view.
Fix scroll bar proportional size: was wrong when the list was only
a little longer than the visible area.
Minor fixes such as "delete files[i];" -> "delete[] files[i];"
(where the item being deleted is an array of characters) and removal of
global variables.
Smooth scrolling when dragging the slider: one item at a time,
rather than one tenth of the list at a time.
Fix a bug that would have occurred if instantiated with arrows=2.
Sort properties primarily by name and then by numerical index
order, rather than a simple ASCII string order. E.g. "js[1]", "js[2]",
"js[10]" rather than "js[1]", "js[10]", "js[2]".
Avoid crashing if the selected property path does not exist;
display an empty list instead. This cannot happen when the property
picker is working properly, but did happen due to missing indices prior
to this patch, and could happen if the user is allowed to type a
pathname, as in the http and telnet interfaces.
Fix truncation of strings to PUSTRING_MAX: was wrong when string
length was exactly 80.
Fix: move the scroll bar to the top each time a new list is
displayed. It was left at its previous position, while the top of the
new list was displayed, not corresponding to the slider.
Use getDisplayName instead of duplicated code: gives a better
decision on whether to display the index, and avoids invalid property
paths being generated which would previously crash find_props().
Replace unnecessary node lookups by name with direct access: tidier
and more efficient. E.g. "getValueTypeString
(node->getNode(name.c_str()))" -> "getValueTypeString (child)".
2002-09-07 12:35:06 +00:00
|
|
|
}
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
num_children = curr->nChildren();
|
|
|
|
children = new SGPropertyNode_ptr[num_children];
|
|
|
|
for (i = 0; i < num_children; i++)
|
|
|
|
children[i] = curr->getChild(i);
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
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];
|
|
|
|
|
|
|
|
if ( child->nChildren() > 0 ) {
|
|
|
|
stdString name = stdString(child->getDisplayName(true)) + '/';
|
|
|
|
files[ pi ] = new char[ name.size() + 1 ];
|
|
|
|
strcpy ( files [ pi ], name.c_str() );
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
} else {
|
|
|
|
files[pi] = NULL; // ensure it's NULL before setting intial value
|
|
|
|
updateTextForEntry(i);
|
|
|
|
child->addChangeListener(this);
|
2003-02-04 22:27:58 +00:00
|
|
|
}
|
2006-05-20 15:25:38 +00:00
|
|
|
|
|
|
|
++pi;
|
Patch from Julian Foad:
When the scroll bar slider is dragged, the list scrolls only far
enough to see all items; only the arrow buttons can scroll it so far
that the last item goes to the top of the view.
Fix scroll bar proportional size: was wrong when the list was only
a little longer than the visible area.
Minor fixes such as "delete files[i];" -> "delete[] files[i];"
(where the item being deleted is an array of characters) and removal of
global variables.
Smooth scrolling when dragging the slider: one item at a time,
rather than one tenth of the list at a time.
Fix a bug that would have occurred if instantiated with arrows=2.
Sort properties primarily by name and then by numerical index
order, rather than a simple ASCII string order. E.g. "js[1]", "js[2]",
"js[10]" rather than "js[1]", "js[10]", "js[2]".
Avoid crashing if the selected property path does not exist;
display an empty list instead. This cannot happen when the property
picker is working properly, but did happen due to missing indices prior
to this patch, and could happen if the user is allowed to type a
pathname, as in the http and telnet interfaces.
Fix truncation of strings to PUSTRING_MAX: was wrong when string
length was exactly 80.
Fix: move the scroll bar to the top each time a new list is
displayed. It was left at its previous position, while the top of the
new list was displayed, not corresponding to the slider.
Use getDisplayName instead of duplicated code: gives a better
decision on whether to display the index, and avoids invalid property
paths being generated which would previously crash find_props().
Replace unnecessary node lookups by name with direct access: tidier
and more efficient. E.g. "getValueTypeString
(node->getNode(name.c_str()))" -> "getValueTypeString (child)".
2002-09-07 12:35:06 +00:00
|
|
|
}
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
files [ num_files ] = NULL;
|
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
proppath -> setLabel(curr->getPath(true));
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
int top = list_box->getTopItem();
|
|
|
|
list_box -> newList ( files );
|
|
|
|
if (restore_pos)
|
|
|
|
list_box->setTopItem(top);
|
|
|
|
|
|
|
|
// adjust the size of the slider...
|
|
|
|
if (num_files > list_box->getNumVisible()) {
|
|
|
|
slider->setSliderFraction((float)list_box->getNumVisible() / num_files);
|
|
|
|
if (!restore_pos)
|
|
|
|
slider->setValue(1.0f);
|
|
|
|
|
|
|
|
slider->reveal();
|
|
|
|
up_arrow->reveal();
|
|
|
|
down_arrow->reveal();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
slider->hide();
|
|
|
|
up_arrow->hide();
|
|
|
|
down_arrow->hide();
|
|
|
|
}
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2003-02-04 22:27:58 +00:00
|
|
|
void fgPropPicker::updateTextForEntry(int index)
|
|
|
|
{
|
|
|
|
assert((index >= 0) && (index < num_children));
|
|
|
|
SGPropertyNode_ptr node = children[index];
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
stdString name = node->getDisplayName(true);
|
|
|
|
stdString type = getValueTypeString(node);
|
2003-02-04 22:27:58 +00:00
|
|
|
stdString value = node->getStringValue();
|
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
stdString line = name + " = '" + value + "' (" + type;
|
2006-05-18 14:46:42 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
if (flags->getBoolValue()) {
|
2006-05-18 14:46:42 +00:00
|
|
|
stdString ext;
|
|
|
|
if (!node->getAttribute(SGPropertyNode::READ))
|
2006-05-20 15:25:38 +00:00
|
|
|
ext += 'r';
|
2006-05-18 14:46:42 +00:00
|
|
|
if (!node->getAttribute(SGPropertyNode::WRITE))
|
2006-05-20 15:25:38 +00:00
|
|
|
ext += 'w';
|
|
|
|
if (node->getAttribute(SGPropertyNode::TRACE_READ))
|
|
|
|
ext += 'R';
|
|
|
|
if (node->getAttribute(SGPropertyNode::TRACE_WRITE))
|
|
|
|
ext += 'W';
|
2006-05-18 14:46:42 +00:00
|
|
|
if (node->getAttribute(SGPropertyNode::ARCHIVE))
|
2006-05-20 15:25:38 +00:00
|
|
|
ext += 'A';
|
2006-05-18 14:46:42 +00:00
|
|
|
if (node->getAttribute(SGPropertyNode::USERARCHIVE))
|
2006-05-20 15:25:38 +00:00
|
|
|
ext += 'U';
|
2006-05-18 14:46:42 +00:00
|
|
|
if (node->isTied())
|
2006-05-20 15:25:38 +00:00
|
|
|
ext += 'T';
|
2006-05-18 14:46:42 +00:00
|
|
|
if (ext.size())
|
|
|
|
line += ", " + ext;
|
|
|
|
}
|
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
line += ')';
|
2006-05-18 14:46:42 +00:00
|
|
|
|
2003-02-04 22:27:58 +00:00
|
|
|
// truncate entries to plib pui limit
|
|
|
|
if (line.length() >= PUSTRING_MAX)
|
|
|
|
line[PUSTRING_MAX-1] = '\0';
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
if (dotFiles)
|
2006-05-20 15:25:38 +00:00
|
|
|
index += 2;
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2003-02-04 22:27:58 +00:00
|
|
|
// don't leak everywhere if we're updating
|
2005-07-02 20:49:38 +00:00
|
|
|
delete[] files[index];
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
files[index] = new char[ line.size() + 1 ];
|
2006-05-19 10:59:04 +00:00
|
|
|
strcpy ( files [ index ], line.c_str() );
|
2003-02-04 22:27:58 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2003-02-04 22:27:58 +00:00
|
|
|
void fgPropPicker::valueChanged(SGPropertyNode *nd)
|
|
|
|
{
|
2006-05-20 15:25:38 +00:00
|
|
|
for (int i = 0; i < num_children; i++)
|
|
|
|
if (children[i] == nd) {
|
|
|
|
updateTextForEntry(i);
|
2003-02-04 22:27:58 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// property editor class ======================================================
|
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
void fgPropEdit::fgPropEditHandleCancel ( puObject* b )
|
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
fgPropEdit* prop_edit = (fgPropEdit*) b -> getUserData ();
|
|
|
|
prop_pickerRefresh();
|
|
|
|
FG_POP_PUI_DIALOG( prop_edit );
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
void fgPropEdit::fgPropEditHandleOK ( puObject* b )
|
|
|
|
{
|
2006-05-19 10:59:04 +00:00
|
|
|
fgPropEdit* prop_edit = (fgPropEdit*) b -> getUserData ();
|
|
|
|
char* tvalue;
|
2001-11-12 20:57:08 +00:00
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
prop_edit -> propinput -> getValue( &tvalue );
|
2006-05-20 15:25:38 +00:00
|
|
|
prop_edit->getEditNode()->setStringValue(tvalue);
|
2001-11-12 20:57:08 +00:00
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
// update the picker display so it shows new value
|
|
|
|
prop_pickerRefresh();
|
2001-11-12 20:57:08 +00:00
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
FG_POP_PUI_DIALOG( prop_edit );
|
2001-11-12 20:57:08 +00:00
|
|
|
}
|
|
|
|
|
2006-05-19 10:59:04 +00:00
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
fgPropEdit::fgPropEdit ( SGPropertyNode *n ) :
|
2005-07-07 21:32:33 +00:00
|
|
|
fgPopup ( 0, 0 ),
|
2006-05-20 15:25:38 +00:00
|
|
|
node(n),
|
2005-07-07 21:32:33 +00:00
|
|
|
_gui((NewGUI *)globals->get_subsystem("gui"))
|
2001-11-12 20:57:08 +00:00
|
|
|
{
|
2006-05-20 15:25:38 +00:00
|
|
|
assert(n);
|
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
puFont LegendFont, LabelFont;
|
|
|
|
puGetDefaultFonts ( &LegendFont, &LabelFont );
|
2005-07-07 21:32:33 +00:00
|
|
|
FGColor txtcol(_gui->getColor("label"));
|
|
|
|
txtcol.merge(_gui->getColor("text"));
|
|
|
|
txtcol.merge(_gui->getColor("text-label"));
|
2001-11-12 20:57:08 +00:00
|
|
|
|
|
|
|
// locate in relation to picker widget...
|
|
|
|
int fx = PROPPICK_X;
|
|
|
|
int fy = PROPPICK_Y + PROPPICK_H;
|
2006-05-19 10:59:04 +00:00
|
|
|
frame = new puFrame (fx,fy, fx+500, fy+120);
|
2001-11-12 20:57:08 +00:00
|
|
|
|
|
|
|
setUserData( this );
|
|
|
|
|
2006-05-20 15:25:38 +00:00
|
|
|
namestring = node->getDisplayName();
|
2006-05-19 10:59:04 +00:00
|
|
|
propname = new puText (fx+10, fy+90);
|
2006-05-20 15:25:38 +00:00
|
|
|
propname -> setLabel(namestring.c_str());
|
2006-05-19 10:59:04 +00:00
|
|
|
propname -> setColor(PUCOL_LABEL, txtcol.red(), txtcol.green(),
|
|
|
|
txtcol.blue(), txtcol.alpha());
|
|
|
|
|
|
|
|
propinput = new puInput (fx+10, fy+50, fx+480, fy+80);
|
2006-05-20 15:25:38 +00:00
|
|
|
propinput -> setValue (node->getStringValue());
|
2006-05-19 10:59:04 +00:00
|
|
|
propinput -> acceptInput();
|
|
|
|
|
|
|
|
ok_button = new puOneShot (fx+10, fy+10, fx+80, fy+30);
|
|
|
|
ok_button -> setUserData (this);
|
|
|
|
ok_button -> setLegend (gui_msg_OK);
|
|
|
|
ok_button -> setCallback (fgPropEditHandleOK);
|
|
|
|
ok_button -> makeReturnDefault (TRUE);
|
|
|
|
|
|
|
|
cancel_button = new puOneShot (fx+100, fy+10, fx+180, fy+30);
|
|
|
|
cancel_button -> setUserData (this);
|
|
|
|
cancel_button -> setLegend (gui_msg_CANCEL);
|
|
|
|
cancel_button -> setCallback (fgPropEditHandleCancel);
|
|
|
|
|
2001-11-12 20:57:08 +00:00
|
|
|
FG_FINALIZE_PUI_DIALOG( this );
|
|
|
|
}
|
2006-05-19 10:59:04 +00:00
|
|
|
|
|
|
|
|