#include <simgear/structure/SGBinding.hxx>
#include <simgear/props/props_io.hxx>
+#include <simgear/debug/BufferedLogCallback.hxx>
+#include <simgear/scene/tsync/terrasync.hxx>
#include <Scripting/NasalSys.hxx>
#include <Main/fg_os.hxx>
#include "FGFontCache.hxx"
#include "FGColor.hxx"
+using std::string;
+
enum format_type { f_INVALID, f_INT, f_LONG, f_FLOAT, f_DOUBLE, f_STRING };
static const int FORMAT_BUFSIZE = 255;
static const int RESIZE_MARGIN = 7;
return type;
}
+////////////////////////////////////////////////////////////////////////
+
+//
+// Custom subclass of puPopup to implement "draggable" windows in the
+// interface. Note that this is a subclass of puPopup, not
+// puDialogBox. Sadly, PUI (mis)uses subclassing to implement a
+// boolean property: modality. That means that we can't implement
+// dragging of both puPopup windows and puDialogBoxes with the same
+// code. Rather than duplicate code, I've chosen to implement only
+// "non-modal dragability" here. Modal dialog boxes (like the exit
+// confirmation) are not draggable.
+//
+class fgPopup : public puPopup {
+public:
+ fgPopup(int x, int y, bool r = true, bool d = true) :
+ puPopup(x, y), _draggable(d), _resizable(r), _dragging(false)
+ {}
+ int checkHit(int b, int up, int x, int y);
+ int checkKey(int key, int updown);
+ int getHitObjects(puObject *, int x, int y);
+ bool checkHitCanvas(puObject *, int x, int y);
+ puObject *getKeyObject(puObject *, int key);
+ puObject *getActiveInputField(puObject *);
+ void applySize(puObject *);
+private:
+ enum { LEFT = 1, RIGHT = 2, TOP = 4, BOTTOM = 8 };
+ bool _draggable;
+ bool _resizable;
+ bool _dragging;
+ int _resizing;
+ int _start_cursor;
+ int _cursor;
+ int _dlgX, _dlgY, _dlgW, _dlgH;
+ int _startX, _startY;
+};
+
+
+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 puaList, public GUI_ID {
+public:
+ fgList(int x1, int y1, int x2, int y2, SGPropertyNode *p, int sw) :
+ fgValueList(p), puaList(x1, y1, x2, y2, _list, sw), GUI_ID(FGCLASS_LIST) {}
+ 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),
+ _inHit(false)
+ {}
+
+ void update();
+
+ virtual void setSize(int w, int h);
+
+ virtual int checkHit(int b, int up, int x, int y);
+
+ virtual void recalc_bbox();
+private:
+ bool _inHit;
+};
+
+class LogList : public puaList, public FGPUIDialog::ActiveWidget, public GUI_ID {
+public:
+ LogList(int x1, int y1, int x2, int y2, int sw) :
+ puaList(x1, y1, x2, y2, sw),
+ GUI_ID(FGCLASS_LOGLIST)
+ {
+ m_buffer = NULL;
+ m_stamp = 0;
+ }
+
+ void setBuffer(simgear::BufferedLogCallback* buf);
+
+ virtual void update();
+private:
+ std::vector<unsigned char*> m_items;
+ simgear::BufferedLogCallback* m_buffer;
+ unsigned int m_stamp;
+};
+
+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) {}
+};
////////////////////////////////////////////////////////////////////////
// Implementation of GUIInfo.
FGPUIDialog *dialog;
SGPropertyNode_ptr node;
- vector <SGBinding *> bindings;
+ std::vector <SGBinding *> bindings;
int key;
string label, legend, text, format;
format_type fmt_type;
_conditionalObjects[j]->update(this);
}
+ for (unsigned int i = 0; i < _activeWidgets.size(); i++) {
+ _activeWidgets[i]->update();
+ }
+
if (_needsRelayout) {
relayout();
}
ScrolledWaypointList* obj = new ScrolledWaypointList(x, y, width, height);
setupObject(obj, props);
return obj;
+
+ } else if (type == "loglist") {
+ LogList* obj = new LogList(x, y, width, height, 20);
+ string logClass = props->getStringValue("logclass");
+ if (logClass == "terrasync") {
+ simgear::SGTerraSync* tsync = (simgear::SGTerraSync*) globals->get_subsystem("terrasync");
+ obj->setBuffer(tsync->log());
+ } else {
+ FGNasalSys* nasal = (FGNasalSys*) globals->get_subsystem("nasal");
+ obj->setBuffer(nasal->log());
+ }
+
+ setupObject(obj, props);
+ _activeWidgets.push_back(obj);
+ return obj;
} else {
return 0;
}
}
SGPropertyNode *dest = fgGetNode("/sim/bindings/gui", true);
- vector<SGPropertyNode_ptr> bindings = props->getChildren("binding");
+ std::vector<SGPropertyNode_ptr> bindings = props->getChildren("binding");
if (bindings.size() > 0) {
info->key = props->getIntValue("keynum", -1);
if (props->hasValue("key"))
vname = _props->getStringValue("property-name");
}
- vector<SGPropertyNode_ptr> value_nodes = values->getChildren(vname);
+ std::vector<SGPropertyNode_ptr> value_nodes = values->getChildren(vname);
_list = new char *[value_nodes.size() + 1];
unsigned int i;
for (i = 0; i < value_nodes.size(); i++) {
setTopItem(top);
}
+////////////////////////////////////////////////////////////////////////
+// Implementation of fgLogList
+////////////////////////////////////////////////////////////////////////
+
+void LogList::update()
+{
+ if (!m_buffer) return;
+
+ if (m_stamp != m_buffer->stamp()) {
+ m_stamp = m_buffer->threadsafeCopy(m_items);
+ m_items.push_back(NULL); // terminator value
+ newList((char**) m_items.data());
+ setTopItem(m_items.size() - 1); // scroll to bottom of list
+ }
+}
+
+void LogList::setBuffer(simgear::BufferedLogCallback* buf)
+{
+ m_buffer = buf;
+ m_stamp = m_buffer->stamp() - 1; // force an update
+ update();
+}
+
+////////////////////////////////////////////////////////////////////////
+// Implementation of fgComboBox
+////////////////////////////////////////////////////////////////////////
+
+
void fgComboBox::update()
{
if (_inHit) {