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));