PDA

View Full Version : Constraints with Variable Targets


antun
11-14-2003, 04:25 PM
Declarative constraints are very easy to use and powerful, but once you set the up you can't change what they depend on. Suppose you wanted to do
something like:


<view x="${targetview.x}" y="${targetview.y}" />


... and then change targetview?

To do this you can create a constraint using by associating a delegate with an event and a method. Then when you want to change the targetview, you unregister the event and register a new one:


<canvas>

<debug y="200"/>
<class name="dragger" bgcolor="green"
onmousedown="draggable.apply(); f.setAttribute('target', this)"
onmouseup="draggable.remove()"
width="40" height="40">
<dragstate name="draggable"/>
<resizestate name="resizer"/>
<view align="right" valign="bottom"
width="5" height="5" bgcolor="blue"
onmousedown="parent.resizer.apply()"
onmouseup="parent.resizer.remove()"/>
</class>

<class name="follower" opacity=".3" bgcolor="yellow"
width="30" height="30">
<attribute name="target" value="null" setter="settarget(target)"/>

<!--- keywords @private -->
<attribute name="xdel" value="null"/>
<attribute name="ydel" value="null"/>
<attribute name="widthdel" value="null"/>
<attribute name="heightdel" value="null"/>
<attribute name="ontarget" value="null"/>

<method name="settarget" args="t"> <![CDATA[
if (this['target'] && t != this.target) {
this.xdel.unregisterall();
this.ydel.unregisterall();
this.widthdel.unregisterall();
this.heightdel.unregisterall();
}
if (!this.xdel) this.xdel = new LzDelegate(this, "followx");
if (!this.ydel) this.ydel = new LzDelegate(this, "followy");
if (!this.widthdel) this.widthdel = new LzDelegate(this,
"followwidth");
if (!this.heightdel) this.heightdel = new LzDelegate(this,
"followheight");
this.target = t;
if (t != null) {
this.xdel.register(t, "onx");
this.ydel.register(t, "ony");
this.widthdel.register(t, "onwidth");
this.heightdel.register(t, "onheight");
followx(); followy();
followwidth(); followheight();
}
if (this.ontarget) this.ontarget.sendEvent(this);
]]> </method>
<method name="followx">
this.setAttribute( "x" , this.target.x - 5);
</method>
<method name="followy">
this.setAttribute( "y" , this.target.y - 5);
</method>
<method name="followwidth">
this.setAttribute( "width" , this.target.width + 10);
</method>
<method name="followheight">
this.setAttribute( "height" , this.target.height + 10);
</method>
</class>

<dragger id="a" x="50" y="50"/>
<dragger id="b" x="100" y="50"/>
<follower id="f" x="-50" y="-50"/>

</canvas>


If you run the example, the yellow overlay (which creates the yellow border and pale green color of the view) is the view that changes the target of its constraint.

Enjoy!

adam
11-17-2003, 11:20 AM
Another way to do this is to put your constraints in a state, and then remove and re-apply the state when the meta-dependency changes. Calendar does this with the eventselector.


<canvas>
<class name="box" bgcolor="blue"
onclick="follower.setAttribute( 'followview' , this )"
width="${20 + Math.random()*20}" height="${20 + Math.random()*20}"/>
<simplelayout axis="x" spacing="20"/>
<box/>
<box/>
<box/>
<box/>
<box/>

<view name="follower" options="ignoreLayout" bgcolor="yellow">
<attribute name="followview"
setter="followstate.remove();
this.followview = followview;
followstate.apply()"/>
<state name="followstate">
<attribute name="x" value="${followview.x}"/>
<attribute name="y" value="${followview.height}"/>
<attribute name="width" value="${followview.width}"/>
<attribute name="height" value="${followview.height}"/>
</state>
</view>
</canvas>

thipperudra
12-02-2003, 01:51 AM
Hi Antun,

In above code we can resize width and height of the green view by using blue view. But I want to resize the width and height of the image (resource) in place of the (bgcolor)green overlay.How do i do this.

With Regards,

Rudresh

antun
12-02-2003, 09:41 AM
To get a view to stretch its resource, you have to say:


<view stretches="both" resource="foo.jpg" />


... or you can have it stretch just the width or the height.

-Antun