1
0
Fork 0

- undefine PUCLASS_LIST, as we have our own (old_warning--)

- PropertyObject: remove additional "values" member again
- don't create entry lists for <list>, <select>, and <combo> at dialog
  creation and delete them on dialog close, but let a separate class
  fgValueList handle this. The three widgets are now subclassed and the
  derived widget lets fgValueList manage the lists
- make <select> consistent with <list>. This breaks backwards
  compatibility, but not a single dialog in fgfs uses it and did so
  since ... forever. (Shoot me!)

Rationale: now that dialogs are a bit more dynamic than they used to be
(thanks to embedded Nasal), we have to delete and recreate entry lists
during dialog use. Deleting only at dialog closing doesn't cut it anymore.
Especially list widgets that are updated several times per second would
use up a lot of memory otherwise. The route-manager doesn't update that
often, but it did already leak. One TODO less.  :-)
This commit is contained in:
mfranz 2006-05-16 12:45:38 +00:00
parent 95b6f8057a
commit 5a38a9d071
2 changed files with 107 additions and 80 deletions

View file

@ -6,15 +6,12 @@
#include <stdlib.h> // atof() #include <stdlib.h> // atof()
#include <plib/puAux.h>
#include <Input/input.hxx> #include <Input/input.hxx>
#include <Scripting/NasalSys.hxx> #include <Scripting/NasalSys.hxx>
#include "dialog.hxx" #include "dialog.hxx"
#include "new_gui.hxx" #include "new_gui.hxx"
#include "puList.hxx"
#include "AirportList.hxx" #include "AirportList.hxx"
#include "layout.hxx" #include "layout.hxx"
@ -49,6 +46,7 @@ GUIInfo::~GUIInfo ()
} }
} }
/** /**
* Key handler. * Key handler.
@ -360,13 +358,6 @@ FGDialog::~FGDialog ()
puDeleteObject(_object); puDeleteObject(_object);
unsigned int i; unsigned int i;
// Delete all the arrays we made
// and were forced to keep around
// because PUI won't do its own
// memory management.
for (i = 0; i < _char_arrays.size(); i++)
destroy_char_array(_char_arrays[i]);
// Delete all the info objects we // Delete all the info objects we
// were forced to keep around because // were forced to keep around because
// PUI cannot delete its own user data. // PUI cannot delete its own user data.
@ -393,10 +384,10 @@ FGDialog::updateValues (const char * objectName)
continue; continue;
puObject *obj = _propertyObjects[i]->object; puObject *obj = _propertyObjects[i]->object;
SGPropertyNode *values = _propertyObjects[i]->values; if (obj->getType() & PUCLASS_LIST) {
if (obj->getType() & PUCLASS_LIST && values) fgList *pl = static_cast<fgList *>(obj);
((puList *)obj)->newList(value_list(values)); pl->update();
else } else
copy_to_pui(_propertyObjects[i]->node, obj); copy_to_pui(_propertyObjects[i]->node, obj);
} }
} }
@ -551,9 +542,8 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
return obj; return obj;
} else if (type == "list") { } else if (type == "list") {
char ** entries = value_list(props);
int slider_width = props->getIntValue("slider", 20); int slider_width = props->getIntValue("slider", 20);
puList * obj = new puList(x, y, x + width, y + height, entries, slider_width); fgList * obj = new fgList(x, y, x + width, y + height, props, slider_width);
if (presetSize) if (presetSize)
obj->setSize(width, height); obj->setSize(width, height);
setupObject(obj, props); setupObject(obj, props);
@ -622,8 +612,7 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
return obj; return obj;
} else if (type == "combo") { } else if (type == "combo") {
char ** entries = value_list(props); fgComboBox * obj = new fgComboBox(x, y, x + width, y + height, props,
puaComboBox * obj = new puaComboBox(x, y, x + width, y + height, entries,
props->getBoolValue("editable", false)); props->getBoolValue("editable", false));
setupObject(obj, props); setupObject(obj, props);
#ifdef PUCOL_EDITFIELD // plib > 0.8.4 #ifdef PUCOL_EDITFIELD // plib > 0.8.4
@ -672,19 +661,7 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight)
return obj; return obj;
} else if (type == "select") { } else if (type == "select") {
vector<SGPropertyNode_ptr> value_nodes; fgSelectBox * obj = new fgSelectBox(x, y, x + width, y + height, props);
SGPropertyNode * selection_node =
fgGetNode(props->getChild("selection")->getStringValue(), true);
for (int q = 0; q < selection_node->nChildren(); q++)
value_nodes.push_back(selection_node->getChild(q));
char ** entries = make_char_array(value_nodes.size());
for (unsigned int i = 0; i < value_nodes.size(); i++)
entries[i] = strdup((char *)value_nodes[i]->getName());
puaSelectBox * obj =
new puaSelectBox(x, y, x + width, y + height, entries);
setupObject(obj, props); setupObject(obj, props);
#ifdef PUCOL_EDITFIELD // plib > 0.8.4 #ifdef PUCOL_EDITFIELD // plib > 0.8.4
setColor(obj, props, EDITFIELD); setColor(obj, props, EDITFIELD);
@ -728,8 +705,7 @@ FGDialog::setupObject (puObject * object, SGPropertyNode * props)
SGPropertyNode_ptr node = fgGetNode(propname, true); SGPropertyNode_ptr node = fgGetNode(propname, true);
copy_to_pui(node, object); copy_to_pui(node, object);
SGPropertyNode * values = type == "list" ? props : 0; PropertyObject* po = new PropertyObject(name, object, node);
PropertyObject* po = new PropertyObject(name, object, node, values);
_propertyObjects.push_back(po); _propertyObjects.push_back(po);
if(props->getBoolValue("live")) if(props->getBoolValue("live"))
_liveObjects.push_back(po); _liveObjects.push_back(po);
@ -934,34 +910,6 @@ FGDialog::getKeyCode(const char *str)
return key; return key;
} }
char **
FGDialog::value_list (const SGPropertyNode *props)
{
vector<SGPropertyNode_ptr> value_nodes = props->getChildren("value");
char ** entries = make_char_array(value_nodes.size());
for (unsigned int i = 0; i < value_nodes.size(); i++)
entries[i] = strdup((char *)value_nodes[i]->getStringValue());
return entries;
}
char **
FGDialog::make_char_array (int size)
{
char ** list = new char*[size+1];
for (int i = 0; i <= size; i++)
list[i] = 0;
_char_arrays.push_back(list);
return list;
}
void
FGDialog::destroy_char_array (char ** array)
{
for (int i = 0; array[i] != 0; i++)
if (array[i])
free(array[i]);// added with strdup
delete[] array;
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
@ -970,14 +918,66 @@ FGDialog::destroy_char_array (char ** array)
FGDialog::PropertyObject::PropertyObject (const char * n, FGDialog::PropertyObject::PropertyObject (const char * n,
puObject * o, puObject * o,
SGPropertyNode_ptr p, SGPropertyNode_ptr p)
SGPropertyNode_ptr v)
: name(n), : name(n),
object(o), object(o),
node(p), node(p)
values(v)
{ {
} }
////////////////////////////////////////////////////////////////////////
// Implementation of fgList and derived pui widgets
////////////////////////////////////////////////////////////////////////
fgValueList::fgValueList(SGPropertyNode *p) :
_props(p)
{
make_list();
}
void
fgValueList::update()
{
destroy_list();
make_list();
}
fgValueList::~fgValueList()
{
destroy_list();
}
void
fgValueList::make_list()
{
vector<SGPropertyNode_ptr> value_nodes = _props->getChildren("value");
_list = new char *[value_nodes.size() + 1];
unsigned int i;
for (i = 0; i < value_nodes.size(); i++)
_list[i] = strdup((char *)value_nodes[i]->getStringValue());
_list[i] = 0;
}
void
fgValueList::destroy_list()
{
for (int i = 0; _list[i] != 0; i++)
if (_list[i])
free(_list[i]);
delete[] _list;
}
void
fgList::update()
{
fgValueList::update();
newList(_list);
}
// end of dialog.cxx // end of dialog.cxx

View file

@ -7,13 +7,16 @@
# error This library requires C++ # error This library requires C++
#endif #endif
#include <plib/pu.h> #include <plib/puAux.h>
#include <plib/sg.h> #include <plib/sg.h>
#include <simgear/compiler.h> // for SG_USING_STD #include <simgear/compiler.h> // for SG_USING_STD
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#undef PUCLASS_LIST
#include "puList.hxx"
#include <vector> #include <vector>
SG_USING_STD(vector); SG_USING_STD(vector);
@ -141,30 +144,18 @@ private:
// PUI provides no way for userdata to be deleted automatically // PUI provides no way for userdata to be deleted automatically
// with a GUI object, so we have to keep track of all the special // with a GUI object, so we have to keep track of all the special
// data we allocated and then free it manually when the dialog // data we allocated and then free it manually when the dialog
// closes. "values" is a node with "value" children and only used // closes.
// by the <list> widget.
vector<void *> _info; vector<void *> _info;
struct PropertyObject { struct PropertyObject {
PropertyObject (const char * name, PropertyObject (const char * name,
puObject * object, puObject * object,
SGPropertyNode_ptr node, SGPropertyNode_ptr node);
SGPropertyNode_ptr values = 0);
string name; string name;
puObject * object; puObject * object;
SGPropertyNode_ptr node; SGPropertyNode_ptr node;
SGPropertyNode_ptr values;
}; };
vector<PropertyObject *> _propertyObjects; vector<PropertyObject *> _propertyObjects;
vector<PropertyObject *> _liveObjects; vector<PropertyObject *> _liveObjects;
// PUI doesn't copy arrays, so we have to allocate string arrays
// and then keep pointers so that we can delete them when the
// dialog closes. value_list() builds such a list from "value"
// children.
char ** make_char_array (int size);
char ** value_list(const SGPropertyNode * prop);
void destroy_char_array (char **array);
vector<char **> _char_arrays;
}; };
// //
@ -191,4 +182,40 @@ private:
int _dX, _dY; int _dX, _dY;
}; };
class fgValueList {
public:
fgValueList(SGPropertyNode *p);
virtual ~fgValueList();
virtual void update();
protected:
char **_list;
private:
void make_list();
void destroy_list();
SGPropertyNode_ptr _props;
};
class fgList : public fgValueList, public puList {
public:
fgList(int x1, int y1, int x2, int y2, SGPropertyNode *p, int sw) :
fgValueList(p), puList(x1, y1, x2, y2, _list, sw) {}
virtual void update();
};
class fgComboBox : public fgValueList, public puaComboBox {
public:
fgComboBox(int x1, int y1, int x2, int y2, SGPropertyNode *p, bool editable) :
fgValueList(p), puaComboBox(x1, y1, x2, y2, _list, editable) {}
};
class fgSelectBox : public fgValueList, public puaSelectBox {
public:
fgSelectBox(int x1, int y1, int x2, int y2, SGPropertyNode *p) :
fgValueList(p), puaSelectBox(x1, y1, x2, y2, _list) {}
};
#endif // __DIALOG_HXX #endif // __DIALOG_HXX