comparison toolboxes/graph_visualisation/graphViz4Matlab/util/graphViz4MatlabNode.m @ 0:e9a9cd732c1e tip

first hg version after svn
author wolffd
date Tue, 10 Feb 2015 15:05:51 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:e9a9cd732c1e
1 classdef graphViz4MatlabNode < dynamicprops & hgsetget
2 % This class represents a drawable node in an arbitrary graph.
3 %
4 % Public properties can be set using the standard Matlab set method as in
5 % set(node,'curvature',[0,0],'linesytle','--','linecolor','g'). Call
6 % node.redraw to redraw it after changing properties.
7 %
8 % Nodes are not really designed to live on their own, they should be
9 % aggregated into a graph object responsible for layout.
10 %
11 % Matthew Dunham
12 % University of British Columbia
13 % http://www.cs.ubc.ca/~mdunham/
14
15 properties
16 label; % displayed name for the node
17 splitLabel; % label split in the middle
18 useFullLabel = false; % if true, the full non-split label is used regardles of how long it is.
19 description = ''; % text displayed when you click on the node
20 curvature = [1 1]; % curvature of the node, [1,1] = circle
21 lineStyle = '-'; % line style for the node
22 lineWidth = 2; % line wdth for the node
23 inedges = []; % indices of edges in
24 outedges = []; % indices of edges out
25 fontSize = 12; % The font size for the node
26 showFullLabel = false; % If true, node labels are not split onto multiple lines regardelss of how long
27 end
28
29 properties
30 % Color properties
31 lineColor = 'k'; % line color for the node
32 selectedColor = [1 1 0.7]; % face color when selected with mouse
33 faceColor = [1 1 0.8]; % face color when not shaded
34 shadedColor = 'r'; % color when shaded, call shade() to shade
35 textColor = 'k'; % label's text color
36 containingGraph = []; % containing graph object
37
38 end
39
40 properties(GetAccess = 'public', SetAccess = 'protected')
41 % Read only properties
42 xpos = 0; % x-coordinate of node center relative to parent axes
43 ypos = 0; % y-coordinate of node center relative to parent axes
44 isvisible = false; % true iff the node is being displayed
45 isshaded = false; % is the node shaded or not?
46 width = 1; % width in data units
47 height = 1; % height in data units
48 end
49
50 properties(GetAccess = 'public', SetAccess = 'protected')
51 % Handles to underlying Matlab graphics objects
52 rechandle = []; % handle to the underlying rectangle object
53 labelhandle = []; % handle to the underlying text object
54 parent = []; % handle to the parent axes object
55 isselected = false; % true iff, the node has been selected
56 end
57
58 methods
59
60 function obj = graphViz4MatlabNode(label)
61 % Node Constructor
62 obj.label = label;
63 obj.setSplitLabel(label);
64
65 end
66
67 function draw(obj,parent)
68 % Draw the node on the specified parent axes. If no parent is
69 % specified, the current axis is used.
70 if(obj.isvisible)
71 warning('GRAPHNODE:draw',['Node ',obj.label,' is already drawn, call redraw().']);
72 return;
73 end
74 if(nargin < 2)
75 if(isempty(obj.parent) || ~ishandle(obj.parent))
76 obj.parent = gca;
77 end
78 else
79 obj.parent = parent;
80 end
81 obj.drawNode();
82 obj.setText();
83 obj.isvisible = true;
84 end
85
86 function redraw(obj)
87 % Redraw the node, (must be called after node properties are
88 % changed).
89 if(obj.isvisible), obj.erase;end
90 obj.draw();
91 end
92
93 function erase(obj)
94 % Erase the node but do not delete it
95 if(~obj.isvisible)
96 warning('GRAPHNODE:erase',['Node ',obj.label,' is already erased']);
97 return;
98 end
99 delete(obj.rechandle);
100 delete(obj.labelhandle);
101 obj.rechandle = [];
102 end
103
104 function shade(obj,color)
105 % Shade the node the specified color. The default color is used if
106 % none given.
107 obj.isshaded = true;
108 if(nargin == 2)
109 obj.shadedColor = color;
110 end
111 if(obj.isvisible)
112 set(obj.rechandle,'FaceColor',obj.shadedColor);
113 end
114 end
115
116 function unshade(obj)
117 % Unshade the node
118 obj.isshaded = false;
119 if(obj.isvisible)
120 set(obj.rechandle,'FaceColor',obj.faceColor);
121 end
122 end
123
124 function resize(obj,width,height)
125 % Resize the node by the specified proportion
126 if(nargin < 3)
127 if(~isempty(obj.containingGraph))
128 height = width;
129 end
130 end
131 obj.width = width;
132 obj.height = height;
133 if(obj.isvisible), obj.redraw; end
134 end
135
136 function move(obj,x,y)
137 % Move the node's center to the new x,y coordinates, (relative to
138 % the parent axes.)
139 obj.xpos = x; obj.ypos = y;
140 if(obj.isvisible),obj.redraw;end
141 end
142
143 function select(obj)
144 % Call this function to set the node in a selected state.
145 obj.isselected = true;
146 if(obj.isvisible)
147 set(obj.rechandle,'faceColor',obj.selectedColor);
148 end
149 end
150
151
152 function deselect(obj)
153 % Call this function to deselect the node.
154 obj.isselected = false;
155 if(obj.isvisible)
156 obj.redraw;
157 end
158 end
159
160 end % end of public methods
161
162 methods(Access = 'protected')
163
164 function nodePressed(obj,varargin)
165 % This function is called whenever the node is pressed.
166 if(~isempty(obj.containingGraph))
167 obj.containingGraph.nodeSelected(obj);
168 end
169 end
170
171 function nodeDeleted(obj)
172 % This function is called whenver the node is deleted, (perhaps
173 % because the figure window was closed for instance).
174 obj.isvisible = false;
175 obj.parent = [];
176 end
177
178 function drawNode(obj)
179 % Draw the actual node
180 recxpos = obj.xpos - obj.width/2;
181 recypos = obj.ypos - obj.height/2;
182 lineColor = obj.lineColor;
183 lineWidth = obj.lineWidth;
184 if(obj.isselected)
185 color = obj.selectedColor;
186 lineColor = 'r';
187 lineWidth = 1.5*lineWidth;
188 elseif(obj.isshaded)
189 color = obj.shadedColor;
190 else
191 color = obj.faceColor;
192 end
193 obj.rechandle = rectangle(...
194 'Parent' ,obj.parent ,...
195 'Position' ,[recxpos,recypos,obj.width,obj.height] ,...
196 'Curvature' ,obj.curvature ,...
197 'LineWidth' , lineWidth ,...
198 'LineStyle' ,obj.lineStyle ,...
199 'EdgeColor' ,lineColor ,...
200 'faceColor' ,color ,...
201 'DisplayName' ,obj.label ,...
202 'Tag' ,obj.label ,...
203 'ButtonDownFcn',@obj.nodePressed ,...
204 'UserData' ,obj ,...
205 'DeleteFcn' ,@(varargin)obj.nodeDeleted() );
206 end
207
208 function setText(obj)
209 % Draw the node's label
210 if((length(obj.label) < 10) || obj.useFullLabel || obj.showFullLabel)
211 label = obj.label;
212 else
213 label = obj.splitLabel;
214 end
215 obj.labelhandle = text(obj.xpos,obj.ypos,label ,...
216 'FontUnits' , 'points' ,...
217 'HitTest' , 'off' ,...
218 'FontWeight' , 'demi' ,...
219 'Margin' , 0.01 ,...
220 'HorizontalAlignment' , 'center' ,...
221 'BackGroundColor' , 'none' ,...
222 'Selected' , 'off' ,...
223 'VerticalAlignment' , 'middle' ,...
224 'LineStyle' , 'none' ,...
225 'FontSize' , obj.fontSize ,...
226 'Color' , obj.textColor );
227 if(obj.useFullLabel)
228 set(obj.labelhandle,'BackgroundColor',obj.selectedColor,'Margin',6,'EdgeColor','k','LineStyle','-');
229 end
230 end
231
232 function resizeText(obj)
233 % Resize the text to fill the node (too slow for large graphs)
234 fontsize = obj.maxFontSize;
235 set(obj.labelhandle,'FontSize',fontsize);
236 extent = get(obj.labelhandle,'Extent');
237
238 while((extent(1) < (obj.xpos - obj.width/2)) || (extent(2)+(extent(4)) > (obj.ypos + obj.height/2)))
239 fontsize = 0.95*fontsize;
240 set(obj.labelhandle,'FontSize',fontsize);
241 extent = get(obj.labelhandle,'Extent');
242 end
243 end
244
245 function setSplitLabel(obj,label)
246
247 obj.splitLabel = splitString(label,8,10);
248
249 end
250
251 end % end of protected methods
252
253 end % end of graphnode class
254
255
256
257
258
259 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
260 function S = splitString(varargin)
261 % Split a string into multiple lines based on camel case.
262 %
263 % Inputs
264 %
265 % '-S' the string to split
266 % '-minSize' does not split at all if length(S) < minSize
267 % '-maxSize' splits no matter what, (even if no camel case change) if length(S) > maxSize
268 % '-center' if true, [default], the string is center justified
269 % '-cellMode' if true, a cell array of strings is returned, instead of a char array.
270
271 [S,minSize,maxSize,cellMode,center] = processArgs(varargin,'*+-S','','-minSize',8,'-maxSize',10,'-cellMode',false,'-center',true);
272
273 S = splitInTwo(S);
274 if center
275 S = strjust(S,'center');
276 end
277 if cellMode
278 S = cellstr(S);
279 end
280
281 function str = splitInTwo(str)
282 % recursively split a string into two based on camel case
283 isupper = isstrprop(str(2:end),'upper');
284 if(size(str,2) >= minSize && any(isupper))
285 first = find(isupper); first = first(1);
286 top = str(1:first);
287 bottom = str(first+1:end);
288 str = strvcat(splitInTwo(top),splitInTwo(bottom)); %#ok
289 elseif(size(str,2) > maxSize)
290 top = [str(1:floor(length(str)/2)),'-'];
291 bottom = str(floor(length(str)/2)+1:end);
292 str = strvcat(splitInTwo(top),splitInTwo(bottom)); %#ok
293 end
294 end
295 end
296
297
298