Constraints can be setup directly from non-expression via operator overrides
diff --git a/lib/cassowary.dart b/lib/cassowary.dart index da634c0..39365bc 100644 --- a/lib/cassowary.dart +++ b/lib/cassowary.dart
@@ -10,3 +10,4 @@ part 'variable.dart'; part 'equation_member.dart'; part 'constant_member.dart'; +part 'solver.dart';
diff --git a/lib/constant_member.dart b/lib/constant_member.dart index 6e594ed..2443c0d 100644 --- a/lib/constant_member.dart +++ b/lib/constant_member.dart
@@ -8,6 +8,14 @@ double value = 0.0; ConstantMember(this.value); + Expression _asExpression() => new Expression([], this.value); + + Constraint operator >=(EquationMember m) => _asExpression() >= m; + + Constraint operator <=(EquationMember m) => _asExpression() <= m; + + operator ==(EquationMember m) => _asExpression() == m; + Expression operator +(EquationMember m) { if (m is ConstantMember) { return new Expression([], this.value + m.value);
diff --git a/lib/expression.dart b/lib/expression.dart index 237d154..a3b33c8 100644 --- a/lib/expression.dart +++ b/lib/expression.dart
@@ -12,18 +12,44 @@ Expression(this.terms, this.constant); - Constraint _createConstraint(double value, Relation relation) { - return new Constraint( - new Expression(this.terms, this.constant + value), relation); + Constraint _createConstraint( + EquationMember /* rhs */ value, Relation relation) { + if (value is ConstantMember) { + return new Constraint(new Expression( + new List.from(this.terms), this.constant - value.value), relation); + } + + if (value is Variable) { + var newTerms = new List<Term>.from(this.terms) + ..add(new Term(value, -1.0)); + return new Constraint(new Expression(newTerms, this.constant), relation); + } + + if (value is Term) { + var newTerms = new List<Term>.from(this.terms) + ..add(new Term(value.variable, -value.coefficient)); + return new Constraint(new Expression(newTerms, this.constant), relation); + } + + if (value is Expression) { + var newTerms = value.terms.fold(new List<Term>.from(this.terms), + (list, t) => list..add(new Term(t.variable, -t.coefficient))); + return new Constraint( + new Expression(newTerms, this.constant - value.constant), relation); + } + + assert(false); + return null; } - Constraint operator >=(double value) => - _createConstraint(-value, Relation.greaterThanOrEqualTo); + Constraint operator >=(EquationMember value) => + _createConstraint(value, Relation.greaterThanOrEqualTo); - Constraint operator <=(double value) => - _createConstraint(-value, Relation.lessThanOrEqualTo); + Constraint operator <=(EquationMember value) => + _createConstraint(value, Relation.lessThanOrEqualTo); - operator ==(double value) => _createConstraint(-value, Relation.equalTo); + operator ==(EquationMember value) => + _createConstraint(value, Relation.equalTo); Expression operator +(EquationMember m) { if (m is ConstantMember) {
diff --git a/lib/solver.dart b/lib/solver.dart new file mode 100644 index 0000000..9038887 --- /dev/null +++ b/lib/solver.dart
@@ -0,0 +1,17 @@ +// Copyright (c) 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +part of cassowary; + +class Solver { + bool addConstraint(Constraint c) { + return false; + } + + bool removeContraint(Constraint c) { + return false; + } + + Solver operator <<(Constraint c) => this..addConstraint(c); +}
diff --git a/lib/term.dart b/lib/term.dart index 460f903..410e724 100644 --- a/lib/term.dart +++ b/lib/term.dart
@@ -11,6 +11,15 @@ Term(this.variable, this.coefficient); + Expression _asExpression() => + new Expression([new Term(this.variable, this.coefficient)], 0.0); + + Constraint operator >=(EquationMember m) => _asExpression() >= m; + + Constraint operator <=(EquationMember m) => _asExpression() <= m; + + operator ==(EquationMember m) => _asExpression() == m; + Expression operator +(EquationMember m) { if (m is ConstantMember) { return new Expression([this], m.value);
diff --git a/lib/variable.dart b/lib/variable.dart index dbe9fa5..23a538c 100644 --- a/lib/variable.dart +++ b/lib/variable.dart
@@ -8,6 +8,14 @@ double value = 0.0; Variable(this.value); + Expression _asExpression() => new Expression([new Term(this, 1.0)], 0.0); + + Constraint operator >=(EquationMember m) => _asExpression() >= m; + + Constraint operator <=(EquationMember m) => _asExpression() <= m; + + operator ==(EquationMember m) => _asExpression() == m; + Expression operator +(EquationMember m) { if (m is ConstantMember) { return new Expression([new Term(this, 1.0)], m.value);
diff --git a/test/cassowary_test.dart b/test/cassowary_test.dart index 6853b1e..662e0df 100644 --- a/test/cassowary_test.dart +++ b/test/cassowary_test.dart
@@ -194,7 +194,7 @@ var left = new Variable(10.0); var right = new Variable(100.0); - var c = right - left >= 25.0; + var c = right - left >= CM(25.0); expect(c is Constraint, true); }); @@ -244,17 +244,17 @@ var left = new Variable(2.0); var right = new Variable(10.0); - var c1 = right - left >= 20.0; + var c1 = right - left >= CM(20.0); expect(c1 is Constraint, true); expect(c1.expression.constant, -20.0); expect(c1.relation, Relation.greaterThanOrEqualTo); - var c2 = (right - left == 30.0) as Constraint; + var c2 = (right - left == CM(30.0)) as Constraint; expect(c2 is Constraint, true); expect(c2.expression.constant, -30.0); expect(c2.relation, Relation.equalTo); - var c3 = right - left <= 30.0; + var c3 = right - left <= CM(30.0); expect(c3 is Constraint, true); expect(c3.expression.constant, -30.0); expect(c3.relation, Relation.lessThanOrEqualTo); @@ -264,10 +264,79 @@ var left = new Variable(2.0); var right = new Variable(10.0); - var c = (right - left >= 200.0) | 750.0; + var c = (right - left >= CM(200.0)) | 750.0; expect(c is Constraint, true); expect(c.expression.terms.length, 2); expect(c.expression.constant, -200.0); expect(c.priority, 750.0); }); + + test('solver', () { + var s = new Solver(); + + var left = new Variable(2.0); + var right = new Variable(100.0); + + var c1 = right - left >= CM(200.0); + var c2 = right + left >= CM(0.0); + + // TODO: Add assertions for this + s << c1 << c2; + }); + + test('constraint_complex', () { + var e = new Variable(200.0) - new Variable(100.0); + + // Constant + var c1 = e >= CM(50.0); + expect(c1 is Constraint, true); + expect(c1.expression.terms.length, 2); + expect(c1.expression.constant, -50.0); + + // Variable + var c2 = e >= new Variable(2.0); + expect(c2 is Constraint, true); + expect(c2.expression.terms.length, 3); + expect(c2.expression.constant, 0.0); + + // Term + var c3 = e >= new Term(new Variable(2.0), 1.0); + expect(c3 is Constraint, true); + expect(c3.expression.terms.length, 3); + expect(c3.expression.constant, 0.0); + + // Expression + var c4 = e >= new Expression([new Term(new Variable(2.0), 1.0)], 20.0); + expect(c4 is Constraint, true); + expect(c4.expression.terms.length, 3); + expect(c4.expression.constant, -20.0); + }); + + test('constraint_complex_non_exprs', () { + // Constant + var c1 = CM(100.0) >= CM(50.0); + expect(c1 is Constraint, true); + expect(c1.expression.terms.length, 0); + expect(c1.expression.constant, 50.0); + + // Variable + var c2 = new Variable(100.0) >= new Variable(2.0); + expect(c2 is Constraint, true); + expect(c2.expression.terms.length, 2); + expect(c2.expression.constant, 0.0); + + // Term + var t = new Term(new Variable(100.0), 1.0); + var c3 = t >= new Term(new Variable(2.0), 1.0); + expect(c3 is Constraint, true); + expect(c3.expression.terms.length, 2); + expect(c3.expression.constant, 0.0); + + // Expression + var e = new Expression([t], 0.0); + var c4 = e >= new Expression([new Term(new Variable(2.0), 1.0)], 20.0); + expect(c4 is Constraint, true); + expect(c4.expression.terms.length, 2); + expect(c4.expression.constant, -20.0); + }); }