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