Skip to main content

Control

The Control element tool is an abstract class which allows you to build tools to control the look or shape of an element by simply dragging a UI handle. It accepts a few additional arguments, which can be passed as an object to the element tool constructor:

selectorstring | nullThe element selector pointing to an element subnode, which the tool draws a frame around during dragging. If null provided, no frame will be shown.
paddingnumberThe padding between the area and the bounding box of the node designated by selector.
handleAttributesfunctionAn object with SVG attributes to be applied to the tool's handle.
scalenumberScale the button up or down on a 2D plane. The default is 1.
namespace Control {
interface Options extends dia.ToolView.Options {
selector?: string;
padding?: number;
handleAttributes?: Partial<attributes.NativeSVGAttributes>
}
}

abstract class Control extends dia.ToolView {
protected getPosition(view: dia.ElementView): dia.Point;
protected setPosition(view: dia.ElementView, coordinates: g.Point): void;
protected resetPosition(view: dia.ElementView): void;
}
getPosition(view: dia.ElementView): dia.Point;

The method should return the position of the handle based on a model value. The position is defined in the element model coordinate system (point [0,0] is the top-left corner; point [width, height] is the bottom-right corner - the element's rotation does not affect this).

setPosition(view: dia.ElementView, coordinates: g.Point): void;

The method is executed each time the handle is moved. It's supposed to set the new model value derived from the current pointer coordinates (defined in the element model coordinate system)

resetPosition(view: dia.ElementView): void;The method is executed when the handle is double-clicked. It's supposed to reset the model value back to a default.

Here's an ES5 example of a tool, which provides the user a way to modify the border radius of an rectangle.

var RadiusTool = elementTools.Control.extend({

getPosition: function(view) {
var model = view.model;
var size = model.size();
var tilt = model.topRy();
return { x: size.width / 2, y: 2 * tilt };
},

setPosition: function(view, coordinates) {
var model = view.model;
var size = model.size();
var tilt = Math.min(Math.max(coordinates.y, 0), size.height / 2);
model.topRy(tilt, { ui: true, tool: this.cid });
},

resetPosition: function(view) {
var radius = this.options.defaultRadius || 0;
model.attr(['body'], { rx: radius, ry: radius });
}
});

TypeScript example of the same control:

interface RadiusControlOptions extends elementTools.Control.Options {
defaultRadius?: number;
}

class RadiusControl extends elementTools.Control {

protected getPosition(view: dia.ElementView): dia.Point {
const { model } = view;
const radius = model.attr(['body', 'ry']) || 0;
return { x: 0, y: radius };
}

protected setPosition(view: dia.ElementView, coordinates: dia.Point): void {
const { model } = view;
const { height } = model.size();
const radius = Math.min(Math.max(coordinates.y, 0), height / 2);
model.attr(['body'], { rx: radius, ry: radius });
}

protected resetPosition(view): void {
const { model } = view;
const { defaultRadius = 0 } = this.options;
model.attr(['body'], { rx: defaultRadius, ry: defaultRadius });
}
}

Add the tool to a rectangle element to allow the user adjust its "border radius".

rectangle.findView(paper).addTools(new dia.ToolsView({
tools: [
new RadiusTool({ handleAttributes: { fill: 'orange' }})
]
}));