Mercurial > hg > camir-aes2014
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 |