Skip to content

Commit

Permalink
libdeng2|Refactor|Fixed: Improved Rules implementation
Browse files Browse the repository at this point in the history
Rules are now passed as argument by const references rather than
const pointers. This allows overriding arithmetic operators to easily
create OperatorRule instances.

The OperatorRule operators return a reference to a refless rule
instance that the caller is expected to take a reference to.

Added a Floor operator to OperatorRule.

Rules are also by default invalid after instantiation.

DelegateRules inform their source when they become invalid so that any
internal dependencies can be resolved. Fixes a problem with
RuleRectangles where invalidating a Width or Height would not cause
the Left/Right, Top/Bottom edges to also become invalid.
  • Loading branch information
skyjake committed Jan 31, 2013
1 parent 8093e14 commit 128a49d
Show file tree
Hide file tree
Showing 14 changed files with 270 additions and 108 deletions.
2 changes: 2 additions & 0 deletions doomsday/libdeng2/include/de/widgets/constantrule.h
Expand Up @@ -33,6 +33,8 @@ namespace de {
class DENG2_PUBLIC ConstantRule : public Rule
{
public:
ConstantRule();

ConstantRule(float constantValue);

/**
Expand Down
4 changes: 4 additions & 0 deletions doomsday/libdeng2/include/de/widgets/delegaterule.h
Expand Up @@ -47,6 +47,8 @@ class DENG2_PUBLIC DelegateRule : public ConstantRule
* @param id Delegate id.
*/
virtual void delegateUpdate(int id) = 0;

virtual void delegateInvalidation(int id) = 0;
};

public:
Expand All @@ -67,6 +69,8 @@ class DENG2_PUBLIC DelegateRule : public ConstantRule
*/
void setSource(ISource *source);

void invalidate();

protected:
~DelegateRule(); // Counted

Expand Down
59 changes: 56 additions & 3 deletions doomsday/libdeng2/include/de/widgets/operatorrule.h
Expand Up @@ -21,6 +21,7 @@
#define LIBDENG2_OPERATORRULE_H

#include "../Rule"
#include "../ConstantRule"

namespace de {

Expand All @@ -42,13 +43,14 @@ class DENG2_PUBLIC OperatorRule : public Rule
Multiply,
Divide,
Maximum,
Minimum
Minimum,
Floor
};

public:
OperatorRule(Operator op, Rule const *unary);
OperatorRule(Operator op, Rule const &unary);

OperatorRule(Operator op, Rule const *left, Rule const *right);
OperatorRule(Operator op, Rule const &left, Rule const &right);

protected:
~OperatorRule();
Expand All @@ -61,6 +63,57 @@ class DENG2_PUBLIC OperatorRule : public Rule
Rule const *_rightOperand;
};

inline OperatorRule &operator + (Rule const &left, int right) {
return *refless(new OperatorRule(OperatorRule::Sum, left, *refless(new ConstantRule(float(right)))));
}

inline OperatorRule &operator + (Rule const &left, float right) {
return *refless(new OperatorRule(OperatorRule::Sum, left, *refless(new ConstantRule(right))));
}

inline OperatorRule &operator + (Rule const &left, Rule const &right) {
return *refless(new OperatorRule(OperatorRule::Sum, left, right));
}

inline OperatorRule &operator - (Rule const &unary) {
return *refless(new OperatorRule(OperatorRule::Negate, unary));
}

inline OperatorRule &operator - (Rule const &left, int right) {
return *refless(new OperatorRule(OperatorRule::Subtract, left, *refless(new ConstantRule(float(right)))));
}

inline OperatorRule &operator - (Rule const &left, float right) {
return *refless(new OperatorRule(OperatorRule::Subtract, left, *refless(new ConstantRule(right))));
}

inline OperatorRule &operator - (Rule const &left, Rule const &right) {
return *refless(new OperatorRule(OperatorRule::Subtract, left, right));
}

inline OperatorRule &operator * (Rule const &left, float right) {
return *refless(new OperatorRule(OperatorRule::Multiply, left, *refless(new ConstantRule(right))));
}

inline OperatorRule &operator * (Rule const &left, Rule const &right) {
return *refless(new OperatorRule(OperatorRule::Multiply, left, right));
}

inline OperatorRule &operator / (Rule const &left, int right) {
return *refless(new OperatorRule(OperatorRule::Floor,
*refless(new OperatorRule(OperatorRule::Divide,
left,
*refless(new ConstantRule(right))))));
}

inline OperatorRule &operator / (Rule const &left, float right) {
return *refless(new OperatorRule(OperatorRule::Divide, left, *refless(new ConstantRule(right))));
}

inline OperatorRule &operator / (Rule const &left, Rule const &right) {
return *refless(new OperatorRule(OperatorRule::Divide, left, right));
}

} // namespace de

#endif // LIBDENG2_OPERATORRULE_H
22 changes: 16 additions & 6 deletions doomsday/libdeng2/include/de/widgets/rootwidget.h
Expand Up @@ -46,12 +46,12 @@ class DENG2_PUBLIC RootWidget : public Widget

Vector2i viewSize() const;

Rule const *viewLeft() const;
Rule const *viewRight() const;
Rule const *viewTop() const;
Rule const *viewBottom() const;
Rule const *viewWidth() const;
Rule const *viewHeight() const;
Rule const &viewLeft() const;
Rule const &viewRight() const;
Rule const &viewTop() const;
Rule const &viewBottom() const;
Rule const &viewWidth() const;
Rule const &viewHeight() const;

/**
* Sets the size of the view. All widgets in the tree are notified.
Expand Down Expand Up @@ -83,6 +83,16 @@ class DENG2_PUBLIC RootWidget : public Widget
bool processEvent(Event const *event);

void initialize();

/**
* Update the widget tree. Call this before drawing the widget tree so that
* the widgets may update their internal state for the current time.
*/
void update();

/**
* Draws the widget tree using the current time.
*/
void draw();

private:
Expand Down
16 changes: 11 additions & 5 deletions doomsday/libdeng2/include/de/widgets/rule.h
Expand Up @@ -47,18 +47,20 @@ class DENG2_PUBLIC Rule : public Counted, public DENG2_AUDIENCE_INTERFACE(RuleIn
DENG2_AUDIENCE(RuleInvalidation)

public:
Rule(float initialValue = 0);
Rule();

Rule(float initialValue);

/**
* Determines the rule's current value. If it has been marked invalid,
* the value is updated first (see update()).
*/
float value() const;
float value() const;

/**
* Marks the rule invalid, causing all dependent rules to be invalid, too.
*/
void invalidate();
virtual void invalidate();

/**
* Updates the rule with a valid value. Derived classes must call
Expand All @@ -81,13 +83,17 @@ class DENG2_PUBLIC Rule : public Counted, public DENG2_AUDIENCE_INTERFACE(RuleIn
* dependency becomes invalid, this rule will likewise become invalid.
* @a dependency will hold a reference to this rule.
*/
void dependsOn(Rule const *dependency);
void dependsOn(Rule const &dependency);

void dependsOn(Rule const *dependencyOrNull);

/**
* Unlinks rules. This rule will no longer depend on @a dependency.
* @a dependency will release its reference to this rule.
*/
void independentOf(Rule const *dependency);
void independentOf(Rule const &dependency);

void independentOf(Rule const *dependencyOrNull);

public:
/**
Expand Down
22 changes: 11 additions & 11 deletions doomsday/libdeng2/include/de/widgets/rulerectangle.h
Expand Up @@ -66,36 +66,36 @@ class DENG2_PUBLIC RuleRectangle : DENG2_OBSERVES(Clock, TimeChange)
* @param right Rule for the right coordinate.
* @param bottom Rule for the bottom coordinate.
*/
RuleRectangle(Rule const *left, Rule const *top, Rule const *right, Rule const *bottom);
RuleRectangle(Rule const &left, Rule const &top, Rule const &right, Rule const &bottom);

RuleRectangle(RuleRectangle const *rect);
RuleRectangle(RuleRectangle const &rect);

~RuleRectangle();

// Output rules.
Rule const *left() const;
Rule const *top() const;
Rule const *right() const;
Rule const *bottom() const;
Rule const *width() const;
Rule const *height() const;
Rule const &left() const;
Rule const &top() const;
Rule const &right() const;
Rule const &bottom() const;
Rule const &width() const;
Rule const &height() const;

/**
* Sets one of the input rules of the rectangle.
*
* @param inputRule InputRule to set.
* @param rule Rule to use as input. A reference is held.
*/
RuleRectangle &setInput(InputRule inputRule, Rule const *rule);
RuleRectangle &setInput(InputRule inputRule, Rule const &rule);

/**
* Returns an input rule.
*/
Rule const *inputRule(InputRule inputRule);
Rule const &inputRule(InputRule inputRule);

template <class RuleType>
RuleType const &inputRuleAs(InputRule input) {
RuleType const *r = dynamic_cast<RuleType const *>(inputRule(input));
RuleType const *r = dynamic_cast<RuleType const *>(&inputRule(input));
DENG2_ASSERT(r != 0);
return *r;
}
Expand Down
2 changes: 1 addition & 1 deletion doomsday/libdeng2/include/de/widgets/scalarrule.h
Expand Up @@ -38,7 +38,7 @@ class DENG2_PUBLIC ScalarRule : public Rule, DENG2_OBSERVES(Clock, TimeChange)

void set(float target, TimeDelta transition = 0);

void set(Rule const *target, TimeDelta transition = 0);
void set(Rule const &target, TimeDelta transition = 0);

/**
* Read-only access to the scalar animation.
Expand Down
5 changes: 5 additions & 0 deletions doomsday/libdeng2/src/widgets/constantrule.cpp
Expand Up @@ -22,6 +22,11 @@

namespace de {

ConstantRule::ConstantRule() : Rule(), _pendingValue(0)
{
// No valid value defined.
}

ConstantRule::ConstantRule(float constantValue)
: Rule(constantValue), _pendingValue(constantValue)
{}
Expand Down
19 changes: 15 additions & 4 deletions doomsday/libdeng2/src/widgets/delegaterule.cpp
Expand Up @@ -22,10 +22,8 @@
namespace de {

DelegateRule::DelegateRule(ISource &source, int delegateId)
: ConstantRule(0), _source(&source), _delegateId(delegateId)
{
invalidate();
}
: ConstantRule(), _source(&source), _delegateId(delegateId)
{}

DelegateRule::~DelegateRule()
{}
Expand All @@ -50,4 +48,17 @@ void DelegateRule::setSource(DelegateRule::ISource *source)
_source = source;
}

void DelegateRule::invalidate()
{
if(isValid())
{
Rule::invalidate();

if(_source)
{
_source->delegateInvalidation(_delegateId);
}
}
}

} // namespace de
14 changes: 8 additions & 6 deletions doomsday/libdeng2/src/widgets/operatorrule.cpp
Expand Up @@ -22,24 +22,22 @@

namespace de {

OperatorRule::OperatorRule(Operator op, Rule const *unary)
: Rule(), _operator(op), _leftOperand(unary), _rightOperand(0)
OperatorRule::OperatorRule(Operator op, Rule const &unary)
: Rule(), _operator(op), _leftOperand(&unary), _rightOperand(0)
{
DENG2_ASSERT(_leftOperand != 0);

dependsOn(_leftOperand);
invalidate();
}

OperatorRule::OperatorRule(Operator op, Rule const *left, Rule const *right)
: Rule(), _operator(op), _leftOperand(left), _rightOperand(right)
OperatorRule::OperatorRule(Operator op, Rule const &left, Rule const &right)
: Rule(), _operator(op), _leftOperand(&left), _rightOperand(&right)
{
DENG2_ASSERT(_leftOperand != 0);
DENG2_ASSERT(_rightOperand != 0);

dependsOn(_leftOperand);
dependsOn(_rightOperand);
invalidate();
}

OperatorRule::~OperatorRule()
Expand Down Expand Up @@ -94,6 +92,10 @@ void OperatorRule::update()
case Minimum:
v = de::min(leftValue, rightValue);
break;

case Floor:
v = de::floor(leftValue);
break;
}

setValue(v);
Expand Down

0 comments on commit 128a49d

Please sign in to comment.