1
0
Fork 0

add new listener type: setlistner(<prop>, <func> [, <type=0>]);

0 -> trigger whenever property is written to (even if it's the old value; default)
1 -> like 0, but also trigger the function initially
2 -> trigger initially, but then only on changes
This commit is contained in:
mfranz 2007-10-12 17:24:43 +00:00
parent 44b8f3704a
commit c979136e5b
2 changed files with 58 additions and 9 deletions

View file

@ -896,8 +896,9 @@ int FGNasalSys::_listenerId = 0;
// setlistener(property, func, bool) extension function. The first argument // setlistener(property, func, bool) extension function. The first argument
// is either a ghost (SGPropertyNode_ptr*) or a string (global property // is either a ghost (SGPropertyNode_ptr*) or a string (global property
// path), the second is a Nasal function, the optional third one a bool. // path), the second is a Nasal function, the optional third one an integer.
// If the bool is true, then the listener is executed initially. The // If it is 1, then the listener is executed initially. If it's 2, then
// the listener is only triggered when the node value actually changed. The
// setlistener() function returns a unique id number, that can be used // setlistener() function returns a unique id number, that can be used
// as argument to the removelistener() function. // as argument to the removelistener() function.
naRef FGNasalSys::setListener(naContext c, int argc, naRef* args) naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
@ -921,11 +922,10 @@ naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
return naNil(); return naNil();
} }
bool initial = argc > 2 && naTrue(args[2]); int type = argc > 2 && naIsNum(args[2]) ? args[2].num : 0;
FGNasalListener *nl = new FGNasalListener(node, handler, this, FGNasalListener *nl = new FGNasalListener(node, handler, this,
gcSave(handler), _listenerId); gcSave(handler), _listenerId, type);
node->addChangeListener(nl, initial); node->addChangeListener(nl, type != 0);
_listener[_listenerId] = nl; _listener[_listenerId] = nl;
return naNum(_listenerId++); return naNum(_listenerId++);
@ -960,15 +960,21 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
// FGNasalListener class. // FGNasalListener class.
FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler, FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler,
FGNasalSys* nasal, int key, int id) : FGNasalSys* nasal, int key, int id,
int type) :
_node(node), _node(node),
_handler(handler), _handler(handler),
_gcKey(key), _gcKey(key),
_id(id), _id(id),
_type(type),
_nas(nasal), _nas(nasal),
_active(0), _active(0),
_dead(false) _dead(false),
_first_call(true),
_last_int(0L),
_last_float(0.0)
{ {
unchanged(node);
} }
FGNasalListener::~FGNasalListener() FGNasalListener::~FGNasalListener()
@ -982,14 +988,51 @@ void FGNasalListener::valueChanged(SGPropertyNode* node)
// drop recursive listener calls // drop recursive listener calls
if(_active || _dead) if(_active || _dead)
return; return;
if(_type == 2 && !_first_call && unchanged(node))
return;
SG_LOG(SG_NASAL, SG_DEBUG, "trigger listener #" << _id); SG_LOG(SG_NASAL, SG_DEBUG, "trigger listener #" << _id);
_active++; _active++;
_nas->_cmdArg = node; _nas->_cmdArg = node;
_nas->call(_handler, naNil()); _nas->call(_handler, naNil());
_active--; _active--;
_first_call = false;
} }
bool FGNasalListener::unchanged(SGPropertyNode* node)
{
SGPropertyNode::Type type = node->getType();
if(type == SGPropertyNode::NONE) return true;
if(type == SGPropertyNode::UNSPECIFIED) return false;
bool result;
switch(type) {
case SGPropertyNode::BOOL:
case SGPropertyNode::INT:
case SGPropertyNode::LONG:
{
long l = node->getLongValue();
result = l == _last_int;
_last_int = l;
return result;
}
case SGPropertyNode::FLOAT:
case SGPropertyNode::DOUBLE:
{
double d = node->getDoubleValue();
result = d == _last_float;
_last_float = d;
return result;
}
default:
{
string s = node->getStringValue();
result = s == _last_string;
_last_string = s;
return result;
}
}
}

View file

@ -132,10 +132,11 @@ private:
class FGNasalListener : public SGPropertyChangeListener { class FGNasalListener : public SGPropertyChangeListener {
public: public:
FGNasalListener(SGPropertyNode_ptr node, naRef handler, FGNasalListener(SGPropertyNode_ptr node, naRef handler,
FGNasalSys* nasal, int key, int id); FGNasalSys* nasal, int key, int id, int type);
~FGNasalListener(); ~FGNasalListener();
void valueChanged(SGPropertyNode* node); void valueChanged(SGPropertyNode* node);
bool unchanged(SGPropertyNode* node);
private: private:
friend class FGNasalSys; friend class FGNasalSys;
@ -143,9 +144,14 @@ private:
naRef _handler; naRef _handler;
int _gcKey; int _gcKey;
int _id; int _id;
int _type;
FGNasalSys* _nas; FGNasalSys* _nas;
unsigned int _active; unsigned int _active;
bool _dead; bool _dead;
bool _first_call;
long _last_int;
double _last_float;
string _last_string;
}; };