// 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 Expression extends EquationMember { final List terms; final double constant; double get value => terms.fold(constant, (value, term) => value + term.value); Expression(this.terms, this.constant); 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.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.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.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 >=(EquationMember value) => _createConstraint(value, Relation.greaterThanOrEqualTo); Constraint operator <=(EquationMember value) => _createConstraint(value, Relation.lessThanOrEqualTo); operator ==(EquationMember value) => _createConstraint(value, Relation.equalTo); Expression operator +(EquationMember m) { if (m is ConstantMember) { return new Expression(new List.from(this.terms), this.constant + m.value); } if (m is Variable) { return new Expression( new List.from(this.terms)..add(new Term(m, 1.0)), this.constant); } if (m is Term) { return new Expression(new List.from(this.terms)..add(m), this.constant); } if (m is Expression) { return new Expression(new List.from(this.terms)..addAll(m.terms), this.constant + m.constant); } assert(false); return null; } Expression operator -(EquationMember m) { if (m is ConstantMember) { return new Expression(new List.from(this.terms), this.constant - m.value); } if (m is Variable) { return new Expression( new List.from(this.terms)..add(new Term(m, -1.0)), this.constant); } if (m is Term) { return new Expression(new List.from(this.terms) ..add(new Term(m.variable, -m.coefficient)), this.constant); } if (m is Expression) { var copiedTerms = new List.from(this.terms); m.terms.forEach( (t) => copiedTerms.add(new Term(t.variable, -t.coefficient))); return new Expression(copiedTerms, this.constant - m.constant); } assert(false); return null; } EquationMember operator *(double m) { var terms = this.terms.fold(new List(), (list, term) => list ..add(new Term(term.variable, term.coefficient * m))); return new Expression(terms, this.constant); } // TODO(csg): Figure out how to dry this up. EquationMember operator /(double m) { var terms = this.terms.fold(new List(), (list, term) => list ..add(new Term(term.variable, term.coefficient / m))); return new Expression(terms, this.constant); } }