Tim's examples
Pointers to Tim's implementation:
sNAKE: (Hit "reset" and open halo on a blue box, then use D(rag) halo item to move box.)
obj = {x: 15, y: 0};
always: { obj.y == obj.x*2 }
// then try to do
obj.x = 11
obj.y
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
pos = this.globalBounds().topRight().addXY(100, 20);
line = $part('Line', 'PartsBin/Basic').openInWorld(pos);
midP = $part('Ellipse', 'PartsBin/Basic').openInWorld(pos);
midP.setExtent(pt(10,10));
;(function() {
    return midP.getPosition().eqPt(line.bounds().center());
}).shouldBeTrue({line: line, midP: midP});
// Error: Constraint expression returned an object that does not respond to #enable
//
// IIRC I had a problem with lines and their bounds in constraint 
// because there was a layer in there somewhere -- Tim
// doit repeatidly to move line:
line.getControlPoint(0).moveBy(pt(10,0));
// cleanup
[line,midP].invoke('remove');
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$part('sNAKE', 'users/timfelgentreff/PartsBin').openInWorld();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$part('Thermometer', 'users/timfelgentreff/PartsBin').openInWorld();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
C/F converter: (Currently throws errors on label update)
$world.browseCode(null, null, "users.timfelgentreff.babelsberg.constraintinterpreter");
$world.browseCode(null, null, "users.timfelgentreff.babelsberg.deltablue_ext");
$world.browseCode(null, null, "users.timfelgentreff.babelsberg.cassowary_ext");
// tests (include code for examples):
$world.browseCode(null, null, "users.timfelgentreff.babelsberg.tests");
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Setting up a simple (delta blue) constraint:
Midpoint example, the first straightforward approach failed
2nd approach: we were able to "approximate" a line (it's endpoints)
pos = this.globalBounds().topRight().addXY(100, 20);
start = $part('Rectangle', 'PartsBin/Basic').openInWorld(pos);
end = $part('Rectangle', 'PartsBin/Basic').openInWorld(pos.addXY(100,100));
[start,end].invoke('applyStyle', {extent: pt(10,10)});
midP = $part('Ellipse', 'PartsBin/Basic').openInWorld(pos);
midP.setExtent(pt(20,20));
// ugly: we need a script to force render refresh
midP.addScript(function update() { this.setPosition(this.getPosition()); });
midP.startStepping(100, 'update') // this can be solved with an additional DeltaBlue constraint
                                  // see the C/F converter label update for code -- Tim
// constraint
always: {
    var center = start.getPosition().addPt(end.getPosition()).scaleBy(0.5);
    midP.getPosition().eqPt(center)
}
// move the start of the "line"
start.moveBy(pt(10,0));
// cleanup
[start,end,midP].invoke('remove');
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
bbb.defaultSolver = new ClSimplexSolver()
hand = $world.firstHand();
pos = hand.getPosition().addPt(pt(200, 0));
start = $part('Rectangle', 'PartsBin/Basic').openInWorld(pos);
end = $part('Rectangle', 'PartsBin/Basic').openInWorld(pos.addXY(100,100));
[start,end].invoke('applyStyle', {extent: pt(10,10)});
midP = $part('Ellipse', 'PartsBin/Basic').openInWorld(pos);
midP.setExtent(pt(20,20));
// ugly: we need a script to force render refresh
midP.addScript(function update() {
    this.setPosition(this.getPosition());
    start.setPosition(start.getPosition());
});
midP.startStepping(100, 'update') // this can be solved with an additional DeltaBlue constraint
                                  // see the C/F converter label update for code -- Tim
// constraint
always: {
    var center = start.getPosition().addPt(end.getPosition()).scaleBy(0.5);
    midP.getPosition().eqPt(center);
}
// start editing.
// first argument is the object to be edited, the second a list of accessors or fields
// note that in the JavaScript implementation, the accessor methods have to return a single value
// the Ruby version does not have this limitation (so we could write
//      bbb.edit(start, ["getPosition"])
// ), but I haven't ported that, yet.
editCallback = bbb.edit(start.getPosition(), ["x", "y"]);
this.onMouseMove = function (evt) {
    editCallback(evt.getPosition().addPt(pt(20, 20)));
}
// end edit by calling callback without values
editCallback();
editCallback = null;
// cleanup
this.onMouseMove = function (evt) {};
[start,end,midP].invoke('remove');
start = end = midP = hand = null;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Edit Constraints
Simple examples
Setup
We're going to use Cassowary in these examples
module('users.timfelgentreff.babelsberg.constraintinterpreter').load(true);
bbb.defaultSolver = new ClSimplexSolver();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Set world extent to lively.pt(1500.0,2000.0)