2006-05-22 14:34:20 +00:00
|
|
|
// Implementation of the <property-list> widget.
|
|
|
|
//
|
|
|
|
// Copyright (C) 2001 Steve BAKER
|
|
|
|
// Copyright (C) 2001 Jim WILSON
|
|
|
|
// Copyright (C) 2006 Melchior FRANZ
|
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program 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
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <simgear/compiler.h>
|
|
|
|
|
2007-05-07 14:29:40 +00:00
|
|
|
#include <sstream>
|
2008-07-25 18:38:29 +00:00
|
|
|
#include <iomanip>
|
2008-06-02 21:07:35 +00:00
|
|
|
#include <iostream>
|
2008-07-25 18:38:29 +00:00
|
|
|
#include <string>
|
2011-10-17 16:41:59 +00:00
|
|
|
|
2008-07-27 16:25:13 +00:00
|
|
|
using std::string;
|
2008-06-02 21:07:35 +00:00
|
|
|
using std::cout;
|
2011-10-17 16:41:59 +00:00
|
|
|
using std::endl;
|
2008-06-02 21:07:35 +00:00
|
|
|
|
2006-05-22 14:34:20 +00:00
|
|
|
typedef string stdString; // puObject has a "string" member
|
|
|
|
|
|
|
|
#include <Main/fg_os.hxx> // fgGetKeyModifiers()
|
|
|
|
#include <Main/fg_props.hxx>
|
|
|
|
|
|
|
|
#include "property_list.hxx"
|
|
|
|
|
|
|
|
|
|
|
|
static string getValueTypeString(const SGPropertyNode *node)
|
|
|
|
{
|
2009-07-17 12:54:12 +00:00
|
|
|
using namespace simgear;
|
2006-05-22 14:34:20 +00:00
|
|
|
string result;
|
|
|
|
|
2009-07-17 12:54:12 +00:00
|
|
|
props::Type type = node->getType();
|
|
|
|
if (type == props::UNSPECIFIED)
|
2006-05-22 14:34:20 +00:00
|
|
|
result = "unspecified";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::NONE)
|
2006-05-22 14:34:20 +00:00
|
|
|
result = "none";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::BOOL)
|
2006-05-22 14:34:20 +00:00
|
|
|
result = "bool";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::INT)
|
2006-05-22 14:34:20 +00:00
|
|
|
result = "int";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::LONG)
|
2006-05-22 14:34:20 +00:00
|
|
|
result = "long";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::FLOAT)
|
2006-05-22 14:34:20 +00:00
|
|
|
result = "float";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::DOUBLE)
|
2006-05-22 14:34:20 +00:00
|
|
|
result = "double";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::STRING)
|
2006-05-22 14:34:20 +00:00
|
|
|
result = "string";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::VEC3D)
|
2009-07-15 23:15:57 +00:00
|
|
|
result = "vec3d";
|
2009-07-17 12:54:12 +00:00
|
|
|
else if (type == props::VEC4D)
|
2009-07-15 23:15:57 +00:00
|
|
|
result = "vec4d";
|
2006-05-22 14:34:20 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-03 21:20:15 +00:00
|
|
|
static void dumpProperties(const SGPropertyNode *node)
|
|
|
|
{
|
2009-07-17 12:54:12 +00:00
|
|
|
using namespace simgear;
|
2007-05-07 14:29:40 +00:00
|
|
|
cout << node->getPath() << '/' << endl;
|
2007-05-03 21:20:15 +00:00
|
|
|
for (int i = 0; i < node->nChildren(); i++) {
|
|
|
|
const SGPropertyNode *c = node->getChild(i);
|
2009-07-17 12:54:12 +00:00
|
|
|
props::Type type = c->getType();
|
|
|
|
if (type == props::ALIAS || c->nChildren())
|
2007-05-03 21:20:15 +00:00
|
|
|
continue;
|
|
|
|
|
|
|
|
int index = c->getIndex();
|
|
|
|
cout << std::setw(11) << getValueTypeString(c) << " " << c->getName();
|
|
|
|
if (index > 0)
|
|
|
|
cout << '[' << index << ']';
|
|
|
|
cout << " = ";
|
|
|
|
|
|
|
|
switch (c->getType()) {
|
2009-07-17 12:54:12 +00:00
|
|
|
case props::DOUBLE:
|
|
|
|
case props::FLOAT:
|
|
|
|
case props::VEC3D:
|
|
|
|
case props::VEC4D:
|
2009-07-15 23:15:57 +00:00
|
|
|
{
|
2011-10-17 16:41:59 +00:00
|
|
|
std::streamsize precision = cout.precision(15);
|
2009-07-15 23:15:57 +00:00
|
|
|
c->printOn(cout);
|
|
|
|
cout.precision(precision);
|
|
|
|
}
|
2007-05-03 21:20:15 +00:00
|
|
|
break;
|
2009-07-17 12:54:12 +00:00
|
|
|
case props::LONG:
|
|
|
|
case props::INT:
|
|
|
|
case props::BOOL:
|
2009-07-15 23:15:57 +00:00
|
|
|
c->printOn(cout);
|
2007-05-03 21:20:15 +00:00
|
|
|
break;
|
2009-07-17 12:54:12 +00:00
|
|
|
case props::STRING:
|
2007-05-03 21:20:15 +00:00
|
|
|
cout << '"' << c->getStringValue() << '"';
|
|
|
|
break;
|
2009-07-17 12:54:12 +00:00
|
|
|
case props::NONE:
|
2007-05-03 21:20:15 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cout << '\'' << c->getStringValue() << '\'';
|
|
|
|
}
|
|
|
|
cout << endl;
|
|
|
|
}
|
|
|
|
cout << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-24 14:00:56 +00:00
|
|
|
static void sanitize(stdString& s)
|
|
|
|
{
|
|
|
|
stdString r = s;
|
|
|
|
s = "";
|
|
|
|
for (unsigned i = 0; i < r.size(); i++) {
|
|
|
|
if (r[i] == '\a')
|
|
|
|
s += "\\a";
|
|
|
|
else if (r[i] == '\b')
|
|
|
|
s += "\\b";
|
|
|
|
else if (r[i] == '\t')
|
|
|
|
s += "\\t";
|
|
|
|
else if (r[i] == '\n')
|
|
|
|
s += "\\n";
|
|
|
|
else if (r[i] == '\v')
|
|
|
|
s += "\\v";
|
|
|
|
else if (r[i] == '\f')
|
|
|
|
s += "\\f";
|
|
|
|
else if (r[i] == '\r')
|
|
|
|
s += "\\r";
|
|
|
|
else if (r[i] == '\'')
|
|
|
|
s += "\'";
|
|
|
|
else if (r[i] == '\\')
|
|
|
|
s += "\\";
|
2006-05-24 21:02:52 +00:00
|
|
|
else if (isprint(r[i]))
|
2006-05-24 14:00:56 +00:00
|
|
|
s += r[i];
|
|
|
|
else {
|
|
|
|
const char *hex = "0123456789abcdef";
|
|
|
|
int c = r[i] & 255;
|
|
|
|
s += stdString("\\x") + hex[c / 16] + hex[c % 16];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-22 14:34:20 +00:00
|
|
|
|
|
|
|
|
Added highlighting system.
If /sim/highlighting/enabled is true, we highlight animated objects under the
pointer, and also highlight other objects that are animated by the same or
related properties.
The intent here is to be able to give a visual indication of what cockpit
controls do or what cockpit controls affect particular aircraft objects - for
example moving the pointer over the flaps will highlight the flaps and also
highlight any controls or rotary indicators in the cockpit that are associated
with the flaps.
To make this work, we have to discover associations between properties. This
is currently done for YASim (e.g. associations between /controls/flight/flaps
and /surface-positions/flap-pos-norm) and autopilot filters (e.g. with
the 777, digital filters associate /controls/flight/rudder-nul with
/fcs/fbw/yaw/rudder-ratio-out). We don't currently gather associations between
properties in JSBSim
We also detect associations between dialogs, menus and keypresses and
properties, which is used to populate /sim/highlighting/current with
information about dialogs, menus and keypresses that are associated with the
currently highlighted nodes' properties.
Details:
src/GUI/Highlight.cxx
src/GUI/Highlight.hxx
src/GUI/CMakeLists.txt
src/Main/fg_init.cxx
New subsystem called 'highlight', with support for registering and
recovering links between menus, dialogs, keypresses and OSG node
animations.
Provides a function Highlight::highlight_nodes() which highlights
related nodes using internal NodeHighlighting class, and populates
/sim/highlighting/current with information about related dialogs, menus and
keypresses.
The NodeHighlighting class works by making nodes use an alternative
StateSet which shows up as a distinct material on screen. We remember each
highlighted node's original StateSet so that we can un-highlight. We update
the material parameters using a listener for /sim/highlighting/material,
which allows some control over the appearence of highlighted nodes.
src/FDM/flight.cxx
src/FDM/flight.hxx
Added virtual method FGInterface::property_associations() which returns
property associations from the FDM. Default implementation returns empty
set. Implemented in YASim, but not (yet) in JSBSim. Uses a simple function
pointer at the moment to avoid requring FDMs to use recent C++ features.
src/FDM/YASim/FGFDM.cpp
src/FDM/YASim/FGFDM.hpp
src/FDM/YASim/YASim.cxx
src/FDM/YASim/YASim.hxx
Gathers information about property associations on startup such as
/controls/flight/flaps => /surface-positions/flap-pos-norm, then
YASim::property_associations() overrides default implementation to return
these associations.
src/Autopilot/analogcomponent.cxx
src/Autopilot/analogcomponent.hxx
src/Autopilot/digitalfilter.cxx
src/Autopilot/inputvalue.cxx
src/Autopilot/inputvalue.hxx
Filters now gather information about their input/output properties and
register with Highlight::add_property_property(). For example this makes
highlighting work on the 777, where pilot controls affect control surfaces
only via filters.
src/GUI/new_gui.cxx
Scan menus, keypresses and dialogs and register associations with
Highlight::add_*().
src/GUI/property_list.cxx
src/GUI/property_list.hxx
src/GUI/FGPUIDialog.cxx
Added <readonly> flag to property-list. If set, we don't show .. or . items
and don't respond to mouse/keyboard.
Used by fgdata's new Highlighting dialogue.
src/Model/acmodel.cxx
src/Model/acmodel.hxx
Visit the user aircraft's scene graph when it is loaded, gathering
information about osg::Node's that are animated by properties, and register
these associations with Highlight::add_property_node().
src/Viewer/renderer.cxx
When scanning for pick highlights, use Highlight::highlight_nodes() to
highlight animated objects under the pointer and related objects.
2021-10-05 21:25:08 +00:00
|
|
|
PropertyList::PropertyList(int minx, int miny, int maxx, int maxy, SGPropertyNode *start, bool readonly) :
|
2008-03-11 15:58:57 +00:00
|
|
|
puaList(minx, miny, maxx, maxy, short(0), 20),
|
2006-05-22 16:14:50 +00:00
|
|
|
GUI_ID(FGCLASS_PROPERTYLIST),
|
2006-05-22 14:34:20 +00:00
|
|
|
_curr(start),
|
|
|
|
_return(0),
|
|
|
|
_entries(0),
|
2006-06-03 11:20:19 +00:00
|
|
|
_num_entries(0),
|
Added highlighting system.
If /sim/highlighting/enabled is true, we highlight animated objects under the
pointer, and also highlight other objects that are animated by the same or
related properties.
The intent here is to be able to give a visual indication of what cockpit
controls do or what cockpit controls affect particular aircraft objects - for
example moving the pointer over the flaps will highlight the flaps and also
highlight any controls or rotary indicators in the cockpit that are associated
with the flaps.
To make this work, we have to discover associations between properties. This
is currently done for YASim (e.g. associations between /controls/flight/flaps
and /surface-positions/flap-pos-norm) and autopilot filters (e.g. with
the 777, digital filters associate /controls/flight/rudder-nul with
/fcs/fbw/yaw/rudder-ratio-out). We don't currently gather associations between
properties in JSBSim
We also detect associations between dialogs, menus and keypresses and
properties, which is used to populate /sim/highlighting/current with
information about dialogs, menus and keypresses that are associated with the
currently highlighted nodes' properties.
Details:
src/GUI/Highlight.cxx
src/GUI/Highlight.hxx
src/GUI/CMakeLists.txt
src/Main/fg_init.cxx
New subsystem called 'highlight', with support for registering and
recovering links between menus, dialogs, keypresses and OSG node
animations.
Provides a function Highlight::highlight_nodes() which highlights
related nodes using internal NodeHighlighting class, and populates
/sim/highlighting/current with information about related dialogs, menus and
keypresses.
The NodeHighlighting class works by making nodes use an alternative
StateSet which shows up as a distinct material on screen. We remember each
highlighted node's original StateSet so that we can un-highlight. We update
the material parameters using a listener for /sim/highlighting/material,
which allows some control over the appearence of highlighted nodes.
src/FDM/flight.cxx
src/FDM/flight.hxx
Added virtual method FGInterface::property_associations() which returns
property associations from the FDM. Default implementation returns empty
set. Implemented in YASim, but not (yet) in JSBSim. Uses a simple function
pointer at the moment to avoid requring FDMs to use recent C++ features.
src/FDM/YASim/FGFDM.cpp
src/FDM/YASim/FGFDM.hpp
src/FDM/YASim/YASim.cxx
src/FDM/YASim/YASim.hxx
Gathers information about property associations on startup such as
/controls/flight/flaps => /surface-positions/flap-pos-norm, then
YASim::property_associations() overrides default implementation to return
these associations.
src/Autopilot/analogcomponent.cxx
src/Autopilot/analogcomponent.hxx
src/Autopilot/digitalfilter.cxx
src/Autopilot/inputvalue.cxx
src/Autopilot/inputvalue.hxx
Filters now gather information about their input/output properties and
register with Highlight::add_property_property(). For example this makes
highlighting work on the 777, where pilot controls affect control surfaces
only via filters.
src/GUI/new_gui.cxx
Scan menus, keypresses and dialogs and register associations with
Highlight::add_*().
src/GUI/property_list.cxx
src/GUI/property_list.hxx
src/GUI/FGPUIDialog.cxx
Added <readonly> flag to property-list. If set, we don't show .. or . items
and don't respond to mouse/keyboard.
Used by fgdata's new Highlighting dialogue.
src/Model/acmodel.cxx
src/Model/acmodel.hxx
Visit the user aircraft's scene graph when it is loaded, gathering
information about osg::Node's that are animated by properties, and register
these associations with Highlight::add_property_node().
src/Viewer/renderer.cxx
When scanning for pick highlights, use Highlight::highlight_nodes() to
highlight animated objects under the pointer and related objects.
2021-10-05 21:25:08 +00:00
|
|
|
_verbose(false),
|
|
|
|
_readonly(readonly)
|
2006-05-22 14:34:20 +00:00
|
|
|
{
|
|
|
|
_list_box->setUserData(this);
|
Added highlighting system.
If /sim/highlighting/enabled is true, we highlight animated objects under the
pointer, and also highlight other objects that are animated by the same or
related properties.
The intent here is to be able to give a visual indication of what cockpit
controls do or what cockpit controls affect particular aircraft objects - for
example moving the pointer over the flaps will highlight the flaps and also
highlight any controls or rotary indicators in the cockpit that are associated
with the flaps.
To make this work, we have to discover associations between properties. This
is currently done for YASim (e.g. associations between /controls/flight/flaps
and /surface-positions/flap-pos-norm) and autopilot filters (e.g. with
the 777, digital filters associate /controls/flight/rudder-nul with
/fcs/fbw/yaw/rudder-ratio-out). We don't currently gather associations between
properties in JSBSim
We also detect associations between dialogs, menus and keypresses and
properties, which is used to populate /sim/highlighting/current with
information about dialogs, menus and keypresses that are associated with the
currently highlighted nodes' properties.
Details:
src/GUI/Highlight.cxx
src/GUI/Highlight.hxx
src/GUI/CMakeLists.txt
src/Main/fg_init.cxx
New subsystem called 'highlight', with support for registering and
recovering links between menus, dialogs, keypresses and OSG node
animations.
Provides a function Highlight::highlight_nodes() which highlights
related nodes using internal NodeHighlighting class, and populates
/sim/highlighting/current with information about related dialogs, menus and
keypresses.
The NodeHighlighting class works by making nodes use an alternative
StateSet which shows up as a distinct material on screen. We remember each
highlighted node's original StateSet so that we can un-highlight. We update
the material parameters using a listener for /sim/highlighting/material,
which allows some control over the appearence of highlighted nodes.
src/FDM/flight.cxx
src/FDM/flight.hxx
Added virtual method FGInterface::property_associations() which returns
property associations from the FDM. Default implementation returns empty
set. Implemented in YASim, but not (yet) in JSBSim. Uses a simple function
pointer at the moment to avoid requring FDMs to use recent C++ features.
src/FDM/YASim/FGFDM.cpp
src/FDM/YASim/FGFDM.hpp
src/FDM/YASim/YASim.cxx
src/FDM/YASim/YASim.hxx
Gathers information about property associations on startup such as
/controls/flight/flaps => /surface-positions/flap-pos-norm, then
YASim::property_associations() overrides default implementation to return
these associations.
src/Autopilot/analogcomponent.cxx
src/Autopilot/analogcomponent.hxx
src/Autopilot/digitalfilter.cxx
src/Autopilot/inputvalue.cxx
src/Autopilot/inputvalue.hxx
Filters now gather information about their input/output properties and
register with Highlight::add_property_property(). For example this makes
highlighting work on the 777, where pilot controls affect control surfaces
only via filters.
src/GUI/new_gui.cxx
Scan menus, keypresses and dialogs and register associations with
Highlight::add_*().
src/GUI/property_list.cxx
src/GUI/property_list.hxx
src/GUI/FGPUIDialog.cxx
Added <readonly> flag to property-list. If set, we don't show .. or . items
and don't respond to mouse/keyboard.
Used by fgdata's new Highlighting dialogue.
src/Model/acmodel.cxx
src/Model/acmodel.hxx
Visit the user aircraft's scene graph when it is loaded, gathering
information about osg::Node's that are animated by properties, and register
these associations with Highlight::add_property_node().
src/Viewer/renderer.cxx
When scanning for pick highlights, use Highlight::highlight_nodes() to
highlight animated objects under the pointer and related objects.
2021-10-05 21:25:08 +00:00
|
|
|
if (!_readonly) _list_box->setCallback(handle_select);
|
2006-05-22 14:34:20 +00:00
|
|
|
_list_box->setValue(0);
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PropertyList::~PropertyList()
|
|
|
|
{
|
2006-05-24 09:42:10 +00:00
|
|
|
delete_arrays();
|
2006-05-22 14:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PropertyList::delete_arrays()
|
|
|
|
{
|
|
|
|
if (!_entries)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (int i = 0; i < _num_entries; i++)
|
|
|
|
delete[] _entries[i];
|
|
|
|
|
|
|
|
delete[] _entries;
|
|
|
|
delete[] _children;
|
|
|
|
_entries = 0;
|
|
|
|
_children = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PropertyList::handle_select(puObject *list_box)
|
|
|
|
{
|
|
|
|
PropertyList *prop_list = (PropertyList *)list_box->getUserData();
|
|
|
|
int selected = list_box->getIntegerValue();
|
2006-05-24 14:00:56 +00:00
|
|
|
int mod_ctrl = fgGetKeyModifiers() & KEYMOD_CTRL;
|
2007-05-03 19:00:55 +00:00
|
|
|
int mod_shift = fgGetKeyModifiers() & KEYMOD_SHIFT;
|
2006-05-22 14:34:20 +00:00
|
|
|
|
|
|
|
if (selected >= 0 && selected < prop_list->_num_entries) {
|
|
|
|
const char *src = prop_list->_entries[selected];
|
|
|
|
|
2006-06-03 11:20:19 +00:00
|
|
|
if (prop_list->_dot_files && (selected < 2)) {
|
2008-12-03 20:18:15 +00:00
|
|
|
if (src[0] == '.' && (src[1] == '\0' || src[1] == ' ')) {
|
2009-04-07 15:05:57 +00:00
|
|
|
if (mod_ctrl && mod_shift)
|
|
|
|
prop_list->_curr->fireValueChanged();
|
|
|
|
else if (mod_ctrl)
|
2007-05-07 14:29:40 +00:00
|
|
|
prop_list->toggleVerbosity();
|
2007-05-03 19:00:55 +00:00
|
|
|
else if (mod_shift)
|
2007-05-03 21:20:15 +00:00
|
|
|
dumpProperties(prop_list->_curr);
|
2006-05-22 14:34:20 +00:00
|
|
|
|
|
|
|
prop_list->update();
|
|
|
|
return;
|
|
|
|
|
|
|
|
} else if (!strcmp(src, "..")) {
|
|
|
|
SGPropertyNode *parent = prop_list->getCurrent()->getParent();
|
|
|
|
if (parent) {
|
|
|
|
if (mod_ctrl)
|
|
|
|
for (; parent->getParent(); parent = parent->getParent())
|
|
|
|
;
|
|
|
|
prop_list->setCurrent(parent);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// we know we're dealing with a regular entry, so convert
|
|
|
|
// it to an index into children[]
|
2006-06-03 11:20:19 +00:00
|
|
|
if (prop_list->_dot_files)
|
2006-05-22 14:34:20 +00:00
|
|
|
selected -= 2;
|
|
|
|
|
2006-05-24 09:42:10 +00:00
|
|
|
SGPropertyNode_ptr child = prop_list->_children[selected].node;
|
2006-05-22 14:34:20 +00:00
|
|
|
|
|
|
|
// check if it's a directory
|
|
|
|
if (child->nChildren()) {
|
2006-05-24 21:02:52 +00:00
|
|
|
prop_list->setTopItem(0);
|
2006-05-22 14:34:20 +00:00
|
|
|
prop_list->setCurrent(child);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// it is a regular property
|
2009-07-15 23:15:17 +00:00
|
|
|
if (child->getType() == simgear::props::BOOL && mod_ctrl) {
|
2006-05-22 14:34:20 +00:00
|
|
|
child->setBoolValue(!child->getBoolValue());
|
2006-05-23 21:35:38 +00:00
|
|
|
prop_list->update(true);
|
2006-05-22 14:34:20 +00:00
|
|
|
} else
|
|
|
|
prop_list->publish(child);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
// the user clicked on blank screen
|
2006-05-23 21:35:38 +00:00
|
|
|
prop_list->update(true);
|
2006-05-22 14:34:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PropertyList::update(bool restore_pos)
|
|
|
|
{
|
|
|
|
int pi;
|
|
|
|
|
|
|
|
delete_arrays();
|
|
|
|
_num_entries = (int)_curr->nChildren();
|
|
|
|
|
|
|
|
// instantiate string objects and add [.] and [..] for subdirs
|
Added highlighting system.
If /sim/highlighting/enabled is true, we highlight animated objects under the
pointer, and also highlight other objects that are animated by the same or
related properties.
The intent here is to be able to give a visual indication of what cockpit
controls do or what cockpit controls affect particular aircraft objects - for
example moving the pointer over the flaps will highlight the flaps and also
highlight any controls or rotary indicators in the cockpit that are associated
with the flaps.
To make this work, we have to discover associations between properties. This
is currently done for YASim (e.g. associations between /controls/flight/flaps
and /surface-positions/flap-pos-norm) and autopilot filters (e.g. with
the 777, digital filters associate /controls/flight/rudder-nul with
/fcs/fbw/yaw/rudder-ratio-out). We don't currently gather associations between
properties in JSBSim
We also detect associations between dialogs, menus and keypresses and
properties, which is used to populate /sim/highlighting/current with
information about dialogs, menus and keypresses that are associated with the
currently highlighted nodes' properties.
Details:
src/GUI/Highlight.cxx
src/GUI/Highlight.hxx
src/GUI/CMakeLists.txt
src/Main/fg_init.cxx
New subsystem called 'highlight', with support for registering and
recovering links between menus, dialogs, keypresses and OSG node
animations.
Provides a function Highlight::highlight_nodes() which highlights
related nodes using internal NodeHighlighting class, and populates
/sim/highlighting/current with information about related dialogs, menus and
keypresses.
The NodeHighlighting class works by making nodes use an alternative
StateSet which shows up as a distinct material on screen. We remember each
highlighted node's original StateSet so that we can un-highlight. We update
the material parameters using a listener for /sim/highlighting/material,
which allows some control over the appearence of highlighted nodes.
src/FDM/flight.cxx
src/FDM/flight.hxx
Added virtual method FGInterface::property_associations() which returns
property associations from the FDM. Default implementation returns empty
set. Implemented in YASim, but not (yet) in JSBSim. Uses a simple function
pointer at the moment to avoid requring FDMs to use recent C++ features.
src/FDM/YASim/FGFDM.cpp
src/FDM/YASim/FGFDM.hpp
src/FDM/YASim/YASim.cxx
src/FDM/YASim/YASim.hxx
Gathers information about property associations on startup such as
/controls/flight/flaps => /surface-positions/flap-pos-norm, then
YASim::property_associations() overrides default implementation to return
these associations.
src/Autopilot/analogcomponent.cxx
src/Autopilot/analogcomponent.hxx
src/Autopilot/digitalfilter.cxx
src/Autopilot/inputvalue.cxx
src/Autopilot/inputvalue.hxx
Filters now gather information about their input/output properties and
register with Highlight::add_property_property(). For example this makes
highlighting work on the 777, where pilot controls affect control surfaces
only via filters.
src/GUI/new_gui.cxx
Scan menus, keypresses and dialogs and register associations with
Highlight::add_*().
src/GUI/property_list.cxx
src/GUI/property_list.hxx
src/GUI/FGPUIDialog.cxx
Added <readonly> flag to property-list. If set, we don't show .. or . items
and don't respond to mouse/keyboard.
Used by fgdata's new Highlighting dialogue.
src/Model/acmodel.cxx
src/Model/acmodel.hxx
Visit the user aircraft's scene graph when it is loaded, gathering
information about osg::Node's that are animated by properties, and register
these associations with Highlight::add_property_node().
src/Viewer/renderer.cxx
When scanning for pick highlights, use Highlight::highlight_nodes() to
highlight animated objects under the pointer and related objects.
2021-10-05 21:25:08 +00:00
|
|
|
if (_readonly || !_curr->getParent()) {
|
2006-05-22 14:34:20 +00:00
|
|
|
_entries = new char*[_num_entries + 1];
|
|
|
|
pi = 0;
|
2006-06-03 11:20:19 +00:00
|
|
|
_dot_files = false;
|
2006-05-22 14:34:20 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
_num_entries += 2; // for . and ..
|
|
|
|
_entries = new char*[_num_entries + 1];
|
|
|
|
|
2008-12-03 20:18:15 +00:00
|
|
|
_entries[0] = new char[16];
|
|
|
|
strcpy(_entries[0], _verbose ? ". [verbose]" : ".");
|
2006-05-22 14:34:20 +00:00
|
|
|
|
|
|
|
_entries[1] = new char[3];
|
|
|
|
strcpy(_entries[1], "..");
|
|
|
|
|
|
|
|
pi = 2;
|
2006-06-03 11:20:19 +00:00
|
|
|
_dot_files = true;
|
2006-05-22 14:34:20 +00:00
|
|
|
}
|
|
|
|
|
2006-05-23 21:35:38 +00:00
|
|
|
int i;
|
2006-05-22 14:34:20 +00:00
|
|
|
_num_children = _curr->nChildren();
|
2006-05-24 09:42:10 +00:00
|
|
|
_children = new NodeData[_num_children];
|
2006-05-22 14:34:20 +00:00
|
|
|
for (i = 0; i < _num_children; i++)
|
2006-05-24 09:42:10 +00:00
|
|
|
_children[i].node = _curr->getChild(i);
|
2006-05-22 14:34:20 +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++, pi++) {
|
2007-05-07 14:29:40 +00:00
|
|
|
_children[i].text = &_entries[pi];
|
|
|
|
_entries[pi] = 0; // make it deletable
|
|
|
|
updateTextForEntry(_children[i]);
|
|
|
|
_children[i].setListener(this);
|
2006-05-22 14:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_entries[_num_entries] = 0;
|
|
|
|
|
|
|
|
int top = getTopItem();
|
|
|
|
newList(_entries);
|
|
|
|
if (restore_pos)
|
|
|
|
setTopItem(top);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-07 14:29:40 +00:00
|
|
|
void PropertyList::updateTextForEntry(NodeData& data)
|
2006-05-22 14:34:20 +00:00
|
|
|
{
|
2009-07-17 12:54:12 +00:00
|
|
|
using namespace simgear;
|
2007-05-07 14:29:40 +00:00
|
|
|
SGPropertyNode *node = data.node;
|
2006-05-22 14:34:20 +00:00
|
|
|
stdString name = node->getDisplayName(true);
|
|
|
|
stdString type = getValueTypeString(node);
|
|
|
|
stdString value = node->getStringValue();
|
|
|
|
|
2007-05-07 14:29:40 +00:00
|
|
|
std::ostringstream line;
|
|
|
|
line << name;
|
|
|
|
|
|
|
|
int children = node->nChildren();
|
2019-03-03 11:56:52 +00:00
|
|
|
if (children) {
|
2007-05-07 14:29:40 +00:00
|
|
|
line << '/';
|
2019-03-03 11:56:52 +00:00
|
|
|
if (_verbose) {
|
|
|
|
const SGPropertyNode* id = node->getChild("id");
|
|
|
|
const SGPropertyNode* name = node->getChild("name");
|
|
|
|
if (id || name) {
|
|
|
|
line << " (";
|
|
|
|
if (id) {
|
|
|
|
line << "id: " << id->getStringValue();
|
|
|
|
if (name != NULL)
|
|
|
|
line << ", ";
|
|
|
|
} else if (name) {
|
|
|
|
line << "name: " << name->getStringValue();
|
|
|
|
}
|
|
|
|
line << ")";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-19 01:16:30 +00:00
|
|
|
if (node->hasValue()) {
|
2009-07-17 12:54:12 +00:00
|
|
|
if (node->getType() == props::STRING
|
|
|
|
|| node->getType() == props::UNSPECIFIED)
|
2007-05-07 14:29:40 +00:00
|
|
|
sanitize(value);
|
|
|
|
|
|
|
|
line << " = '" << value << "' (" << type;
|
|
|
|
|
|
|
|
if (_verbose) {
|
|
|
|
stdString ext;
|
|
|
|
if (!node->getAttribute(SGPropertyNode::READ))
|
|
|
|
ext += 'r';
|
|
|
|
if (!node->getAttribute(SGPropertyNode::WRITE))
|
|
|
|
ext += 'w';
|
|
|
|
if (node->getAttribute(SGPropertyNode::TRACE_READ))
|
|
|
|
ext += 'R';
|
|
|
|
if (node->getAttribute(SGPropertyNode::TRACE_WRITE))
|
|
|
|
ext += 'W';
|
|
|
|
if (node->getAttribute(SGPropertyNode::ARCHIVE))
|
|
|
|
ext += 'A';
|
|
|
|
if (node->getAttribute(SGPropertyNode::USERARCHIVE))
|
|
|
|
ext += 'U';
|
2011-06-12 18:31:56 +00:00
|
|
|
if (node->getAttribute(SGPropertyNode::PRESERVE))
|
|
|
|
ext += 'P';
|
2007-05-07 14:29:40 +00:00
|
|
|
if (node->isTied())
|
|
|
|
ext += 'T';
|
|
|
|
|
|
|
|
if (!ext.empty())
|
|
|
|
line << ", " << ext;
|
|
|
|
|
|
|
|
int num = node->nListeners();
|
|
|
|
if (data.listener)
|
|
|
|
num--;
|
2007-05-07 14:37:38 +00:00
|
|
|
if (num)
|
2007-05-07 14:29:40 +00:00
|
|
|
line << ", L" << num;
|
|
|
|
}
|
|
|
|
line << ')';
|
2006-05-22 14:34:20 +00:00
|
|
|
}
|
2011-06-12 18:31:56 +00:00
|
|
|
else
|
|
|
|
if ((_verbose)&&(node->getAttribute(SGPropertyNode::PRESERVE)))
|
|
|
|
{
|
|
|
|
// only preserve/protection flag matters for nodes without values
|
|
|
|
line << " (P)";
|
|
|
|
}
|
2006-05-22 14:34:20 +00:00
|
|
|
|
2007-05-07 14:29:40 +00:00
|
|
|
stdString out = line.str();
|
|
|
|
if (out.size() >= PUSTRING_MAX)
|
|
|
|
out.resize(PUSTRING_MAX - 1);
|
2006-05-22 14:34:20 +00:00
|
|
|
|
2007-05-07 14:29:40 +00:00
|
|
|
delete[] *data.text;
|
|
|
|
*data.text = new char[out.size() + 1];
|
|
|
|
strcpy(*data.text, out.c_str());
|
2006-05-22 14:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PropertyList::valueChanged(SGPropertyNode *nd)
|
|
|
|
{
|
|
|
|
for (int i = 0; i < _num_children; i++)
|
2006-05-24 09:42:10 +00:00
|
|
|
if (_children[i].node == nd) {
|
2007-05-07 14:29:40 +00:00
|
|
|
updateTextForEntry(_children[i]);
|
2006-05-22 14:34:20 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-24 21:02:52 +00:00
|
|
|
int PropertyList::nodeNameCompare(const void *p1, const void *p2)
|
2006-05-24 09:42:10 +00:00
|
|
|
{
|
2006-05-24 21:02:52 +00:00
|
|
|
const SGPropertyNode *n1 = (*(const NodeData *)p1).node;
|
|
|
|
const SGPropertyNode *n2 = (*(const NodeData *)p2).node;
|
2006-05-24 09:42:10 +00:00
|
|
|
|
2006-05-24 21:02:52 +00:00
|
|
|
int diff = strcmp(n1->getName(), n2->getName());
|
|
|
|
return diff ? diff : n1->getIndex() - n2->getIndex();
|
2006-05-24 09:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-22 14:34:20 +00:00
|
|
|
void PropertyList::setValue(const char *s)
|
2006-05-24 10:51:35 +00:00
|
|
|
{
|
|
|
|
try {
|
|
|
|
SGPropertyNode *p = fgGetNode(s, false);
|
|
|
|
if (p)
|
|
|
|
setCurrent(p);
|
|
|
|
else
|
|
|
|
throw stdString("node doesn't exist");
|
|
|
|
} catch (const stdString& m) {
|
2006-05-24 14:00:56 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_DEBUG, "property-list node '" << s << "': " << m);
|
2006-05-24 10:51:35 +00:00
|
|
|
}
|
2006-05-22 14:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-23 20:24:56 +00:00
|
|
|
void PropertyList::setCurrent(SGPropertyNode *p)
|
|
|
|
{
|
|
|
|
bool same = (_curr == p);
|
|
|
|
_return = _curr = p;
|
|
|
|
update(same);
|
|
|
|
if (!same)
|
|
|
|
publish(p);
|
|
|
|
}
|
|
|
|
|