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
// is either a ghost (SGPropertyNode_ptr*) or a string (global property
// path), the second is a Nasal function, the optional third one a bool.
// If the bool is true, then the listener is executed initially. The
// path), the second is a Nasal function, the optional third one an integer.
// 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
// as argument to the removelistener() function.
naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
@ -921,11 +922,10 @@ naRef FGNasalSys::setListener(naContext c, int argc, naRef* args)
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,
gcSave(handler), _listenerId);
node->addChangeListener(nl, initial);
gcSave(handler), _listenerId, type);
node->addChangeListener(nl, type != 0);
_listener[_listenerId] = nl;
return naNum(_listenerId++);
@ -960,15 +960,21 @@ naRef FGNasalSys::removeListener(naContext c, int argc, naRef* args)
// FGNasalListener class.
FGNasalListener::FGNasalListener(SGPropertyNode_ptr node, naRef handler,
FGNasalSys* nasal, int key, int id) :
FGNasalSys* nasal, int key, int id,
int type) :
_node(node),
_handler(handler),
_gcKey(key),
_id(id),
_type(type),
_nas(nasal),
_active(0),
_dead(false)
_dead(false),
_first_call(true),
_last_int(0L),
_last_float(0.0)
{
unchanged(node);
}
FGNasalListener::~FGNasalListener()
@ -982,14 +988,51 @@ void FGNasalListener::valueChanged(SGPropertyNode* node)
// drop recursive listener calls
if(_active || _dead)
return;
if(_type == 2 && !_first_call && unchanged(node))
return;
SG_LOG(SG_NASAL, SG_DEBUG, "trigger listener #" << _id);
_active++;
_nas->_cmdArg = node;
_nas->call(_handler, naNil());
_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 {
public:
FGNasalListener(SGPropertyNode_ptr node, naRef handler,
FGNasalSys* nasal, int key, int id);
FGNasalSys* nasal, int key, int id, int type);
~FGNasalListener();
void valueChanged(SGPropertyNode* node);
bool unchanged(SGPropertyNode* node);
private:
friend class FGNasalSys;
@ -143,9 +144,14 @@ private:
naRef _handler;
int _gcKey;
int _id;
int _type;
FGNasalSys* _nas;
unsigned int _active;
bool _dead;
bool _first_call;
long _last_int;
double _last_float;
string _last_string;
};