Mercurial > hg > octave-nkf
comparison scripts/plot/legend.m @ 10949:848f3a13b7cf
Backed out changeset 6b50fd2d4ca6
author | David Bateman <dbateman@free.fr> |
---|---|
date | Tue, 07 Sep 2010 21:44:13 +0200 |
parents | 6b50fd2d4ca6 |
children | 6ea65c5de87a |
comparison
equal
deleted
inserted
replaced
10948:6b50fd2d4ca6 | 10949:848f3a13b7cf |
---|---|
1 ## Copyright (C) 2010 David Bateman | 1 ## Copyright (C) 2001, 2006, 2007, 2008, 2009 Laurent Mazet |
2 ## Copyright (C) 2006 John W. Eaton | |
2 ## | 3 ## |
3 ## This file is part of Octave. | 4 ## This file is part of Octave. |
4 ## | 5 ## |
5 ## Octave is free software; you can redistribute it and/or modify it | 6 ## Octave is free software; you can redistribute it and/or modify it |
6 ## under the terms of the GNU General Public License as published by | 7 ## under the terms of the GNU General Public License as published by |
19 ## -*- texinfo -*- | 20 ## -*- texinfo -*- |
20 ## @deftypefn {Function File} {} legend (@var{str1}, @var{str2}, @dots{}) | 21 ## @deftypefn {Function File} {} legend (@var{str1}, @var{str2}, @dots{}) |
21 ## @deftypefnx {Function File} {} legend (@var{matstr}) | 22 ## @deftypefnx {Function File} {} legend (@var{matstr}) |
22 ## @deftypefnx {Function File} {} legend (@var{cell}) | 23 ## @deftypefnx {Function File} {} legend (@var{cell}) |
23 ## @deftypefnx {Function File} {} legend (@dots{}, "location", @var{pos}) | 24 ## @deftypefnx {Function File} {} legend (@dots{}, "location", @var{pos}) |
24 ## @deftypefnx {Function File} {} legend (@dots{}, "orientation", @var{orient}) | |
25 ## @deftypefnx {Function File} {} legend (@var{hax}, @dots{}) | 25 ## @deftypefnx {Function File} {} legend (@var{hax}, @dots{}) |
26 ## @deftypefnx {Function File} {} legend (@var{hobjs}, @dots{}) | 26 ## @deftypefnx {Function File} {} legend (@var{hobjs}, @dots{}) |
27 ## @deftypefnx {Function File} {} legend (@var{hax}, @var{hobjs}, @dots{}) | 27 ## @deftypefnx {Function File} {} legend (@var{hax}, @var{hobjs}, @dots{}) |
28 ## @deftypefnx {Function File} {} legend ("@var{option}") | 28 ## @deftypefnx {Function File} {} legend ("@var{option}") |
29 ## | 29 ## |
68 ## | 68 ## |
69 ## @item @tab outside @tab | 69 ## @item @tab outside @tab |
70 ## can be appended to any location string | 70 ## can be appended to any location string |
71 ## @end multitable | 71 ## @end multitable |
72 ## | 72 ## |
73 ## The optional parameter @var{orient} determines if the key elements | |
74 ## are placed vertically or horizontally. The allowed values are "vertical" | |
75 ## or "horizontal" with the default being "vertical". | |
76 ## | |
77 ## The following customizations are available using @var{option}: | 73 ## The following customizations are available using @var{option}: |
78 ## | 74 ## |
79 ## @table @asis | 75 ## @table @asis |
80 ## @item "show" | 76 ## @item "show" |
81 ## Show legend on the plot | 77 ## Show legend on the plot |
96 ## @item "right" | 92 ## @item "right" |
97 ## Place text to the right of the keys | 93 ## Place text to the right of the keys |
98 ## @end table | 94 ## @end table |
99 ## @end deftypefn | 95 ## @end deftypefn |
100 | 96 |
101 function [hlegend2, hobjects2, hplot2, text_strings2] = legend (varargin) | 97 function legend (varargin) |
102 | 98 |
103 [ca, varargin, nargs] = __plt_get_axis_arg__ (true, "legend", varargin{:}); | 99 [ca, varargin, nargin] = __plt_get_axis_arg__ ("legend", varargin{:}); |
104 if (isnan (ca)) | 100 nargs = nargin; |
105 fig = get (0, "currentfigure"); | |
106 if (isempty (fig)) | |
107 ca = gca (); | |
108 fig = get (ca, "parent"); | |
109 else | |
110 ca = get (fig, "children"); | |
111 ca ( ! strcmp (get (get (fig, "children"), "type"), "axes")) = []; | |
112 ca_pos = get (get (fig, "currentaxes"), "position"); | |
113 ca_outpos = get (get (fig, "currentaxes"), "outerposition"); | |
114 for i = numel (ca) : -1 : 1 | |
115 if (! all (ca_pos, get (ca(i), "position") ) | |
116 || ! all (ca_outpos, get (ca(i), "outerposition"))) | |
117 ca(i) = []; | |
118 endif | |
119 endfor | |
120 endif | |
121 else | |
122 fig = get (ca, "parent"); | |
123 endif | |
124 | 101 |
125 if (all (ishandle (varargin{1}))) | 102 if (all (ishandle (varargin{1}))) |
126 kids = flipud (varargin{1}(:)); | 103 kids = flipud (varargin{1}(:)); |
127 varargin(1) = []; | 104 varargin(1) = []; |
128 nargs = numel (varargin); | 105 nargs = numel (varargin); |
129 else | 106 else |
130 kids = get (fig, "children"); | 107 kids = get (ca, "children"); |
131 kids (strcmp (get (kids, "tag"), "legend")) = []; | |
132 if (isscalar (kids)) | |
133 kids = get(kids, "children")(:); | |
134 else | |
135 kids = [get(kids, "children"){:}](:); | |
136 endif | |
137 endif | 108 endif |
138 nkids = numel (kids); | 109 nkids = numel (kids); |
139 | 110 |
140 position = "northeast"; | |
141 orientation = "vertical"; | |
142 if (nargs > 0) | 111 if (nargs > 0) |
143 pos = varargin{nargs}; | 112 pos = varargin{nargs}; |
144 if (isnumeric (pos) && isscalar (pos) && round (pos) == pos) | 113 if (isnumeric (pos) && isscalar (pos) && round (pos) == pos) |
145 if (pos >= -1 && pos <= 4) | 114 if (pos >= -1 && pos <= 4) |
146 position = {"northeastoutside", "best", "northeast", | 115 set (ca, "keypos", pos); |
147 "northwest", "southwest", "southeast"} (pos + 2); | |
148 nargs--; | 116 nargs--; |
149 else | 117 else |
150 error ("legend: invalid position specified"); | 118 error ("legend: invalid position specified"); |
151 endif | 119 endif |
152 endif | 120 endif |
153 endif | 121 endif |
154 | 122 |
155 while (nargs > 1) | 123 if (nargs > 1) |
156 pos = varargin{nargs-1}; | 124 pos = varargin{nargs-1}; |
157 str = varargin{nargs}; | 125 str = varargin{nargs}; |
158 if (strcmpi (pos, "location") && ischar (str)) | 126 if (strcmpi (pos, "location") && ischar (str)) |
159 position = lower (str); | 127 set (ca, "keypos", str); |
160 nargs -= 2; | 128 nargs -= 2; |
161 elseif (strcmpi (pos, "orientation") && ischar (str)) | 129 endif |
162 orientation = lower (str); | 130 endif |
163 nargs -= 2; | 131 |
164 else | 132 k = 1; |
165 break; | 133 turn_on_legend = false; |
166 endif | |
167 endwhile | |
168 | |
169 ## Validate the orientation | |
170 switch (orientation) | |
171 case {"vertical", "horizontal"} | |
172 otherwise | |
173 error ("legend: unrecognized legend orientation"); | |
174 endswitch | |
175 | |
176 ## Validate the position type is valid | |
177 outside = false; | |
178 inout = findstr (position, "outside"); | |
179 if (! isempty (inout)) | |
180 outside = true; | |
181 position = position(1:inout-1); | |
182 else | |
183 outside = false; | |
184 endif | |
185 | |
186 switch (position) | |
187 case {"north", "south", "east", "west", "northeast", "northwest", ... | |
188 "southeast", "southwest"} | |
189 case "best" | |
190 warning ("legend: 'Best' not yet implemented for location specifier\n"); | |
191 position = "northeast"; | |
192 otherwise | |
193 error ("legend: unrecognized legend position"); | |
194 endswitch | |
195 | |
196 show = "create"; | |
197 textpos = "default"; | |
198 reverse = false; | |
199 box = "default"; | |
200 | |
201 hlegend = []; | |
202 fkids = get (fig, "children"); | |
203 for i = 1 : numel(fkids) | |
204 if (ishandle (fkids (i)) && strcmp (get (fkids (i), "type"), "axes") | |
205 && (strcmp (get (fkids (i), "tag"), "legend"))) | |
206 udata = get (fkids (i), "userdata"); | |
207 if (! isempty (intersect (udata.handle, ca))) | |
208 hlegend = fkids (i); | |
209 break; | |
210 endif | |
211 endif | |
212 endfor | |
213 | 134 |
214 if (nargs == 1) | 135 if (nargs == 1) |
215 arg = varargin{1}; | 136 arg = varargin{1}; |
216 if (ischar (arg)) | 137 if (ischar (arg)) |
217 if (rows (arg) == 1) | 138 if (rows (arg) == 1) |
218 str = tolower (deblank (arg)); | 139 str = tolower (deblank (arg)); |
219 switch (str) | 140 switch (str) |
220 case {"off", "hide"} | 141 case {"off", "hide"} |
221 show = "off"; | 142 set (ca, "key", "off"); |
222 nargs--; | 143 nargs--; |
223 case "show" | 144 case "show" |
224 show = "on"; | 145 set (ca, "key", "on"); |
225 nargs--; | 146 nargs--; |
226 case "toggle" | 147 case "toggle" |
227 if (isempty (hlegend) || strcmp (get (hlegend, "visible"), "off")) | 148 val = get (ca, "key"); |
228 show = "on"; | 149 if (strcmpi (val, "on")) |
150 set (ca, "key", "off"); | |
229 else | 151 else |
230 show = "off"; | 152 set (ca, "key", "on"); |
231 endif | 153 endif |
232 nargs--; | 154 nargs--; |
233 case "boxon" | 155 case "boxon" |
234 box = "on"; | 156 set (ca, "key", "on", "keybox", "on"); |
235 nargs--; | 157 nargs--; |
236 case "boxoff" | 158 case "boxoff" |
237 box = "off"; | 159 set (ca, "keybox", "off"); |
238 nargs--; | 160 nargs--; |
239 case "left" | 161 case "left" |
240 textpos = "left"; | 162 set (ca, "keyreverse", "off") |
241 reverse = false; | |
242 nargs--; | 163 nargs--; |
243 case "right" | 164 case "right" |
244 textpos = "right"; | 165 set (ca, "keyreverse", "on") |
245 reverse = true; | |
246 nargs--; | 166 nargs--; |
247 otherwise | 167 otherwise |
248 endswitch | 168 endswitch |
249 else | 169 else |
250 varargin = cellstr (arg); | 170 varargin = cellstr (arg); |
256 else | 176 else |
257 error ("legend: expecting argument to be a character string"); | 177 error ("legend: expecting argument to be a character string"); |
258 endif | 178 endif |
259 endif | 179 endif |
260 | 180 |
261 if (strcmp (show, "off")) | 181 if (nargs > 0) |
262 if (! isempty (hlegend)) | 182 have_data = false; |
263 set (hlegend, "visible", "off"); | 183 for k = 1:nkids |
264 set (get (hlegend, "children"), "visible", "off"); | 184 typ = get (kids(k), "type"); |
265 hlegend = []; | 185 if (strcmp (typ, "line") || strcmp (typ, "surface") |
266 endif | 186 || strcmp (typ, "patch") || strcmp (typ, "hggroup")) |
267 hobjects = []; | 187 have_data = true; |
268 hplots = []; | |
269 text_strings = {}; | |
270 elseif (strcmp (show, "on")) | |
271 if (! isempty (hlegend)) | |
272 set (hlegend, "visible", "on"); | |
273 set (get (hlegend, "children"), "visible", "on"); | |
274 else | |
275 hobjects = []; | |
276 hplots = []; | |
277 text_strings = {}; | |
278 endif | |
279 elseif (strcmp (box, "on")) | |
280 if (! isempty (hlegend)) | |
281 set (hlegend, "visible", "on", "box", "on"); | |
282 endif | |
283 elseif (strcmp (box, "off")) | |
284 if (! isempty (hlegend)) | |
285 set (hlegend, "box", "off", "visible", "off"); | |
286 endif | |
287 else | |
288 hobjects = []; | |
289 hplots = []; | |
290 text_strings = {}; | |
291 | |
292 if (nargs > 0) | |
293 have_data = false; | |
294 for k = 1:nkids | |
295 typ = get (kids(k), "type"); | |
296 if (strcmp (typ, "line") || strcmp (typ, "surface") | |
297 || strcmp (typ, "patch") || strcmp (typ, "hggroup")) | |
298 have_data = true; | |
299 break; | |
300 endif | |
301 endfor | |
302 | |
303 if (! have_data) | |
304 warning ("legend: plot data is empty; setting key labels has no effect"); | |
305 endif | |
306 endif | |
307 | |
308 if (strcmp (textpos, "default")) | |
309 warned = false; | |
310 k = nkids; | |
311 for i = 1 : nargs | |
312 arg = varargin{i}; | |
313 if (ischar (arg)) | |
314 typ = get (kids(k), "type"); | |
315 while (k > 0 | |
316 && ! (strcmp (typ, "line") || strcmp (typ, "surface") | |
317 || strcmp (typ, "patch") || strcmp (typ, "hggroup"))) | |
318 typ = get (kids(--k), "type"); | |
319 endwhile | |
320 if (k > 0) | |
321 if (strcmp (get (kids(k), "type"), "hggroup")) | |
322 hgkids = get (kids(k), "children"); | |
323 for j = 1 : length (hgkids) | |
324 hgobj = get (hgkids (j)); | |
325 if (isfield (hgobj, "displayname")) | |
326 set (hgkids(j), "displayname", arg); | |
327 hplots = [hplots, hgkids(j)]; | |
328 text_strings = {text_strings{:}, arg}; | |
329 break; | |
330 endif | |
331 endfor | |
332 else | |
333 set (kids(k), "displayname", arg); | |
334 hplots = [hplots, kids(k)]; | |
335 text_strings = {text_strings{:}, arg}; | |
336 endif | |
337 | |
338 if (--k == 0) | |
339 break; | |
340 endif | |
341 elseif (! warned) | |
342 warned = true; | |
343 warning ("legend: ignoring extra labels"); | |
344 endif | |
345 else | |
346 error ("legend: expecting argument to be a character string"); | |
347 endif | |
348 endfor | |
349 else | |
350 k = nkids; | |
351 while (k > 0) | |
352 typ = get (kids(k), "type"); | |
353 while (k > 0 | |
354 && ! (strcmp (typ, "line") || strcmp (typ, "surface") | |
355 || strcmp (typ, "patch") || strcmp (typ, "hggroup"))) | |
356 typ = get (kids(--k), "type"); | |
357 endwhile | |
358 if (k > 0) | |
359 if (strcmp (get (kids(k), "type"), "hggroup")) | |
360 hgkids = get (kids(k), "children"); | |
361 for j = 1 : length (hgkids) | |
362 hgobj = get (hgkids (j)); | |
363 if (isfield (hgobj, "displayname") | |
364 && ! isempty (hgobj.displayname)) | |
365 hplots = [hplots, hgkids(j)]; | |
366 text_strings = {text_strings{:}, hbobj.displayname}; | |
367 break; | |
368 endif | |
369 endfor | |
370 else | |
371 if (! isempty (get (kids (k), "displayname"))) | |
372 hplots = [hplots, kids(k)]; | |
373 text_strings = {text_strings{:}, get(kids (k), "displayname")}; | |
374 endif | |
375 endif | |
376 if (--k == 0) | |
377 break; | |
378 endif | |
379 endif | |
380 endwhile | |
381 endif | |
382 | |
383 if (isempty (hplots)) | |
384 if (! isempty (hlegend)) | |
385 fkids = get (fig, "children"); | |
386 delete (fkids (fkids == hlegend)); | |
387 hlegend = []; | |
388 hobjects = []; | |
389 hplots = []; | |
390 text_strings = {}; | |
391 endif | |
392 else | |
393 ## Delete the old legend if it exists | |
394 if (! isempty (hlegend)) | |
395 fkids = get (fig, "children"); | |
396 delete (fkids (fkids == hlegend)); | |
397 endif | |
398 | |
399 ## Force the figure to be drawn here, so that the figure position | |
400 ## is updated correctly before reading it | |
401 drawnow (); | |
402 | |
403 ## Get axis size and fontsize in points. | |
404 ## Rely on listener to handle coversion. | |
405 units = get (ca(1), "units"); | |
406 fontunits = get (ca(1), "fontunits"); | |
407 unwind_protect | |
408 set (ca(1), "units", "points"); | |
409 set (ca(1), "fontunits", "points"); | |
410 ca_pos = get (ca(1), "position"); | |
411 ca_outpos = get (ca(1), "outerposition"); | |
412 ca_fontsize = get (ca(1), "fontsize"); | |
413 unwind_protect_cleanup | |
414 set (ca(1), "units", units); | |
415 set (ca(1), "fontunits", fontunits); | |
416 end_unwind_protect | |
417 | |
418 ## Padding between legend entries horizontally and vertically | |
419 xpadding = 1.2; | |
420 ypadding = 1.2; | |
421 | |
422 ## Length of line segments in the legend in points | |
423 linelength = 15; | |
424 | |
425 ## Create the axis first | |
426 ## FIXME hlegend should inherit properties from "ca" | |
427 curaxes = get (fig, "currentaxes"); | |
428 unwind_protect | |
429 hlegend = axes ("tag", "legend", "userdata", struct ("handle", ca), | |
430 "box", "off", "outerposition", [0, 0, 0, 0], | |
431 "xtick", [], "ytick", [], "xticklabel", "", | |
432 "yticklabel", "", "zticklabel", "", | |
433 "xlim", [0, 1], "ylim", [0, 1], "visible", "off", | |
434 "activepositionproperty", "position"); | |
435 | |
436 ## Add text label to the axis first, checking their extents | |
437 nentries = numel (hplots); | |
438 texthandle = []; | |
439 maxwidth = 0; | |
440 maxheight = 0; | |
441 for k = 1 : nentries | |
442 if (reverse) | |
443 texthandle = [texthandle, text(0, 0, text_strings {k}, | |
444 "horizontalalignment", "left")]; | |
445 else | |
446 texthandle = [texthandle, text(0, 0, text_strings {k}, | |
447 "horizontalalignment", "right")]; | |
448 endif | |
449 units = get (texthandle (end), "units"); | |
450 unwind_protect | |
451 set (texthandle (end), "units", "points"); | |
452 extents = get (texthandle (end), "extent"); | |
453 ## FIXME fudge for gnuplot as the text extents are calculated from | |
454 ## the FreeType text render rather than from gnuplot itself. Your | |
455 ## luck will vary depending on the terminals that are used. | |
456 if (strcmp (get (fig, "__backend__"), "gnuplot")) | |
457 extents = [1,1,1.1,1] .* extents; | |
458 linelength = 20; | |
459 endif | |
460 maxwidth = max (maxwidth, extents (3)); | |
461 maxheight = max (maxheight, extents (4)); | |
462 unwind_protect_cleanup | |
463 set (texthandle (end), "units", units); | |
464 end_unwind_protect | |
465 endfor | |
466 | |
467 num1 = nentries; | |
468 if (strcmp (orientation, "vertical")) | |
469 height = nentries * ypadding * maxheight; | |
470 if (outside) | |
471 if (height > ca_pos (4)) | |
472 ## Avoid shrinking the height of the axis to zero if outside | |
473 num1 = ca_pos(4) / maxheight / ypadding / 2; | |
474 endif | |
475 else | |
476 if (height > 0.9 * ca_pos (4)) | |
477 num1 = 0.9 * ca_pos(4) / maxheight / ypadding; | |
478 endif | |
479 endif | |
480 else | |
481 width = nentries * ypadding * maxwidth; | |
482 if (outside) | |
483 if (width > ca_pos (3)) | |
484 ## Avoid shrinking the width of the axis to zero if outside | |
485 num1 = ca_pos(3) / maxwidth / ypadding / 2; | |
486 endif | |
487 else | |
488 if (width > 0.9 * ca_pos (3)) | |
489 num1 = 0.9 * ca_pos(3) / maxwidth / ypadding; | |
490 endif | |
491 endif | |
492 endif | |
493 num2 = ceil (nentries / num1); | |
494 | |
495 xstep = xpadding * (maxwidth + linelength); | |
496 xpad = (xpadding - 1) * (maxwidth + linelength); | |
497 if (reverse) | |
498 xoffset = xpad / 3; | |
499 txoffset = 2 * xpad / 3 + linelength; | |
500 else | |
501 xoffset = 2 * xpad / 3 + maxwidth; | |
502 txoffset = xpad / 3 + maxwidth; | |
503 endif | |
504 ystep = ypadding * maxheight; | |
505 ypad = (ypadding - 1) * maxheight; | |
506 yoffset = ystep / 2; | |
507 | |
508 ## Place the legend in the desired position | |
509 if (strcmp (orientation, "vertical")) | |
510 lpos = [0, 0, num2 * xstep, num1 * ystep]; | |
511 else | |
512 lpos = [0, 0, num1 * xstep, num2 * ystep]; | |
513 endif | |
514 switch(position) | |
515 case "north" | |
516 if (outside) | |
517 lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ... | |
518 ca_outpos(2) + ca_outpos(4) - lpos(4), lpos(3), lpos(4)]; | |
519 | |
520 new_pos = [ca_pos(1), ca_pos(2), ca_pos(3), ca_pos(4) - lpos(4)]; | |
521 new_outpos = [ca_outpos(1), ca_outpos(2), ca_outpos(3), ... | |
522 ca_outpos(4) - lpos(4)]; | |
523 else | |
524 ca_pos | |
525 lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ... | |
526 ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)]; | |
527 endif | |
528 case "south" | |
529 if (outside) | |
530 lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ca_outpos(2), ... | |
531 lpos(3), lpos(4)]; | |
532 new_pos = [ca_pos(1), ca_pos(2) + lpos(4), ca_pos(3), ... | |
533 ca_pos(4) - lpos(4)]; | |
534 new_outpos = [ca_outpos(1), ca_outpos(2) + lpos(4), ... | |
535 ca_outpos(3), ca_outpos(4) - lpos(4)]; | |
536 else | |
537 lpos = [ca_pos(1) + (ca_pos(3) - lpos(3)) / 2, ... | |
538 ca_pos(2) + ypad, lpos(3), lpos(4)]; | |
539 endif | |
540 case "east" | |
541 if (outside) | |
542 lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3), ... | |
543 ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)]; | |
544 new_pos = [ca_pos(1), ca_pos(2), ca_pos(3) - lpos(3), ca_pos(4)]; | |
545 new_outpos = [ca_outpos(1), ca_outpos(2), ... | |
546 ca_outpos(3) - lpos(3), ca_outpos(4)]; | |
547 else | |
548 lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ... | |
549 ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)]; | |
550 endif | |
551 case "west" | |
552 if (outside) | |
553 lpos = [ca_outpos(1), ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, ... | |
554 lpos(3), lpos(4)]; | |
555 new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ... | |
556 ca_pos(3) - lpos(3), ca_pos(4)]; | |
557 new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ... | |
558 ca_outpos(3) - lpos(3), ca_outpos(4)]; | |
559 else | |
560 lpos = [ca_pos(1) + ypad, ... | |
561 ca_pos(2) + (ca_pos(4) - lpos(4)) / 2, lpos(3), lpos(4)]; | |
562 endif | |
563 case "northeast" | |
564 if (outside) | |
565 lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3), ... | |
566 ca_outpos(2) + ca_outpos(4) - lpos(4), lpos(3), lpos(4)]; | |
567 new_pos = [ca_pos(1), ca_pos(2), ca_pos(3) - lpos(3), ... | |
568 ca_pos(4) - lpos(4)]; | |
569 new_outpos = [ca_outpos(1), ca_outpos(2), ... | |
570 ca_outpos(3) - lpos(3), ca_outpos(4) - lpos(4)]; | |
571 else | |
572 lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ... | |
573 ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)]; | |
574 endif | |
575 case "northwest" | |
576 if (outside) | |
577 lpos = [ca_outpos(1), ca_outpos(2) + ca_outpos(4) - lpos(4), ... | |
578 lpos(3), lpos(4)]; | |
579 new_pos = [ca_pos(1) + lpos(3), ca_pos(2), ... | |
580 ca_pos(3) - lpos(3), ca_pos(4) - lpos(4)]; | |
581 new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2), ... | |
582 ca_outpos(3) - lpos(3), ca_outpos(4) - lpos(4)]; | |
583 else | |
584 lpos = [ca_pos(1) + ypad, ... | |
585 ca_pos(2) + ca_pos(4) - lpos(4) - ypad, lpos(3), lpos(4)]; | |
586 endif | |
587 case "southeast" | |
588 if (outside) | |
589 lpos = [ca_outpos(1) + ca_outpos(3) - lpos(3), ca_outpos(2), | |
590 lpos(3), lpos(4)]; | |
591 new_pos = [ca_pos(1), ca_pos(2) + lpos(4), ... | |
592 ca_pos(3) - lpos(3), ca_pos(4) - lpos(4)]; | |
593 new_outpos = [ca_outpos(1), ca_outpos(2) + lpos(4), ... | |
594 ca_outpos(3) - lpos(3), ca_outpos(4) - lpos(4)]; | |
595 else | |
596 lpos = [ca_pos(1) + ca_pos(3) - lpos(3) - ypad, ... | |
597 ca_pos(2) + ypad, lpos(3), lpos(4)]; | |
598 endif | |
599 case "southwest" | |
600 if (outside) | |
601 lpos = [ca_outpos(1), ca_outpos(2), 0, lpos(3), lpos(4)]; | |
602 new_pos = [ca_pos(1) +lpos(3), ca_pos(2) + lpos(4), ... | |
603 ca_pos(3) - lpos(3), ca_pos(4) - lpos(4)]; | |
604 new_outpos = [ca_outpos(1) + lpos(3), ca_outpos(2) + lpos(4), ... | |
605 ca_outpos(3) - lpos(3), ca_outpos(4) - lpos(4)]; | |
606 else | |
607 lpos = [ca_pos(1) + ypad, ca_pos(2) + ypad, lpos(3), lpos(4)]; | |
608 endif | |
609 endswitch | |
610 | |
611 units = get (hlegend, "units"); | |
612 unwind_protect | |
613 set (hlegend, "units", "points"); | |
614 set (hlegend, "position", lpos, "outerposition", lpos); | |
615 unwind_protect_cleanup | |
616 set (hlegend, "units", units); | |
617 end_unwind_protect | |
618 | |
619 ## Now write the line segments and place the text objects correctly | |
620 xk = 0; | |
621 yk = 0; | |
622 for k = 1 : numel (hplots) | |
623 hobjects = [hobjects, texthandle (k)]; | |
624 color = get (hplots (k), "color"); | |
625 style = get (hplots (k), "linestyle"); | |
626 if (! strcmp (style, "none")) | |
627 l1 = line ("xdata", ([xoffset, xoffset + linelength] + xk * xstep) / lpos(3), | |
628 "ydata", [1, 1] .* (lpos(4) - yoffset - yk * ystep) / lpos(4), | |
629 "color", color, "linestyle", style); | |
630 hobjects = [hobjects, l1]; | |
631 endif | |
632 marker = get (hplots (k), "marker"); | |
633 if (! strcmp (marker, "none")) | |
634 l1 = line ("xdata", (xoffset + 0.5 * linelength + xk * xstep) / lpos(3), | |
635 "ydata", (lpos(4) - yoffset - yk * ystep) / lpos(4), | |
636 "color", color, "marker", marker, | |
637 "markeredgecolor", get (hplots (k), "markeredgecolor"), | |
638 "markerfacecolor", get (hplots (k), "markerfacecolor"), | |
639 "markersize", get (hplots (k), "markersize")); | |
640 hobjects = [hobjects, l1]; | |
641 endif | |
642 set (texthandle (k), "position", [(txoffset + xk * xstep) / lpos(3), ... | |
643 (lpos(4) - yoffset - yk * ystep) / lpos(4)]); | |
644 | |
645 if (strcmp (orientation, "vertical")) | |
646 yk++; | |
647 if (yk > num1) | |
648 yk = 0; | |
649 xk++; | |
650 endif | |
651 else | |
652 xk++; | |
653 if (xk > num1) | |
654 xk = 0; | |
655 yk++; | |
656 endif | |
657 endif | |
658 endfor | |
659 | |
660 ## Add an invisible text object to original axis | |
661 ## that when it is destroyed will remove the legend | |
662 t1 = text (0, 0, "", "parent", ca(1), "tag", "legend", | |
663 "handlevisibility", "off", "visible", "off", | |
664 "xliminclude", "off", "yliminclude", "off"); | |
665 set (t1, "deletefcn", {@deletelegend1, hlegend}); | |
666 | |
667 ## Resize the axis the legend is attached to if the | |
668 ## legend is "outside" the plot and create listener to | |
669 ## resize axis to original size if the legend is deleted, | |
670 ## hidden or shown | |
671 if (outside) | |
672 for i = 1 : numel (ca) | |
673 units = get (ca(i), "units"); | |
674 unwind_protect | |
675 set (ca(i), "units", "points"); | |
676 set (ca (i), "position", new_pos, "outerposition", new_outpos); | |
677 unwind_protect_cleanup | |
678 set (ca(i), "units", units); | |
679 end_unwind_protect | |
680 endfor | |
681 | |
682 set (hlegend, "deletefcn", {@deletelegend2, ca, ... | |
683 ca_pos, ca_outpos, t1}); | |
684 addlistener (hlegend, "visible", {@hideshowlegend, ca, ... | |
685 ca_pos, new_pos, ... | |
686 ca_outpos, new_outpos}); | |
687 else | |
688 set (hlegend, "deletefcn", {@deletelegend2, ca, [], [], t1}); | |
689 endif | |
690 unwind_protect_cleanup | |
691 set (fig, "currentaxes", curaxes); | |
692 end_unwind_protect | |
693 endif | |
694 endif | |
695 | |
696 if (nargout > 0) | |
697 hlegend2 = hlegend2; | |
698 hobjects2 = hobjects; | |
699 hplot2 = hplots; | |
700 text_strings2 = text_strings; | |
701 endif | |
702 | |
703 endfunction | |
704 | |
705 function hideshowlegend (h, d, ca, pos1, pos2, outpos1, outpos2) | |
706 isvisible = strcmp (get (h, "visible"), "off"); | |
707 if (! isvisible) | |
708 kids = get (h, "children"); | |
709 for i = 1 : numel (kids) | |
710 if (! strcmp (get (kids(i), "visible"), "off")) | |
711 isvisible = true; | |
712 break; | 188 break; |
713 endif | 189 endif |
714 endfor | 190 endfor |
715 endif | 191 if (! have_data) |
716 | 192 warning ("legend: plot data is empty; setting key labels has no effect"); |
717 for i = 1 : numel (ca) | 193 endif |
718 if (ishandle (ca(i)) && strcmp (get (ca(i), "type"), "axes") && | 194 endif |
719 (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off")) && | 195 |
720 strcmp (get (ca(i), "beingdeleted"), "off")) | 196 warned = false; |
721 units = get (ca(i), "units"); | 197 k = nkids; |
722 unwind_protect | 198 for i = 1:nargs |
723 set (ca(i), "units", "points"); | 199 arg = varargin{i}; |
724 if (isvisible) | 200 if (ischar (arg)) |
725 set (ca(i), "position", pos2, "outerposition", outpos2); | 201 typ = get (kids(k), "type"); |
202 while (k > 1 | |
203 && ! (strcmp (typ, "line") || strcmp (typ, "surface") | |
204 || strcmp (typ, "patch") || strcmp (typ, "hggroup"))) | |
205 typ = get (kids(--k), "type"); | |
206 endwhile | |
207 if (k > 0) | |
208 if (strcmp (get (kids(k), "type"), "hggroup")) | |
209 hgkids = get (kids(k), "children"); | |
210 for j = 1 : length (hgkids) | |
211 hgobj = get (hgkids (j)); | |
212 if (isfield (hgobj, "keylabel")) | |
213 set (hgkids(j), "keylabel", arg); | |
214 break; | |
215 endif | |
216 endfor | |
726 else | 217 else |
727 set (ca(i), "position", pos1, "outerposition", outpos1); | 218 set (kids(k), "keylabel", arg); |
728 endif | 219 endif |
729 unwind_protect_cleanup | 220 turn_on_legend = true; |
730 set (ca(i), "units", units); | 221 if (--k == 0) |
731 end_unwind_protect | 222 break; |
223 endif | |
224 elseif (! warned) | |
225 warned = true; | |
226 warning ("legend: ignoring extra labels"); | |
227 endif | |
228 else | |
229 error ("legend: expecting argument to be a character string"); | |
732 endif | 230 endif |
733 endfor | 231 endfor |
734 endfunction | 232 |
735 | 233 if (turn_on_legend) |
736 function deletelegend1 (h, d, ca) | 234 set (ca, "key", "on"); |
737 if (ishandle (ca) && strcmp (get (ca, "type"), "axes") && | 235 endif |
738 (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off")) && | 236 |
739 strcmp (get (ca, "beingdeleted"), "off")) | |
740 delete (ca); | |
741 endif | |
742 endfunction | |
743 | |
744 function deletelegend2 (h, d, ca, pos, outpos, t1) | |
745 for i = 1 : numel (ca) | |
746 if (ishandle (ca(i)) && strcmp (get (ca(i), "type"), "axes") && | |
747 (isempty (gcbf()) || strcmp (get (gcbf(), "beingdeleted"),"off")) && | |
748 strcmp (get (ca(i), "beingdeleted"), "off")) | |
749 if (!isempty (pos) && !isempty(outpos)) | |
750 units = get (ca(i), "units"); | |
751 unwind_protect | |
752 set (ca(i), "units", "points"); | |
753 set (ca(i), "position", pos, "outerposition", outpos, "deletefcn", ""); | |
754 unwind_protect_cleanup | |
755 set (ca(i), "units", units); | |
756 end_unwind_protect | |
757 endif | |
758 if (i == 1) | |
759 set (t1, "deletefcn", ""); | |
760 delete (t1); | |
761 endif | |
762 endif | |
763 endfor | |
764 endfunction | 237 endfunction |
765 | 238 |
766 %!demo | 239 %!demo |
767 %! clf | 240 %! clf |
768 %! plot(1:10, 1:10, 1:10, fliplr(1:10)); | 241 %! plot(1:10, 1:10, 1:10, fliplr(1:10)); |