d3.demo.shape = function() { "use strict"; var width = 150, height = 100, x = 0, y = 0, label = "", selected = false, base = null, uuid = d3.demo.util.uuid(); var dispatch = d3.dispatch( "shapeDragStart", "shapeDrag", "shapeDragEnd", "shapeResize", "shapeUpdated"); function shape(selection) { base = selection; selection.each(function(d, i) { var parent = d3.select(this); var container = parent.append("g") .attr("class", "shape") .attr("transform", "translate(" + x + "," + y + ")"); shape.node = container.node(); var background = container.append("rect") .attr("class", "background") .attr("filter", "url('#shapeDropShadow')") .attr("width", width) .attr("height", height) .attr("rx", "4") .attr("ry", "4"); var labelText = container.append("text") .attr("class", "label") .attr("transform", "translate(5, 20)") .text(label); // HANDLES var rightHandle = d3.demo.handle(); rightHandle .x(width - rightHandle.width()/2) .y(height/2 - rightHandle.height()/2) .type(rightHandle.TYPE_RIGHT) .on("handleDrag", function(event) { width += d3.event.dx; shape.render(); dispatch.shapeUpdated({ this: container, shape: shape }); }) .on("handleDragEnd", function(event) { dispatch.shapeUpdated({ this: container, shape: shape }); }); container.call(rightHandle, shape); var drag = d3.behavior.drag() .on("dragstart", function(d) { d3.event.sourceEvent.stopImmediatePropagation(); d3.demo.util.bringToFront(container.node()); dispatch.shapeDragStart({ shape: shape, pos: [d3.event.x, d3.event.y] }); }) .on("drag", function(d) { d3.event.sourceEvent.stopImmediatePropagation(); background.classed("dragging", true); dispatch.shapeDrag({ shape: shape, pos: [d3.event.x, d3.event.y] }); x += d3.event.dx; y += d3.event.dy; shape.render(); }) .on("dragend", function(d) { d3.event.sourceEvent.stopImmediatePropagation(); background.classed("dragging", false); dispatch.shapeDragEnd({ shape: shape, pos: [d3.event.x, d3.event.y] }); }); container.call(drag); shape.render = function() { container.attr("transform", "translate(" + x + "," + y + ")") .attr("width", width) .attr("height", height) .classed("selected", selected) .select(".background") .attr("width", width) .attr("height", height); dispatch.shapeUpdated({ this: container, shape: this }); labelText.text(label); rightHandle.x(width - rightHandle.width()/2).y(height/2 - rightHandle.height()/2).render(); }; }); } shape.x = function(value) { if (!arguments.length) { return x; } x = parseInt(value, 10); return this; }; shape.y = function(value) { if (!arguments.length) { return y; } y = parseInt(value, 10); return this; }; shape.width = function(value) { if (!arguments.length) { return width; } width = parseInt(value, 10); if (shape.render) { shape.render(); } return this; }; shape.height = function(value) { if (!arguments.length) { return height; } height = parseInt(value, 10); if (shape.render) { shape.render(); } return this; }; shape.label = function(value) { if (!arguments.length) { return label; } label = value; return this; }; shape.selected = function(value) { if (!arguments.length) { return selected; } selected = value; return this; }; shape.slaveDragStart = function() { d3.select(this.node).select(".background").classed("dragging", true); }; shape.slaveDrag = function() { x += d3.event.dx; y += d3.event.dy; shape.render(); }; shape.slaveDragEnd = function() { d3.select(this.node).select(".background").classed("dragging", false); }; shape.uuid = function(value) { if (!arguments.length) { return uuid; } uuid = value; return this; }; d3.rebind(shape, dispatch, "on"); return shape; }; // A method assignment helper for hierarchy subclasses. function d3_shape_rebind(object, hierarchy) { d3.rebind(object, hierarchy, "render", "x", "y", "width", "height", "label", "selected", "slaveDragStart", "slaveDrag", "slaveDragEnd", "uuid", "on"); return object; }