From bc4bab3f797f715e66652d61bf368fb2e04d9969 Mon Sep 17 00:00:00 2001 From: skyjake Date: Tue, 22 Jan 2013 17:39:17 +0200 Subject: [PATCH] Shell|libdeng2: Working on rules Todo: Rule dependencies and ownership need to be reference-counted. --- .../include/de/widgets/rectanglerule.h | 2 +- doomsday/libdeng2/include/de/widgets/rule.h | 8 ++- .../libdeng2/include/de/widgets/scalarrule.h | 15 ++++- .../libdeng2/src/widgets/rectanglerule.cpp | 2 +- doomsday/libdeng2/src/widgets/rule.cpp | 29 +++++++-- doomsday/libdeng2/src/widgets/scalarrule.cpp | 65 ++++++++++++++++--- .../tools/shell/shell-text/src/cursesapp.cpp | 2 + .../shell/shell-text/src/cursestextcanvas.cpp | 2 + .../tools/shell/shell-text/src/logwidget.cpp | 1 - .../tools/shell/shell-text/src/shellapp.cpp | 5 +- 10 files changed, 109 insertions(+), 22 deletions(-) diff --git a/doomsday/libdeng2/include/de/widgets/rectanglerule.h b/doomsday/libdeng2/include/de/widgets/rectanglerule.h index 37a9614f25..7d148f1269 100644 --- a/doomsday/libdeng2/include/de/widgets/rectanglerule.h +++ b/doomsday/libdeng2/include/de/widgets/rectanglerule.h @@ -113,7 +113,7 @@ class RectangleRule : public Rule * (1, 1) to the bottom right. * @param transition Transition time for the change. */ - void setAnchorPoint(Vector2f const &normalizedPoint, Time::Delta const &transition = 0); + void setAnchorPoint(Vector2f const &normalizedPoint, TimeDelta const &transition = 0); /** * Returns the current rectangle as defined by the input rules. diff --git a/doomsday/libdeng2/include/de/widgets/rule.h b/doomsday/libdeng2/include/de/widgets/rule.h index bce641ac1e..2e3fbc74da 100644 --- a/doomsday/libdeng2/include/de/widgets/rule.h +++ b/doomsday/libdeng2/include/de/widgets/rule.h @@ -64,15 +64,19 @@ class Rule : public QObject */ virtual void update(); + bool isValid() const; + protected: /** * Links rules together. This rule will depend on @a dependency. */ void dependsOn(Rule const *dependency); + void independentOf(Rule const *dependency); + void addDependent(Rule *rule); void removeDependent(Rule *rule); - void setValue(float value, bool markValid = true); + void setValue(float value); float cachedValue() const; @@ -91,6 +95,8 @@ class Rule : public QObject */ virtual void dependencyReplaced(Rule const *oldRule, Rule const *newRule); + void invalidateSilently(); + public slots: void invalidate(); diff --git a/doomsday/libdeng2/include/de/widgets/scalarrule.h b/doomsday/libdeng2/include/de/widgets/scalarrule.h index 1df868141e..719bbf4cd5 100644 --- a/doomsday/libdeng2/include/de/widgets/scalarrule.h +++ b/doomsday/libdeng2/include/de/widgets/scalarrule.h @@ -37,7 +37,11 @@ class ScalarRule : public Rule public: explicit ScalarRule(float initialValue, QObject *parent = 0); - void set(float value, Time::Delta transition = 0); + void set(float target, TimeDelta transition = 0); + + void set(Rule const *target, TimeDelta transition = 0); + + void set(Rule *targetOwn, TimeDelta transition = 0); /** * Read-only access to the scalar animation. @@ -48,10 +52,17 @@ class ScalarRule : public Rule protected: void update(); + void dependencyReplaced(Rule const *oldRule, Rule const *newRule); + + void dismissTargetRule(); + +protected slots: + void timeChanged(); private: Animation _animation; - Time _validAt; + Rule const *_rule; + bool _ruleOwned; }; } // namespace de diff --git a/doomsday/libdeng2/src/widgets/rectanglerule.cpp b/doomsday/libdeng2/src/widgets/rectanglerule.cpp index d0a8699cbe..2cbdf53789 100644 --- a/doomsday/libdeng2/src/widgets/rectanglerule.cpp +++ b/doomsday/libdeng2/src/widgets/rectanglerule.cpp @@ -246,7 +246,7 @@ Rule const *RectangleRule::inputRule(InputRule inputRule) return d->ruleRef(inputRule).rule.constPtr; } -void RectangleRule::setAnchorPoint(Vector2f const &normalizedPoint, Time::Delta const &transition) +void RectangleRule::setAnchorPoint(Vector2f const &normalizedPoint, TimeDelta const &transition) { d->normalizedAnchorPoint.setValue(normalizedPoint, transition); invalidate(); diff --git a/doomsday/libdeng2/src/widgets/rule.cpp b/doomsday/libdeng2/src/widgets/rule.cpp index f961ae59f2..ffaa1d7bb2 100644 --- a/doomsday/libdeng2/src/widgets/rule.cpp +++ b/doomsday/libdeng2/src/widgets/rule.cpp @@ -45,6 +45,8 @@ float Rule::value() const // Force an update. const_cast(this)->update(); } + DENG2_ASSERT(_isValid); + return _value; } @@ -54,24 +56,30 @@ void Rule::update() _isValid = true; } +bool Rule::isValid() const +{ + return _isValid; +} + void Rule::dependencyReplaced(Rule const *, Rule const *) { // No dependencies. } +void Rule::invalidateSilently() +{ + _isValid = false; +} + float Rule::cachedValue() const { return _value; } -void Rule::setValue(float v, bool markValid) +void Rule::setValue(float v) { _value = v; - - if(markValid) - { - _isValid = true; - } + _isValid = true; } void Rule::transferDependencies(Rule *toRule) @@ -98,6 +106,13 @@ void Rule::dependsOn(Rule const *dependency) const_cast(dependency)->addDependent(this); } +void Rule::independentOf(Rule const *dependency) +{ + DENG2_ASSERT(dependency != 0); + + const_cast(dependency)->removeDependent(this); +} + void Rule::addDependent(Rule *rule) { DENG2_ASSERT(!_dependentRules.contains(rule)); @@ -122,7 +137,7 @@ void Rule::invalidate() { if(_isValid) { - _isValid = false; + invalidateSilently(); emit valueInvalidated(); } } diff --git a/doomsday/libdeng2/src/widgets/scalarrule.cpp b/doomsday/libdeng2/src/widgets/scalarrule.cpp index ba72672720..10d2d055bd 100644 --- a/doomsday/libdeng2/src/widgets/scalarrule.cpp +++ b/doomsday/libdeng2/src/widgets/scalarrule.cpp @@ -18,27 +18,76 @@ */ #include "de/ScalarRule" +#include "de/Clock" +#include namespace de { ScalarRule::ScalarRule(float initialValue, QObject *parent) - : Rule(initialValue, parent), _animation(initialValue) + : Rule(initialValue, parent), _animation(initialValue), _rule(0), _ruleOwned(false) {} -void ScalarRule::set(float value, de::Time::Delta transition) +void ScalarRule::set(float target, de::TimeDelta transition) { - _animation.setValue(value, transition); + dismissTargetRule(); + + connect(&_animation.clock(), SIGNAL(timeChanged()), this, SLOT(timeChanged())); + _animation.setValue(target, transition); invalidate(); } +void ScalarRule::set(Rule const *target, TimeDelta transition) +{ + set(target->value(), transition); + + _ruleOwned = false; + _rule = target; + dependsOn(_rule); +} + +void ScalarRule::set(Rule *targetOwn, TimeDelta transition) +{ + set(targetOwn->value(), transition); + + _ruleOwned = claim(targetOwn); + _rule = targetOwn; + dependsOn(_rule); +} + void ScalarRule::update() { - // Avoid repeated evaluation. - Time const now = Animation::currentTime(); - if(_validAt != now) + setValue(_animation); +} + +void ScalarRule::dependencyReplaced(Rule const *oldRule, Rule const *newRule) +{ + if(oldRule == _rule) + { + dismissTargetRule(); + oldRule = newRule; + } +} + +void ScalarRule::dismissTargetRule() +{ + if(_rule) + { + independentOf(_rule); + if(_ruleOwned) delete _rule; + _rule = 0; + } + _ruleOwned = false; +} + +void ScalarRule::timeChanged() +{ + if(!_animation.done() || cachedValue() != _animation.value()) + { + invalidate(); + } + if(_animation.done()) { - setValue(_animation, _animation.done()); - _validAt = now; + disconnect(this, SLOT(timeChanged())); } } diff --git a/doomsday/tools/shell/shell-text/src/cursesapp.cpp b/doomsday/tools/shell/shell-text/src/cursesapp.cpp index 9f4450e598..d62aa2177a 100644 --- a/doomsday/tools/shell/shell-text/src/cursesapp.cpp +++ b/doomsday/tools/shell/shell-text/src/cursesapp.cpp @@ -186,6 +186,8 @@ struct CursesApp::Instance qDebug() << "Got key" << QString("0x%1").arg(key, 0, 16).toAscii().constData(); } } + + rootWidget->draw(); } void windowWasResized() // called from signal handler diff --git a/doomsday/tools/shell/shell-text/src/cursestextcanvas.cpp b/doomsday/tools/shell/shell-text/src/cursestextcanvas.cpp index 0ea1a7edf2..f4c3087e5f 100644 --- a/doomsday/tools/shell/shell-text/src/cursestextcanvas.cpp +++ b/doomsday/tools/shell/shell-text/src/cursestextcanvas.cpp @@ -62,6 +62,8 @@ void CursesTextCanvas::show() } } + wmove(_window, 0, 0); + // Mark everything clean. TextCanvas::show(); diff --git a/doomsday/tools/shell/shell-text/src/logwidget.cpp b/doomsday/tools/shell/shell-text/src/logwidget.cpp index 987d631fe0..857c919ad1 100644 --- a/doomsday/tools/shell/shell-text/src/logwidget.cpp +++ b/doomsday/tools/shell/shell-text/src/logwidget.cpp @@ -17,7 +17,6 @@ */ #include "logwidget.h" -#include struct LogWidget::Instance { diff --git a/doomsday/tools/shell/shell-text/src/shellapp.cpp b/doomsday/tools/shell/shell-text/src/shellapp.cpp index de431907d8..7069924c2f 100644 --- a/doomsday/tools/shell/shell-text/src/shellapp.cpp +++ b/doomsday/tools/shell/shell-text/src/shellapp.cpp @@ -30,8 +30,11 @@ struct ShellApp::Instance { logWidget = new LogWidget; + ScalarRule *anim = new ScalarRule(0); + anim->set(5, 2); + logWidget->rule() - .setInput(RectangleRule::Left, new ConstantRule(0)) + .setInput(RectangleRule::Left, anim) .setInput(RectangleRule::Top, new ConstantRule(0)) .setInput(RectangleRule::Width, self.rootWidget().viewWidth()) .setInput(RectangleRule::Height, self.rootWidget().viewHeight());