1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
/**
* $Id: mxCellOverlay.js,v 1.18 2012-12-06 15:58:44 gaudenz Exp $
* Copyright (c) 2006-2010, JGraph Ltd
*/
/**
* Class: mxCellOverlay
*
* Extends <mxEventSource> to implement a graph overlay, represented by an icon
* and a tooltip. Overlays can handle and fire <click> events and are added to
* the graph using <mxGraph.addCellOverlay>, and removed using
* <mxGraph.removeCellOverlay>, or <mxGraph.removeCellOverlays> to remove all overlays.
* The <mxGraph.getCellOverlays> function returns the array of overlays for a given
* cell in a graph. If multiple overlays exist for the same cell, then
* <getBounds> should be overridden in at least one of the overlays.
*
* Overlays appear on top of all cells in a special layer. If this is not
* desirable, then the image must be rendered as part of the shape or label of
* the cell instead.
*
* Example:
*
* The following adds a new overlays for a given vertex and selects the cell
* if the overlay is clicked.
*
* (code)
* var overlay = new mxCellOverlay(img, html);
* graph.addCellOverlay(vertex, overlay);
* overlay.addListener(mxEvent.CLICK, function(sender, evt)
* {
* var cell = evt.getProperty('cell');
* graph.setSelectionCell(cell);
* });
* (end)
*
* For cell overlays to be printed use <mxPrintPreview.printOverlays>.
*
* Event: mxEvent.CLICK
*
* Fires when the user clicks on the overlay. The <code>event</code> property
* contains the corresponding mouse event and the <code>cell</code> property
* contains the cell. For touch devices this is fired if the element receives
* a touchend event.
*
* Constructor: mxCellOverlay
*
* Constructs a new overlay using the given image and tooltip.
*
* Parameters:
*
* image - <mxImage> that represents the icon to be displayed.
* tooltip - Optional string that specifies the tooltip.
* align - Optional horizontal alignment for the overlay. Possible
* values are <ALIGN_LEFT>, <ALIGN_CENTER> and <ALIGN_RIGHT>
* (default).
* verticalAlign - Vertical alignment for the overlay. Possible
* values are <ALIGN_TOP>, <ALIGN_MIDDLE> and <ALIGN_BOTTOM>
* (default).
*/
function mxCellOverlay(image, tooltip, align, verticalAlign, offset, cursor)
{
this.image = image;
this.tooltip = tooltip;
this.align = (align != null) ? align : this.align;
this.verticalAlign = (verticalAlign != null) ? verticalAlign : this.verticalAlign;
this.offset = (offset != null) ? offset : new mxPoint();
this.cursor = (cursor != null) ? cursor : 'help';
};
/**
* Extends mxEventSource.
*/
mxCellOverlay.prototype = new mxEventSource();
mxCellOverlay.prototype.constructor = mxCellOverlay;
/**
* Variable: image
*
* Holds the <mxImage> to be used as the icon.
*/
mxCellOverlay.prototype.image = null;
/**
* Variable: tooltip
*
* Holds the optional string to be used as the tooltip.
*/
mxCellOverlay.prototype.tooltip = null;
/**
* Variable: align
*
* Holds the horizontal alignment for the overlay. Default is
* <mxConstants.ALIGN_RIGHT>. For edges, the overlay always appears in the
* center of the edge.
*/
mxCellOverlay.prototype.align = mxConstants.ALIGN_RIGHT;
/**
* Variable: verticalAlign
*
* Holds the vertical alignment for the overlay. Default is
* <mxConstants.ALIGN_BOTTOM>. For edges, the overlay always appears in the
* center of the edge.
*/
mxCellOverlay.prototype.verticalAlign = mxConstants.ALIGN_BOTTOM;
/**
* Variable: offset
*
* Holds the offset as an <mxPoint>. The offset will be scaled according to the
* current scale.
*/
mxCellOverlay.prototype.offset = null;
/**
* Variable: cursor
*
* Holds the cursor for the overlay. Default is 'help'.
*/
mxCellOverlay.prototype.cursor = null;
/**
* Variable: defaultOverlap
*
* Defines the overlapping for the overlay, that is, the proportional distance
* from the origin to the point defined by the alignment. Default is 0.5.
*/
mxCellOverlay.prototype.defaultOverlap = 0.5;
/**
* Function: getBounds
*
* Returns the bounds of the overlay for the given <mxCellState> as an
* <mxRectangle>. This should be overridden when using multiple overlays
* per cell so that the overlays do not overlap.
*
* The following example will place the overlay along an edge (where
* x=[-1..1] from the start to the end of the edge and y is the
* orthogonal offset in px).
*
* (code)
* overlay.getBounds = function(state)
* {
* var bounds = mxCellOverlay.prototype.getBounds.apply(this, arguments);
*
* if (state.view.graph.getModel().isEdge(state.cell))
* {
* var pt = state.view.getPoint(state, {x: 0, y: 0, relative: true});
*
* bounds.x = pt.x - bounds.width / 2;
* bounds.y = pt.y - bounds.height / 2;
* }
*
* return bounds;
* };
* (end)
*
* Parameters:
*
* state - <mxCellState> that represents the current state of the
* associated cell.
*/
mxCellOverlay.prototype.getBounds = function(state)
{
var isEdge = state.view.graph.getModel().isEdge(state.cell);
var s = state.view.scale;
var pt = null;
var w = this.image.width;
var h = this.image.height;
if (isEdge)
{
var pts = state.absolutePoints;
if (pts.length % 2 == 1)
{
pt = pts[Math.floor(pts.length / 2)];
}
else
{
var idx = pts.length / 2;
var p0 = pts[idx-1];
var p1 = pts[idx];
pt = new mxPoint(p0.x + (p1.x - p0.x) / 2,
p0.y + (p1.y - p0.y) / 2);
}
}
else
{
pt = new mxPoint();
if (this.align == mxConstants.ALIGN_LEFT)
{
pt.x = state.x;
}
else if (this.align == mxConstants.ALIGN_CENTER)
{
pt.x = state.x + state.width / 2;
}
else
{
pt.x = state.x + state.width;
}
if (this.verticalAlign == mxConstants.ALIGN_TOP)
{
pt.y = state.y;
}
else if (this.verticalAlign == mxConstants.ALIGN_MIDDLE)
{
pt.y = state.y + state.height / 2;
}
else
{
pt.y = state.y + state.height;
}
}
return new mxRectangle(pt.x - (w * this.defaultOverlap - this.offset.x) * s,
pt.y - (h * this.defaultOverlap - this.offset.y) * s, w * s, h * s);
};
/**
* Function: toString
*
* Returns the textual representation of the overlay to be used as the
* tooltip. This implementation returns <tooltip>.
*/
mxCellOverlay.prototype.toString = function()
{
return this.tooltip;
};
|