Mercurial > octave-nkf
comparison scripts/plot/private/__bar__.m @ 17519:cc9befe5d271
Overhaul bar family of plot functions.
* scripts/plot/bar.m, scripts/plot/barh.m: Document new "hist", "histc"
arguments.
* scripts/plot/private/__bar__.m: "grouped" bars now default to having
a gap between them for Matlab compatibility. Added new style options
"hist", "histc". Renamed variable names for clarity. Removed unnecessary
for loops in listener functions. Stop recursion in listener functions.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 30 Sep 2013 16:50:41 -0700 |
parents | 177147bf7b55 |
children | 76614e624818 |
comparison
equal
deleted
inserted
replaced
17518:6c62150b454a | 17519:cc9befe5d271 |
---|---|
23 | 23 |
24 ## Author: jwe | 24 ## Author: jwe |
25 | 25 |
26 function varargout = __bar__ (vertical, func, varargin) | 26 function varargout = __bar__ (vertical, func, varargin) |
27 | 27 |
28 [hax, varargin, nargs] = __plt_get_axis_arg__ (func, varargin{:}); | 28 [hax, varargin, nargin] = __plt_get_axis_arg__ (func, varargin{:}); |
29 | 29 |
30 ## Slightly smaller than 0.8 to avoid clipping issue in gnuplot 4.0 | 30 ## Slightly smaller than 0.8 to avoid clipping issue in gnuplot 4.0 |
31 width = 0.8 - 10 * eps; | 31 width = 0.8 - 10 * eps; |
32 group = true; | 32 group = true; |
33 bv = 0; | 33 histc = NA; |
34 | 34 bv = 0; # BaseValue |
35 if (nargs > 1 && isnumeric (varargin{2})) | 35 |
36 if (nargin > 1 && isnumeric (varargin{2})) | |
36 x = varargin{1}; | 37 x = varargin{1}; |
37 if (isvector (x)) | 38 if (isvector (x)) |
38 x = x(:); | 39 x = x(:); |
39 endif | 40 endif |
40 y = varargin{2}; | 41 y = varargin{2}; |
63 idx = 2; | 64 idx = 2; |
64 endif | 65 endif |
65 | 66 |
66 newargs = {}; | 67 newargs = {}; |
67 have_line_spec = false; | 68 have_line_spec = false; |
68 while (idx <= nargs) | 69 while (idx <= nargin) |
69 if (ischar (varargin{idx}) && strcmpi (varargin{idx}, "grouped")) | 70 if (ischar (varargin{idx}) && strcmpi (varargin{idx}, "grouped")) |
70 group = true; | 71 group = true; |
71 idx++; | 72 idx++; |
72 elseif (ischar (varargin{idx}) && strcmpi (varargin{idx}, "stacked")) | 73 elseif (ischar (varargin{idx}) && strcmpi (varargin{idx}, "stacked")) |
73 group = false; | 74 group = false; |
75 idx++; | |
76 elseif (ischar (varargin{idx}) && strcmpi (varargin{idx}, "histc")) | |
77 group = true; | |
78 histc = true; | |
79 idx++; | |
80 elseif (ischar (varargin{idx}) && strcmpi (varargin{idx}, "hist")) | |
81 group = true; | |
82 histc = false; | |
74 idx++; | 83 idx++; |
75 else | 84 else |
76 if ((ischar (varargin{idx}) || iscellstr (varargin{idx})) | 85 if ((ischar (varargin{idx}) || iscellstr (varargin{idx})) |
77 && ! have_line_spec) | 86 && ! have_line_spec) |
78 [linespec, valid] = __pltopt__ (func, varargin{idx}, false); | 87 [linespec, valid] = __pltopt__ (func, varargin{idx}, false); |
85 continue; | 94 continue; |
86 endif | 95 endif |
87 endif | 96 endif |
88 if (isscalar (varargin{idx})) | 97 if (isscalar (varargin{idx})) |
89 width = varargin{idx++}; | 98 width = varargin{idx++}; |
90 elseif (idx == nargs) | 99 elseif (idx == nargin) |
91 newargs = [newargs,varargin(idx++)]; | 100 newargs = [newargs, varargin(idx++)]; |
92 elseif (ischar (varargin{idx}) | 101 elseif (ischar (varargin{idx}) |
93 && strcmpi (varargin{idx}, "basevalue") | 102 && strcmpi (varargin{idx}, "basevalue") |
94 && isscalar (varargin{idx+1})) | 103 && isscalar (varargin{idx+1})) |
95 bv = varargin{idx+1}; | 104 bv = varargin{idx+1}; |
96 idx += 2; | 105 idx += 2; |
97 else | 106 else |
98 newargs = [newargs,varargin(idx:idx+1)]; | 107 newargs = [newargs, varargin(idx:idx+1)]; |
99 idx += 2; | 108 idx += 2; |
100 endif | 109 endif |
101 endif | 110 endif |
102 endwhile | 111 endwhile |
103 | 112 |
104 xlen = rows (x); | 113 ngrp = rows (x); |
105 ylen = rows (y); | 114 if (ngrp != rows (y)) |
106 | |
107 if (xlen != ylen) | |
108 error ("%s: length of X and Y must be equal", func); | 115 error ("%s: length of X and Y must be equal", func); |
109 endif | 116 endif |
110 if (any (x(2:end) < x(1:end-1))) | 117 if (any (x(2:end) < x(1:end-1))) |
111 error ("%s: X vector values must be in ascending order", func); | 118 error ("%s: X vector values must be in ascending order", func); |
112 endif | 119 endif |
113 | 120 |
114 ycols = columns (y); | 121 nbars = columns (y); |
122 | |
123 ## Column width is 1 for 'hist*' styles. Otherwise, same as group width. | |
124 if (nbars == 1) | |
125 cwidth = 1; | |
126 gwidth = width; | |
127 elseif (islogical (histc)) | |
128 cwidth = 1; | |
129 gwidth = width^2; | |
130 else | |
131 cwidth = gwidth = width; | |
132 endif | |
133 | |
134 ## Complicated algorithm sizes bars with unitless parameter width. | |
135 ## If width is 1.0, adjacent bars in a group are touching. | |
136 ## Otherwise, bar size is cwidth and the remaining space is split evenly on | |
137 ## either side of the bar. For the default 0.8, spacing is [0.1 0.8 0.1]. | |
138 ## Groups of bars are spaced by gwidth. If gwidth is 1.0 then adjacent | |
139 ## groups will just touch. | |
115 if (numel (x) > 1) | 140 if (numel (x) > 1) |
116 cutoff = min (diff (double (x))) / 2; | 141 cutoff = min (diff (double (x))) / 2; |
117 else | 142 else |
118 cutoff = 1; | 143 cutoff = 1; |
119 endif | 144 endif |
120 if (group) | 145 if (group) |
121 delta_p = delta_m = repmat (cutoff * width / ycols, size (x)); | 146 gdelta = cutoff * gwidth / nbars; |
122 else | 147 cdelta = repmat ((1 - ((1 - cwidth) / 2)) * gdelta, size (x)); |
123 delta_p = delta_m = repmat (cutoff * width, size (x)); | 148 else |
124 endif | 149 cdelta = repmat (cutoff * gwidth, size (x)); |
125 x1 = (x - delta_m)(:)'; | 150 endif |
126 x2 = (x + delta_p)(:)'; | 151 x1 = (x - cdelta)(:)'; |
127 xb = repmat ([x1; x1; x2; x2](:), 1, ycols); | 152 x2 = (x + cdelta)(:)'; |
153 xb = repmat ([x1; x1; x2; x2](:), 1, nbars); | |
128 | 154 |
129 if (group) | 155 if (group) |
130 offset = ((delta_p + delta_m) * [-(ycols - 1) / 2 : (ycols - 1) / 2]); | 156 if (islogical (histc) && histc) |
131 xb(1:4:4*ylen,:) += offset; | 157 offset = 2*cdelta * [0:(nbars-1)] + cdelta(1); # not centered |
132 xb(2:4:4*ylen,:) += offset; | 158 else |
133 xb(3:4:4*ylen,:) += offset; | 159 offset = 2*cdelta * [-(nbars - 1) / 2 : (nbars - 1) / 2]; |
134 xb(4:4:4*ylen,:) += offset; | 160 endif |
161 | |
162 xb(1:4:4*ngrp,:) += offset + (1-cwidth) / 2 * (2 * gdelta); | |
163 xb(2:4:4*ngrp,:) += offset + (1-cwidth) / 2 * (2 * gdelta); | |
164 xb(3:4:4*ngrp,:) += offset - (1-cwidth) / 2 * (2 * gdelta); | |
165 xb(4:4:4*ngrp,:) += offset - (1-cwidth) / 2 * (2 * gdelta); | |
166 | |
135 y0 = zeros (size (y)) + bv; | 167 y0 = zeros (size (y)) + bv; |
136 y1 = y; | 168 y1 = y; |
137 else | 169 else |
138 y1 = cumsum (y,2); | 170 y1 = cumsum (y,2); |
139 y0 = [zeros(ylen,1)+bv, y1(:,1:end-1)]; | 171 y0 = [zeros(ngrp,1)+bv, y1(:,1:end-1)]; |
140 endif | 172 endif |
141 | 173 |
142 yb = zeros (4*ylen, ycols); | 174 yb = zeros (4*ngrp, nbars); |
143 yb(1:4:4*ylen,:) = y0; | 175 yb(1:4:4*ngrp,:) = y0; |
144 yb(2:4:4*ylen,:) = y1; | 176 yb(2:4:4*ngrp,:) = y1; |
145 yb(3:4:4*ylen,:) = y1; | 177 yb(3:4:4*ngrp,:) = y1; |
146 yb(4:4:4*ylen,:) = y0; | 178 yb(4:4:4*ngrp,:) = y0; |
147 | 179 |
148 xb = reshape (xb, [4, numel(xb) / 4 / ycols, ycols]); | 180 xb = reshape (xb, [4, ngrp, nbars]); |
149 yb = reshape (yb, [4, numel(yb) / 4 / ycols, ycols]); | 181 yb = reshape (yb, [4, ngrp, nbars]); |
150 | 182 |
151 if (nargout < 2) | 183 if (nargout < 2) |
152 oldfig = []; | 184 oldfig = []; |
153 if (! isempty (hax)) | 185 if (! isempty (hax)) |
154 oldfig = get (0, "currentfigure"); | 186 oldfig = get (0, "currentfigure"); |
155 endif | 187 endif |
156 unwind_protect | 188 unwind_protect |
157 hax = newplot (hax); | 189 hax = newplot (hax); |
158 | 190 |
159 htmp = bars (hax, vertical, x, y, xb, yb, width, group, | 191 htmp = bars (hax, vertical, x, y, xb, yb, gwidth, group, |
160 have_line_spec, bv, newargs{:}); | 192 have_line_spec, bv, newargs{:}); |
193 | |
194 if (! ishold (hax)) | |
195 if (all (x(:,1) == fix (x(:,1)))) | |
196 if (vertical) | |
197 set (hax, "xtick", x(:,1)); | |
198 else | |
199 set (hax, "ytick", x(:,1)); | |
200 endif | |
201 endif | |
202 ## Hack prevents color and xlim setting changes when basevalue changes. | |
203 if (vertical) | |
204 set (hax, "clim", [0 1], "xlimmode", "manual"); | |
205 else | |
206 set (hax, "clim", [0 1], "ylimmode", "manual"); | |
207 endif | |
208 endif | |
161 unwind_protect_cleanup | 209 unwind_protect_cleanup |
162 if (! isempty (oldfig)) | 210 if (! isempty (oldfig)) |
163 set (0, "currentfigure", oldfig); | 211 set (0, "currentfigure", oldfig); |
164 endif | 212 endif |
165 end_unwind_protect | 213 end_unwind_protect |
176 endif | 224 endif |
177 endif | 225 endif |
178 | 226 |
179 endfunction | 227 endfunction |
180 | 228 |
181 function tmp = bars (ax, vertical, x, y, xb, yb, width, group, have_color_spec, base_value, varargin) | 229 function hglist = bars (hax, vertical, x, y, xb, yb, width, group, have_color_spec, base_value, varargin) |
182 | 230 |
183 ycols = columns (y); | 231 nbars = columns (y); |
184 clim = get (ax, "clim"); | 232 clim = get (hax, "clim"); |
185 tmp = []; | 233 hglist = []; |
186 | 234 |
187 for i = 1:ycols | 235 for i = 1:nbars |
188 hg = hggroup (); | 236 hg = hggroup (); |
189 tmp = [tmp; hg]; | 237 hglist = [hglist; hg]; |
190 args = __add_datasource__ ("bar", hg, {"x", "y"}, varargin{:}); | 238 args = __add_datasource__ ("bar", hg, {"x", "y"}, varargin{:}); |
191 | 239 |
192 if (vertical) | 240 if (vertical) |
193 if (! have_color_spec) | 241 if (! have_color_spec) |
194 if (ycols == 1) | 242 if (nbars == 1) |
195 lev = clim(1); | 243 lev = clim(1); |
196 else | 244 else |
197 lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1); | 245 lev = (i - 1) * (clim(2) - clim(1)) / (nbars - 1) - clim(1); |
198 endif | 246 endif |
199 h = patch (ax, xb(:,:,i), yb(:,:,i), "FaceColor", "flat", | 247 h = patch (hax, xb(:,:,i), yb(:,:,i), |
200 "cdata", lev, "parent", hg); | 248 "FaceColor", "flat", "cdata", lev, "parent", hg); |
201 else | 249 else |
202 h = patch (ax, xb(:,:,i), yb(:,:,i), "parent", hg); | 250 h = patch (hax, xb(:,:,i), yb(:,:,i), "parent", hg); |
203 endif | 251 endif |
204 else | 252 else |
205 if (! have_color_spec) | 253 if (! have_color_spec) |
206 if (ycols == 1) | 254 if (nbars == 1) |
207 lev = clim(1); | 255 lev = clim(1); |
208 else | 256 else |
209 lev = (i - 1) * (clim(2) - clim(1)) / (ycols - 1) - clim(1); | 257 lev = (i - 1) * (clim(2) - clim(1)) / (nbars - 1) - clim(1); |
210 endif | 258 endif |
211 h = patch (ax, yb(:,:,i), xb(:,:,i), "FaceColor", "flat", | 259 h = patch (hax, yb(:,:,i), xb(:,:,i), |
212 "cdata", lev, "parent", hg); | 260 "FaceColor", "flat", "cdata", lev, "parent", hg); |
213 else | 261 else |
214 h = patch (ax, yb(:,:,i), xb(:,:,i), "parent", hg); | 262 h = patch (hax, yb(:,:,i), xb(:,:,i), "parent", hg); |
215 endif | 263 endif |
216 endif | 264 endif |
217 | 265 |
218 if (i == 1) | 266 if (i == 1) |
219 x_axis_range = get (ax, "xlim"); | 267 ## Add baseline object the first time through loop |
220 h_baseline = line (ax, x_axis_range, [base_value, base_value], | 268 x_axis_range = get (hax, "xlim"); |
221 "color", [0, 0, 0]); | 269 h_baseline = line (hax, x_axis_range, [base_value, base_value], |
222 set (h_baseline, "handlevisibility", "off"); | 270 "color", [0, 0, 0]); |
223 set (h_baseline, "xliminclude", "off"); | 271 set (h_baseline, "handlevisibility", "off", "xliminclude", "off"); |
224 addlistener (ax, "xlim", @update_xlim); | 272 set (h_baseline, "parent", get (hg, "parent")); |
225 addlistener (h_baseline, "ydata", @update_baseline); | |
226 addlistener (h_baseline, "visible", @update_baseline); | |
227 endif | 273 endif |
228 | 274 |
229 ## Setup the hggroup and listeners | 275 ## Setup the hggroup and listeners |
230 addproperty ("showbaseline", hg, "radio", "{on}|off"); | 276 addproperty ("showbaseline", hg, "radio", "{on}|off"); |
231 addproperty ("basevalue", hg, "data", base_value); | 277 addproperty ("basevalue", hg, "data", base_value); |
250 addlistener (hg, "barwidth", @update_group); | 296 addlistener (hg, "barwidth", @update_group); |
251 addlistener (hg, "barlayout", @update_group); | 297 addlistener (hg, "barlayout", @update_group); |
252 addlistener (hg, "horizontal", @update_group); | 298 addlistener (hg, "horizontal", @update_group); |
253 | 299 |
254 addproperty ("edgecolor", hg, "patchedgecolor", get (h, "edgecolor")); | 300 addproperty ("edgecolor", hg, "patchedgecolor", get (h, "edgecolor")); |
301 addproperty ("facecolor", hg, "patchfacecolor", get (h, "facecolor")); | |
302 addproperty ("linestyle", hg, "patchlinestyle", get (h, "linestyle")); | |
255 addproperty ("linewidth", hg, "patchlinewidth", get (h, "linewidth")); | 303 addproperty ("linewidth", hg, "patchlinewidth", get (h, "linewidth")); |
256 addproperty ("linestyle", hg, "patchlinestyle", get (h, "linestyle")); | |
257 addproperty ("facecolor", hg, "patchfacecolor", get (h, "facecolor")); | |
258 | 304 |
259 addlistener (hg, "edgecolor", @update_props); | 305 addlistener (hg, "edgecolor", @update_props); |
306 addlistener (hg, "facecolor", @update_props); | |
307 addlistener (hg, "linestyle", @update_props); | |
260 addlistener (hg, "linewidth", @update_props); | 308 addlistener (hg, "linewidth", @update_props); |
261 addlistener (hg, "linestyle", @update_props); | |
262 addlistener (hg, "facecolor", @update_props); | |
263 | 309 |
264 if (isvector (x)) | 310 if (isvector (x)) |
265 addproperty ("xdata", hg, "data", x); | 311 addproperty ("xdata", hg, "data", x); |
266 else | 312 else |
267 addproperty ("xdata", hg, "data", x(:, i)); | 313 addproperty ("xdata", hg, "data", x(:, i)); |
270 | 316 |
271 addlistener (hg, "xdata", @update_data); | 317 addlistener (hg, "xdata", @update_data); |
272 addlistener (hg, "ydata", @update_data); | 318 addlistener (hg, "ydata", @update_data); |
273 | 319 |
274 addproperty ("bargroup", hg, "data"); | 320 addproperty ("bargroup", hg, "data"); |
275 set (tmp, "bargroup", tmp); | 321 set (hglist, "bargroup", hglist); |
276 if (! isempty (args)) | 322 if (! isempty (args)) |
277 set (hg, args{:}); | 323 set (hg, args{:}); |
278 endif | 324 endif |
279 if (i == 1) | |
280 set (h_baseline, "parent", get (hg, "parent")); | |
281 endif | |
282 endfor | 325 endfor |
283 | 326 |
284 update_xlim (ax, []); | 327 update_xlim (hax, []); |
285 endfunction | 328 ## Add listeners outside of for loop to prevent constant updating during |
286 | 329 ## creation of plot when patch objects are added. |
287 function update_xlim (h, d) | 330 addlistener (hax, "xlim", @update_xlim); |
331 addlistener (h_baseline, "ydata", @update_baseline); | |
332 addlistener (h_baseline, "visible", @update_baseline); | |
333 | |
334 endfunction | |
335 | |
336 function update_xlim (h, ~) | |
288 kids = get (h, "children"); | 337 kids = get (h, "children"); |
289 xlim = get (h, "xlim"); | 338 xlim = get (h, "xlim"); |
290 | 339 |
291 for i = 1 : length (kids) | 340 for i = 1 : length (kids) |
292 obj = get (kids (i)); | 341 obj = get (kids(i)); |
293 if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline")) | 342 if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline")) |
294 if (any (get (obj.baseline, "xdata") != xlim)) | 343 if (any (get (obj.baseline, "xdata") != xlim)) |
295 set (obj.baseline, "xdata", xlim); | 344 set (obj.baseline, "xdata", xlim); |
296 endif | 345 endif |
297 endif | 346 endif |
298 endfor | 347 endfor |
299 endfunction | 348 endfunction |
300 | 349 |
301 function update_baseline (h, d) | 350 function update_baseline (h, ~) |
302 visible = get (h, "visible"); | 351 visible = get (h, "visible"); |
303 ydata = get (h, "ydata")(1); | 352 ydata = get (h, "ydata")(1); |
304 | 353 |
354 ## Search axis for a bargroup that contains this baseline handle | |
305 kids = get (get (h, "parent"), "children"); | 355 kids = get (get (h, "parent"), "children"); |
306 for i = 1 : length (kids) | 356 for i = 1 : length (kids) |
307 obj = get (kids (i)); | 357 obj = get (kids(i)); |
308 if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline") | 358 if (strcmp (obj.type, "hggroup") && isfield (obj, "baseline") |
309 && obj.baseline == h) | 359 && obj.baseline == h) |
310 ## Only alter if changed to avoid recursion of the listener functions | 360 set (obj.bargroup, "showbaseline", visible, "basevalue", ydata); |
311 if (! strcmpi (get (kids(i), "showbaseline"), visible)) | 361 break; |
312 set (kids (i), "showbaseline", visible); | |
313 endif | |
314 if (! strcmpi (get (kids(i), "basevalue"), visible)) | |
315 set (kids (i), "basevalue", ydata); | |
316 endif | |
317 endif | 362 endif |
318 endfor | 363 endfor |
319 endfunction | 364 endfunction |
320 | 365 |
321 function show_baseline (h, d, prop = "") | 366 function show_baseline (h, ~, prop = "") |
322 persistent recursion = false; | 367 persistent recursion = false; |
323 | 368 |
324 ## Don't allow recursion | 369 ## Don't allow recursion |
325 if (! recursion) | 370 if (! recursion) |
326 unwind_protect | 371 unwind_protect |
327 recursion = true; | 372 recursion = true; |
328 hlist = get (h, "bargroup"); | 373 hlist = get (h, "bargroup"); |
329 if (strcmp (prop, "showbl")) | 374 if (strcmp (prop, "showbl")) |
330 showbaseline = get (h, "showbaseline"); | 375 showbaseline = get (h, "showbaseline"); |
331 for hh = hlist(:)' | 376 hlist = hlist(hlist != h); # remove current handle being updated |
332 if (hh != h) | 377 set (hlist, "showbaseline", showbaseline); |
333 set (hh, "showbaseline", showbaseline); | |
334 endif | |
335 endfor | |
336 elseif (strcmp (prop, "visib")) | 378 elseif (strcmp (prop, "visib")) |
337 showbaseline = "on"; | 379 showbaseline = "on"; |
338 if (all (strcmp (get (hlist, "visible"), "off"))) | 380 if (all (strcmp (get (hlist, "visible"), "off"))) |
339 showbaseline = "off"; | 381 showbaseline = "off"; |
340 endif | 382 endif |
344 recursion = false; | 386 recursion = false; |
345 end_unwind_protect | 387 end_unwind_protect |
346 endif | 388 endif |
347 endfunction | 389 endfunction |
348 | 390 |
349 function move_baseline (h, d) | 391 function move_baseline (h, ~) |
350 b0 = get (h, "basevalue"); | 392 persistent recursion = false; |
351 bl = get (h, "baseline"); | 393 |
352 | 394 ## Don't allow recursion |
353 if (get (bl, "ydata") != [b0, b0]) | 395 if (! recursion) |
354 set (bl, "ydata", [b0, b0]); | 396 recursion = true; |
355 endif | 397 unwind_protect |
356 | 398 b0 = get (h, "basevalue"); |
357 if (strcmpi (get (h, "barlayout"), "grouped")) | 399 bl = get (h, "baseline"); |
358 update_data (h, d); | 400 set (bl, "ydata", [b0, b0]); |
359 endif | 401 |
360 endfunction | 402 if (strcmp (get (h, "barlayout"), "grouped")) |
361 | 403 update_data (h); |
362 function update_props (h, d) | 404 endif |
405 unwind_protect_cleanup | |
406 recursion = false; | |
407 end_unwind_protect | |
408 endif | |
409 endfunction | |
410 | |
411 function update_props (h, ~) | |
363 kids = get (h, "children"); | 412 kids = get (h, "children"); |
364 set (kids, "edgecolor", get (h, "edgecolor"), | 413 set (kids, {"edgecolor", "linewidth", "linestyle", "facecolor"}, |
365 "linewidth", get (h, "linewidth"), | 414 get (h, {"edgecolor", "linewidth", "linestyle", "facecolor"})); |
366 "linestyle", get (h, "linestyle"), | 415 endfunction |
367 "facecolor", get (h, "facecolor")); | 416 |
368 endfunction | 417 function update_data (h, ~) |
369 | |
370 function update_data (h, d) | |
371 persistent recursion = false; | 418 persistent recursion = false; |
372 | 419 |
373 ## Don't allow recursion | 420 ## Don't allow recursion |
374 if (! recursion) | 421 if (! recursion) |
375 unwind_protect | 422 unwind_protect |
376 recursion = true; | 423 recursion = true; |
377 hlist = get (h, "bargroup"); | 424 hlist = get (h, "bargroup"); |
378 x = get (h, "xdata"); | 425 x = get (h, "xdata"); |
379 if (!isvector (x)) | 426 if (! isvector (x)) |
380 x = x(:); | 427 x = x(:); |
381 endif | 428 endif |
382 y = []; | 429 ydat = get (hlist, "ydata"); |
383 for hh = hlist(:)' | 430 if (iscell (ydat)) |
384 ytmp = get (hh, "ydata"); | 431 y = cell2mat (ydat.'); |
385 y = [y ytmp(:)]; | 432 else |
386 endfor | 433 y = ydat; |
434 endif | |
387 | 435 |
388 [xb, yb] = bar (x, y, get (h, "barwidth"), get (h, "barlayout"), | 436 [xb, yb] = bar (x, y, get (h, "barwidth"), get (h, "barlayout"), |
389 "basevalue", get (h, "basevalue")); | 437 "basevalue", get (h, "basevalue")); |
390 ny = columns (y); | 438 |
391 vert = strcmpi (get (h, "horizontal"), "off"); | 439 vertical = strcmp (get (h, "horizontal"), "off"); |
392 | 440 for i = 1:columns (y) |
393 for i = 1:ny | |
394 hp = get (hlist(i), "children"); | 441 hp = get (hlist(i), "children"); |
395 if (vert) | 442 if (vertical) |
396 set (hp, "xdata", xb(:,:,i), "ydata", yb(:,:,i)); | 443 set (hp, "xdata", xb(:,:,i), "ydata", yb(:,:,i)); |
397 else | 444 else |
398 set (hp, "xdata", yb(:,:,i), "ydata", xb(:,:,i)); | 445 set (hp, "xdata", yb(:,:,i), "ydata", xb(:,:,i)); |
399 endif | 446 endif |
400 endfor | 447 endfor |
402 recursion = false; | 449 recursion = false; |
403 end_unwind_protect | 450 end_unwind_protect |
404 endif | 451 endif |
405 endfunction | 452 endfunction |
406 | 453 |
407 function update_group (h, d) | 454 function update_group (h, ~) |
408 persistent recursion = false; | 455 persistent recursion = false; |
409 | 456 |
410 ## Don't allow recursion | 457 ## Don't allow recursion |
411 if (! recursion) | 458 if (! recursion) |
412 unwind_protect | 459 unwind_protect |
414 hlist = get (h, "bargroup"); | 461 hlist = get (h, "bargroup"); |
415 barwidth = get (h, "barwidth"); | 462 barwidth = get (h, "barwidth"); |
416 barlayout = get (h, "barlayout"); | 463 barlayout = get (h, "barlayout"); |
417 horizontal = get (h, "horizontal"); | 464 horizontal = get (h, "horizontal"); |
418 | 465 |
419 ## To prevent recursion, only change if modified | 466 hlist = hlist(hlist != h); # remove current handle being updated |
420 for hh = hlist(:)' | 467 set (hlist, "barwidth", barwidth, "barlayout", barlayout, |
421 if (hh != h) | 468 "horizontal", horizontal); |
422 if (get (hh, "barwidth") != barwidth) | 469 update_data (h); |
423 set (hh, "barwidth", barwidth); | |
424 endif | |
425 if (! strcmpi (get (hh, "barlayout"), barlayout)) | |
426 set (hh, "barlayout", barlayout); | |
427 endif | |
428 if (! strcmpi (get (hh, "horizontal"), horizontal)) | |
429 set (hh, "horizontal", horizontal); | |
430 endif | |
431 endif | |
432 endfor | |
433 update_data (h, d); | |
434 unwind_protect_cleanup | 470 unwind_protect_cleanup |
435 recursion = false; | 471 recursion = false; |
436 end_unwind_protect | 472 end_unwind_protect |
437 endif | 473 endif |
438 endfunction | 474 endfunction |