From 5a38a9d071f3d58b14225cbdcfdaf4abe1f0e2dc Mon Sep 17 00:00:00 2001 From: mfranz Date: Tue, 16 May 2006 12:45:38 +0000 Subject: [PATCH] - undefine PUCLASS_LIST, as we have our own (old_warning--) - PropertyObject: remove additional "values" member again - don't create entry lists for , consistent with . 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. :-) --- src/GUI/dialog.cxx | 128 ++++++++++++++++++++++----------------------- src/GUI/dialog.hxx | 57 ++++++++++++++------ 2 files changed, 106 insertions(+), 79 deletions(-) diff --git a/src/GUI/dialog.cxx b/src/GUI/dialog.cxx index a33dde1ce..803346588 100644 --- a/src/GUI/dialog.cxx +++ b/src/GUI/dialog.cxx @@ -6,15 +6,12 @@ #include // atof() -#include - #include #include #include "dialog.hxx" #include "new_gui.hxx" -#include "puList.hxx" #include "AirportList.hxx" #include "layout.hxx" @@ -49,6 +46,7 @@ GUIInfo::~GUIInfo () } } + /** * Key handler. @@ -360,13 +358,6 @@ FGDialog::~FGDialog () puDeleteObject(_object); 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 // were forced to keep around because // PUI cannot delete its own user data. @@ -393,10 +384,10 @@ FGDialog::updateValues (const char * objectName) continue; puObject *obj = _propertyObjects[i]->object; - SGPropertyNode *values = _propertyObjects[i]->values; - if (obj->getType() & PUCLASS_LIST && values) - ((puList *)obj)->newList(value_list(values)); - else + if (obj->getType() & PUCLASS_LIST) { + fgList *pl = static_cast(obj); + pl->update(); + } else copy_to_pui(_propertyObjects[i]->node, obj); } } @@ -551,9 +542,8 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight) return obj; } else if (type == "list") { - char ** entries = value_list(props); 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) obj->setSize(width, height); setupObject(obj, props); @@ -622,8 +612,7 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight) return obj; } else if (type == "combo") { - char ** entries = value_list(props); - puaComboBox * obj = new puaComboBox(x, y, x + width, y + height, entries, + fgComboBox * obj = new fgComboBox(x, y, x + width, y + height, props, props->getBoolValue("editable", false)); setupObject(obj, props); #ifdef PUCOL_EDITFIELD // plib > 0.8.4 @@ -672,19 +661,7 @@ FGDialog::makeObject (SGPropertyNode * props, int parentWidth, int parentHeight) return obj; } else if (type == "select") { - vector value_nodes; - 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); + fgSelectBox * obj = new fgSelectBox(x, y, x + width, y + height, props); setupObject(obj, props); #ifdef PUCOL_EDITFIELD // plib > 0.8.4 setColor(obj, props, EDITFIELD); @@ -728,8 +705,7 @@ FGDialog::setupObject (puObject * object, SGPropertyNode * props) SGPropertyNode_ptr node = fgGetNode(propname, true); copy_to_pui(node, object); - SGPropertyNode * values = type == "list" ? props : 0; - PropertyObject* po = new PropertyObject(name, object, node, values); + PropertyObject* po = new PropertyObject(name, object, node); _propertyObjects.push_back(po); if(props->getBoolValue("live")) _liveObjects.push_back(po); @@ -934,50 +910,74 @@ FGDialog::getKeyCode(const char *str) return key; } -char ** -FGDialog::value_list (const SGPropertyNode *props) + + +//////////////////////////////////////////////////////////////////////// +// Implementation of FGDialog::PropertyObject. +//////////////////////////////////////////////////////////////////////// + +FGDialog::PropertyObject::PropertyObject (const char * n, + puObject * o, + SGPropertyNode_ptr p) + : name(n), + object(o), + node(p) { - vector 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) + + + +//////////////////////////////////////////////////////////////////////// +// Implementation of fgList and derived pui widgets +//////////////////////////////////////////////////////////////////////// + + +fgValueList::fgValueList(SGPropertyNode *p) : + _props(p) { - char ** list = new char*[size+1]; - for (int i = 0; i <= size; i++) - list[i] = 0; - _char_arrays.push_back(list); - return list; + make_list(); } void -FGDialog::destroy_char_array (char ** array) +fgValueList::update() { - for (int i = 0; array[i] != 0; i++) - if (array[i]) - free(array[i]);// added with strdup - delete[] array; + destroy_list(); + make_list(); } - -//////////////////////////////////////////////////////////////////////// -// Implementation of FGDialog::PropertyObject. -//////////////////////////////////////////////////////////////////////// +fgValueList::~fgValueList() +{ + destroy_list(); +} -FGDialog::PropertyObject::PropertyObject (const char * n, - puObject * o, - SGPropertyNode_ptr p, - SGPropertyNode_ptr v) - : name(n), - object(o), - node(p), - values(v) +void +fgValueList::make_list() +{ + vector 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 diff --git a/src/GUI/dialog.hxx b/src/GUI/dialog.hxx index 65c010395..f30f3cf22 100644 --- a/src/GUI/dialog.hxx +++ b/src/GUI/dialog.hxx @@ -7,13 +7,16 @@ # error This library requires C++ #endif -#include +#include #include #include // for SG_USING_STD #include #include +#undef PUCLASS_LIST +#include "puList.hxx" + #include SG_USING_STD(vector); @@ -141,30 +144,18 @@ private: // PUI provides no way for userdata to be deleted automatically // 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 - // closes. "values" is a node with "value" children and only used - // by the widget. + // closes. vector _info; struct PropertyObject { PropertyObject (const char * name, puObject * object, - SGPropertyNode_ptr node, - SGPropertyNode_ptr values = 0); + SGPropertyNode_ptr node); string name; puObject * object; SGPropertyNode_ptr node; - SGPropertyNode_ptr values; }; vector _propertyObjects; vector _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_arrays; }; // @@ -191,4 +182,40 @@ private: 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 -- 2.39.5