Mercurial > hg > camir-ismir2012
comparison toolboxes/graph_visualisation/graphViz4Matlab/util/graphViz4MatlabNode.m @ 0:cc4b1211e677 tip
initial commit to HG from
Changeset:
646 (e263d8a21543) added further path and more save "camirversion.m"
| author | Daniel Wolff |
|---|---|
| date | Fri, 19 Aug 2016 13:07:06 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:cc4b1211e677 |
|---|---|
| 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 |
