GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
graphics.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2007-2015 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <cctype>
28 #include <cfloat>
29 #include <cstdlib>
30 #include <ctime>
31 
32 #include <algorithm>
33 #include <list>
34 #include <map>
35 #include <set>
36 #include <string>
37 #include <sstream>
38 
39 #include "cmd-edit.h"
40 #include "file-ops.h"
41 #include "file-stat.h"
42 #include "oct-locbuf.h"
43 #include "singleton-cleanup.h"
44 
45 #include "builtins.h"
46 #include "cutils.h"
47 #include "defun.h"
48 #include "display.h"
49 #include "error.h"
50 #include "graphics.h"
51 #include "input.h"
52 #include "ov.h"
53 #include "oct-obj.h"
54 #include "oct-map.h"
55 #include "ov-fcn-handle.h"
56 #include "pager.h"
57 #include "parse.h"
58 #include "toplev.h"
59 #include "txt-eng-ft.h"
60 #include "unwind-prot.h"
61 #include "octave-default-image.h"
62 
63 // forward declarations
64 static octave_value xget (const graphics_handle& h, const caseless_str& name);
65 
66 static void
67 gripe_set_invalid (const std::string& pname)
68 {
69  error ("set: invalid value for %s property", pname.c_str ());
70 }
71 
72 // Check to see that PNAME matches just one of PNAMES uniquely.
73 // Return the full name of the match, or an empty caseless_str object
74 // if there is no match, or the match is ambiguous.
75 
76 static caseless_str
77 validate_property_name (const std::string& who, const std::string& what,
78  const std::set<std::string>& pnames,
79  const caseless_str& pname)
80 {
81  size_t len = pname.length ();
82  std::set<std::string> matches;
83 
84  for (std::set<std::string>::const_iterator p = pnames.begin ();
85  p != pnames.end (); p++)
86  {
87  if (pname.compare (*p, len))
88  {
89  if (len == p->length ())
90  {
91  // Exact match.
92  return pname;
93  }
94 
95  matches.insert (*p);
96  }
97  }
98 
99  size_t num_matches = matches.size ();
100 
101  if (num_matches == 0)
102  {
103  error ("%s: unknown %s property %s",
104  who.c_str (), what.c_str (), pname.c_str ());
105  }
106  else if (num_matches > 1)
107  {
108  string_vector sv (matches);
109 
110  std::ostringstream os;
111 
112  sv.list_in_columns (os);
113 
114  std::string match_list = os.str ();
115 
116  error ("%s: ambiguous %s property name %s; possible matches:\n\n%s",
117  who.c_str (), what.c_str (), pname.c_str (), match_list.c_str ());
118  }
119  else if (num_matches == 1)
120  {
121  // Exact match was handled above.
122 
123  std::string possible_match = *(matches.begin ());
124 
125  warning_with_id ("Octave:abbreviated-property-match",
126  "%s: allowing %s to match %s property %s",
127  who.c_str (), pname.c_str (), what.c_str (),
128  possible_match.c_str ());
129 
130  return possible_match;
131  }
132 
133  return caseless_str ();
134 }
135 
136 static Matrix
138 {
139  Matrix cmap (64, 3, 0.0);
140 
141  // Produce X in the same manner as linspace so that
142  // jet_colormap and jet.m produce *exactly* the same result.
143  double delta = 1.0 / 63.0;
144 
145  for (octave_idx_type i = 0; i < 64; i++)
146  {
147  // This is the jet colormap. It would be nice to be able
148  // to feval the jet function but since there is a static
149  // property object that includes a colormap_property
150  // object, we need to initialize this before main is even
151  // called, so calling an interpreted function is not
152  // possible.
153 
154  double x = i*delta;
155 
156  if (x >= 3.0/8.0 && x < 5.0/8.0)
157  cmap(i,0) = 4.0 * x - 3.0/2.0;
158  else if (x >= 5.0/8.0 && x < 7.0/8.0)
159  cmap(i,0) = 1.0;
160  else if (x >= 7.0/8.0)
161  cmap(i,0) = -4.0 * x + 9.0/2.0;
162 
163  if (x >= 1.0/8.0 && x < 3.0/8.0)
164  cmap(i,1) = 4.0 * x - 1.0/2.0;
165  else if (x >= 3.0/8.0 && x < 5.0/8.0)
166  cmap(i,1) = 1.0;
167  else if (x >= 5.0/8.0 && x < 7.0/8.0)
168  cmap(i,1) = -4.0 * x + 7.0/2.0;
169 
170  if (x < 1.0/8.0)
171  cmap(i,2) = 4.0 * x + 1.0/2.0;
172  else if (x >= 1.0/8.0 && x < 3.0/8.0)
173  cmap(i,2) = 1.0;
174  else if (x >= 3.0/8.0 && x < 5.0/8.0)
175  cmap(i,2) = -4.0 * x + 5.0/2.0;
176  }
177 
178  return cmap;
179 }
180 
181 static double
183 {
184  return display_info::depth ();
185 }
186 
187 static Matrix
189 {
190  Matrix retval (1, 4, 1.0);
191 
192  retval(2) = display_info::width ();
193  retval(3) = display_info::height ();
194 
195  return retval;
196 }
197 
198 static double
200 {
201  return (display_info::x_dpi () + display_info::y_dpi ()) / 2;
202 }
203 
204 static Matrix
206 {
207  Matrix retval (7, 3, 0.0);
208 
209  retval(0,2) = 1.0;
210 
211  retval(1,1) = 0.5;
212 
213  retval(2,0) = 1.0;
214 
215  retval(3,1) = 0.75;
216  retval(3,2) = 0.75;
217 
218  retval(4,0) = 0.75;
219  retval(4,2) = 0.75;
220 
221  retval(5,0) = 0.75;
222  retval(5,1) = 0.75;
223 
224  retval(6,0) = 0.25;
225  retval(6,1) = 0.25;
226  retval(6,2) = 0.25;
227 
228  return retval;
229 }
230 
231 static Matrix
232 default_lim (bool logscale = false)
233 {
234  Matrix m (1, 2, 0);
235 
236  if (logscale)
237  {
238  m(0) = 0.1;
239  m(1) = 1.0;
240  }
241  else
242  m(1) = 1;
243 
244  return m;
245 }
246 
247 static Matrix
249 {
250  Matrix retval (1, 2);
251 
252  retval(0) = 0;
253  retval(1) = 1;
254 
255  return retval;
256 }
257 
258 static Matrix
260 {
261  Matrix m (64, 64, 0.0);
262  int i = 0;
263  for (int col = 0; col < 64; col++)
264  for (int row = 0; row < 64; row++)
265  {
266  m(col,row) = static_cast<double> (default_im_data[i]);
267  i++;
268  }
269 
270  return m;
271 }
272 
273 static Matrix
275 {
276  Matrix m (3, 3, 0.0);
277  for (int col = 0; col < 3; col++)
278  for (int row = 0; row < 3; row++)
279  m(row,col) = col+1;
280 
281  return m;
282 }
283 
284 static Matrix
286 {
287  Matrix m (3, 3, 0.0);
288  for (int row = 0; row < 3; row++)
289  for (int col = 0; col < 3; col++)
290  m(row,col) = row+1;
291 
292  return m;
293 }
294 
295 static Matrix
297 {
298  Matrix m (3, 3, 0.0);
299  for (int row = 0; row < 3; row++)
300  m(row,row) = 1.0;
301  return m;
302 }
303 
304 static Matrix
306 {
307  return default_surface_zdata ();
308 }
309 
310 static Matrix
312 {
313  Matrix m (1, 3, 1.0);
314  m(1) = 2.0;
315  m(2) = 3.0;
316  return m;
317 }
318 
319 static Matrix
321 {
322  Matrix m (3, 2, 0);
323  m(1) = 1.0;
324  m(3) = 1.0;
325  m(4) = 1.0;
326  return m;
327 }
328 
329 static Matrix
331 {
332  Matrix m (3, 1, 0.0);
333  m(1) = 1.0;
334  return m;
335 }
336 
337 static Matrix
339 {
340  Matrix m (3, 1, 1.0);
341  m(2) = 0.0;
342  return m;
343 }
344 
345 static Matrix
347 {
348  Matrix m (1, 4, 0.0);
349  m(0) = 0.13;
350  m(1) = 0.11;
351  m(2) = 0.775;
352  m(3) = 0.815;
353  return m;
354 }
355 
356 static Matrix
358 {
359  Matrix m (1, 4, 0.0);
360  m(2) = m(3) = 1.0;
361  return m;
362 }
363 
364 static Matrix
366 {
367  Matrix m (1, 2, 0.0);
368  m(1) = 90.0;
369  return m;
370 }
371 
372 static Matrix
374 {
375  Matrix m (1, 6, 0.0);
376  m(0) = 0.0;
377  m(1) = 0.2;
378  m(2) = 0.4;
379  m(3) = 0.6;
380  m(4) = 0.8;
381  m(5) = 1.0;
382  return m;
383 }
384 
385 static Matrix
387 {
388  Matrix m (1, 2, 0.0);
389  m(0) = 0.01;
390  m(1) = 0.025;
391  return m;
392 }
393 
394 static Matrix
396 {
397  Matrix m (1, 4, 0.0);
398  m(0) = 300;
399  m(1) = 200;
400  m(2) = 560;
401  m(3) = 420;
402  return m;
403 }
404 
405 static Matrix
407 {
408  Matrix m (1, 2, 0.0);
409  m(0) = 8.5;
410  m(1) = 11.0;
411  return m;
412 }
413 
414 static Matrix
416 {
417  Matrix m (1, 4, 0.0);
418  m(0) = 0.25;
419  m(1) = 2.50;
420  m(2) = 8.00;
421  m(3) = 6.00;
422  return m;
423 }
424 
425 static Matrix
427 {
428  Matrix retval (1, 4, 0.0);
429 
430  retval(0) = 0;
431  retval(1) = 0;
432  retval(2) = 80;
433  retval(3) = 30;
434 
435  return retval;
436 }
437 
438 static Matrix
440 {
441  Matrix retval (1, 2, 0.0);
442 
443  retval(0) = 0.01;
444  retval(1) = 0.1;
445 
446  return retval;
447 }
448 
449 static Matrix
451 {
452  Matrix retval (1, 4, 0.0);
453 
454  retval(0) = 0;
455  retval(1) = 0;
456  retval(2) = 1;
457  retval(3) = 1;
458 
459  return retval;
460 }
461 
462 static double
463 convert_font_size (double font_size, const caseless_str& from_units,
464  const caseless_str& to_units, double parent_height = 0)
465 {
466  // Simple case where from_units == to_units
467 
468  if (from_units.compare (to_units))
469  return font_size;
470 
471  // Converts the given fontsize using the following transformation:
472  // <old_font_size> => points => <new_font_size>
473 
474  double points_size = 0;
475  double res = 0;
476 
477  if (from_units.compare ("points"))
478  points_size = font_size;
479  else
480  {
481  res = xget (0, "screenpixelsperinch").double_value ();
482 
483  if (from_units.compare ("pixels"))
484  points_size = font_size * 72.0 / res;
485  else if (from_units.compare ("inches"))
486  points_size = font_size * 72.0;
487  else if (from_units.compare ("centimeters"))
488  points_size = font_size * 72.0 / 2.54;
489  else if (from_units.compare ("normalized"))
490  points_size = font_size * parent_height * 72.0 / res;
491  }
492 
493  double new_font_size = 0;
494 
495  if (to_units.compare ("points"))
496  new_font_size = points_size;
497  else
498  {
499  if (res <= 0)
500  res = xget (0, "screenpixelsperinch").double_value ();
501 
502  if (to_units.compare ("pixels"))
503  new_font_size = points_size * res / 72.0;
504  else if (to_units.compare ("inches"))
505  new_font_size = points_size / 72.0;
506  else if (to_units.compare ("centimeters"))
507  new_font_size = points_size * 2.54 / 72.0;
508  else if (to_units.compare ("normalized"))
509  {
510  // Avoid setting font size to (0/0) = NaN
511 
512  if (parent_height > 0)
513  new_font_size = points_size * res / (parent_height * 72.0);
514  }
515  }
516 
517  return new_font_size;
518 }
519 
520 static Matrix
521 convert_position (const Matrix& pos, const caseless_str& from_units,
522  const caseless_str& to_units, const Matrix& parent_dim)
523 {
524  Matrix retval (1, pos.numel ());
525  double res = 0;
526  bool is_rectangle = (pos.numel () == 4);
527  bool is_2d = (pos.numel () == 2);
528 
529  if (from_units.compare ("pixels"))
530  retval = pos;
531  else if (from_units.compare ("normalized"))
532  {
533  retval(0) = pos(0) * parent_dim(0) + 1;
534  retval(1) = pos(1) * parent_dim(1) + 1;
535  if (is_rectangle)
536  {
537  retval(2) = pos(2) * parent_dim(0);
538  retval(3) = pos(3) * parent_dim(1);
539  }
540  else if (! is_2d)
541  retval(2) = 0;
542  }
543  else if (from_units.compare ("characters"))
544  {
545  if (res <= 0)
546  res = xget (0, "screenpixelsperinch").double_value ();
547 
548  double f = 0.0;
549 
550  // FIXME: this assumes the system font is Helvetica 10pt
551  // (for which "x" requires 6x12 pixels at 74.951 pixels/inch)
552  f = 12.0 * res / 74.951;
553 
554  if (f > 0)
555  {
556  retval(0) = 0.5 * pos(0) * f;
557  retval(1) = pos(1) * f;
558  if (is_rectangle)
559  {
560  retval(2) = 0.5 * pos(2) * f;
561  retval(3) = pos(3) * f;
562  }
563  else if (! is_2d)
564  retval(2) = 0;
565  }
566  }
567  else
568  {
569  if (res <= 0)
570  res = xget (0, "screenpixelsperinch").double_value ();
571 
572  double f = 0.0;
573 
574  if (from_units.compare ("points"))
575  f = res / 72.0;
576  else if (from_units.compare ("inches"))
577  f = res;
578  else if (from_units.compare ("centimeters"))
579  f = res / 2.54;
580 
581  if (f > 0)
582  {
583  retval(0) = pos(0) * f + 1;
584  retval(1) = pos(1) * f + 1;
585  if (is_rectangle)
586  {
587  retval(2) = pos(2) * f;
588  retval(3) = pos(3) * f;
589  }
590  else if (! is_2d)
591  retval(2) = 0;
592  }
593  }
594 
595  if (! to_units.compare ("pixels"))
596  {
597  if (to_units.compare ("normalized"))
598  {
599  retval(0) = (retval(0) - 1) / parent_dim(0);
600  retval(1) = (retval(1) - 1) / parent_dim(1);
601  if (is_rectangle)
602  {
603  retval(2) /= parent_dim(0);
604  retval(3) /= parent_dim(1);
605  }
606  else if (! is_2d)
607  retval(2) = 0;
608  }
609  else if (to_units.compare ("characters"))
610  {
611  if (res <= 0)
612  res = xget (0, "screenpixelsperinch").double_value ();
613 
614  double f = 0.0;
615 
616  f = 12.0 * res / 74.951;
617 
618  if (f > 0)
619  {
620  retval(0) = 2 * retval(0) / f;
621  retval(1) = retval(1) / f;
622  if (is_rectangle)
623  {
624  retval(2) = 2 * retval(2) / f;
625  retval(3) = retval(3) / f;
626  }
627  else if (! is_2d)
628  retval(2) = 0;
629  }
630  }
631  else
632  {
633  if (res <= 0)
634  res = xget (0, "screenpixelsperinch").double_value ();
635 
636  double f = 0.0;
637 
638  if (to_units.compare ("points"))
639  f = res / 72.0;
640  else if (to_units.compare ("inches"))
641  f = res;
642  else if (to_units.compare ("centimeters"))
643  f = res / 2.54;
644 
645  if (f > 0)
646  {
647  retval(0) = (retval(0) - 1) / f;
648  retval(1) = (retval(1) - 1) / f;
649  if (is_rectangle)
650  {
651  retval(2) /= f;
652  retval(3) /= f;
653  }
654  else if (! is_2d)
655  retval(2) = 0;
656  }
657  }
658  }
659  else if (! is_rectangle && ! is_2d)
660  retval(2) = 0;
661 
662  return retval;
663 }
664 
665 static Matrix
667  const caseless_str& from_units,
668  const caseless_str& to_units)
669 {
671  graphics_object ax = go.get_ancestor ("axes");
672 
673  Matrix retval;
674 
675  if (ax.valid_object ())
676  {
677  const axes::properties& ax_props =
678  dynamic_cast<const axes::properties&> (ax.get_properties ());
679  graphics_xform ax_xform = ax_props.get_transform ();
680  bool is_rectangle = (pos.numel () == 4);
681  Matrix ax_bbox = ax_props.get_boundingbox (true),
682  ax_size = ax_bbox.extract_n (0, 2, 1, 2);
683 
684  if (from_units.compare ("data"))
685  {
686  if (is_rectangle)
687  {
688  ColumnVector v1 = ax_xform.transform (pos(0), pos(1), 0),
689  v2 = ax_xform.transform (pos(0) + pos(2),
690  pos(1) + pos(3), 0);
691 
692  retval.resize (1, 4);
693 
694  retval(0) = v1(0) - ax_bbox(0) + 1;
695  retval(1) = ax_bbox(1) + ax_bbox(3) - v1(1) + 1;
696  retval(2) = v2(0) - v1(0);
697  retval(3) = v1(1) - v2(1);
698  }
699  else
700  {
701  ColumnVector v = ax_xform.transform (pos(0), pos(1), pos(2));
702 
703  retval.resize (1, 3);
704 
705  retval(0) = v(0) - ax_bbox(0) + 1;
706  retval(1) = ax_bbox(1) + ax_bbox(3) - v(1) + 1;
707  retval(2) = 0;
708  }
709  }
710  else
711  retval = convert_position (pos, from_units, "pixels", ax_size);
712 
713  if (! to_units.compare ("pixels"))
714  {
715  if (to_units.compare ("data"))
716  {
717  if (is_rectangle)
718  {
719  ColumnVector v1, v2;
720  v1 = ax_xform.untransform (
721  retval(0) + ax_bbox(0) - 1,
722  ax_bbox(1) + ax_bbox(3) - retval(1) + 1);
723  v2 = ax_xform.untransform (
724  retval(0) + retval(2) + ax_bbox(0) - 1,
725  ax_bbox(1) + ax_bbox(3) - (retval(1) + retval(3)) + 1);
726 
727  retval.resize (1, 4);
728 
729  retval(0) = v1(0);
730  retval(1) = v1(1);
731  retval(2) = v2(0) - v1(0);
732  retval(3) = v2(1) - v1(1);
733  }
734  else
735  {
736  ColumnVector v;
737  v = ax_xform.untransform (
738  retval(0) + ax_bbox(0) - 1,
739  ax_bbox(1) + ax_bbox(3) - retval(1) + 1);
740 
741  retval.resize (1, 3);
742 
743  retval(0) = v(0);
744  retval(1) = v(1);
745  retval(2) = v(2);
746  }
747  }
748  else
749  retval = convert_position (retval, "pixels", to_units, ax_size);
750  }
751  }
752 
753  return retval;
754 }
755 
756 // This function always returns the screensize in pixels
757 static Matrix
759 {
761  Matrix sz = obj.get ("screensize").matrix_value ();
762  return convert_position (sz, obj.get ("units").string_value (), "pixels",
763  sz.extract_n (0, 2, 1, 2)).extract_n (0, 2, 1, 2);
764 }
765 
766 static void
767 convert_cdata_2 (bool is_scaled, bool is_real, double clim_0, double clim_1,
768  const double *cmapv, double x, octave_idx_type lda,
769  octave_idx_type nc, octave_idx_type i, double *av)
770 {
771  if (is_scaled)
772  x = xround ((nc - 1) * (x - clim_0) / (clim_1 - clim_0));
773  else if (is_real)
774  x = xround (x - 1);
775 
776  if (xisnan (x))
777  {
778  av[i] = x;
779  av[i+lda] = x;
780  av[i+2*lda] = x;
781  }
782  else
783  {
784  if (x < 0)
785  x = 0;
786  else if (x >= nc)
787  x = (nc - 1);
788 
789  octave_idx_type idx = static_cast<octave_idx_type> (x);
790 
791  av[i] = cmapv[idx];
792  av[i+lda] = cmapv[idx+nc];
793  av[i+2*lda] = cmapv[idx+2*nc];
794  }
795 }
796 
797 template <class T>
798 void
799 convert_cdata_1 (bool is_scaled, bool is_real, double clim_0, double clim_1,
800  const double *cmapv, const T *cv, octave_idx_type lda,
801  octave_idx_type nc, double *av)
802 {
803  for (octave_idx_type i = 0; i < lda; i++)
804  convert_cdata_2 (is_scaled, is_real,
805  clim_0, clim_1, cmapv, cv[i], lda, nc, i, av);
806 }
807 
808 static octave_value
809 convert_cdata (const base_properties& props, const octave_value& cdata,
810  bool is_scaled, int cdim)
811 {
812  dim_vector dv (cdata.dims ());
813 
814  // TrueColor data doesn't require conversion
815  if (dv.length () == cdim && dv(cdim-1) == 3)
816  return cdata;
817 
818  Matrix cmap (1, 3, 0.0);
819  Matrix clim (1, 2, 0.0);
820 
822  graphics_object fig = go.get_ancestor ("figure");
823 
824  if (fig.valid_object ())
825  {
826  Matrix _cmap = fig.get (caseless_str ("colormap")).matrix_value ();
827 
828  if (! error_state)
829  cmap = _cmap;
830  }
831 
832  if (is_scaled)
833  {
834  graphics_object ax = go.get_ancestor ("axes");
835 
836  if (ax.valid_object ())
837  {
838  Matrix _clim = ax.get (caseless_str ("clim")).matrix_value ();
839 
840  if (! error_state)
841  clim = _clim;
842  }
843  }
844 
845  dv.resize (cdim);
846  dv(cdim-1) = 3;
847 
848  NDArray a (dv);
849 
850  octave_idx_type lda = a.numel () / static_cast<octave_idx_type> (3);
851  octave_idx_type nc = cmap.rows ();
852 
853  double *av = a.fortran_vec ();
854  const double *cmapv = cmap.data ();
855 
856  double clim_0 = clim(0);
857  double clim_1 = clim(1);
858 
859  // FIXME: There is a lot of processing time spent just on data conversion
860  // both here in graphics.cc and again in gl-render.cc. There must
861  // be room for improvement! Here a macro expands to a templated
862  // function which in turn calls another function (covert_cdata_2).
863  // And in gl-render.cc (opengl_renderer::draw_image), only GLfloat
864  // is supported anyways so there is another double for loop across
865  // height and width to convert all of the input data to GLfloat.
866 
867 #define CONVERT_CDATA_1(ARRAY_T, VAL_FN, IS_REAL) \
868  do \
869  { \
870  ARRAY_T tmp = cdata. VAL_FN ## array_value (); \
871  \
872  convert_cdata_1 (is_scaled, IS_REAL, clim_0, clim_1, cmapv, \
873  tmp.data (), lda, nc, av); \
874  } \
875  while (0)
876 
877  if (cdata.is_uint8_type ())
878  CONVERT_CDATA_1 (uint8NDArray, uint8_, false);
879  else if (cdata.is_uint16_type ())
880  CONVERT_CDATA_1 (uint16NDArray, uint16_, false);
881  else if (cdata.is_double_type ())
882  CONVERT_CDATA_1 (NDArray, , true);
883  else if (cdata.is_single_type ())
884  CONVERT_CDATA_1 (FloatNDArray, float_, true);
885  else if (cdata.is_bool_type ())
886  CONVERT_CDATA_1 (boolNDArray, bool_, false);
887  else
888  error ("unsupported type for cdata (= %s)", cdata.type_name ().c_str ());
889 
890 #undef CONVERT_CDATA_1
891 
892  return octave_value (a);
893 }
894 
895 template<class T>
896 static void
897 get_array_limits (const Array<T>& m, double& emin, double& emax,
898  double& eminp, double& emaxp)
899 {
900  const T *data = m.data ();
901  octave_idx_type n = m.numel ();
902 
903  for (octave_idx_type i = 0; i < n; i++)
904  {
905  double e = double (data[i]);
906 
907  // Don't need to test for NaN here as NaN>x and NaN<x is always false
908  if (! xisinf (e))
909  {
910  if (e < emin)
911  emin = e;
912 
913  if (e > emax)
914  emax = e;
915 
916  if (e > 0 && e < eminp)
917  eminp = e;
918 
919  if (e < 0 && e > emaxp)
920  emaxp = e;
921  }
922  }
923 }
924 
925 static bool
927  caseless_str& rest)
928 {
929  int len = name.length ();
930  int offset = 0;
931  bool result = false;
932 
933  if (len >= 4)
934  {
935  caseless_str pfx = name.substr (0, 4);
936 
937  if (pfx.compare ("axes") || pfx.compare ("line")
938  || pfx.compare ("text"))
939  offset = 4;
940  else if (len >= 5)
941  {
942  pfx = name.substr (0, 5);
943 
944  if (pfx.compare ("image") || pfx.compare ("patch"))
945  offset = 5;
946  else if (len >= 6)
947  {
948  pfx = name.substr (0, 6);
949 
950  if (pfx.compare ("figure") || pfx.compare ("uimenu"))
951  offset = 6;
952  else if (len >= 7)
953  {
954  pfx = name.substr (0, 7);
955 
956  if (pfx.compare ("surface") || pfx.compare ("hggroup")
957  || pfx.compare ("uipanel"))
958  offset = 7;
959  else if (len >= 9)
960  {
961  pfx = name.substr (0, 9);
962 
963  if (pfx.compare ("uicontrol")
964  || pfx.compare ("uitoolbar"))
965  offset = 9;
966  else if (len >= 10)
967  {
968  pfx = name.substr (0, 10);
969 
970  if (pfx.compare ("uipushtool"))
971  offset = 10;
972  else if (len >= 12)
973  {
974  pfx = name.substr (0, 12);
975 
976  if (pfx.compare ("uitoggletool"))
977  offset = 12;
978  else if (len >= 13)
979  {
980  pfx = name.substr (0, 13);
981 
982  if (pfx.compare ("uicontextmenu"))
983  offset = 13;
984  }
985  }
986  }
987  }
988  }
989  }
990  }
991 
992  if (offset > 0)
993  {
994  go_name = pfx;
995  rest = name.substr (offset);
996  result = true;
997  }
998  }
999 
1000  return result;
1001 }
1002 
1003 static base_graphics_object*
1005  const graphics_handle& h = graphics_handle (),
1006  const graphics_handle& p = graphics_handle ())
1007 {
1008  base_graphics_object *go = 0;
1009 
1010  if (type.compare ("figure"))
1011  go = new figure (h, p);
1012  else if (type.compare ("axes"))
1013  go = new axes (h, p);
1014  else if (type.compare ("line"))
1015  go = new line (h, p);
1016  else if (type.compare ("text"))
1017  go = new text (h, p);
1018  else if (type.compare ("image"))
1019  go = new image (h, p);
1020  else if (type.compare ("patch"))
1021  go = new patch (h, p);
1022  else if (type.compare ("surface"))
1023  go = new surface (h, p);
1024  else if (type.compare ("hggroup"))
1025  go = new hggroup (h, p);
1026  else if (type.compare ("uimenu"))
1027  go = new uimenu (h, p);
1028  else if (type.compare ("uicontrol"))
1029  go = new uicontrol (h, p);
1030  else if (type.compare ("uipanel"))
1031  go = new uipanel (h, p);
1032  else if (type.compare ("uicontextmenu"))
1033  go = new uicontextmenu (h, p);
1034  else if (type.compare ("uitoolbar"))
1035  go = new uitoolbar (h, p);
1036  else if (type.compare ("uipushtool"))
1037  go = new uipushtool (h, p);
1038  else if (type.compare ("uitoggletool"))
1039  go = new uitoggletool (h, p);
1040  return go;
1041 }
1042 
1043 // ---------------------------------------------------------------------
1044 
1045 bool
1046 base_property::set (const octave_value& v, bool do_run, bool do_notify_toolkit)
1047 {
1048  if (do_set (v))
1049  {
1050 
1051  // Notify graphics toolkit.
1052  if (id >= 0 && do_notify_toolkit)
1053  {
1055  if (go)
1056  go.update (id);
1057  }
1058 
1059  // run listeners
1060  if (do_run && ! error_state)
1062 
1063  return true;
1064  }
1065 
1066  return false;
1067 }
1068 
1069 
1070 void
1072 {
1073  const octave_value_list& l = listeners[mode];
1074 
1075  for (int i = 0; i < l.length (); i++)
1076  {
1078 
1079  if (error_state)
1080  break;
1081  }
1082 }
1083 
1084 radio_values::radio_values (const std::string& opt_string)
1085  : default_val (), possible_vals ()
1086 {
1087  size_t beg = 0;
1088  size_t len = opt_string.length ();
1089  bool done = len == 0;
1090 
1091  while (! done)
1092  {
1093  size_t end = opt_string.find ('|', beg);
1094 
1095  if (end == std::string::npos)
1096  {
1097  end = len;
1098  done = true;
1099  }
1100 
1101  std::string t = opt_string.substr (beg, end-beg);
1102 
1103  // Might want more error checking here...
1104  if (t[0] == '{')
1105  {
1106  t = t.substr (1, t.length () - 2);
1107  default_val = t;
1108  }
1109  else if (beg == 0) // ensure default value
1110  default_val = t;
1111 
1112  possible_vals.insert (t);
1113 
1114  beg = end + 1;
1115  }
1116 }
1117 
1118 std::string
1120 {
1121  std::string retval;
1122  for (std::set<caseless_str>::const_iterator it = possible_vals.begin ();
1123  it != possible_vals.end (); it++)
1124  {
1125  if (retval.empty ())
1126  {
1127  if (*it == default_value ())
1128  retval = "{" + *it + "}";
1129  else
1130  retval = *it;
1131  }
1132  else
1133  {
1134  if (*it == default_value ())
1135  retval += " | {" + *it + "}";
1136  else
1137  retval += " | " + *it;
1138  }
1139  }
1140 
1141  if (! retval.empty ())
1142  retval = "[ " + retval + " ]";
1143 
1144  return retval;
1145 }
1146 
1147 Cell
1149 {
1150  octave_idx_type i = 0;
1151  Cell retval (nelem (), 1);
1152  for (std::set<caseless_str>::const_iterator it = possible_vals.begin ();
1153  it != possible_vals.end (); it++)
1154  retval(i++) = std::string (*it);
1155  return retval;
1156 }
1157 
1158 bool
1159 color_values::str2rgb (const std::string& str_arg)
1160 {
1161  bool retval = true;
1162 
1163  double tmp_rgb[3] = {0, 0, 0};
1164 
1165  std::string str = str_arg;
1166  unsigned int len = str.length ();
1167 
1168  std::transform (str.begin (), str.end (), str.begin (), tolower);
1169 
1170  if (str.compare (0, len, "blue", 0, len) == 0)
1171  tmp_rgb[2] = 1;
1172  else if (str.compare (0, len, "black", 0, len) == 0
1173  || str.compare (0, len, "k", 0, len) == 0)
1174  tmp_rgb[0] = tmp_rgb[1] = tmp_rgb[2] = 0;
1175  else if (str.compare (0, len, "red", 0, len) == 0)
1176  tmp_rgb[0] = 1;
1177  else if (str.compare (0, len, "green", 0, len) == 0)
1178  tmp_rgb[1] = 1;
1179  else if (str.compare (0, len, "yellow", 0, len) == 0)
1180  tmp_rgb[0] = tmp_rgb[1] = 1;
1181  else if (str.compare (0, len, "magenta", 0, len) == 0)
1182  tmp_rgb[0] = tmp_rgb[2] = 1;
1183  else if (str.compare (0, len, "cyan", 0, len) == 0)
1184  tmp_rgb[1] = tmp_rgb[2] = 1;
1185  else if (str.compare (0, len, "white", 0, len) == 0
1186  || str.compare (0, len, "w", 0, len) == 0)
1187  tmp_rgb[0] = tmp_rgb[1] = tmp_rgb[2] = 1;
1188  else
1189  retval = false;
1190 
1191  if (retval)
1192  {
1193  for (int i = 0; i < 3; i++)
1194  xrgb(i) = tmp_rgb[i];
1195  }
1196 
1197  return retval;
1198 }
1199 
1200 bool
1202 {
1203  if (val.is_string ())
1204  {
1205  std::string s = val.string_value ();
1206 
1207  if (! s.empty ())
1208  {
1209  std::string match;
1210 
1211  if (radio_val.contains (s, match))
1212  {
1213  if (current_type != radio_t || match != current_val)
1214  {
1215  if (s.length () != match.length ())
1216  warning_with_id ("Octave:abbreviated-property-match",
1217  "%s: allowing %s to match %s value %s",
1218  "set", s.c_str (), get_name ().c_str (),
1219  match.c_str ());
1220  current_val = match;
1222  return true;
1223  }
1224  }
1225  else
1226  {
1227  color_values col (s);
1228  if (! error_state)
1229  {
1230  if (current_type != color_t || col != color_val)
1231  {
1232  color_val = col;
1234  return true;
1235  }
1236  }
1237  else
1238  error ("invalid value for color property \"%s\" (value = %s)",
1239  get_name ().c_str (), s.c_str ());
1240  }
1241  }
1242  else
1243  error ("invalid value for color property \"%s\"",
1244  get_name ().c_str ());
1245  }
1246  else if (val.is_numeric_type ())
1247  {
1248  Matrix m = val.matrix_value ();
1249 
1250  if (m.numel () == 3)
1251  {
1252  color_values col (m(0), m(1), m(2));
1253  if (! error_state)
1254  {
1255  if (current_type != color_t || col != color_val)
1256  {
1257  color_val = col;
1259  return true;
1260  }
1261  }
1262  }
1263  else
1264  error ("invalid value for color property \"%s\"",
1265  get_name ().c_str ());
1266  }
1267  else
1268  error ("invalid value for color property \"%s\"",
1269  get_name ().c_str ());
1270 
1271  return false;
1272 }
1273 
1274 bool
1276 {
1277  if (val.is_string ())
1278  {
1279  std::string s = val.string_value ();
1280  std::string match;
1281 
1282  if (! s.empty () && radio_val.contains (s, match))
1283  {
1284  if (current_type != radio_t || match != current_val)
1285  {
1286  if (s.length () != match.length ())
1287  warning_with_id ("Octave:abbreviated-property-match",
1288  "%s: allowing %s to match %s value %s",
1289  "set", s.c_str (), get_name ().c_str (),
1290  match.c_str ());
1291  current_val = match;
1293  return true;
1294  }
1295  }
1296  else
1297  error ("invalid value for double_radio property \"%s\"",
1298  get_name ().c_str ());
1299  }
1300  else if (val.is_scalar_type () && val.is_real_type ())
1301  {
1302  double new_dval = val.double_value ();
1303 
1304  if (current_type != double_t || new_dval != dval)
1305  {
1306  dval = new_dval;
1308  return true;
1309  }
1310  }
1311  else
1312  error ("invalid value for double_radio property \"%s\"",
1313  get_name ().c_str ());
1314 
1315  return false;
1316 }
1317 
1318 bool
1320 {
1321  bool xok = false;
1322 
1323  // check value type
1324  if (type_constraints.size () > 0)
1325  {
1326  if (type_constraints.find (v.class_name ()) != type_constraints.end ())
1327  xok = true;
1328 
1329  // check if complex is allowed (it's also of class "double", so
1330  // checking that alone is not enough to ensure real type)
1331  if (type_constraints.find ("real") != type_constraints.end ()
1332  && v.is_complex_type ())
1333  xok = false;
1334  }
1335  else
1336  xok = v.is_numeric_type () || v.is_bool_scalar ();
1337 
1338  if (xok)
1339  {
1340  if (size_constraints.size () == 0)
1341  return true;
1342 
1343  dim_vector vdims = v.dims ();
1344  int vlen = vdims.length ();
1345 
1346  xok = false;
1347 
1348  // check dimensional size constraints until a match is found
1349  for (std::list<dim_vector>::const_iterator it = size_constraints.begin ();
1350  ! xok && it != size_constraints.end (); ++it)
1351  {
1352  dim_vector itdims = (*it);
1353 
1354  if (itdims.length () == vlen)
1355  {
1356  xok = true;
1357 
1358  for (int i = 0; xok && i < vlen; i++)
1359  {
1360  if (itdims(i) > 0)
1361  {
1362  if (itdims(i) != vdims(i))
1363  xok = false;
1364  }
1365  else if (v.is_empty ())
1366  break;
1367  }
1368  }
1369  }
1370  }
1371 
1372  return xok;
1373 }
1374 
1375 bool
1377 {
1378  if (data.type_name () == v.type_name ())
1379  {
1380  if (data.dims () == v.dims ())
1381  {
1382 
1383 #define CHECK_ARRAY_EQUAL(T,F,A) \
1384  { \
1385  if (data.numel () == 1) \
1386  return data.F ## scalar_value () == \
1387  v.F ## scalar_value (); \
1388  else \
1389  { \
1390  /* Keep copy of array_value to allow sparse/bool arrays */ \
1391  /* that are converted, to not be deallocated early */ \
1392  const A m1 = data.F ## array_value (); \
1393  const T* d1 = m1.data (); \
1394  const A m2 = v.F ## array_value (); \
1395  const T* d2 = m2.data ();\
1396  \
1397  bool flag = true; \
1398  \
1399  for (int i = 0; flag && i < data.numel (); i++) \
1400  if (d1[i] != d2[i]) \
1401  flag = false; \
1402  \
1403  return flag; \
1404  } \
1405  }
1406 
1407  if (data.is_double_type () || data.is_bool_type ())
1408  CHECK_ARRAY_EQUAL (double, , NDArray)
1409  else if (data.is_single_type ())
1410  CHECK_ARRAY_EQUAL (float, float_, FloatNDArray)
1411  else if (data.is_int8_type ())
1413  else if (data.is_int16_type ())
1415  else if (data.is_int32_type ())
1417  else if (data.is_int64_type ())
1419  else if (data.is_uint8_type ())
1421  else if (data.is_uint16_type ())
1423  else if (data.is_uint32_type ())
1425  else if (data.is_uint64_type ())
1427  }
1428  }
1429 
1430  return false;
1431 }
1432 
1433 void
1435 {
1436  xmin = xminp = octave_Inf;
1437  xmax = xmaxp = -octave_Inf;
1438 
1439  if (! data.is_empty ())
1440  {
1441  if (data.is_integer_type ())
1442  {
1443  if (data.is_int8_type ())
1445  xmin, xmax, xminp, xmaxp);
1446  else if (data.is_uint8_type ())
1448  xmin, xmax, xminp, xmaxp);
1449  else if (data.is_int16_type ())
1451  xmin, xmax, xminp, xmaxp);
1452  else if (data.is_uint16_type ())
1454  xmin, xmax, xminp, xmaxp);
1455  else if (data.is_int32_type ())
1457  xmin, xmax, xminp, xmaxp);
1458  else if (data.is_uint32_type ())
1460  xmin, xmax, xminp, xmaxp);
1461  else if (data.is_int64_type ())
1463  xmin, xmax, xminp, xmaxp);
1464  else if (data.is_uint64_type ())
1466  xmin, xmax, xminp, xmaxp);
1467  }
1468  else
1470  }
1471 }
1472 
1473 bool
1475 {
1476  // Users may want to use empty matrix to reset a handle property
1477  if (v.is_empty ())
1478  {
1479  if (! get ().is_empty ())
1480  {
1482  return true;
1483  }
1484  else
1485  return false;
1486  }
1487 
1488  double dv = v.double_value ();
1489 
1490  if (! error_state)
1491  {
1493 
1494  if (xisnan (gh.value ()) || gh.ok ())
1495  {
1496  if (current_val != gh)
1497  {
1498  current_val = gh;
1499  return true;
1500  }
1501  }
1502  else
1503  error ("set: invalid graphics handle (= %g) for property \"%s\"",
1504  dv, get_name ().c_str ());
1505  }
1506  else
1507  error ("set: invalid graphics handle for property \"%s\"",
1508  get_name ().c_str ());
1509 
1510  return false;
1511 }
1512 
1513 Matrix
1514 children_property::do_get_children (bool return_hidden) const
1515 {
1516  Matrix retval (children_list.size (), 1);
1517  octave_idx_type k = 0;
1518 
1520 
1521  root_figure::properties& props =
1522  dynamic_cast<root_figure::properties&> (go.get_properties ());
1523 
1524  if (! props.is_showhiddenhandles ())
1525  {
1526  for (const_children_list_iterator p = children_list.begin ();
1527  p != children_list.end (); p++)
1528  {
1529  graphics_handle kid = *p;
1530 
1532  {
1533  if (! return_hidden)
1534  retval(k++) = *p;
1535  }
1536  else if (return_hidden)
1537  retval(k++) = *p;
1538  }
1539 
1540  retval.resize (k, 1);
1541  }
1542  else
1543  {
1544  for (const_children_list_iterator p = children_list.begin ();
1545  p != children_list.end (); p++)
1546  retval(k++) = *p;
1547  }
1548 
1549  return retval;
1550 }
1551 
1552 void
1554 {
1555  for (children_list_iterator p = children_list.begin ();
1556  p != children_list.end (); p++)
1557  {
1559 
1560  if (go.valid_object ())
1561  gh_manager::free (*p);
1562 
1563  }
1564 
1565  if (clear)
1566  children_list.clear ();
1567 }
1568 
1569 bool
1571 {
1572  // case 1: function handle
1573  // case 2: cell array with first element being a function handle
1574  // case 3: string corresponding to known function name
1575  // case 4: evaluatable string
1576  // case 5: empty matrix
1577 
1578  if (v.is_function_handle ())
1579  return true;
1580  else if (v.is_string ())
1581  // complete validation will be done at execution-time
1582  return true;
1583  else if (v.is_cell () && v.length () > 0
1584  && (v.rows () == 1 || v.columns () == 1)
1585  && v.cell_value ()(0).is_function_handle ())
1586  return true;
1587  else if (v.is_empty ())
1588  return true;
1589 
1590  return false;
1591 }
1592 
1593 // If TRUE, we are executing any callback function, or the functions it
1594 // calls. Used to determine handle visibility inside callback
1595 // functions.
1596 static bool executing_callback = false;
1597 
1598 void
1600 {
1601  unwind_protect frame;
1602 
1603  // We are executing the callback function associated with this
1604  // callback property. When set to true, we avoid recursive calls to
1605  // callback routines.
1606  frame.protect_var (executing);
1607 
1608  // We are executing a callback function, so allow handles that have
1609  // their handlevisibility property set to "callback" to be visible.
1610  frame.protect_var (executing_callback);
1611 
1612  if (! executing)
1613  {
1614  executing = true;
1615  executing_callback = true;
1616 
1617  if (callback.is_defined () && ! callback.is_empty ())
1619  }
1620 }
1621 
1622 // Used to cache dummy graphics objects from which dynamic
1623 // properties can be cloned.
1624 static std::map<caseless_str, graphics_object> dprop_obj_map;
1625 
1626 property
1627 property::create (const std::string& name, const graphics_handle& h,
1628  const caseless_str& type, const octave_value_list& args)
1629 {
1630  property retval;
1631 
1632  if (type.compare ("string"))
1633  {
1634  std::string val = (args.length () > 0 ? args(0).string_value () : "");
1635 
1636  if (! error_state)
1637  retval = property (new string_property (name, h, val));
1638  }
1639  else if (type.compare ("any"))
1640  {
1641  octave_value val = args.length () > 0 ? args(0)
1642  : octave_value (Matrix ());
1643 
1644  retval = property (new any_property (name, h, val));
1645  }
1646  else if (type.compare ("radio"))
1647  {
1648  if (args.length () > 0)
1649  {
1650  std::string vals = args(0).string_value ();
1651 
1652  if (! error_state)
1653  {
1654  retval = property (new radio_property (name, h, vals));
1655 
1656  if (args.length () > 1)
1657  retval.set (args(1));
1658  }
1659  else
1660  error ("addproperty: invalid argument for radio property, expected a string value");
1661  }
1662  else
1663  error ("addproperty: missing possible values for radio property");
1664  }
1665  else if (type.compare ("double"))
1666  {
1667  double d = (args.length () > 0 ? args(0).double_value () : 0);
1668 
1669  if (! error_state)
1670  retval = property (new double_property (name, h, d));
1671  }
1672  else if (type.compare ("handle"))
1673  {
1674  double hh = (args.length () > 0 ? args(0).double_value () : octave_NaN);
1675 
1676  if (! error_state)
1677  {
1678  graphics_handle gh (hh);
1679 
1680  retval = property (new handle_property (name, h, gh));
1681  }
1682  }
1683  else if (type.compare ("boolean"))
1684  {
1685  retval = property (new bool_property (name, h, false));
1686 
1687  if (args.length () > 0)
1688  retval.set (args(0));
1689  }
1690  else if (type.compare ("data"))
1691  {
1692  retval = property (new array_property (name, h, Matrix ()));
1693 
1694  if (args.length () > 0)
1695  {
1696  retval.set (args(0));
1697 
1698  // FIXME: additional argument could define constraints,
1699  // but is this really useful?
1700  }
1701  }
1702  else if (type.compare ("color"))
1703  {
1704  color_values cv (0, 0, 0);
1705  radio_values rv;
1706 
1707  if (args.length () > 1)
1708  rv = radio_values (args(1).string_value ());
1709 
1710  if (! error_state)
1711  {
1712  retval = property (new color_property (name, h, cv, rv));
1713 
1714  if (! error_state)
1715  {
1716  if (args.length () > 0 && ! args(0).is_empty ())
1717  retval.set (args(0));
1718  else
1719  retval.set (rv.default_value ());
1720  }
1721  }
1722  }
1723  else
1724  {
1725  caseless_str go_name, go_rest;
1726 
1727  if (lookup_object_name (type, go_name, go_rest))
1728  {
1729  graphics_object go;
1730 
1731  std::map<caseless_str, graphics_object>::const_iterator it =
1732  dprop_obj_map.find (go_name);
1733 
1734  if (it == dprop_obj_map.end ())
1735  {
1736  base_graphics_object *bgo =
1738 
1739  if (bgo)
1740  {
1741  go = graphics_object (bgo);
1742 
1743  dprop_obj_map[go_name] = go;
1744  }
1745  }
1746  else
1747  go = it->second;
1748 
1749  if (go.valid_object ())
1750  {
1751  property prop = go.get_properties ().get_property (go_rest);
1752 
1753  if (! error_state)
1754  {
1755  retval = prop.clone ();
1756 
1757  retval.set_parent (h);
1758  retval.set_name (name);
1759 
1760  if (args.length () > 0)
1761  retval.set (args(0));
1762  }
1763  }
1764  else
1765  error ("addproperty: invalid object type (= %s)",
1766  go_name.c_str ());
1767  }
1768  else
1769  error ("addproperty: unsupported type for dynamic property (= %s)",
1770  type.c_str ());
1771  }
1772 
1773  return retval;
1774 }
1775 
1776 static void
1778 {
1780 
1781  if (go)
1782  {
1783  Matrix children = go.get_properties ().get_all_children ();
1784 
1785  for (int k = 0; k < children.numel (); k++)
1786  finalize_r (children(k));
1787 
1788  go.finalize ();
1789  }
1790 }
1791 
1792 static void
1794 {
1796 
1797  if (go)
1798  {
1799  Matrix children = go.get_properties ().get_all_children ();
1800 
1801  go.initialize ();
1802 
1803  for (int k = 0; k < children.numel (); k++)
1804  initialize_r (children(k));
1805  }
1806 }
1807 
1808 void
1810 {
1811  if (toolkit)
1813 
1814  toolkit = b;
1816  __plot_stream__ = Matrix ();
1817 
1818  if (toolkit)
1820 
1821  mark_modified ();
1822 }
1823 
1824 void
1826 {
1827  if (! error_state)
1828  {
1829  std::string direction = "in";
1830 
1831  octave_value val = val_arg;
1832 
1833  if (val.is_string ())
1834  {
1835  std::string modestr = val.string_value ();
1836 
1837  if (modestr == "zoom in")
1838  {
1839  val = modestr = "zoom";
1840  direction = "in";
1841  }
1842  else if (modestr == "zoom out")
1843  {
1844  val = modestr = "zoom";
1845  direction = "out";
1846  }
1847 
1848  if (__mouse_mode__.set (val, true))
1849  {
1850  std::string mode = __mouse_mode__.current_value ();
1851 
1852  octave_scalar_map pm = get___pan_mode__ ().scalar_map_value ();
1853  pm.setfield ("Enable", mode == "pan" ? "on" : "off");
1854  set___pan_mode__ (pm);
1855 
1856  octave_scalar_map rm = get___rotate_mode__ ().scalar_map_value ();
1857  rm.setfield ("Enable", mode == "rotate" ? "on" : "off");
1858  set___rotate_mode__ (rm);
1859 
1860  octave_scalar_map zm = get___zoom_mode__ ().scalar_map_value ();
1861  zm.setfield ("Enable", mode == "zoom" ? "on" : "off");
1862  zm.setfield ("Direction", direction);
1863  set___zoom_mode__ (zm);
1864 
1865  mark_modified ();
1866  }
1867  else if (modestr == "zoom")
1868  {
1869  octave_scalar_map zm = get___zoom_mode__ ().scalar_map_value ();
1870  std::string curr_direction
1871  = zm.getfield ("Direction").string_value ();
1872 
1873  if (direction != curr_direction)
1874  {
1875  zm.setfield ("Direction", direction);
1876  set___zoom_mode__ (zm);
1877 
1878  mark_modified ();
1879  }
1880  }
1881  }
1882  }
1883 }
1884 
1885 // ---------------------------------------------------------------------
1886 
1887 void
1889 {
1890  size_t offset = 0;
1891 
1892  size_t len = name.length ();
1893 
1894  if (len > 4)
1895  {
1896  caseless_str pfx = name.substr (0, 4);
1897 
1898  if (pfx.compare ("axes") || pfx.compare ("line")
1899  || pfx.compare ("text"))
1900  offset = 4;
1901  else if (len > 5)
1902  {
1903  pfx = name.substr (0, 5);
1904 
1905  if (pfx.compare ("image") || pfx.compare ("patch"))
1906  offset = 5;
1907  else if (len > 6)
1908  {
1909  pfx = name.substr (0, 6);
1910 
1911  if (pfx.compare ("figure") || pfx.compare ("uimenu"))
1912  offset = 6;
1913  else if (len > 7)
1914  {
1915  pfx = name.substr (0, 7);
1916 
1917  if (pfx.compare ("surface") || pfx.compare ("hggroup")
1918  || pfx.compare ("uipanel"))
1919  offset = 7;
1920  else if (len > 9)
1921  {
1922  pfx = name.substr (0, 9);
1923 
1924  if (pfx.compare ("uicontrol")
1925  || pfx.compare ("uitoolbar"))
1926  offset = 9;
1927  else if (len > 10)
1928  {
1929  pfx = name.substr (0, 10);
1930 
1931  if (pfx.compare ("uipushtool"))
1932  offset = 10;
1933  else if (len > 12)
1934  {
1935  pfx = name.substr (0, 12);
1936 
1937  if (pfx.compare ("uitoogletool"))
1938  offset = 12;
1939  else if (len > 13)
1940  {
1941  pfx = name.substr (0, 13);
1942 
1943  if (pfx.compare ("uicontextmenu"))
1944  offset = 13;
1945  }
1946  }
1947  }
1948  }
1949  }
1950  }
1951  }
1952 
1953  if (offset > 0)
1954  {
1955  // FIXME: should we validate property names and values here?
1956 
1957  std::string pname = name.substr (offset);
1958 
1959  std::transform (pfx.begin (), pfx.end (), pfx.begin (), tolower);
1960  std::transform (pname.begin (), pname.end (), pname.begin (),
1961  tolower);
1962 
1963  bool has_property = false;
1964  if (pfx == "axes")
1965  has_property = axes::properties::has_core_property (pname);
1966  else if (pfx == "line")
1967  has_property = line::properties::has_core_property (pname);
1968  else if (pfx == "text")
1969  has_property = text::properties::has_core_property (pname);
1970  else if (pfx == "image")
1971  has_property = image::properties::has_core_property (pname);
1972  else if (pfx == "patch")
1973  has_property = patch::properties::has_core_property (pname);
1974  else if (pfx == "figure")
1975  has_property = figure::properties::has_core_property (pname);
1976  else if (pfx == "surface")
1977  has_property = surface::properties::has_core_property (pname);
1978  else if (pfx == "hggroup")
1979  has_property = hggroup::properties::has_core_property (pname);
1980  else if (pfx == "uimenu")
1981  has_property = uimenu::properties::has_core_property (pname);
1982  else if (pfx == "uicontrol")
1983  has_property = uicontrol::properties::has_core_property (pname);
1984  else if (pfx == "uipanel")
1985  has_property = uipanel::properties::has_core_property (pname);
1986  else if (pfx == "uicontextmenu")
1987  has_property = uicontextmenu::properties::has_core_property (pname);
1988  else if (pfx == "uitoolbar")
1989  has_property = uitoolbar::properties::has_core_property (pname);
1990  else if (pfx == "uipushtool")
1991  has_property = uipushtool::properties::has_core_property (pname);
1992 
1993  if (has_property)
1994  {
1995  bool remove = false;
1996  if (val.is_string ())
1997  {
1998  std::string tval = val.string_value ();
1999 
2000  remove = (tval.compare ("remove") == 0);
2001  }
2002 
2003  pval_map_type& pval_map = plist_map[pfx];
2004 
2005  if (remove)
2006  {
2007  pval_map_iterator p = pval_map.find (pname);
2008 
2009  if (p != pval_map.end ())
2010  pval_map.erase (p);
2011  }
2012  else
2013  pval_map[pname] = val;
2014  }
2015  else
2016  error ("invalid %s property '%s'", pfx.c_str (), pname.c_str ());
2017  }
2018  }
2019 
2020  if (! error_state && offset == 0)
2021  error ("invalid default property specification");
2022 }
2023 
2026 {
2027  octave_value retval;
2028 
2029  size_t offset = 0;
2030 
2031  size_t len = name.length ();
2032 
2033  if (len > 4)
2034  {
2035  caseless_str pfx = name.substr (0, 4);
2036 
2037  if (pfx.compare ("axes") || pfx.compare ("line")
2038  || pfx.compare ("text"))
2039  offset = 4;
2040  else if (len > 5)
2041  {
2042  pfx = name.substr (0, 5);
2043 
2044  if (pfx.compare ("image") || pfx.compare ("patch"))
2045  offset = 5;
2046  else if (len > 6)
2047  {
2048  pfx = name.substr (0, 6);
2049 
2050  if (pfx.compare ("figure") || pfx.compare ("uimenu"))
2051  offset = 6;
2052  else if (len > 7)
2053  {
2054  pfx = name.substr (0, 7);
2055 
2056  if (pfx.compare ("surface") || pfx.compare ("hggroup")
2057  || pfx.compare ("uipanel"))
2058  offset = 7;
2059  else if (len > 9)
2060  {
2061  pfx = name.substr (0, 9);
2062 
2063  if (pfx.compare ("uicontrol")
2064  || pfx.compare ("uitoolbar"))
2065  offset = 9;
2066  else if (len > 10)
2067  {
2068  pfx = name.substr (0, 10);
2069 
2070  if (pfx.compare ("uipushtool"))
2071  offset = 10;
2072  else if (len > 12)
2073  {
2074  pfx = name.substr (0, 12);
2075 
2076  if (pfx.compare ("uitoggletool"))
2077  offset = 12;
2078  else if (len > 13)
2079  {
2080  pfx = name.substr (0, 13);
2081 
2082  if (pfx.compare ("uicontextmenu"))
2083  offset = 13;
2084  }
2085  }
2086  }
2087  }
2088  }
2089  }
2090  }
2091 
2092  if (offset > 0)
2093  {
2094  std::string pname = name.substr (offset);
2095 
2096  std::transform (pfx.begin (), pfx.end (), pfx.begin (), tolower);
2097  std::transform (pname.begin (), pname.end (), pname.begin (),
2098  tolower);
2099 
2100  plist_map_const_iterator p = find (pfx);
2101 
2102  if (p != end ())
2103  {
2104  const pval_map_type& pval_map = p->second;
2105 
2106  pval_map_const_iterator q = pval_map.find (pname);
2107 
2108  if (q != pval_map.end ())
2109  retval = q->second;
2110  }
2111  }
2112  }
2113 
2114  return retval;
2115 }
2116 
2118 property_list::as_struct (const std::string& prefix_arg) const
2119 {
2121 
2122  for (plist_map_const_iterator p = begin (); p != end (); p++)
2123  {
2124  std::string prefix = prefix_arg + p->first;
2125 
2126  const pval_map_type pval_map = p->second;
2127 
2128  for (pval_map_const_iterator q = pval_map.begin ();
2129  q != pval_map.end ();
2130  q++)
2131  m.assign (prefix + q->first, q->second);
2132  }
2133 
2134  return m;
2135 }
2136 
2137 // Set properties given as a cs-list of name, value pairs.
2138 
2139 void
2141 {
2142  int nargin = args.length ();
2143 
2144  if (nargin == 0)
2145  error ("graphics_object::set: Nothing to set");
2146  else if (nargin % 2 == 0)
2147  {
2148  for (int i = 0; i < nargin; i += 2)
2149  {
2150  caseless_str name = args(i).string_value ();
2151 
2152  if (! error_state)
2153  {
2154  octave_value val = args(i+1);
2155 
2156  set_value_or_default (name, val);
2157 
2158  if (error_state)
2159  break;
2160  }
2161  else
2162  error ("set: expecting argument %d to be a property name", i);
2163  }
2164  }
2165  else
2166  error ("set: invalid number of arguments");
2167 }
2168 
2169 /*
2170 ## test set with name, value pairs
2171 %!test
2172 %! hf = figure ("visible", "off");
2173 %! h = plot (1:10, 10:-1:1);
2174 %! set (h, "linewidth", 10, "marker", "x");
2175 %! lw = get (h, "linewidth");
2176 %! mk = get (h, "marker");
2177 %! close (hf);
2178 %! assert (lw, 10);
2179 %! assert (mk, "x");
2180 */
2181 
2182 // Set properties given in two cell arrays containing names and values.
2183 void
2185  const Cell& values, octave_idx_type row)
2186 {
2187  if (names.numel () != values.columns ())
2188  {
2189  error ("set: number of names must match number of value columns (%d != %d)",
2190  names.numel (), values.columns ());
2191  }
2192 
2193  octave_idx_type k = names.columns ();
2194 
2195  for (octave_idx_type column = 0; column < k; column++)
2196  {
2197  caseless_str name = names(column);
2198  octave_value val = values(row, column);
2199 
2200  set_value_or_default (name, val);
2201 
2202  if (error_state)
2203  break;
2204  }
2205 }
2206 
2207 /*
2208 ## test set with cell array arguments
2209 %!test
2210 %! hf = figure ("visible", "off");
2211 %! h = plot (1:10, 10:-1:1);
2212 %! set (h, {"linewidth", "marker"}, {10, "x"});
2213 %! lw = get (h, "linewidth");
2214 %! mk = get (h, "marker");
2215 %! close (hf);
2216 %! assert (lw, 10);
2217 %! assert (mk, "x");
2218 
2219 ## test set with multiple handles and cell array arguments
2220 %!test
2221 %! hf = figure ("visible", "off");
2222 %! unwind_protect
2223 %! h = plot (1:10, 10:-1:1, 1:10, 1:10);
2224 %! set (h, {"linewidth", "marker"}, {10, "x"; 5, "o"});
2225 %! assert (get (h, "linewidth"), {10; 5});
2226 %! assert (get (h, "marker"), {"x"; "o"});
2227 %! set (h, {"linewidth", "marker"}, {10, "x"});
2228 %! assert (get (h, "linewidth"), {10; 10});
2229 %! assert (get (h, "marker"), {"x"; "x"});
2230 %! unwind_protect_cleanup
2231 %! close (hf);
2232 %! end_unwind_protect;
2233 
2234 %!error <set: number of graphics handles must match number of value rows>
2235 %! hf = figure ("visible", "off");
2236 %! unwind_protect
2237 %! h = plot (1:10, 10:-1:1, 1:10, 1:10);
2238 %! set (h, {"linewidth", "marker"}, {10, "x"; 5, "o"; 7, "."});
2239 %! unwind_protect_cleanup
2240 %! close (hf);
2241 %! end_unwind_protect
2242 
2243 %!error <set: number of names must match number of value columns>
2244 %! hf = figure ("visible", "off");
2245 %! unwind_protect
2246 %! h = plot (1:10, 10:-1:1, 1:10, 1:10);
2247 %! set (h, {"linewidth"}, {10, "x"; 5, "o"});
2248 %! unwind_protect_cleanup
2249 %! close (hf);
2250 %! end_unwind_protect
2251 */
2252 
2253 // Set properties given in a struct array
2254 void
2256 {
2257  for (octave_idx_type p = 0; p < m.nfields (); p++)
2258  {
2259  caseless_str name = m.keys ()[p];
2260 
2261  octave_value val = octave_value (m.contents (name).elem (m.numel () - 1));
2262 
2263  set_value_or_default (name, val);
2264 
2265  if (error_state)
2266  break;
2267  }
2268 }
2269 
2270 /*
2271 ## test set ticklabels for compatibility
2272 %!test
2273 %! hf = figure ("visible", "off");
2274 %! set (gca (), "xticklabel", [0, 0.2, 0.4, 0.6, 0.8, 1]);
2275 %! xticklabel = get (gca (), "xticklabel");
2276 %! close (hf);
2277 %! assert (class (xticklabel), "char");
2278 %! assert (size (xticklabel), [6, 3]);
2279 
2280 %!test
2281 %! hf = figure ("visible", "off");
2282 %! set (gca (), "xticklabel", "0|0.2|0.4|0.6|0.8|1");
2283 %! xticklabel = get (gca (), "xticklabel");
2284 %! close (hf);
2285 %! assert (class (xticklabel), "char");
2286 %! assert (size (xticklabel), [6, 3]);
2287 
2288 %!test
2289 %! hf = figure ("visible", "off");
2290 %! set (gca (), "xticklabel", ["0 "; "0.2"; "0.4"; "0.6"; "0.8"; "1 "]);
2291 %! xticklabel = get (gca (), "xticklabel");
2292 %! close (hf);
2293 %! assert (class (xticklabel), "char");
2294 %! assert (size (xticklabel), [6, 3]);
2295 
2296 %!test
2297 %! hf = figure ("visible", "off");
2298 %! set (gca (), "xticklabel", {"0", "0.2", "0.4", "0.6", "0.8", "1"});
2299 %! xticklabel = get (gca (), "xticklabel");
2300 %! close (hf);
2301 %! assert (class (xticklabel), "cell");
2302 %! assert (size (xticklabel), [6, 1]);
2303 */
2304 
2305 /*
2306 ## test set with struct arguments
2307 %!test
2308 %! hf = figure ("visible", "off");
2309 %! unwind_protect
2310 %! h = plot (1:10, 10:-1:1);
2311 %! set (h, struct ("linewidth", 10, "marker", "x"));
2312 %! assert (get (h, "linewidth"), 10);
2313 %! assert (get (h, "marker"), "x");
2314 %! h = plot (1:10, 10:-1:1, 1:10, 1:10);
2315 %! set (h, struct ("linewidth", {5, 10}));
2316 %! assert (get (h, "linewidth"), {10; 10});
2317 %! unwind_protect_cleanup
2318 %! close (hf);
2319 %! end_unwind_protect
2320 
2321 ## test ordering
2322 %!test
2323 %! markchanged = @(h, foobar, name) set (h, "userdata", [get(h,"userdata"); {name}]);
2324 %! hf = figure ("visible", "off");
2325 %! unwind_protect
2326 %! h = line ();
2327 %! set (h, "userdata", {});
2328 %! addlistener (h, "color", {markchanged, "color"});
2329 %! addlistener (h, "linewidth", {markchanged, "linewidth"});
2330 %! ## "linewidth" first
2331 %! props.linewidth = 2;
2332 %! props.color = "r";
2333 %! set (h, props);
2334 %! assert (get (h, "userdata"), fieldnames (props));
2335 %! clear props;
2336 %! clf ();
2337 %! h = line ();
2338 %! set (h, "userdata", {});
2339 %! addlistener (h, "color", {markchanged, "color"});
2340 %! addlistener (h, "linewidth", {markchanged, "linewidth"});
2341 %! ## "color" first
2342 %! props.color = "r";
2343 %! props.linewidth = 2;
2344 %! set (h, props);
2345 %! assert (get (h, "userdata"), fieldnames (props));
2346 %! unwind_protect_cleanup
2347 %! close (hf);
2348 %! end_unwind_protect
2349 */
2350 
2351 // Set a property to a value or to its (factory) default value.
2352 
2353 void
2355  const octave_value& val)
2356 {
2357  if (val.is_string ())
2358  {
2359  std::string tval = val.string_value ();
2360 
2361  octave_value default_val;
2362 
2363  if (tval.compare ("default") == 0)
2364  {
2365  default_val = get_default (name);
2366 
2367  if (error_state)
2368  return;
2369 
2370  rep->set (name, default_val);
2371  }
2372  else if (tval.compare ("factory") == 0)
2373  {
2374  default_val = get_factory_default (name);
2375 
2376  if (error_state)
2377  return;
2378 
2379  rep->set (name, default_val);
2380  }
2381  else
2382  {
2383  // Matlab specifically uses "\default" to escape string setting
2384  if (tval.compare ("\\default") == 0)
2385  rep->set (name, "default");
2386  else if (tval.compare ("\\factory") == 0)
2387  rep->set (name, "factory");
2388  else
2389  rep->set (name, val);
2390  }
2391  }
2392  else
2393  rep->set (name, val);
2394 }
2395 
2396 /*
2397 ## test setting of default values
2398 %!test
2399 %! old_lw = get (0, "defaultlinelinewidth");
2400 %! unwind_protect
2401 %! hf = figure ("visible", "off");
2402 %! h = plot (1:10, 10:-1:1);
2403 %! set (0, "defaultlinelinewidth", 20);
2404 %! set (h, "linewidth", "default");
2405 %! assert (get (h, "linewidth"), 20);
2406 %! set (h, "linewidth", "factory");
2407 %! assert (get (h, "linewidth"), 0.5);
2408 %! unwind_protect_cleanup
2409 %! close (hf);
2410 %! set (0, "defaultlinelinewidth", old_lw);
2411 %! end_unwind_protect
2412 */
2413 
2414 static double
2416 {
2417  static double maxrand = RAND_MAX + 2.0;
2418 
2419  return (rand () + 1.0) / maxrand;
2420 }
2421 
2423 gh_manager::do_get_handle (bool integer_figure_handle)
2424 {
2425  graphics_handle retval;
2426 
2427  if (integer_figure_handle)
2428  {
2429  // Figure handles are positive integers corresponding to the
2430  // figure number.
2431 
2432  // We always want the lowest unused figure number.
2433 
2434  retval = 1;
2435 
2436  while (handle_map.find (retval) != handle_map.end ())
2437  retval++;
2438  }
2439  else
2440  {
2441  // Other graphics handles are negative integers plus some random
2442  // fractional part. To avoid running out of integers, we
2443  // recycle the integer part but tack on a new random part each
2444  // time.
2445 
2446  free_list_iterator p = handle_free_list.begin ();
2447 
2448  if (p != handle_free_list.end ())
2449  {
2450  retval = *p;
2451  handle_free_list.erase (p);
2452  }
2453  else
2454  {
2455  retval = graphics_handle (next_handle);
2456 
2457  next_handle = std::ceil (next_handle) - 1.0 - make_handle_fraction ();
2458  }
2459  }
2460 
2461  return retval;
2462 }
2463 
2464 void
2466 {
2467  if (h.ok ())
2468  {
2469  if (h.value () != 0)
2470  {
2471  iterator p = handle_map.find (h);
2472 
2473  if (p != handle_map.end ())
2474  {
2475  base_properties& bp = p->second.get_properties ();
2476 
2477  bp.set_beingdeleted (true);
2478 
2479  bp.delete_children ();
2480 
2481  octave_value val = bp.get_deletefcn ();
2482 
2483  bp.execute_deletefcn ();
2484 
2485  // Notify graphics toolkit.
2486  p->second.finalize ();
2487 
2488  // Note: this will be valid only for first explicitly
2489  // deleted object. All its children will then have an
2490  // unknown graphics toolkit.
2491 
2492  // Graphics handles for non-figure objects are negative
2493  // integers plus some random fractional part. To avoid
2494  // running out of integers, we recycle the integer part
2495  // but tack on a new random part each time.
2496 
2497  handle_map.erase (p);
2498 
2499  if (h.value () < 0)
2500  handle_free_list.insert
2501  (std::ceil (h.value ()) - make_handle_fraction ());
2502  }
2503  else
2504  error ("graphics_handle::free: invalid object %g", h.value ());
2505  }
2506  else
2507  error ("graphics_handle::free: can't delete root figure");
2508  }
2509 }
2510 
2511 void
2513  const graphics_handle& new_gh)
2514 {
2515  iterator p = handle_map.find (old_gh);
2516 
2517  if (p != handle_map.end ())
2518  {
2519  graphics_object go = p->second;
2520 
2521  handle_map.erase (p);
2522 
2523  handle_map[new_gh] = go;
2524 
2525  if (old_gh.value () < 0)
2526  handle_free_list.insert (std::ceil (old_gh.value ())
2527  - make_handle_fraction ());
2528  }
2529  else
2530  error ("graphics_handle::free: invalid object %g", old_gh.value ());
2531 
2532  for (figure_list_iterator q = figure_list.begin ();
2533  q != figure_list.end (); q++)
2534  {
2535  if (*q == old_gh)
2536  {
2537  *q = new_gh;
2538  break;
2539  }
2540  }
2541 }
2542 
2544 
2545 static void
2546 xset (const graphics_handle& h, const caseless_str& name,
2547  const octave_value& val)
2548 {
2550  obj.set (name, val);
2551 }
2552 
2553 static void
2554 xset (const graphics_handle& h, const octave_value_list& args)
2555 {
2556  if (args.length () > 0)
2557  {
2559  obj.set (args);
2560  }
2561 }
2562 
2563 static octave_value
2564 xget (const graphics_handle& h, const caseless_str& name)
2565 {
2567  return obj.get (name);
2568 }
2569 
2570 static graphics_handle
2571 reparent (const octave_value& ov, const std::string& who,
2572  const std::string& property, const graphics_handle& new_parent,
2573  bool adopt = true)
2574 {
2576 
2577  double val = ov.double_value ();
2578 
2579  if (! error_state)
2580  {
2581  h = gh_manager::lookup (val);
2582 
2583  if (h.ok ())
2584  {
2586 
2587  graphics_handle parent_h = obj.get_parent ();
2588 
2589  graphics_object parent_obj = gh_manager::get_object (parent_h);
2590 
2591  parent_obj.remove_child (h);
2592 
2593  if (adopt)
2594  obj.set ("parent", new_parent.value ());
2595  else
2596  obj.reparent (new_parent);
2597  }
2598  else
2599  error ("%s: invalid graphics handle (= %g) for %s",
2600  who.c_str (), val, property.c_str ());
2601  }
2602  else
2603  error ("%s: expecting %s to be a graphics handle",
2604  who.c_str (), property.c_str ());
2605 
2606  return h;
2607 }
2608 
2609 // This function is NOT equivalent to the scripting language function gcf.
2611 gcf (void)
2612 {
2613  octave_value val = xget (0, "currentfigure");
2614 
2615  return val.is_empty () ? octave_NaN : val.double_value ();
2616 }
2617 
2618 // This function is NOT equivalent to the scripting language function gca.
2620 gca (void)
2621 {
2622  octave_value val = xget (gcf (), "currentaxes");
2623 
2624  return val.is_empty () ? octave_NaN : val.double_value ();
2625 }
2626 
2627 static void
2629 {
2630  if (h.ok ())
2631  {
2633 
2634  // Don't do recursive deleting, due to callbacks
2635  if (! obj.get_properties ().is_beingdeleted ())
2636  {
2637  graphics_handle parent_h = obj.get_parent ();
2638 
2639  graphics_object parent_obj =
2640  gh_manager::get_object (parent_h);
2641 
2642  // NOTE: free the handle before removing it from its
2643  // parent's children, such that the object's
2644  // state is correct when the deletefcn callback
2645  // is executed
2646 
2647  gh_manager::free (h);
2648 
2649  // A callback function might have already deleted
2650  // the parent
2651  if (parent_obj.valid_object ())
2652  parent_obj.remove_child (h);
2653 
2654  Vdrawnow_requested = true;
2655  }
2656  }
2657 }
2658 
2659 static void
2661 {
2663 }
2664 
2665 static void
2667 {
2668  for (octave_idx_type i = 0; i < vals.numel (); i++)
2669  delete_graphics_object (vals.elem (i));
2670 }
2671 
2672 static void
2674 {
2675  octave_value closerequestfcn = xget (handle, "closerequestfcn");
2676 
2677  OCTAVE_SAFE_CALL (gh_manager::execute_callback, (handle, closerequestfcn));
2678 }
2679 
2680 static void
2682 {
2683  // Remove the deletefcn and closerequestfcn callbacks and delete the
2684  // object directly.
2685 
2686  xset (handle, "deletefcn", Matrix ());
2687  xset (handle, "closerequestfcn", Matrix ());
2688 
2689  delete_graphics_object (handle);
2690 }
2691 
2692 void
2694 {
2695  // FIXME: should we process or discard pending events?
2696 
2697  event_queue.clear ();
2698 
2699  // Don't use figure_list_iterator because we'll be removing elements
2700  // from the list elsewhere.
2701 
2702  Matrix hlist = do_figure_handle_list (true);
2703 
2704  for (octave_idx_type i = 0; i < hlist.numel (); i++)
2705  {
2706  graphics_handle h = gh_manager::lookup (hlist(i));
2707 
2708  if (h.ok ())
2709  close_figure (h);
2710  }
2711 
2712  // They should all be closed now. If not, force them to close.
2713 
2714  hlist = do_figure_handle_list (true);
2715 
2716  for (octave_idx_type i = 0; i < hlist.numel (); i++)
2717  {
2718  graphics_handle h = gh_manager::lookup (hlist(i));
2719 
2720  if (h.ok ())
2721  force_close_figure (h);
2722  }
2723 
2724  // None left now, right?
2725 
2726  hlist = do_figure_handle_list (true);
2727 
2728  assert (hlist.numel () == 0);
2729 
2730  // Clear all callback objects from our list.
2731 
2732  callback_objects.clear ();
2733 }
2734 
2735 static void
2737 {
2738  graphics_object parent_obj = gh_manager::get_object (p);
2739  parent_obj.adopt (h);
2740 }
2741 
2742 static bool
2744 {
2745  return h.ok ();
2746 }
2747 
2748 static bool
2749 is_handle (double val)
2750 {
2752 
2753  return h.ok ();
2754 }
2755 
2756 static octave_value
2758 {
2759  octave_value retval = false;
2760 
2761  if (val.is_real_scalar () && is_handle (val.double_value ()))
2762  retval = true;
2763  else if (val.is_numeric_type () && val.is_real_type ())
2764  {
2765  const NDArray handles = val.array_value ();
2766 
2767  if (! error_state)
2768  {
2769  boolNDArray result (handles.dims ());
2770 
2771  for (octave_idx_type i = 0; i < handles.numel (); i++)
2772  result.xelem (i) = is_handle (handles (i));
2773 
2774  retval = result;
2775  }
2776  }
2777 
2778  return retval;
2779 }
2780 
2781 static bool
2782 is_figure (double val)
2783 {
2785 
2786  return obj && obj.isa ("figure");
2787 }
2788 
2789 static void
2791 {
2794 }
2795 
2796 static void
2798 {
2800 
2801  if (go)
2802  go.initialize ();
2803 }
2804 
2805 // ---------------------------------------------------------------------
2806 
2807 void
2809 {
2811 
2812  update (go, id);
2813 }
2814 
2815 bool
2817 {
2819 
2820  return initialize (go);
2821 }
2822 
2823 void
2825 {
2827 
2828  finalize (go);
2829 }
2830 
2831 static void
2833  property_list::pval_map_type factory_pval)
2834 {
2836 
2837  // Replace factory defaults by user defined ones
2838  std::string go_name = obj.get_properties ().graphics_object_name ();
2840  obj.build_user_defaults_map (pval, go_name);
2841 
2842  for (property_list::pval_map_const_iterator p = pval.begin ();
2843  p != pval.end (); p++)
2844  {
2845  factory_pval[p->first] = p->second;
2846  }
2847 
2848 
2849  // Reset defaults
2850  for (property_list::pval_map_const_iterator it = factory_pval.begin ();
2851  it != factory_pval.end (); it++)
2852  {
2853  std::string pname = it->first;
2854 
2855  // Don't reset internal properties and handle_properties
2856  if (! obj.has_readonly_property (pname)
2857  && pname.find ("__") != 0 && pname.find ("current") != 0
2858  && pname != "uicontextmenu" && pname != "parent")
2859  {
2860  // Store *mode prop/val in order to set them last
2861  if (pname.find ("mode") == (pname.length () - 4))
2862  pval[pname] = it->second;
2863  else
2864  obj.set (pname, it->second);
2865  }
2866  }
2867 
2868  // set *mode properties
2869  for (property_list::pval_map_const_iterator it = pval.begin ();
2870  it != pval.end (); it++)
2871  obj.set (it->first, it->second);
2872 }
2873 
2874 // ---------------------------------------------------------------------
2875 
2876 void
2879 {
2880  std::string go_name = graphics_object_name ();
2881 
2882  property_list::plist_map_const_iterator p = defaults.find (go_name);
2883 
2884  if (p != defaults.end ())
2885  {
2886  const property_list::pval_map_type pval_map = p->second;
2887 
2888  for (property_list::pval_map_const_iterator q = pval_map.begin ();
2889  q != pval_map.end ();
2890  q++)
2891  {
2892  std::string pname = q->first;
2893 
2894  obj.set (pname, q->second);
2895 
2896  if (error_state)
2897  {
2898  error ("error setting default property %s", pname.c_str ());
2899  break;
2900  }
2901  }
2902  }
2903 }
2904 
2905 /*
2906 ## test defaults are set in the order they were stored
2907 %!test
2908 %! set(0, "defaultfigureunits", "normalized");
2909 %! set(0, "defaultfigureposition", [0.7 0 0.3 0.3]);
2910 %! hf = figure ("visible", "off");
2911 %! tol = 20 * eps;
2912 %! unwind_protect
2913 %! assert (get (hf, "position"), [0.7 0 0.3 0.3], tol);
2914 %! unwind_protect_cleanup
2915 %! close (hf);
2916 %! set(0, "defaultfigureunits", "remove");
2917 %! set(0, "defaultfigureposition", "remove");
2918 %! end_unwind_protect
2919 */
2920 
2923 {
2924  octave_value retval;
2925 
2926  std::map<caseless_str, property, cmp_caseless_str>::const_iterator it =
2927  all_props.find (name);
2928 
2929  if (it != all_props.end ())
2930  retval = it->second.get ();
2931  else
2932  error ("get: unknown property \"%s\"", name.c_str ());
2933 
2934  return retval;
2935 }
2936 
2939 {
2941 
2942  for (std::map<caseless_str, property, cmp_caseless_str>::const_iterator
2943  it = all_props.begin (); it != all_props.end (); ++it)
2944  if (all || ! it->second.is_hidden ())
2945  m.assign (it->second.get_name (), it->second.get ());
2946 
2947  return m;
2948 }
2949 
2950 std::set<std::string>
2952 {
2953  return dynamic_properties;
2954 }
2955 
2956 bool
2957 base_properties::has_dynamic_property (const std::string& pname)
2958 {
2959  const std::set<std::string>& dynprops = dynamic_property_names ();
2960 
2961  if (dynprops.find (pname) != dynprops.end ())
2962  return true;
2963  else
2964  return all_props.find (pname) != all_props.end ();
2965 }
2966 
2967 void
2969  const octave_value& val)
2970 {
2971  std::map<caseless_str, property, cmp_caseless_str>::iterator it =
2972  all_props.find (pname);
2973 
2974  if (it != all_props.end ())
2975  it->second.set (val);
2976  else
2977  error ("set: unknown property \"%s\"", pname.c_str ());
2978 
2979  if (! error_state)
2980  {
2981  dynamic_properties.insert (pname);
2982 
2983  mark_modified ();
2984  }
2985 }
2986 
2987 property
2989 {
2990  std::map<caseless_str, property, cmp_caseless_str>::const_iterator it =
2991  all_props.find (name);
2992 
2993  if (it == all_props.end ())
2994  {
2995  error ("get_property: unknown property \"%s\"", name.c_str ());
2996  return property ();
2997  }
2998  else
2999  return it->second;
3000 }
3001 
3002 void
3004 {
3005  double hnp = val.double_value ();
3006 
3007  graphics_handle new_parent = octave_NaN;
3008 
3009  if (! error_state)
3010  {
3011  if (hnp == __myhandle__)
3012  error ("set: can not set object parent to be object itself");
3013  else
3014  {
3015  new_parent = gh_manager::lookup (hnp);
3016 
3017  if (new_parent.ok ())
3018  {
3019  // Remove child from current parent
3020  graphics_object old_parent_obj;
3021  old_parent_obj = gh_manager::get_object (get_parent ());
3022 
3023 
3024  if (old_parent_obj.get_handle () != hnp)
3025  old_parent_obj.remove_child (__myhandle__);
3026  else
3027  // Do nothing more
3028  return;
3029 
3030  // Check new parent's parent is not this child to avoid recursion
3031  graphics_object new_parent_obj;
3032  new_parent_obj = gh_manager::get_object (new_parent);
3033  if (new_parent_obj.get_parent () == __myhandle__)
3034  {
3035  // new parent's parent gets child's original parent
3036  new_parent_obj.get_properties ().set_parent (get_parent ().as_octave_value ());
3037  }
3038 
3039  // Set parent property to new_parent and do adoption
3040  parent = new_parent.as_octave_value ();
3041  ::adopt (parent.handle_value (), __myhandle__);
3042  }
3043  else
3044  error ("set: invalid graphics handle (= %g) for parent", hnp);
3045  }
3046  }
3047  else
3048  error ("set: expecting parent to be a graphics handle");
3049 }
3050 
3051 /*
3052 %!test
3053 %! hf = figure ("visible", "off");
3054 %! unwind_protect
3055 %! hax = gca ();
3056 %! set (hax, "parent", gcf ())
3057 %! assert (gca (), hax)
3058 %! unwind_protect_cleanup
3059 %! close (hf);
3060 %! end_unwind_protect
3061 */
3062 
3063 void
3065 {
3066  __modified__ = "on";
3068  if (parent_obj)
3069  parent_obj.mark_modified ();
3070 }
3071 
3072 void
3074 {
3076 
3077  if (parent_obj)
3078  parent_obj.override_defaults (obj);
3079 }
3080 
3081 void
3082 base_properties::update_axis_limits (const std::string& axis_type) const
3083 {
3084  graphics_object obj = gh_manager::get_object (__myhandle__);
3085 
3086  if (obj)
3087  obj.update_axis_limits (axis_type);
3088 }
3089 
3090 void
3091 base_properties::update_axis_limits (const std::string& axis_type,
3092  const graphics_handle& h) const
3093 {
3094  graphics_object obj = gh_manager::get_object (__myhandle__);
3095 
3096  if (obj)
3097  obj.update_axis_limits (axis_type, h);
3098 }
3099 
3100 void
3102 {
3103  if (uicontextmenu.get ().is_empty ())
3104  return;
3105 
3107  if (obj && obj.isa ("uicontextmenu"))
3108  {
3109  uicontextmenu::properties& props =
3110  reinterpret_cast<uicontextmenu::properties&> (obj.get_properties ());
3111  props.add_dependent_obj (__myhandle__);
3112  }
3113 }
3114 
3115 bool
3117 {
3118  return (handlevisibility.is ("on")
3119  || (executing_callback && ! handlevisibility.is ("off")));
3120 }
3121 
3124 {
3126 
3127  if (go)
3128  return go.get_toolkit ();
3129  else
3130  return graphics_toolkit ();
3131 }
3132 
3133 void
3135 {
3136  Matrix kids = get_children ();
3137 
3138  for (int i = 0; i < kids.numel (); i++)
3139  {
3140  graphics_object go = gh_manager::get_object (kids(i));
3141 
3142  if (go.valid_object ())
3144  }
3145 }
3146 
3147 void
3148 base_properties::update_autopos (const std::string& elem_type)
3149 {
3151 
3152  if (parent_obj.valid_object ())
3153  parent_obj.get_properties ().update_autopos (elem_type);
3154 }
3155 
3156 void
3158  listener_mode mode)
3159 {
3160  property p = get_property (nm);
3161 
3162  if (! error_state && p.ok ())
3163  p.add_listener (v, mode);
3164 }
3165 
3166 void
3168  const octave_value& v, listener_mode mode)
3169 {
3170  property p = get_property (nm);
3171 
3172  if (! error_state && p.ok ())
3173  p.delete_listener (v, mode);
3174 }
3175 
3176 // ---------------------------------------------------------------------
3177 
3178 void
3179 base_graphics_object::update_axis_limits (const std::string& axis_type)
3180 {
3181  if (valid_object ())
3182  {
3184 
3185  if (parent_obj)
3186  parent_obj.update_axis_limits (axis_type);
3187  }
3188  else
3189  error ("base_graphics_object::update_axis_limits: invalid graphics object");
3190 }
3191 
3192 void
3193 base_graphics_object::update_axis_limits (const std::string& axis_type,
3194  const graphics_handle& h)
3195 {
3196  if (valid_object ())
3197  {
3199 
3200  if (parent_obj)
3201  parent_obj.update_axis_limits (axis_type, h);
3202  }
3203  else
3204  error ("base_graphics_object::update_axis_limits: invalid graphics object");
3205 }
3206 
3207 void
3209 {
3210  octave_map m = get (true).map_value ();
3211 
3212  for (octave_map::const_iterator pa = m.begin (); pa != m.end (); pa++)
3213  {
3214  // FIXME: there has to be a better way. I think we want to
3215  // ask whether it is OK to delete the listener for the given
3216  // property. How can we know in advance that it will be OK?
3217 
3218  unwind_protect frame;
3219 
3220  frame.protect_var (error_state);
3222  frame.protect_var (Vdebug_on_error);
3224 
3225  discard_error_messages = true;
3226  Vdebug_on_error = false;
3227  Vdebug_on_warning = false;
3228 
3229  property p = get_properties ().get_property (pa->first);
3230 
3231  if (! error_state && p.ok ())
3232  p.delete_listener ();
3233  }
3234 }
3235 
3236 void
3238 {
3239  property_list local_defaults = get_defaults_list ();
3241  local_defaults.find (go_name);
3242 
3243  if (p != local_defaults.end ())
3244  {
3245  property_list::pval_map_type pval = p->second;
3246  for (property_list::pval_map_const_iterator q = pval.begin ();
3247  q != pval.end (); q++)
3248  {
3249  std::string pname = q->first;
3250  if (def.find (pname) == def.end ())
3251  def[pname] = q->second;
3252  }
3253  }
3254 
3256 
3257  if (parent_obj)
3258  parent_obj.build_user_defaults_map (def, go_name);
3259 
3260 }
3261 
3262 void
3264 {
3265  if (valid_object ())
3266  {
3267  property_list::pval_map_type factory_pval =
3269  .find (type ())->second;
3270 
3271  xreset_default_properties (get_handle (), factory_pval);
3272  }
3273 }
3274 
3275 std::string
3277 {
3278  std::string retval;
3279 
3280  if (valid_object ())
3281  {
3282  octave_map m = get ().map_value ();
3284 
3285  for (octave_map::const_iterator pa = m.begin (); pa != m.end (); pa++)
3286  {
3287  if (pa->first != "children"
3288  && ! obj.has_readonly_property (pa->first))
3289  {
3290  property p = get_properties ().get_property (pa->first);
3291 
3292  if (p.ok () && ! p.is_hidden ())
3293  {
3294  retval += "\n\t" + std::string (pa->first) + ": ";
3295  if (p.is_radio ())
3296  retval += p.values_as_string ();
3297  }
3298  }
3299  }
3300 
3301  if (! retval.empty ())
3302  retval += "\n";
3303  }
3304  else
3305  error ("base_graphics_object::values_as_string: invalid graphics object");
3306 
3307  return retval;
3308 }
3309 
3310 std::string
3311 base_graphics_object::value_as_string (const std::string& prop)
3312 {
3313  std::string retval;
3314 
3315  if (valid_object ())
3316  {
3318 
3319  if (prop != "children" && ! obj.has_readonly_property (prop))
3320  {
3321  property p = get_properties ().get_property (prop);
3322 
3323  if (p.ok () && ! p.is_hidden ())
3324  {
3325  if (p.is_radio ())
3326  retval += p.values_as_string ();
3327  }
3328  }
3329 
3330  if (! retval.empty ())
3331  retval += "\n";
3332  }
3333  else
3334  error ("base_graphics_object::value_as_string: invalid graphics object");
3335 
3336  return retval;
3337 }
3338 
3341 {
3342  octave_scalar_map retval;
3343 
3344  if (valid_object ())
3345  {
3346  octave_scalar_map m = get ().scalar_map_value ();
3348 
3350  pa != m.end (); pa++)
3351  {
3352  if (pa->first != "children"
3353  && ! obj.has_readonly_property (pa->first))
3354  {
3355  property p = get_properties ().get_property (pa->first);
3356 
3357  if (p.ok () && ! p.is_hidden ())
3358  {
3359  if (p.is_radio ())
3360  retval.assign (p.get_name (), p.values_as_cell ());
3361  else
3362  retval.assign (p.get_name (), Cell ());
3363  }
3364  }
3365  }
3366  }
3367  else
3368  error ("base_graphics_object::values_as_struct: invalid graphics object");
3369 
3370  return retval;
3371 }
3372 
3373 /*
3374 %!test
3375 %! hfig = figure ("visible", "off");
3376 %! unwind_protect
3377 %! hax = axes ();
3378 %! ret = set (hax, "tightinset");
3379 %! assert (isempty (ret));
3380 %! ret = set (hax, "type");
3381 %! assert (isempty (ret));
3382 %! ret = set (hfig, "tag");
3383 %! assert (isempty (ret));
3384 %! ret = set (0, "commandwindowsize");
3385 %! assert (isempty (ret));
3386 %! ret = set (0);
3387 %! assert (! isfield (ret, "commandwindowsize"));
3388 %! unwind_protect_cleanup
3389 %! close (hfig);
3390 %! end_unwind_protect
3391 */
3392 
3394 graphics_object::get_ancestor (const std::string& obj_type) const
3395 {
3396  if (valid_object ())
3397  {
3398  if (isa (obj_type))
3399  return *this;
3400  else
3401  return gh_manager::get_object (get_parent ()).get_ancestor (obj_type);
3402  }
3403  else
3404  return graphics_object ();
3405 }
3406 
3407 // ---------------------------------------------------------------------
3408 
3409 #include "graphics-props.cc"
3410 
3411 // ---------------------------------------------------------------------
3412 
3413 void
3415 {
3416  graphics_handle val (v);
3417 
3418  if (error_state)
3419  return;
3420 
3421  if (xisnan (val.value ()))
3422  {
3423  if (! cbo_stack.empty ())
3424  {
3425  val = cbo_stack.front ();
3426 
3427  cbo_stack.pop_front ();
3428  }
3429 
3430  callbackobject = val;
3431  }
3432  else if (is_handle (val))
3433  {
3434  if (get_callbackobject ().ok ())
3435  cbo_stack.push_front (get_callbackobject ());
3436 
3437  callbackobject = val;
3438  }
3439  else
3440  gripe_set_invalid ("callbackobject");
3441 }
3442 
3443 void
3445 {
3446  graphics_handle val (v);
3447 
3448  if (error_state)
3449  return;
3450 
3451  if (xisnan (val.value ()) || is_handle (val))
3452  {
3453  currentfigure = val;
3454 
3455  if (val.ok ())
3457  }
3458  else
3459  gripe_set_invalid ("currentfigure");
3460 }
3461 
3462 std::string
3464 {
3465  bool is_diary_on = F__diarystate__ ()(0).bool_value ();
3466  if (is_diary_on)
3467  return std::string ("on");
3468  else
3469  return std::string ("off");
3470 }
3471 
3472 void
3474 {
3475  if (! error_state)
3476  {
3477  // Input checking and abrev. matching
3478  diary.set (val, false);
3479 
3480  if (! error_state)
3481  {
3482  Fdiary (ovl (diary.current_value ()));
3483 
3484  diary.run_listeners ();
3485  }
3486  }
3487 }
3488 
3489 std::string
3491 {
3492  return F__diaryfile__ ()(0).string_value ();
3493 }
3494 
3495 void
3497 {
3498  if (! error_state)
3499  {
3500  // Input checking and abrev. matching
3501  diaryfile.set (val, false);
3502 
3503  if (! error_state)
3504  {
3505  Fdiary (ovl (diaryfile.string_value ()));
3506 
3507  diaryfile.run_listeners ();
3508  }
3509  }
3510 }
3511 
3512 std::string
3514 {
3515  bool is_echo_on = F__echostate__ ()(0).bool_value ();
3516  if (is_echo_on)
3517  return std::string ("on");
3518  else
3519  return std::string ("off");
3520 }
3521 
3522 void
3524 {
3525  if (! error_state)
3526  {
3527  // Input checking and abrev. matching
3528  echo.set (val, false);
3529 
3530  if (! error_state)
3531  {
3532  Fecho (ovl (echo.current_value ()));
3533 
3534  echo.run_listeners ();
3535  }
3536  }
3537 }
3538 
3539 std::string
3541 {
3542  return Flasterr ()(0).string_value ();
3543 }
3544 
3545 std::string
3547 {
3548  return F__formatstring__ ()(0).string_value ();
3549 }
3550 
3551 void
3553 {
3554  if (! error_state)
3555  {
3556  // Input checking and abrev. matching
3557  format.set (val, false);
3558 
3559  if (! error_state)
3560  {
3561  Fformat (ovl (format.current_value ()));
3562 
3563  format.run_listeners ();
3564  }
3565  }
3566 }
3567 
3568 std::string
3570 {
3571  bool iscompact = F__compactformat__ ()(0).bool_value ();
3572  if (iscompact)
3573  return std::string ("compact");
3574  else
3575  return std::string ("loose");
3576 }
3577 
3578 void
3580 {
3581  if (! error_state)
3582  {
3583  // Input checking and abrev. matching
3584  formatspacing.set (val, false);
3585 
3586  if (! error_state)
3587  {
3588  std::string strval = formatspacing.current_value ();
3589 
3590  if (strval == "compact")
3591  F__compactformat__ (ovl (true));
3592  else
3593  F__compactformat__ (ovl (false));
3594 
3595  formatspacing.run_listeners ();
3596  }
3597  }
3598 }
3599 
3600 
3601 double
3603 {
3604  return Fmax_recursion_depth ()(0).double_value ();
3605 }
3606 
3607 void
3609 {
3610  if (! error_state)
3611  {
3612  // Input checking and abrev. matching
3613  recursionlimit.set (val, false);
3614 
3615  if (! error_state)
3616  {
3617  double dval = recursionlimit.double_value ();
3618 
3619  Fmax_recursion_depth (ovl (dval));
3620 
3621  recursionlimit.run_listeners ();
3622  }
3623  }
3624 }
3625 
3626 void
3628 {
3629  if (! error_state)
3630  {
3631  if (integerhandle.set (val, true))
3632  {
3633  bool int_fig_handle = integerhandle.is_on ();
3634 
3635  graphics_object this_go = gh_manager::get_object (__myhandle__);
3636 
3637  graphics_handle old_myhandle = __myhandle__;
3638 
3639  __myhandle__ = gh_manager::get_handle (int_fig_handle);
3640 
3641  gh_manager::renumber_figure (old_myhandle, __myhandle__);
3642 
3644 
3645  base_properties& props = parent_go.get_properties ();
3646 
3647  props.renumber_child (old_myhandle, __myhandle__);
3648 
3649  Matrix kids = get_children ();
3650 
3651  for (octave_idx_type i = 0; i < kids.numel (); i++)
3652  {
3653  graphics_object kid = gh_manager::get_object (kids(i));
3654 
3655  kid.get_properties ().renumber_parent (__myhandle__);
3656  }
3657 
3659 
3660  if (__myhandle__ == cf)
3661  xset (0, "currentfigure", __myhandle__.value ());
3662 
3663  this_go.update (integerhandle.get_id ());
3664 
3665  mark_modified ();
3666  }
3667  }
3668 }
3669 
3670 // FIXME: This should update monitorpositions and pointerlocation, but
3671 // as these properties are yet used, and so it doesn't matter that they
3672 // aren't set yet.
3673 void
3675 {
3676  caseless_str xunits = get_units ();
3677 
3678  Matrix ss = default_screensize ();
3679 
3680  double dpi = get_screenpixelsperinch ();
3681 
3682  if (xunits.compare ("inches"))
3683  {
3684  ss(0) = 0;
3685  ss(1) = 0;
3686  ss(2) /= dpi;
3687  ss(3) /= dpi;
3688  }
3689  else if (xunits.compare ("centimeters"))
3690  {
3691  ss(0) = 0;
3692  ss(1) = 0;
3693  ss(2) *= 2.54 / dpi;
3694  ss(3) *= 2.54 / dpi;
3695  }
3696  else if (xunits.compare ("normalized"))
3697  {
3698  ss = Matrix (1, 4, 1.0);
3699  ss(0) = 0;
3700  ss(1) = 0;
3701  }
3702  else if (xunits.compare ("points"))
3703  {
3704  ss(0) = 0;
3705  ss(1) = 0;
3706  ss(2) *= 72 / dpi;
3707  ss(3) *= 72 / dpi;
3708  }
3709 
3710  set_screensize (ss);
3711 }
3712 
3713 Matrix
3715 {
3716  Matrix screen_size = screen_size_pixels ();
3717  Matrix pos = Matrix (1, 4, 0);
3718  pos(2) = screen_size(0);
3719  pos(3) = screen_size(1);
3720  return pos;
3721 }
3722 
3723 /*
3724 %!test
3725 %! old_units = get (0, "units");
3726 %! unwind_protect
3727 %! set (0, "units", "pixels");
3728 %! sz = get (0, "screensize") - [1, 1, 0, 0];
3729 %! dpi = get (0, "screenpixelsperinch");
3730 %! set (0, "units", "inches");
3731 %! assert (get (0, "screensize"), sz / dpi, 0.5 / dpi);
3732 %! set (0, "units", "centimeters");
3733 %! assert (get (0, "screensize"), sz / dpi * 2.54, 0.5 / dpi * 2.54);
3734 %! set (0, "units", "points");
3735 %! assert (get (0, "screensize"), sz / dpi * 72, 0.5 / dpi * 72);
3736 %! set (0, "units", "normalized");
3737 %! assert (get (0, "screensize"), [0.0, 0.0, 1.0, 1.0]);
3738 %! set (0, "units", "pixels");
3739 %! assert (get (0, "screensize"), sz + [1, 1, 0, 0]);
3740 %! unwind_protect_cleanup
3741 %! set (0, "units", old_units);
3742 %! end_unwind_protect
3743 */
3744 
3745 void
3747 {
3749 
3751 
3752  xset (0, "currentfigure", cf.value ());
3753 
3755 }
3756 
3759 
3760 void
3762 {
3763  // empty list of local defaults
3765 
3768 }
3769 
3770 // ---------------------------------------------------------------------
3771 
3772 void
3774 {
3775  graphics_handle val (v);
3776 
3777  if (error_state)
3778  return;
3779 
3780  if (xisnan (val.value ()) || is_handle (val))
3781  currentaxes = val;
3782  else
3783  gripe_set_invalid ("currentaxes");
3784 }
3785 
3786 void
3788 {
3790 
3791  if (gh == currentaxes.handle_value ())
3792  {
3793  graphics_handle new_currentaxes;
3794 
3795  Matrix kids = get_children ();
3796 
3797  for (octave_idx_type i = 0; i < kids.numel (); i++)
3798  {
3799  graphics_handle kid = kids(i);
3800 
3802 
3803  if (go.isa ("axes"))
3804  {
3805  new_currentaxes = kid;
3806  break;
3807  }
3808  }
3809 
3810  currentaxes = new_currentaxes;
3811  }
3812 }
3813 
3814 void
3816 {
3818 
3819  if (! get_currentaxes ().ok ())
3820  {
3822 
3823  if (go.type () == "axes")
3824  set_currentaxes (h.as_octave_value ());
3825  }
3826 }
3827 
3828 /*
3829 %!test
3830 %! hf1 = figure ("visible", "off");
3831 %! ax1 = subplot (1,2,1);
3832 %! ax2 = subplot (1,2,2);
3833 %! hf2 = figure ("visible", "off");
3834 %! unwind_protect
3835 %! set (ax2, "parent", hf2);
3836 %! assert (get (hf2, "currentaxes"), ax2);
3837 %! assert (get (hf1, "currentaxes"), ax1);
3838 %! set (ax1, "parent", hf2);
3839 %! assert (get (hf2, "currentaxes"), ax2);
3840 %! unwind_protect_cleanup
3841 %! close (hf1);
3842 %! close (hf2);
3843 %! end_unwind_protect
3844 */
3845 
3846 void
3848 {
3849  std::string s = val.string_value ();
3850 
3851  if (! error_state)
3852  {
3853  if (s == "on")
3854  xset (0, "currentfigure", __myhandle__.value ());
3855 
3856  visible = val;
3857  }
3858 }
3859 
3860 Matrix
3861 figure::properties::get_boundingbox (bool internal, const Matrix&) const
3862 {
3863  Matrix screen_size = screen_size_pixels ();
3864  Matrix pos = (internal ?
3865  get_position ().matrix_value () :
3866  get_outerposition ().matrix_value ());
3867 
3868  pos = convert_position (pos, get_units (), "pixels", screen_size);
3869 
3870  pos(0)--;
3871  pos(1)--;
3872  pos(1) = screen_size(1) - pos(1) - pos(3);
3873 
3874  return pos;
3875 }
3876 
3877 void
3879  bool do_notify_toolkit)
3880 {
3881  Matrix screen_size = screen_size_pixels ();
3882  Matrix pos = bb;
3883 
3884  pos(1) = screen_size(1) - pos(1) - pos(3);
3885  pos(1)++;
3886  pos(0)++;
3887  pos = convert_position (pos, "pixels", get_units (), screen_size);
3888 
3889  if (internal)
3890  set_position (pos, do_notify_toolkit);
3891  else
3892  set_outerposition (pos, do_notify_toolkit);
3893 }
3894 
3895 Matrix
3897 {
3898  Matrix bb = get_boundingbox (true);
3899  Matrix pos (1, 2, 0);
3900 
3901  pos(0) = x;
3902  pos(1) = y;
3903 
3904  pos(1) = bb(3) - pos(1);
3905  pos(0)++;
3906  pos = convert_position (pos, "pixels", get_units (),
3907  bb.extract_n (0, 2, 1, 2));
3908 
3909  return pos;
3910 }
3911 
3912 Matrix
3914 {
3915  Matrix bb = get_boundingbox (true);
3916  Matrix pos (1, 2, 0);
3917 
3918  pos(0) = x;
3919  pos(1) = y;
3920 
3921  pos = convert_position (pos, get_units (), "pixels",
3922  bb.extract_n (0, 2, 1, 2));
3923  pos(0)--;
3924  pos(1) = bb(3) - pos(1);
3925 
3926  return pos;
3927 }
3928 
3929 void
3931  bool do_notify_toolkit)
3932 {
3933  if (! error_state)
3934  {
3935  Matrix old_bb, new_bb;
3936  bool modified = false;
3937 
3938  old_bb = get_boundingbox (true);
3939  modified = position.set (v, false, do_notify_toolkit);
3940  new_bb = get_boundingbox (true);
3941 
3942  if (old_bb != new_bb)
3943  {
3944  if (old_bb(2) != new_bb(2) || old_bb(3) != new_bb(3))
3945  {
3946  execute_resizefcn ();
3947  update_boundingbox ();
3948  }
3949  }
3950 
3951  if (modified)
3952  {
3953  position.run_listeners (POSTSET);
3954  mark_modified ();
3955  }
3956 
3957  if (paperpositionmode.is ("auto"))
3958  paperposition.set (get_auto_paperposition ());
3959  }
3960 }
3961 
3962 void
3964  bool do_notify_toolkit)
3965 {
3966  if (! error_state)
3967  {
3968  if (outerposition.set (v, true, do_notify_toolkit))
3969  {
3970  mark_modified ();
3971  }
3972  }
3973 }
3974 
3975 void
3977 {
3978  if (! error_state)
3979  {
3980  caseless_str typ = get_papertype ();
3981  caseless_str punits = v.string_value ();
3982  if (! error_state)
3983  {
3984  if (punits.compare ("normalized") && typ.compare ("<custom>"))
3985  error ("set: can't set the paperunits to normalized when the papertype is custom");
3986  else
3987  {
3988  caseless_str old_paperunits = get_paperunits ();
3989  if (paperunits.set (v, true))
3990  {
3991  update_paperunits (old_paperunits);
3992  mark_modified ();
3993  }
3994  }
3995  }
3996  }
3997 }
3998 
3999 void
4001 {
4002  if (! error_state)
4003  {
4004  caseless_str typ = v.string_value ();
4005  caseless_str punits = get_paperunits ();
4006  if (! error_state)
4007  {
4008  if (punits.compare ("normalized") && typ.compare ("<custom>"))
4009  error ("set: can't set the paperunits to normalized when the papertype is custom");
4010  else
4011  {
4012  if (papertype.set (v, true))
4013  {
4014  update_papertype ();
4015  mark_modified ();
4016  }
4017  }
4018  }
4019  }
4020 }
4021 
4022 static Matrix
4024 {
4025  Matrix ret (1, 2, 1.0);
4026 
4027  if (! punits.compare ("normalized"))
4028  {
4029  double in2units;
4030  double mm2units;
4031 
4032  if (punits.compare ("inches"))
4033  {
4034  in2units = 1.0;
4035  mm2units = 1 / 25.4 ;
4036  }
4037  else if (punits.compare ("centimeters"))
4038  {
4039  in2units = 2.54;
4040  mm2units = 1 / 10.0;
4041  }
4042  else // points
4043  {
4044  in2units = 72.0;
4045  mm2units = 72.0 / 25.4;
4046  }
4047 
4048  if (typ.compare ("usletter"))
4049  {
4050  ret (0) = 8.5 * in2units;
4051  ret (1) = 11.0 * in2units;
4052  }
4053  else if (typ.compare ("uslegal"))
4054  {
4055  ret (0) = 8.5 * in2units;
4056  ret (1) = 14.0 * in2units;
4057  }
4058  else if (typ.compare ("tabloid"))
4059  {
4060  ret (0) = 11.0 * in2units;
4061  ret (1) = 17.0 * in2units;
4062  }
4063  else if (typ.compare ("a0"))
4064  {
4065  ret (0) = 841.0 * mm2units;
4066  ret (1) = 1189.0 * mm2units;
4067  }
4068  else if (typ.compare ("a1"))
4069  {
4070  ret (0) = 594.0 * mm2units;
4071  ret (1) = 841.0 * mm2units;
4072  }
4073  else if (typ.compare ("a2"))
4074  {
4075  ret (0) = 420.0 * mm2units;
4076  ret (1) = 594.0 * mm2units;
4077  }
4078  else if (typ.compare ("a3"))
4079  {
4080  ret (0) = 297.0 * mm2units;
4081  ret (1) = 420.0 * mm2units;
4082  }
4083  else if (typ.compare ("a4"))
4084  {
4085  ret (0) = 210.0 * mm2units;
4086  ret (1) = 297.0 * mm2units;
4087  }
4088  else if (typ.compare ("a5"))
4089  {
4090  ret (0) = 148.0 * mm2units;
4091  ret (1) = 210.0 * mm2units;
4092  }
4093  else if (typ.compare ("b0"))
4094  {
4095  ret (0) = 1029.0 * mm2units;
4096  ret (1) = 1456.0 * mm2units;
4097  }
4098  else if (typ.compare ("b1"))
4099  {
4100  ret (0) = 728.0 * mm2units;
4101  ret (1) = 1028.0 * mm2units;
4102  }
4103  else if (typ.compare ("b2"))
4104  {
4105  ret (0) = 514.0 * mm2units;
4106  ret (1) = 728.0 * mm2units;
4107  }
4108  else if (typ.compare ("b3"))
4109  {
4110  ret (0) = 364.0 * mm2units;
4111  ret (1) = 514.0 * mm2units;
4112  }
4113  else if (typ.compare ("b4"))
4114  {
4115  ret (0) = 257.0 * mm2units;
4116  ret (1) = 364.0 * mm2units;
4117  }
4118  else if (typ.compare ("b5"))
4119  {
4120  ret (0) = 182.0 * mm2units;
4121  ret (1) = 257.0 * mm2units;
4122  }
4123  else if (typ.compare ("arch-a"))
4124  {
4125  ret (0) = 9.0 * in2units;
4126  ret (1) = 12.0 * in2units;
4127  }
4128  else if (typ.compare ("arch-b"))
4129  {
4130  ret (0) = 12.0 * in2units;
4131  ret (1) = 18.0 * in2units;
4132  }
4133  else if (typ.compare ("arch-c"))
4134  {
4135  ret (0) = 18.0 * in2units;
4136  ret (1) = 24.0 * in2units;
4137  }
4138  else if (typ.compare ("arch-d"))
4139  {
4140  ret (0) = 24.0 * in2units;
4141  ret (1) = 36.0 * in2units;
4142  }
4143  else if (typ.compare ("arch-e"))
4144  {
4145  ret (0) = 36.0 * in2units;
4146  ret (1) = 48.0 * in2units;
4147  }
4148  else if (typ.compare ("a"))
4149  {
4150  ret (0) = 8.5 * in2units;
4151  ret (1) = 11.0 * in2units;
4152  }
4153  else if (typ.compare ("b"))
4154  {
4155  ret (0) = 11.0 * in2units;
4156  ret (1) = 17.0 * in2units;
4157  }
4158  else if (typ.compare ("c"))
4159  {
4160  ret (0) = 17.0 * in2units;
4161  ret (1) = 22.0 * in2units;
4162  }
4163  else if (typ.compare ("d"))
4164  {
4165  ret (0) = 22.0 * in2units;
4166  ret (1) = 34.0 * in2units;
4167  }
4168  else if (typ.compare ("e"))
4169  {
4170  ret (0) = 34.0 * in2units;
4171  ret (1) = 43.0 * in2units;
4172  }
4173  }
4174 
4175  return ret;
4176 }
4177 
4178 
4179 Matrix
4181 {
4182  Matrix pos = get_position ().matrix_value ();
4183  Matrix sz;
4184 
4185  caseless_str funits = get_units ();
4186  caseless_str punits = get_paperunits ();
4187 
4188  // Convert position from figure units to paperunits
4189  if (funits == "normalized" || punits == "normalized")
4190  {
4191  sz = screen_size_pixels ();
4192  pos = convert_position (pos, funits, "inches", sz);
4193 
4194  if (punits == "normalized")
4195  sz = papersize_from_type ("points", get_papertype ());
4196 
4197  pos = convert_position (pos, "inches", punits, sz);
4198  }
4199  else
4200  pos = convert_position (pos, funits, punits, sz);
4201 
4202  // Center the figure on the page
4203  sz = get_papersize ().matrix_value ();
4204 
4205  pos(0) = sz(0)/2 - pos(2)/2;
4206  pos(1) = sz(1)/2 - pos(3)/2;
4207 
4208  return pos;
4209 }
4210 
4211 /*
4212 %!test
4213 %! hf = figure ("visible", "off", "paperpositionmode", "auto");
4214 %! in_pos = [0 0 4 5];
4215 %! tol = 20 * eps ();
4216 %! unwind_protect
4217 %! ## paperpositionmode "auto" converts figure size to paper units
4218 %! set (hf, "units", "inches");
4219 %! set (hf, "position", in_pos);
4220 %! set (hf, "paperunits", "centimeters");
4221 %! psz = get (hf, "papersize");
4222 %! fsz = in_pos(3:4) * 2.54;
4223 %! pos = [(psz/2 .- fsz/2) fsz];
4224 %! set (hf, "paperpositionmode", "auto");
4225 %! assert (get (hf, "paperposition"), pos, tol)
4226 %! unwind_protect_cleanup
4227 %! close (hf);
4228 %! end_unwind_protect
4229 
4230 %!test
4231 %! hf = figure ("visible", "off", "paperpositionmode", "auto");
4232 %! in_pos = [0 0 4 5];
4233 %! tol = 20 * eps ();
4234 %! unwind_protect
4235 %! ## likewise with normalized units
4236 %! set (hf, "units", "inches");
4237 %! set (hf, "position", in_pos);
4238 %! psz = get (hf, "papersize");
4239 %! set (hf, "paperunits", "normalized");
4240 %! fsz = in_pos(3:4) ./ psz;
4241 %! pos = [([0.5 0.5] .- fsz/2) fsz];
4242 %! assert (get (hf, "paperposition"), pos, tol)
4243 %! unwind_protect_cleanup
4244 %! close (hf);
4245 %! end_unwind_protect
4246 
4247 %!test
4248 %! hf = figure ("visible", "off", "paperpositionmode", "auto");
4249 %! in_pos = [0 0 4 5];
4250 %! tol = 20 * eps ();
4251 %! unwind_protect
4252 %! ## changing papertype updates paperposition
4253 %! set (hf, "units", "inches");
4254 %! set (hf, "position", in_pos);
4255 %! set (hf, "papertype", "a4");
4256 %! psz = get (hf, "papersize");
4257 %! fsz = in_pos(3:4);
4258 %! pos = [(psz/2 .- fsz/2) fsz];
4259 %! assert (get (hf, "paperposition"), pos, tol)
4260 %! unwind_protect_cleanup
4261 %! close (hf);
4262 %! end_unwind_protect
4263 
4264 %!test
4265 %! hf = figure ("visible", "off", "paperpositionmode", "auto");
4266 %! in_pos = [0 0 4 5];
4267 %! tol = 20 * eps ();
4268 %! unwind_protect
4269 %! ## lanscape updates paperposition
4270 %! set (hf, "units", "inches");
4271 %! set (hf, "position", in_pos);
4272 %! set (hf, "paperorientation", "landscape");
4273 %! psz = get (hf, "papersize");
4274 %! fsz = in_pos(3:4);
4275 %! pos = [(psz/2 .- fsz/2) fsz];
4276 %! assert (get (hf, "paperposition"), pos, tol)
4277 %! unwind_protect_cleanup
4278 %! close (hf);
4279 %! end_unwind_protect
4280 
4281 %!test
4282 %! hf = figure ("visible", "off", "paperpositionmode", "auto");
4283 %! in_pos = [0 0 4 5];
4284 %! unwind_protect
4285 %! ## back to manual mode
4286 %! set (hf, "paperposition", in_pos * 1.1)
4287 %! assert (get (hf, "paperpositionmode"), "manual")
4288 %! assert (get (hf, "paperposition"), in_pos * 1.1)
4289 %! unwind_protect_cleanup
4290 %! close (hf);
4291 %! end_unwind_protect
4292 */
4293 
4294 void
4296 {
4297  Matrix pos = get_paperposition ().matrix_value ();
4298  Matrix sz = get_papersize ().matrix_value ();
4299 
4300  pos(0) /= sz(0);
4301  pos(1) /= sz(1);
4302  pos(2) /= sz(0);
4303  pos(3) /= sz(1);
4304 
4305  std::string porient = get_paperorientation ();
4306  caseless_str punits = get_paperunits ();
4307  caseless_str typ = get_papertype ();
4308 
4309  if (typ.compare ("<custom>"))
4310  {
4311  if (old_paperunits.compare ("centimeters"))
4312  {
4313  sz(0) /= 2.54;
4314  sz(1) /= 2.54;
4315  }
4316  else if (old_paperunits.compare ("points"))
4317  {
4318  sz(0) /= 72.0;
4319  sz(1) /= 72.0;
4320  }
4321 
4322  if (punits.compare ("centimeters"))
4323  {
4324  sz(0) *= 2.54;
4325  sz(1) *= 2.54;
4326  }
4327  else if (punits.compare ("points"))
4328  {
4329  sz(0) *= 72.0;
4330  sz(1) *= 72.0;
4331  }
4332  }
4333  else
4334  {
4335  sz = papersize_from_type (punits, typ);
4336  if (porient == "landscape")
4337  std::swap (sz(0), sz(1));
4338  }
4339 
4340  pos(0) *= sz(0);
4341  pos(1) *= sz(1);
4342  pos(2) *= sz(0);
4343  pos(3) *= sz(1);
4344 
4345  papersize.set (octave_value (sz));
4346  paperposition.set (octave_value (pos));
4347 }
4348 
4349 void
4351 {
4352  caseless_str typ = get_papertype ();
4353  if (! typ.compare ("<custom>"))
4354  {
4355  Matrix sz = papersize_from_type (get_paperunits (), typ);
4356  if (get_paperorientation () == "landscape")
4357  std::swap (sz(0), sz(1));
4358  // Call papersize.set rather than set_papersize to avoid loops
4359  // between update_papersize and update_papertype
4360  papersize.set (octave_value (sz));
4361  }
4362 
4363  if (paperpositionmode.is ("auto"))
4364  paperposition.set (get_auto_paperposition ());
4365 }
4366 
4367 void
4369 {
4370  Matrix sz = get_papersize ().matrix_value ();
4371  if (sz(0) > sz(1))
4372  {
4373  std::swap (sz(0), sz(1));
4374  papersize.set (octave_value (sz));
4375  paperorientation.set (octave_value ("landscape"));
4376  }
4377  else
4378  {
4379  paperorientation.set ("portrait");
4380  }
4381  std::string punits = get_paperunits ();
4382  if (punits == "centimeters")
4383  {
4384  sz(0) /= 2.54;
4385  sz(1) /= 2.54;
4386  }
4387  else if (punits == "points")
4388  {
4389  sz(0) /= 72.0;
4390  sz(1) /= 72.0;
4391  }
4392  if (punits == "normalized")
4393  {
4394  caseless_str typ = get_papertype ();
4395  if (get_papertype () == "<custom>")
4396  error ("set: can't set the papertype to <custom> when the paperunits is normalized");
4397  }
4398  else
4399  {
4400  // TODO - the papersizes info is also in papersize_from_type().
4401  // Both should be rewritten to avoid the duplication.
4402  std::string typ = "<custom>";
4403  const double mm2in = 1.0 / 25.4;
4404  const double tol = 0.01;
4405 
4406  if (std::abs (sz(0) - 8.5) + std::abs (sz(1) - 11.0) < tol)
4407  typ = "usletter";
4408  else if (std::abs (sz(0) - 8.5) + std::abs (sz(1) - 14.0) < tol)
4409  typ = "uslegal";
4410  else if (std::abs (sz(0) - 11.0) + std::abs (sz(1) - 17.0) < tol)
4411  typ = "tabloid";
4412  else if (std::abs (sz(0) - 841.0 * mm2in)
4413  + std::abs (sz(1) - 1198.0 * mm2in) < tol)
4414  typ = "a0";
4415  else if (std::abs (sz(0) - 594.0 * mm2in)
4416  + std::abs (sz(1) - 841.0 * mm2in) < tol)
4417  typ = "a1";
4418  else if (std::abs (sz(0) - 420.0 * mm2in)
4419  + std::abs (sz(1) - 594.0 * mm2in) < tol)
4420  typ = "a2";
4421  else if (std::abs (sz(0) - 297.0 * mm2in)
4422  + std::abs (sz(1) - 420.0 * mm2in) < tol)
4423  typ = "a3";
4424  else if (std::abs (sz(0) - 210.0 * mm2in)
4425  + std::abs (sz(1) - 297.0 * mm2in) < tol)
4426  typ = "a4";
4427  else if (std::abs (sz(0) - 148.0 * mm2in)
4428  + std::abs (sz(1) - 210.0 * mm2in) < tol)
4429  typ = "a5";
4430  else if (std::abs (sz(0) - 1029.0 * mm2in)
4431  + std::abs (sz(1) - 1456.0 * mm2in) < tol)
4432  typ = "b0";
4433  else if (std::abs (sz(0) - 728.0 * mm2in)
4434  + std::abs (sz(1) - 1028.0 * mm2in) < tol)
4435  typ = "b1";
4436  else if (std::abs (sz(0) - 514.0 * mm2in)
4437  + std::abs (sz(1) - 728.0 * mm2in) < tol)
4438  typ = "b2";
4439  else if (std::abs (sz(0) - 364.0 * mm2in)
4440  + std::abs (sz(1) - 514.0 * mm2in) < tol)
4441  typ = "b3";
4442  else if (std::abs (sz(0) - 257.0 * mm2in)
4443  + std::abs (sz(1) - 364.0 * mm2in) < tol)
4444  typ = "b4";
4445  else if (std::abs (sz(0) - 182.0 * mm2in)
4446  + std::abs (sz(1) - 257.0 * mm2in) < tol)
4447  typ = "b5";
4448  else if (std::abs (sz(0) - 9.0)
4449  + std::abs (sz(1) - 12.0) < tol)
4450  typ = "arch-a";
4451  else if (std::abs (sz(0) - 12.0)
4452  + std::abs (sz(1) - 18.0) < tol)
4453  typ = "arch-b";
4454  else if (std::abs (sz(0) - 18.0)
4455  + std::abs (sz(1) - 24.0) < tol)
4456  typ = "arch-c";
4457  else if (std::abs (sz(0) - 24.0)
4458  + std::abs (sz(1) - 36.0) < tol)
4459  typ = "arch-d";
4460  else if (std::abs (sz(0) - 36.0)
4461  + std::abs (sz(1) - 48.0) < tol)
4462  typ = "arch-e";
4463  else if (std::abs (sz(0) - 8.5)
4464  + std::abs (sz(1) - 11.0) < tol)
4465  typ = "a";
4466  else if (std::abs (sz(0) - 11.0)
4467  + std::abs (sz(1) - 17.0) < tol)
4468  typ = "b";
4469  else if (std::abs (sz(0) - 17.0)
4470  + std::abs (sz(1) - 22.0) < tol)
4471  typ = "c";
4472  else if (std::abs (sz(0) - 22.0)
4473  + std::abs (sz(1) - 34.0) < tol)
4474  typ = "d";
4475  else if (std::abs (sz(0) - 34.0)
4476  + std::abs (sz(1) - 43.0) < tol)
4477  typ = "e";
4478  // Call papertype.set rather than set_papertype to avoid loops between
4479  // update_papersize and update_papertype
4480  papertype.set (typ);
4481  }
4482  if (punits == "centimeters")
4483  {
4484  sz(0) *= 2.54;
4485  sz(1) *= 2.54;
4486  }
4487  else if (punits == "points")
4488  {
4489  sz(0) *= 72.0;
4490  sz(1) *= 72.0;
4491  }
4492  if (get_paperorientation () == "landscape")
4493  {
4494  std::swap (sz(0), sz(1));
4495  papersize.set (octave_value (sz));
4496  }
4497 
4498  if (paperpositionmode.is ("auto"))
4499  paperposition.set (get_auto_paperposition ());
4500 }
4501 
4502 /*
4503 %!test
4504 %! hf = figure ("visible", "off");
4505 %! unwind_protect
4506 %! set (hf, "paperunits", "inches");
4507 %! set (hf, "papersize", [5, 4]);
4508 %! set (hf, "paperunits", "points");
4509 %! assert (get (hf, "papersize"), [5, 4] * 72, 1);
4510 %! papersize = get (hf, "papersize");
4511 %! set (hf, "papersize", papersize + 1);
4512 %! set (hf, "papersize", papersize);
4513 %! assert (get (hf, "papersize"), [5, 4] * 72, 1);
4514 %! unwind_protect_cleanup
4515 %! close (hf);
4516 %! end_unwind_protect
4517 
4518 %!test
4519 %! hf = figure ("visible", "off");
4520 %! unwind_protect
4521 %! set (hf, "paperunits", "inches");
4522 %! set (hf, "papersize", [5, 4]);
4523 %! set (hf, "paperunits", "centimeters");
4524 %! assert (get (hf, "papersize"), [5, 4] * 2.54, 2.54/72);
4525 %! papersize = get (hf, "papersize");
4526 %! set (hf, "papersize", papersize + 1);
4527 %! set (hf, "papersize", papersize);
4528 %! assert (get (hf, "papersize"), [5, 4] * 2.54, 2.54/72);
4529 %! unwind_protect_cleanup
4530 %! close (hf);
4531 %! end_unwind_protect
4532 */
4533 
4534 void
4536 {
4537  std::string porient = get_paperorientation ();
4538  Matrix sz = get_papersize ().matrix_value ();
4539  Matrix pos = get_paperposition ().matrix_value ();
4540  if ((sz(0) > sz(1) && porient == "portrait")
4541  || (sz(0) < sz(1) && porient == "landscape"))
4542  {
4543  std::swap (sz(0), sz(1));
4544  std::swap (pos(0), pos(1));
4545  std::swap (pos(2), pos(3));
4546  // Call papertype.set rather than set_papertype to avoid loops
4547  // between update_papersize and update_papertype
4548  papersize.set (octave_value (sz));
4549  paperposition.set (octave_value (pos));
4550  }
4551 
4552  if (paperpositionmode.is ("auto"))
4553  paperposition.set (get_auto_paperposition ());
4554 }
4555 
4556 /*
4557 %!test
4558 %! hf = figure ("visible", "off");
4559 %! unwind_protect
4560 %! tol = 100 * eps ();
4561 %! ## UPPER case and MiXed case is part of test and should not be changed.
4562 %! set (hf, "paperorientation", "PORTRAIT");
4563 %! set (hf, "paperunits", "inches");
4564 %! set (hf, "papertype", "USletter");
4565 %! assert (get (hf, "papersize"), [8.5, 11.0], tol);
4566 %! set (hf, "paperorientation", "Landscape");
4567 %! assert (get (hf, "papersize"), [11.0, 8.5], tol);
4568 %! set (hf, "paperunits", "centimeters");
4569 %! assert (get (hf, "papersize"), [11.0, 8.5] * 2.54, tol);
4570 %! set (hf, "papertype", "a4");
4571 %! assert (get (hf, "papersize"), [29.7, 21.0], tol);
4572 %! set (hf, "paperunits", "inches", "papersize", [8.5, 11.0]);
4573 %! assert (get (hf, "papertype"), "usletter");
4574 %! assert (get (hf, "paperorientation"), "portrait");
4575 %! set (hf, "papersize", [11.0, 8.5]);
4576 %! assert (get (hf, "papertype"), "usletter");
4577 %! assert (get (hf, "paperorientation"), "landscape");
4578 %! unwind_protect_cleanup
4579 %! close (hf);
4580 %! end_unwind_protect
4581 */
4582 
4583 void
4585 {
4586  if (! error_state)
4587  {
4588  caseless_str old_units = get_units ();
4589  if (units.set (v, true))
4590  {
4591  update_units (old_units);
4592  mark_modified ();
4593  }
4594  }
4595 }
4596 
4597 void
4599 {
4600  position.set (convert_position (get_position ().matrix_value (), old_units,
4601  get_units (), screen_size_pixels ()), false);
4602 }
4603 
4604 /*
4605 %!test
4606 %! hf = figure ("visible", "off");
4607 %! old_units = get (0, "units");
4608 %! unwind_protect
4609 %! set (0, "units", "pixels");
4610 %! rsz = get (0, "screensize");
4611 %! set (gcf (), "units", "pixels");
4612 %! fsz = get (gcf (), "position");
4613 %! set (gcf (), "units", "normalized");
4614 %! pos = get (gcf (), "position");
4615 %! assert (pos, (fsz - [1, 1, 0, 0]) ./ rsz([3, 4, 3, 4]));
4616 %! unwind_protect_cleanup
4617 %! close (hf);
4618 %! set (0, "units", old_units);
4619 %! end_unwind_protect
4620 */
4621 
4622 std::string
4624 {
4625  if (is_numbertitle ())
4626  {
4627  std::ostringstream os;
4628  std::string nm = get_name ();
4629 
4630  os << "Figure " << __myhandle__.value ();
4631  if (! nm.empty ())
4632  os << ": " << get_name ();
4633 
4634  return os.str ();
4635  }
4636  else
4637  return get_name ();
4638 }
4639 
4642 {
4643  octave_value retval = default_properties.lookup (name);
4644 
4645  if (retval.is_undefined ())
4646  {
4647  graphics_handle parent = get_parent ();
4648  graphics_object parent_obj = gh_manager::get_object (parent);
4649 
4650  retval = parent_obj.get_default (name);
4651  }
4652 
4653  return retval;
4654 }
4655 
4656 void
4658 {
4659  // empty list of local defaults
4661 
4663  plist.erase ("units");
4664  plist.erase ("position");
4665  plist.erase ("outerposition");
4666  plist.erase ("paperunits");
4667  plist.erase ("paperposition");
4668  plist.erase ("windowstyle");
4669 
4671 }
4672 
4673 // ---------------------------------------------------------------------
4674 
4675 void
4677 {
4678  position.add_constraint (dim_vector (1, 4));
4679  outerposition.add_constraint (dim_vector (1, 4));
4680  tightinset.add_constraint (dim_vector (1, 4));
4681  looseinset.add_constraint (dim_vector (1, 4));
4682  colororder.add_constraint (dim_vector (-1, 3));
4683  dataaspectratio.add_constraint (dim_vector (1, 3));
4684  plotboxaspectratio.add_constraint (dim_vector (1, 3));
4685  alim.add_constraint (2);
4686  clim.add_constraint (2);
4687  xlim.add_constraint (2);
4688  ylim.add_constraint (2);
4689  zlim.add_constraint (2);
4690  xtick.add_constraint (dim_vector (1, -1));
4691  ytick.add_constraint (dim_vector (1, -1));
4692  ztick.add_constraint (dim_vector (1, -1));
4693  ticklength.add_constraint (dim_vector (1, 2));
4694  Matrix vw (1, 2, 0);
4695  vw(1) = 90;
4696  view = vw;
4697  view.add_constraint (dim_vector (1, 2));
4698  cameraposition.add_constraint (dim_vector (1, 3));
4699  cameratarget.add_constraint (dim_vector (1, 3));
4700  Matrix upv (1, 3, 0.0);
4701  upv(2) = 1.0;
4702  cameraupvector = upv;
4703  cameraupvector.add_constraint (dim_vector (1, 3));
4704  currentpoint.add_constraint (dim_vector (2, 3));
4705  // No constraints for hidden transform properties
4706  update_font ();
4707 
4708  x_zlim.resize (1, 2);
4709 
4710  sx = "linear";
4711  sy = "linear";
4712  sz = "linear";
4713 
4714  calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
4715  calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
4716  calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
4717 
4718  xset (xlabel.handle_value (), "handlevisibility", "off");
4719  xset (ylabel.handle_value (), "handlevisibility", "off");
4720  xset (zlabel.handle_value (), "handlevisibility", "off");
4721  xset (title.handle_value (), "handlevisibility", "off");
4722 
4723  xset (xlabel.handle_value (), "horizontalalignment", "center");
4724  xset (xlabel.handle_value (), "horizontalalignmentmode", "auto");
4725  xset (ylabel.handle_value (), "horizontalalignment", "center");
4726  xset (ylabel.handle_value (), "horizontalalignmentmode", "auto");
4727  xset (zlabel.handle_value (), "horizontalalignment", "right");
4728  xset (zlabel.handle_value (), "horizontalalignmentmode", "auto");
4729  xset (title.handle_value (), "horizontalalignment", "center");
4730  xset (title.handle_value (), "horizontalalignmentmode", "auto");
4731 
4732  xset (xlabel.handle_value (), "verticalalignment", "top");
4733  xset (xlabel.handle_value (), "verticalalignmentmode", "auto");
4734  xset (ylabel.handle_value (), "verticalalignment", "bottom");
4735  xset (ylabel.handle_value (), "verticalalignmentmode", "auto");
4736  xset (title.handle_value (), "verticalalignment", "bottom");
4737  xset (title.handle_value (), "verticalalignmentmode", "auto");
4738 
4739  xset (ylabel.handle_value (), "rotation", 90.0);
4740  xset (ylabel.handle_value (), "rotationmode", "auto");
4741 
4742  xset (zlabel.handle_value (), "visible", "off");
4743 
4744  xset (xlabel.handle_value (), "clipping", "off");
4745  xset (ylabel.handle_value (), "clipping", "off");
4746  xset (zlabel.handle_value (), "clipping", "off");
4747  xset (title.handle_value (), "clipping", "off");
4748 
4749  xset (xlabel.handle_value (), "autopos_tag", "xlabel");
4750  xset (ylabel.handle_value (), "autopos_tag", "ylabel");
4751  xset (zlabel.handle_value (), "autopos_tag", "zlabel");
4752  xset (title.handle_value (), "autopos_tag", "title");
4753 
4754  adopt (xlabel.handle_value ());
4755  adopt (ylabel.handle_value ());
4756  adopt (zlabel.handle_value ());
4757  adopt (title.handle_value ());
4758 
4759  Matrix tlooseinset = default_axes_position ();
4760  tlooseinset(2) = 1-tlooseinset(0)-tlooseinset(2);
4761  tlooseinset(3) = 1-tlooseinset(1)-tlooseinset(3);
4762  looseinset = tlooseinset;
4763 }
4764 
4765 Matrix
4767 {
4768  Matrix pos = init_pos;
4770  Matrix parent_bb = obj.get_properties ().get_boundingbox (true);
4771  Matrix ext = get_extent (true, true);
4772  ext(1) = parent_bb(3) - ext(1) - ext(3);
4773  ext(0)++;
4774  ext(1)++;
4775  ext = convert_position (ext, "pixels", get_units (),
4776  parent_bb.extract_n (0, 2, 1, 2));
4777  if (ext(0) < pos(0))
4778  {
4779  pos(2) += pos(0)-ext(0);
4780  pos(0) = ext(0);
4781  }
4782  if (ext(0)+ext(2) > pos(0)+pos(2))
4783  pos(2) = ext(0)+ext(2)-pos(0);
4784 
4785  if (ext(1) < pos(1))
4786  {
4787  pos(3) += pos(1)-ext(1);
4788  pos(1) = ext(1);
4789  }
4790  if (ext(1)+ext(3) > pos(1)+pos(3))
4791  pos(3) = ext(1)+ext(3)-pos(1);
4792  return pos;
4793 }
4794 
4795 void
4797 {
4798  // First part is equivalent to `update_tightinset ()'
4799  if (activepositionproperty.is ("position"))
4800  update_position ();
4801  else
4802  update_outerposition ();
4803  caseless_str old_units = get_units ();
4804  set_units ("normalized");
4805  Matrix pos = position.get ().matrix_value ();
4806  Matrix outpos = outerposition.get ().matrix_value ();
4807  Matrix tightpos = calc_tightbox (pos);
4808  Matrix tinset (1, 4, 1.0);
4809  tinset(0) = pos(0)-tightpos(0);
4810  tinset(1) = pos(1)-tightpos(1);
4811  tinset(2) = tightpos(0)+tightpos(2)-pos(0)-pos(2);
4812  tinset(3) = tightpos(1)+tightpos(3)-pos(1)-pos(3);
4813  tightinset = tinset;
4814  set_units (old_units);
4815  update_transform ();
4816  if (activepositionproperty.is ("position"))
4817  update_position ();
4818  else
4819  update_outerposition ();
4820 }
4821 
4822 /*
4823 %!testif HAVE_FLTK
4824 %! hf = figure ("visible", "off");
4825 %! graphics_toolkit (hf, "fltk");
4826 %! unwind_protect
4827 %! subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
4828 %! hax = findall (gcf (), "type", "axes");
4829 %! positions = cell2mat (get (hax, "position"));
4830 %! outerpositions = cell2mat (get (hax, "outerposition"));
4831 %! looseinsets = cell2mat (get (hax, "looseinset"));
4832 %! tightinsets = cell2mat (get (hax, "tightinset"));
4833 %! subplot(2,1,1); plot(rand(10,1)); subplot(2,1,2); plot(rand(10,1));
4834 %! hax = findall (gcf (), "type", "axes");
4835 %! assert (cell2mat (get (hax, "position")), positions, 1e-4);
4836 %! assert (cell2mat (get (hax, "outerposition")), outerpositions, 1e-4);
4837 %! assert (cell2mat (get (hax, "looseinset")), looseinsets, 1e-4);
4838 %! assert (cell2mat (get (hax, "tightinset")), tightinsets, 1e-4);
4839 %! unwind_protect_cleanup
4840 %! close (hf);
4841 %! end_unwind_protect
4842 %!testif HAVE_FLTK
4843 %! hf = figure ("visible", "off");
4844 %! graphics_toolkit (hf, "fltk");
4845 %! fpos = get (hf, "position");
4846 %! unwind_protect
4847 %! plot (rand (3))
4848 %! position = get (gca, "position");
4849 %! outerposition = get (gca, "outerposition");
4850 %! looseinset = get (gca, "looseinset");
4851 %! tightinset = get (gca, "tightinset");
4852 %! set (hf, "position", [fpos(1:2), 2*fpos(3:4)])
4853 %! set (hf, "position", fpos);
4854 %! assert (get (gca, "outerposition"), outerposition, 0.001)
4855 %! assert (get (gca, "position"), position, 0.001)
4856 %! assert (get (gca, "looseinset"), looseinset, 0.001)
4857 %! assert (get (gca, "tightinset"), tightinset, 0.001)
4858 %! unwind_protect_cleanup
4859 %! close (hf);
4860 %! end_unwind_protect
4861 %!testif HAVE_FLTK
4862 %! hf = figure ("visible", "off");
4863 %! graphics_toolkit (hf, "fltk");
4864 %! fpos = get (hf, "position");
4865 %! set (gca, "activepositionproperty", "position")
4866 %! unwind_protect
4867 %! plot (rand (3))
4868 %! position = get (gca, "position");
4869 %! outerposition = get (gca, "outerposition");
4870 %! looseinset = get (gca, "looseinset");
4871 %! tightinset = get (gca, "tightinset");
4872 %! set (hf, "position", [fpos(1:2), 2*fpos(3:4)])
4873 %! set (hf, "position", fpos);
4874 %! assert (get (gca, "position"), position, 0.001)
4875 %! assert (get (gca, "outerposition"), outerposition, 0.001)
4876 %! assert (get (gca, "looseinset"), looseinset, 0.001)
4877 %! assert (get (gca, "tightinset"), tightinset, 0.001)
4878 %! unwind_protect_cleanup
4879 %! close (hf);
4880 %! end_unwind_protect
4881 */
4882 
4883 void
4885  const std::string& who,
4886  const octave_value& v)
4887 {
4888  if (v.is_string ())
4889  {
4890  xset (hp.handle_value (), "string", v);
4891  return;
4892  }
4893 
4894  graphics_handle val;
4896 
4897  if (go.isa ("text"))
4898  val = ::reparent (v, "set", who, __myhandle__, false);
4899  else
4900  {
4901  std::string cname = v.class_name ();
4902 
4903  error ("set: expecting text graphics object or character string for %s property, found %s",
4904  who.c_str (), cname.c_str ());
4905  }
4906 
4907  if (! error_state)
4908  {
4909  xset (val, "handlevisibility", "off");
4910 
4912 
4914 
4915  hp = val;
4916 
4917  adopt (hp.handle_value ());
4918  }
4919 }
4920 
4921 void
4923 {
4924  set_text_child (xlabel, "xlabel", v);
4925  xset (xlabel.handle_value (), "positionmode", "auto");
4926  xset (xlabel.handle_value (), "rotationmode", "auto");
4927  xset (xlabel.handle_value (), "horizontalalignmentmode", "auto");
4928  xset (xlabel.handle_value (), "verticalalignmentmode", "auto");
4929  xset (xlabel.handle_value (), "clipping", "off");
4930  xset (xlabel.handle_value (), "color", get_xcolor ());
4931  xset (xlabel.handle_value (), "autopos_tag", "xlabel");
4932  update_xlabel_position ();
4933 }
4934 
4935 void
4937 {
4938  set_text_child (ylabel, "ylabel", v);
4939  xset (ylabel.handle_value (), "positionmode", "auto");
4940  xset (ylabel.handle_value (), "rotationmode", "auto");
4941  xset (ylabel.handle_value (), "horizontalalignmentmode", "auto");
4942  xset (ylabel.handle_value (), "verticalalignmentmode", "auto");
4943  xset (ylabel.handle_value (), "clipping", "off");
4944  xset (ylabel.handle_value (), "color", get_ycolor ());
4945  xset (ylabel.handle_value (), "autopos_tag", "ylabel");
4946  update_ylabel_position ();
4947 }
4948 
4949 void
4951 {
4952  set_text_child (zlabel, "zlabel", v);
4953  xset (zlabel.handle_value (), "positionmode", "auto");
4954  xset (zlabel.handle_value (), "rotationmode", "auto");
4955  xset (zlabel.handle_value (), "horizontalalignmentmode", "auto");
4956  xset (zlabel.handle_value (), "verticalalignmentmode", "auto");
4957  xset (zlabel.handle_value (), "clipping", "off");
4958  xset (zlabel.handle_value (), "color", get_zcolor ());
4959  xset (zlabel.handle_value (), "autopos_tag", "zlabel");
4960  update_zlabel_position ();
4961 }
4962 
4963 void
4965 {
4966  set_text_child (title, "title", v);
4967  xset (title.handle_value (), "positionmode", "auto");
4968  xset (title.handle_value (), "horizontalalignment", "center");
4969  xset (title.handle_value (), "horizontalalignmentmode", "auto");
4970  xset (title.handle_value (), "verticalalignment", "bottom");
4971  xset (title.handle_value (), "verticalalignmentmode", "auto");
4972  xset (title.handle_value (), "clipping", "off");
4973  xset (title.handle_value (), "autopos_tag", "title");
4974  update_title_position ();
4975 }
4976 
4977 void
4979  const std::string& mode)
4980 {
4981  box = "on";
4982  colororder = default_colororder ();
4983  // Note: dataspectratio will be set through update_aspectratios
4984  dataaspectratiomode = "auto";
4985  layer = "bottom";
4986 
4987  Matrix tlim (1, 2, 0.0);
4988  tlim(1) = 1;
4989  xlim = tlim;
4990  ylim = tlim;
4991  zlim = tlim;
4992 
4993  Matrix cl (1, 2, 0);
4994  cl(1) = 1;
4995  clim = cl;
4996 
4997  alim = tlim;
4998 
4999  xlimmode = "auto";
5000  ylimmode = "auto";
5001  zlimmode = "auto";
5002  climmode = "auto";
5003  alimmode = "auto";
5004 
5005  xgrid = "off";
5006  ygrid = "off";
5007  zgrid = "off";
5008  xminorgrid = "off";
5009  yminorgrid = "off";
5010  zminorgrid = "off";
5011  xtick = Matrix ();
5012  ytick = Matrix ();
5013  ztick = Matrix ();
5014  xtickmode = "auto";
5015  ytickmode = "auto";
5016  ztickmode = "auto";
5017  xminortick = "off";
5018  yminortick = "off";
5019  zminortick = "off";
5020  xticklabel = "";
5021  yticklabel = "";
5022  zticklabel = "";
5023  xticklabelmode = "auto";
5024  yticklabelmode = "auto";
5025  zticklabelmode = "auto";
5026 
5027  interpreter = "none";
5028 
5029  color = color_values ("white");
5030  xcolor = color_values ("black");
5031  ycolor = color_values ("black");
5032  zcolor = color_values ("black");
5033  xscale = "linear";
5034  yscale = "linear";
5035  zscale = "linear";
5036  xdir = "normal";
5037  ydir = "normal";
5038  zdir = "normal";
5039  yaxislocation = "left";
5040  xaxislocation = "bottom";
5041 
5042  Matrix tview (1, 2, 0.0);
5043  tview(1) = 90;
5044  view = tview;
5045 
5046  __hold_all__ = "off";
5047  nextplot = "replace";
5048 
5049  ambientlightcolor = Matrix (1, 3, 1.0);
5050 
5051  // Note: camera properties (not mode) will be set in update_transform
5052  camerapositionmode = "auto";
5053  cameratargetmode = "auto";
5054  cameraupvectormode = "auto";
5055  cameraviewanglemode = "auto";
5056 
5057  drawmode = "normal";
5058 
5059  fontangle = "normal";
5060  fontname = OCTAVE_DEFAULT_FONTNAME;
5061  fontsize = 10;
5062  fontunits = "points";
5063  fontweight = "normal";
5064 
5065  gridlinestyle = ":";
5066  linestyleorder = "-";
5067  linewidth = 0.5;
5068  minorgridlinestyle = ":";
5069 
5070  // Note: plotboxaspectratio will be set through update_aspectratios
5071  plotboxaspectratiomode = "auto";
5072  projection = "orthographic";
5073 
5074  tickdir = "in";
5075  tickdirmode = "auto";
5076  ticklength = default_axes_ticklength ();
5077 
5078  tightinset = Matrix (1, 4, 0.0);
5079 
5080  sx = "linear";
5081  sy = "linear";
5082  sz = "linear";
5083 
5084  visible = "on";
5085 
5086  // Replace/Reset preserves Position and Units properties
5087  if (mode != "replace" && mode != "reset")
5088  {
5089  outerposition = default_axes_outerposition ();
5090  position = default_axes_position ();
5091  activepositionproperty = "outerposition";
5092  }
5093 
5094  if (mode != "reset")
5095  {
5096  delete_children (true);
5097 
5098  xlabel.invalidate ();
5099  ylabel.invalidate ();
5100  zlabel.invalidate ();
5101  title.invalidate ();
5102 
5103  xlabel = gh_manager::make_graphics_handle ("text", __myhandle__,
5104  false, false, false);
5105  ylabel = gh_manager::make_graphics_handle ("text", __myhandle__,
5106  false, false, false);
5107  zlabel = gh_manager::make_graphics_handle ("text", __myhandle__,
5108  false, false, false);
5109  title = gh_manager::make_graphics_handle ("text", __myhandle__,
5110  false, false, false);
5111 
5112  adopt (xlabel.handle_value ());
5113  adopt (ylabel.handle_value ());
5114  adopt (zlabel.handle_value ());
5115  adopt (title.handle_value ());
5116 
5117  update_xlabel_position ();
5118  update_ylabel_position ();
5119  update_zlabel_position ();
5120  update_title_position ();
5121  }
5122  else
5123  {
5124  graphics_object go = gh_manager::get_object (xlabel.handle_value ());
5126  go = gh_manager::get_object (ylabel.handle_value ());
5128  go = gh_manager::get_object (zlabel.handle_value ());
5130  go = gh_manager::get_object (title.handle_value ());
5132  }
5133 
5134  xset (xlabel.handle_value (), "handlevisibility", "off");
5135  xset (ylabel.handle_value (), "handlevisibility", "off");
5136  xset (zlabel.handle_value (), "handlevisibility", "off");
5137  xset (title.handle_value (), "handlevisibility", "off");
5138 
5139  xset (xlabel.handle_value (), "horizontalalignment", "center");
5140  xset (xlabel.handle_value (), "horizontalalignmentmode", "auto");
5141  xset (ylabel.handle_value (), "horizontalalignment", "center");
5142  xset (ylabel.handle_value (), "horizontalalignmentmode", "auto");
5143  xset (zlabel.handle_value (), "horizontalalignment", "right");
5144  xset (zlabel.handle_value (), "horizontalalignmentmode", "auto");
5145  xset (title.handle_value (), "horizontalalignment", "center");
5146  xset (title.handle_value (), "horizontalalignmentmode", "auto");
5147 
5148  xset (xlabel.handle_value (), "verticalalignment", "top");
5149  xset (xlabel.handle_value (), "verticalalignmentmode", "auto");
5150  xset (ylabel.handle_value (), "verticalalignment", "bottom");
5151  xset (ylabel.handle_value (), "verticalalignmentmode", "auto");
5152  xset (title.handle_value (), "verticalalignment", "bottom");
5153  xset (title.handle_value (), "verticalalignmentmode", "auto");
5154 
5155  xset (ylabel.handle_value (), "rotation", 90.0);
5156  xset (ylabel.handle_value (), "rotationmode", "auto");
5157 
5158  xset (zlabel.handle_value (), "visible", "off");
5159 
5160  xset (xlabel.handle_value (), "clipping", "off");
5161  xset (ylabel.handle_value (), "clipping", "off");
5162  xset (zlabel.handle_value (), "clipping", "off");
5163  xset (title.handle_value (), "clipping", "off");
5164 
5165  xset (xlabel.handle_value (), "autopos_tag", "xlabel");
5166  xset (ylabel.handle_value (), "autopos_tag", "ylabel");
5167  xset (zlabel.handle_value (), "autopos_tag", "zlabel");
5168  xset (title.handle_value (), "autopos_tag", "title");
5169 
5170  update_transform ();
5171  sync_positions ();
5172  override_defaults (obj);
5173 }
5174 
5175 void
5177 {
5178  graphics_handle h = hp.handle_value ();
5179 
5180  if (h.ok ())
5181  {
5183 
5184  if (go.valid_object ())
5185  gh_manager::free (h);
5186 
5188  }
5189 
5190  // FIXME: is it necessary to check whether the axes object is
5191  // being deleted now? I think this function is only called when an
5192  // individual child object is delete and not when the parent axes
5193  // object is deleted.
5194 
5195  if (! is_beingdeleted ())
5196  {
5197  hp = gh_manager::make_graphics_handle ("text", __myhandle__,
5198  false, false);
5199 
5200  xset (hp.handle_value (), "handlevisibility", "off");
5201 
5202  adopt (hp.handle_value ());
5203  }
5204 }
5205 
5206 void
5208 {
5209  if (xlabel.handle_value ().ok () && h == xlabel.handle_value ())
5210  {
5211  delete_text_child (xlabel);
5212  update_xlabel_position ();
5213  }
5214  else if (ylabel.handle_value ().ok () && h == ylabel.handle_value ())
5215  {
5216  delete_text_child (ylabel);
5217  update_ylabel_position ();
5218  }
5219  else if (zlabel.handle_value ().ok () && h == zlabel.handle_value ())
5220  {
5221  delete_text_child (zlabel);
5222  update_zlabel_position ();
5223  }
5224  else if (title.handle_value ().ok () && h == title.handle_value ())
5225  {
5226  delete_text_child (title);
5227  update_title_position ();
5228  }
5229  else
5231 }
5232 
5233 inline Matrix
5235 {
5236  Matrix m (4, 4, 0.0);
5237  for (int i = 0; i < 4; i++)
5238  m(i,i) = 1;
5239  return m;
5240 }
5241 
5242 inline ColumnVector
5244 {
5245  ColumnVector v (4, 0.0);
5246  v(3) = 1;
5247  return v;
5248 }
5249 
5250 inline ColumnVector
5251 xform_vector (double x, double y, double z)
5252 {
5253  ColumnVector v (4, 1.0);
5254  v(0) = x; v(1) = y; v(2) = z;
5255  return v;
5256 }
5257 
5258 inline ColumnVector
5259 transform (const Matrix& m, double x, double y, double z)
5260 {
5261  return (m * xform_vector (x, y, z));
5262 }
5263 
5264 inline Matrix
5265 xform_scale (double x, double y, double z)
5266 {
5267  Matrix m (4, 4, 0.0);
5268  m(0,0) = x; m(1,1) = y; m(2,2) = z; m(3,3) = 1;
5269  return m;
5270 }
5271 
5272 inline Matrix
5273 xform_translate (double x, double y, double z)
5274 {
5275  Matrix m = xform_matrix ();
5276  m(0,3) = x; m(1,3) = y; m(2,3) = z; m(3,3) = 1;
5277  return m;
5278 }
5279 
5280 inline void
5281 scale (Matrix& m, double x, double y, double z)
5282 {
5283  m = m * xform_scale (x, y, z);
5284 }
5285 
5286 inline void
5287 translate (Matrix& m, double x, double y, double z)
5288 {
5289  m = m * xform_translate (x, y, z);
5290 }
5291 
5292 inline void
5293 xform (ColumnVector& v, const Matrix& m)
5294 {
5295  v = m*v;
5296 }
5297 
5298 inline void
5299 scale (ColumnVector& v, double x, double y, double z)
5300 {
5301  v(0) *= x;
5302  v(1) *= y;
5303  v(2) *= z;
5304 }
5305 
5306 inline void
5307 translate (ColumnVector& v, double x, double y, double z)
5308 {
5309  v(0) += x;
5310  v(1) += y;
5311  v(2) += z;
5312 }
5313 
5314 inline void
5316 {
5317  double fact = 1.0 / sqrt (v(0)*v(0)+v(1)*v(1)+v(2)*v(2));
5318  scale (v, fact, fact, fact);
5319 }
5320 
5321 inline double
5323 {
5324  return (v1(0)*v2(0)+v1(1)*v2(1)+v1(2)*v2(2));
5325 }
5326 
5327 inline double
5328 norm (const ColumnVector& v)
5329 {
5330  return sqrt (dot (v, v));
5331 }
5332 
5333 inline ColumnVector
5335 {
5336  ColumnVector r = xform_vector ();
5337  r(0) = v1(1)*v2(2)-v1(2)*v2(1);
5338  r(1) = v1(2)*v2(0)-v1(0)*v2(2);
5339  r(2) = v1(0)*v2(1)-v1(1)*v2(0);
5340  return r;
5341 }
5342 
5343 inline Matrix
5345 {
5346  static double data[32] =
5347  {
5348  0,0,0,1,
5349  1,0,0,1,
5350  0,1,0,1,
5351  0,0,1,1,
5352  1,1,0,1,
5353  1,0,1,1,
5354  0,1,1,1,
5355  1,1,1,1
5356  };
5357  Matrix m (4, 8);
5358  memcpy (m.fortran_vec (), data, sizeof (double)*32);
5359  return m;
5360 }
5361 
5362 inline ColumnVector
5364 {
5365  ColumnVector retval (4, 1.0);
5366  memcpy (retval.fortran_vec (), m.fortran_vec (), sizeof (double)*3);
5367  return retval;
5368 }
5369 
5370 inline RowVector
5372 {
5373  return v.extract_n (0, 3).transpose ();
5374 }
5375 
5376 void
5378 {
5379  double xd = (xdir_is ("normal") ? 1 : -1);
5380  double yd = (ydir_is ("normal") ? 1 : -1);
5381  double zd = (zdir_is ("normal") ? 1 : -1);
5382 
5383  Matrix xlimits = sx.scale (get_xlim ().matrix_value ());
5384  Matrix ylimits = sy.scale (get_ylim ().matrix_value ());
5385  Matrix zlimits = sz.scale (get_zlim ().matrix_value ());
5386 
5387  double xo = xlimits(xd > 0 ? 0 : 1);
5388  double yo = ylimits(yd > 0 ? 0 : 1);
5389  double zo = zlimits(zd > 0 ? 0 : 1);
5390 
5391  Matrix pb = get_plotboxaspectratio ().matrix_value ();
5392 
5393  bool autocam = (camerapositionmode_is ("auto")
5394  && cameratargetmode_is ("auto")
5395  && cameraupvectormode_is ("auto")
5396  && cameraviewanglemode_is ("auto"));
5397  bool dowarp = (autocam && dataaspectratiomode_is ("auto")
5398  && plotboxaspectratiomode_is ("auto"));
5399 
5400  ColumnVector c_eye (xform_vector ());
5401  ColumnVector c_center (xform_vector ());
5402  ColumnVector c_upv (xform_vector ());
5403 
5404  if (cameratargetmode_is ("auto"))
5405  {
5406  c_center(0) = (xlimits(0)+xlimits(1))/2;
5407  c_center(1) = (ylimits(0)+ylimits(1))/2;
5408  c_center(2) = (zlimits(0)+zlimits(1))/2;
5409 
5410  cameratarget = xform2cam (c_center);
5411  }
5412  else
5413  c_center = cam2xform (get_cameratarget ().matrix_value ());
5414 
5415  if (camerapositionmode_is ("auto"))
5416  {
5417  Matrix tview = get_view ().matrix_value ();
5418  double az = tview(0);
5419  double el = tview(1);
5420  double d = 5 * sqrt (pb(0)*pb(0)+pb(1)*pb(1)+pb(2)*pb(2));
5421 
5422  if (el == 90 || el == -90)
5423  c_eye(2) = d*signum (el);
5424  else
5425  {
5426  az *= M_PI/180.0;
5427  el *= M_PI/180.0;
5428  c_eye(0) = d * cos (el) * sin (az);
5429  c_eye(1) = -d* cos (el) * cos (az);
5430  c_eye(2) = d * sin (el);
5431  }
5432  c_eye(0) = c_eye(0)*(xlimits(1)-xlimits(0))/(xd*pb(0))+c_center(0);
5433  c_eye(1) = c_eye(1)*(ylimits(1)-ylimits(0))/(yd*pb(1))+c_center(1);
5434  c_eye(2) = c_eye(2)*(zlimits(1)-zlimits(0))/(zd*pb(2))+c_center(2);
5435 
5436  cameraposition = xform2cam (c_eye);
5437  }
5438  else
5439  c_eye = cam2xform (get_cameraposition ().matrix_value ());
5440 
5441  if (cameraupvectormode_is ("auto"))
5442  {
5443  Matrix tview = get_view ().matrix_value ();
5444  double az = tview(0);
5445  double el = tview(1);
5446 
5447  if (el == 90 || el == -90)
5448  {
5449  c_upv(0) =
5450  -signum (el) *sin (az*M_PI/180.0)*(xlimits(1)-xlimits(0))/pb(0);
5451  c_upv(1) =
5452  signum (el) * cos (az*M_PI/180.0)*(ylimits(1)-ylimits(0))/pb(1);
5453  }
5454  else
5455  c_upv(2) = 1;
5456 
5457  cameraupvector = xform2cam (c_upv);
5458  }
5459  else
5460  c_upv = cam2xform (get_cameraupvector ().matrix_value ());
5461 
5462  Matrix x_view = xform_matrix ();
5463  Matrix x_projection = xform_matrix ();
5464  Matrix x_viewport = xform_matrix ();
5465  Matrix x_normrender = xform_matrix ();
5466  Matrix x_pre = xform_matrix ();
5467 
5468  x_render = xform_matrix ();
5469  x_render_inv = xform_matrix ();
5470 
5471  scale (x_pre, pb(0), pb(1), pb(2));
5472  translate (x_pre, -0.5, -0.5, -0.5);
5473  scale (x_pre, xd/(xlimits(1)-xlimits(0)), yd/(ylimits(1)-ylimits(0)),
5474  zd/(zlimits(1)-zlimits(0)));
5475  translate (x_pre, -xo, -yo, -zo);
5476 
5477  xform (c_eye, x_pre);
5478  xform (c_center, x_pre);
5479  scale (c_upv, pb(0)/(xlimits(1)-xlimits(0)), pb(1)/(ylimits(1)-ylimits(0)),
5480  pb(2)/(zlimits(1)-zlimits(0)));
5481  translate (c_center, -c_eye(0), -c_eye(1), -c_eye(2));
5482 
5483  ColumnVector F (c_center), f (F), UP (c_upv);
5484  normalize (f);
5485  normalize (UP);
5486 
5487  if (std::abs (dot (f, UP)) > 1e-15)
5488  {
5489  double fa = 1 / sqrt(1-f(2)*f(2));
5490  scale (UP, fa, fa, fa);
5491  }
5492 
5493  ColumnVector s = cross (f, UP);
5494  ColumnVector u = cross (s, f);
5495 
5496  scale (x_view, 1, 1, -1);
5497  Matrix l = xform_matrix ();
5498  l(0,0) = s(0); l(0,1) = s(1); l(0,2) = s(2);
5499  l(1,0) = u(0); l(1,1) = u(1); l(1,2) = u(2);
5500  l(2,0) = -f(0); l(2,1) = -f(1); l(2,2) = -f(2);
5501  x_view = x_view * l;
5502  translate (x_view, -c_eye(0), -c_eye(1), -c_eye(2));
5503  scale (x_view, pb(0), pb(1), pb(2));
5504  translate (x_view, -0.5, -0.5, -0.5);
5505 
5506  Matrix x_cube = x_view * unit_cube ();
5507  ColumnVector cmin = x_cube.row_min ();
5508  ColumnVector cmax = x_cube.row_max ();
5509  double xM = cmax(0)-cmin(0);
5510  double yM = cmax(1)-cmin(1);
5511 
5512  Matrix bb = get_boundingbox (true);
5513 
5514  double v_angle;
5515 
5516  if (cameraviewanglemode_is ("auto"))
5517  {
5518  double af;
5519 
5520  // FIXME: was this really needed? When compared to Matlab, it
5521  // does not seem to be required. Need investigation with concrete
5522  // graphics toolkit to see results visually.
5523  if (false && dowarp)
5524  af = 1.0 / (xM > yM ? xM : yM);
5525  else
5526  {
5527  if ((bb(2)/bb(3)) > (xM/yM))
5528  af = 1.0 / yM;
5529  else
5530  af = 1.0 / xM;
5531  }
5532  v_angle = 2 * (180.0 / M_PI) * atan (1 / (2 * af * norm (F)));
5533 
5534  cameraviewangle = v_angle;
5535  }
5536  else
5537  v_angle = get_cameraviewangle ();
5538 
5539  double pf = 1 / (2 * tan ((v_angle / 2) * M_PI / 180.0) * norm (F));
5540  scale (x_projection, pf, pf, 1);
5541 
5542  if (dowarp)
5543  {
5544  xM *= pf;
5545  yM *= pf;
5546  translate (x_viewport, bb(0)+bb(2)/2, bb(1)+bb(3)/2, 0);
5547  scale (x_viewport, bb(2)/xM, -bb(3)/yM, 1);
5548  }
5549  else
5550  {
5551  double pix = 1;
5552  if (autocam)
5553  {
5554  if ((bb(2)/bb(3)) > (xM/yM))
5555  pix = bb(3);
5556  else
5557  pix = bb(2);
5558  }
5559  else
5560  pix = (bb(2) < bb(3) ? bb(2) : bb(3));
5561  translate (x_viewport, bb(0)+bb(2)/2, bb(1)+bb(3)/2, 0);
5562  scale (x_viewport, pix, -pix, 1);
5563  }
5564 
5565  x_normrender = x_viewport * x_projection * x_view;
5566 
5567  x_cube = x_normrender * unit_cube ();
5568  cmin = x_cube.row_min ();
5569  cmax = x_cube.row_max ();
5570  x_zlim.resize (1, 2);
5571  x_zlim(0) = cmin(2);
5572  x_zlim(1) = cmax(2);
5573 
5574  x_render = x_normrender;
5575  scale (x_render, xd/(xlimits(1)-xlimits(0)), yd/(ylimits(1)-ylimits(0)),
5576  zd/(zlimits(1)-zlimits(0)));
5577  translate (x_render, -xo, -yo, -zo);
5578 
5579  x_viewtransform = x_view;
5580  x_projectiontransform = x_projection;
5581  x_viewporttransform = x_viewport;
5582  x_normrendertransform = x_normrender;
5583  x_rendertransform = x_render;
5584 
5585  x_render_inv = x_render.inverse ();
5586 
5587  // Note: these matrices are a slight modified version of the regular
5588  // matrices, more suited for OpenGL rendering (x_gl_mat1 => light
5589  // => x_gl_mat2)
5590  x_gl_mat1 = x_view;
5591  scale (x_gl_mat1, xd/(xlimits(1)-xlimits(0)), yd/(ylimits(1)-ylimits(0)),
5592  zd/(zlimits(1)-zlimits(0)));
5593  translate (x_gl_mat1, -xo, -yo, -zo);
5594  x_gl_mat2 = x_viewport * x_projection;
5595 }
5596 
5597 static bool updating_axes_layout = false;
5598 
5599 void
5601 {
5602  if (updating_axes_layout)
5603  return;
5604 
5605  graphics_xform xform = get_transform ();
5606 
5607  double xd = (xdir_is ("normal") ? 1 : -1);
5608  double yd = (ydir_is ("normal") ? 1 : -1);
5609  double zd = (zdir_is ("normal") ? 1 : -1);
5610 
5611  const Matrix xlims = xform.xscale (get_xlim ().matrix_value ());
5612  const Matrix ylims = xform.yscale (get_ylim ().matrix_value ());
5613  const Matrix zlims = xform.zscale (get_zlim ().matrix_value ());
5614 
5615  double x_min, x_max, y_min, y_max, z_min, z_max;
5616  x_min = xlims(0), x_max = xlims(1);
5617  y_min = ylims(0), y_max = ylims(1);
5618  z_min = zlims(0), z_max = zlims(1);
5619 
5620  ColumnVector p1, p2, dir (3);
5621 
5622  xstate = ystate = zstate = AXE_ANY_DIR;
5623 
5624  p1 = xform.transform (x_min, (y_min+y_max)/2, (z_min+z_max)/2, false);
5625  p2 = xform.transform (x_max, (y_min+y_max)/2, (z_min+z_max)/2, false);
5626  dir(0) = xround (p2(0)-p1(0));
5627  dir(1) = xround (p2(1)-p1(1));
5628  dir(2) = (p2(2)-p1(2));
5629  if (dir(0) == 0 && dir(1) == 0)
5630  xstate = AXE_DEPTH_DIR;
5631  else if (dir(2) == 0)
5632  {
5633  if (dir(0) == 0)
5634  xstate = AXE_VERT_DIR;
5635  else if (dir(1) == 0)
5636  xstate = AXE_HORZ_DIR;
5637  }
5638 
5639  if (dir(2) == 0)
5640  {
5641  if (dir(1) == 0)
5642  xPlane = (dir(0) > 0 ? x_max : x_min);
5643  else
5644  xPlane = (dir(1) < 0 ? x_max : x_min);
5645  }
5646  else
5647  xPlane = (dir(2) < 0 ? x_min : x_max);
5648 
5649  xPlaneN = (xPlane == x_min ? x_max : x_min);
5650  fx = (x_max-x_min) / sqrt (dir(0)*dir(0)+dir(1)*dir(1));
5651 
5652  p1 = xform.transform ((x_min+x_max)/2, y_min, (z_min+z_max)/2, false);
5653  p2 = xform.transform ((x_min+x_max)/2, y_max, (z_min+z_max)/2, false);
5654  dir(0) = xround (p2(0)-p1(0));
5655  dir(1) = xround (p2(1)-p1(1));
5656  dir(2) = (p2(2)-p1(2));
5657  if (dir(0) == 0 && dir(1) == 0)
5658  ystate = AXE_DEPTH_DIR;
5659  else if (dir(2) == 0)
5660  {
5661  if (dir(0) == 0)
5662  ystate = AXE_VERT_DIR;
5663  else if (dir(1) == 0)
5664  ystate = AXE_HORZ_DIR;
5665  }
5666 
5667  if (dir(2) == 0)
5668  {
5669  if (dir(1) == 0)
5670  yPlane = (dir(0) > 0 ? y_max : y_min);
5671  else
5672  yPlane = (dir(1) < 0 ? y_max : y_min);
5673  }
5674  else
5675  yPlane = (dir(2) < 0 ? y_min : y_max);
5676 
5677  yPlaneN = (yPlane == y_min ? y_max : y_min);
5678  fy = (y_max-y_min) / sqrt (dir(0)*dir(0)+dir(1)*dir(1));
5679 
5680  p1 = xform.transform ((x_min+x_max)/2, (y_min+y_max)/2, z_min, false);
5681  p2 = xform.transform ((x_min+x_max)/2, (y_min+y_max)/2, z_max, false);
5682  dir(0) = xround (p2(0)-p1(0));
5683  dir(1) = xround (p2(1)-p1(1));
5684  dir(2) = (p2(2)-p1(2));
5685  if (dir(0) == 0 && dir(1) == 0)
5686  zstate = AXE_DEPTH_DIR;
5687  else if (dir(2) == 0)
5688  {
5689  if (dir(0) == 0)
5690  zstate = AXE_VERT_DIR;
5691  else if (dir(1) == 0)
5692  zstate = AXE_HORZ_DIR;
5693  }
5694 
5695  if (dir(2) == 0)
5696  {
5697  if (dir(1) == 0)
5698  zPlane = (dir(0) > 0 ? z_min : z_max);
5699  else
5700  zPlane = (dir(1) < 0 ? z_min : z_max);
5701  }
5702  else
5703  zPlane = (dir(2) < 0 ? z_min : z_max);
5704 
5705  zPlaneN = (zPlane == z_min ? z_max : z_min);
5706  fz = (z_max-z_min) / sqrt (dir(0)*dir(0)+dir(1)*dir(1));
5707 
5708  unwind_protect frame;
5709  frame.protect_var (updating_axes_layout);
5710  updating_axes_layout = true;
5711 
5712  xySym = (xd*yd*(xPlane-xPlaneN)*(yPlane-yPlaneN) > 0);
5713  zSign = (zd*(zPlane-zPlaneN) <= 0);
5714  xyzSym = zSign ? xySym : !xySym;
5715  xpTick = (zSign ? xPlaneN : xPlane);
5716  ypTick = (zSign ? yPlaneN : yPlane);
5717  zpTick = (zSign ? zPlane : zPlaneN);
5718  xpTickN = (zSign ? xPlane : xPlaneN);
5719  ypTickN = (zSign ? yPlane : yPlaneN);
5720  zpTickN = (zSign ? zPlaneN : zPlane);
5721 
5722  /* 2D mode */
5723  x2Dtop = false;
5724  y2Dright = false;
5725  layer2Dtop = false;
5726  if (xstate == AXE_HORZ_DIR && ystate == AXE_VERT_DIR)
5727  {
5728  if (xaxislocation_is ("top"))
5729  {
5730  std::swap (yPlane, yPlaneN);
5731  x2Dtop = true;
5732  }
5733  ypTick = yPlaneN;
5734  ypTickN = yPlane;
5735  if (yaxislocation_is ("right"))
5736  {
5737  std::swap (xPlane, xPlaneN);
5738  y2Dright = true;
5739  }
5740  xpTick = xPlaneN;
5741  xpTickN = xPlane;
5742  if (layer_is ("top"))
5743  {
5744  zpTick = zPlaneN;
5745  layer2Dtop = true;
5746  }
5747  else
5748  zpTick = zPlane;
5749  }
5750 
5751  Matrix viewmat = get_view ().matrix_value ();
5752  nearhoriz = std::abs (viewmat(1)) <= 5;
5753  is2D = viewmat(1) == 90;
5754 
5755  update_ticklength ();
5756 }
5757 
5758 void
5760 {
5761  bool mode2d = (((xstate > AXE_DEPTH_DIR ? 1 : 0) +
5762  (ystate > AXE_DEPTH_DIR ? 1 : 0) +
5763  (zstate > AXE_DEPTH_DIR ? 1 : 0)) == 2);
5764 
5765  if (tickdirmode_is ("auto"))
5766  tickdir.set (mode2d ? "in" : "out", true);
5767 
5768  double ticksign = (tickdir_is ("in") ? -1 : 1);
5769 
5770  Matrix bbox = get_boundingbox (true);
5771  Matrix ticklen = get_ticklength ().matrix_value ();
5772  ticklen(0) = ticklen(0) * std::max (bbox(2), bbox(3));
5773  ticklen(1) = ticklen(1) * std::max (bbox(2), bbox(3));
5774 
5775  xticklen = ticksign * (mode2d ? ticklen(0) : ticklen(1));
5776  yticklen = ticksign * (mode2d ? ticklen(0) : ticklen(1));
5777  zticklen = ticksign * (mode2d ? ticklen(0) : ticklen(1));
5778 
5779  xtickoffset = (mode2d ? std::max (0., xticklen) : std::abs (xticklen)) + 5;
5780  ytickoffset = (mode2d ? std::max (0., yticklen) : std::abs (yticklen)) + 5;
5781  ztickoffset = (mode2d ? std::max (0., zticklen) : std::abs (zticklen)) + 5;
5782 
5783  update_xlabel_position ();
5784  update_ylabel_position ();
5785  update_zlabel_position ();
5786  update_title_position ();
5787 }
5788 
5789 /*
5790 ## FIXME: A demo can't be called in a C++ file. This should be made a test
5791 ## or moved to a .m file where it can be called.
5792 %!demo
5793 %! clf;
5794 %! subplot (2,1,1);
5795 %! plot (rand (3));
5796 %! xlabel xlabel;
5797 %! ylabel ylabel;
5798 %! title title;
5799 %! subplot (2,1,2);
5800 %! plot (rand (3));
5801 %! set (gca, "ticklength", get (gca, "ticklength") * 2, "tickdir", "out");
5802 %! xlabel xlabel;
5803 %! ylabel ylabel;
5804 %! title title;
5805 */
5806 
5807 static ColumnVector
5809  const text::properties& props,
5810  const graphics_xform& xform,
5811  const Matrix& bbox)
5812 {
5813  ColumnVector retval;
5814 
5815  caseless_str to_units = props.get_units ();
5816 
5817  if (! to_units.compare ("data"))
5818  {
5819  ColumnVector v = xform.transform (p(0), p(1), p(2));
5820 
5821  retval.resize (3);
5822 
5823  retval(0) = v(0) - bbox(0) + 1;
5824  retval(1) = bbox(1) + bbox(3) - v(1) + 1;
5825  retval(2) = 0;
5826 
5827  retval = convert_position (retval, "pixels", to_units,
5828  bbox.extract_n (0, 2, 1, 2));
5829  }
5830  else
5831  retval = p;
5832 
5833  return retval;
5834 }
5835 
5836 static bool updating_xlabel_position = false;
5837 
5838 void
5840 {
5841  if (updating_xlabel_position)
5842  return;
5843 
5844  graphics_object obj = gh_manager::get_object (get_xlabel ());
5845 
5846  if (! obj.valid_object ())
5847  return;
5848 
5849  text::properties& xlabel_props
5850  = reinterpret_cast<text::properties&> (obj.get_properties ());
5851 
5852  bool is_empty = xlabel_props.get_string ().is_empty ();
5853 
5854  unwind_protect frame;
5855  frame.protect_var (updating_xlabel_position);
5856  updating_xlabel_position = true;
5857 
5858  if (! is_empty)
5859  {
5860  if (xlabel_props.horizontalalignmentmode_is ("auto"))
5861  {
5862  xlabel_props.set_horizontalalignment
5863  (xstate > AXE_DEPTH_DIR
5864  ? "center" : (xyzSym ? "left" : "right"));
5865 
5866  xlabel_props.set_horizontalalignmentmode ("auto");
5867  }
5868 
5869  if (xlabel_props.verticalalignmentmode_is ("auto"))
5870  {
5871  xlabel_props.set_verticalalignment
5872  (xstate == AXE_VERT_DIR || x2Dtop ? "bottom" : "top");
5873 
5874  xlabel_props.set_verticalalignmentmode ("auto");
5875  }
5876  }
5877 
5878  if (xlabel_props.positionmode_is ("auto")
5879  || xlabel_props.rotationmode_is ("auto"))
5880  {
5881  graphics_xform xform = get_transform ();
5882 
5883  Matrix ext (1, 2, 0.0);
5884  ext = get_ticklabel_extents (get_xtick ().matrix_value (),
5885  get_xticklabel ().all_strings (),
5886  get_xlim ().matrix_value ());
5887 
5888  double wmax = ext(0);
5889  double hmax = ext(1);
5890  double angle = 0;
5891  ColumnVector p =
5892  graphics_xform::xform_vector ((xpTickN+xpTick)/2, ypTick, zpTick);
5893 
5894  bool tick_along_z = nearhoriz || xisinf (fy);
5895  if (tick_along_z)
5896  p(2) += (signum (zpTick-zpTickN)*fz*xtickoffset);
5897  else
5898  p(1) += (signum (ypTick-ypTickN)*fy*xtickoffset);
5899 
5900  p = xform.transform (p(0), p(1), p(2), false);
5901 
5902  switch (xstate)
5903  {
5904  case AXE_ANY_DIR:
5905  p(0) += (xyzSym ? wmax : -wmax);
5906  p(1) += hmax;
5907  break;
5908 
5909  case AXE_VERT_DIR:
5910  p(0) -= wmax;
5911  angle = 90;
5912  break;
5913 
5914  case AXE_HORZ_DIR:
5915  p(1) += (x2Dtop ? -hmax : hmax);
5916  break;
5917  }
5918 
5919  if (xlabel_props.positionmode_is ("auto"))
5920  {
5921  p = xform.untransform (p(0), p(1), p(2), true);
5922 
5923  p = convert_label_position (p, xlabel_props, xform,
5924  get_extent (false));
5925 
5926  xlabel_props.set_position (p.extract_n (0, 3).transpose ());
5927  xlabel_props.set_positionmode ("auto");
5928  }
5929 
5930  if (! is_empty && xlabel_props.rotationmode_is ("auto"))
5931  {
5932  xlabel_props.set_rotation (angle);
5933  xlabel_props.set_rotationmode ("auto");
5934  }
5935  }
5936 }
5937 
5938 static bool updating_ylabel_position = false;
5939 
5940 void
5942 {
5943  if (updating_ylabel_position)
5944  return;
5945 
5946  graphics_object obj = gh_manager::get_object (get_ylabel ());
5947 
5948  if (! obj.valid_object ())
5949  return;
5950 
5951  text::properties& ylabel_props
5952  = reinterpret_cast<text::properties&> (obj.get_properties ());
5953 
5954  bool is_empty = ylabel_props.get_string ().is_empty ();
5955 
5956  unwind_protect frame;
5957  frame.protect_var (updating_ylabel_position);
5958  updating_ylabel_position = true;
5959 
5960  if (! is_empty)
5961  {
5962  if (ylabel_props.horizontalalignmentmode_is ("auto"))
5963  {
5964  ylabel_props.set_horizontalalignment
5965  (ystate > AXE_DEPTH_DIR
5966  ? "center" : (!xyzSym ? "left" : "right"));
5967 
5968  ylabel_props.set_horizontalalignmentmode ("auto");
5969  }
5970 
5971  if (ylabel_props.verticalalignmentmode_is ("auto"))
5972  {
5973  ylabel_props.set_verticalalignment
5974  (ystate == AXE_VERT_DIR && !y2Dright ? "bottom" : "top");
5975 
5976  ylabel_props.set_verticalalignmentmode ("auto");
5977  }
5978  }
5979 
5980  if (ylabel_props.positionmode_is ("auto")
5981  || ylabel_props.rotationmode_is ("auto"))
5982  {
5983  graphics_xform xform = get_transform ();
5984 
5985  Matrix ext (1, 2, 0.0);
5986 
5987  // The underlying get_extents() from FreeType produces mismatched values.
5988  // x-extent accurately measures the width of the glyphs.
5989  // y-extent instead measures from baseline-to-baseline.
5990  // Pad x-extent (+4) so that it approximately matches y-extent.
5991  // This keeps ylabels about the same distance from y-axis as
5992  // xlabels are from x-axis.
5993  // ALWAYS use an even number for padding or horizontal alignment
5994  // will be off.
5995  ext = get_ticklabel_extents (get_ytick ().matrix_value (),
5996  get_yticklabel ().all_strings (),
5997  get_ylim ().matrix_value ());
5998 
5999  double wmax = ext(0)+4;
6000  double hmax = ext(1);
6001  double angle = 0;
6002  ColumnVector p =
6003  graphics_xform::xform_vector (xpTick, (ypTickN+ypTick)/2, zpTick);
6004 
6005  bool tick_along_z = nearhoriz || xisinf (fx);
6006  if (tick_along_z)
6007  p(2) += (signum (zpTick-zpTickN)*fz*ytickoffset);
6008  else
6009  p(0) += (signum (xpTick-xpTickN)*fx*ytickoffset);
6010 
6011  p = xform.transform (p(0), p(1), p(2), false);
6012 
6013  switch (ystate)
6014  {
6015  case AXE_ANY_DIR:
6016  p(0) += (!xyzSym ? wmax : -wmax);
6017  p(1) += hmax;
6018  break;
6019 
6020  case AXE_VERT_DIR:
6021  p(0) += (y2Dright ? wmax : -wmax);
6022  angle = 90;
6023  break;
6024 
6025  case AXE_HORZ_DIR:
6026  p(1) += hmax;
6027  break;
6028  }
6029 
6030  if (ylabel_props.positionmode_is ("auto"))
6031  {
6032  p = xform.untransform (p(0), p(1), p(2), true);
6033 
6034  p = convert_label_position (p, ylabel_props, xform,
6035  get_extent (false));
6036 
6037  ylabel_props.set_position (p.extract_n (0, 3).transpose ());
6038  ylabel_props.set_positionmode ("auto");
6039  }
6040 
6041  if (! is_empty && ylabel_props.rotationmode_is ("auto"))
6042  {
6043  ylabel_props.set_rotation (angle);
6044  ylabel_props.set_rotationmode ("auto");
6045  }
6046  }
6047 }
6048 
6049 static bool updating_zlabel_position = false;
6050 
6051 void
6053 {
6054  if (updating_zlabel_position)
6055  return;
6056 
6057  graphics_object obj = gh_manager::get_object (get_zlabel ());
6058 
6059  if (! obj.valid_object ())
6060  return;
6061 
6062  text::properties& zlabel_props
6063  = reinterpret_cast<text::properties&> (obj.get_properties ());
6064 
6065  bool camAuto = cameraupvectormode_is ("auto");
6066  bool is_empty = zlabel_props.get_string ().is_empty ();
6067 
6068  unwind_protect frame;
6069  frame.protect_var (updating_zlabel_position);
6070  updating_zlabel_position = true;
6071 
6072  if (! is_empty)
6073  {
6074  if (zlabel_props.horizontalalignmentmode_is ("auto"))
6075  {
6076  zlabel_props.set_horizontalalignment
6077  ((zstate > AXE_DEPTH_DIR || camAuto) ? "center" : "right");
6078 
6079  zlabel_props.set_horizontalalignmentmode ("auto");
6080  }
6081 
6082  if (zlabel_props.verticalalignmentmode_is ("auto"))
6083  {
6084  zlabel_props.set_verticalalignment
6085  (zstate == AXE_VERT_DIR
6086  ? "bottom" : ((zSign || camAuto) ? "bottom" : "top"));
6087 
6088  zlabel_props.set_verticalalignmentmode ("auto");
6089  }
6090  }
6091 
6092  if (zlabel_props.positionmode_is ("auto")
6093  || zlabel_props.rotationmode_is ("auto"))
6094  {
6095  graphics_xform xform = get_transform ();
6096 
6097  Matrix ext (1, 2, 0.0);
6098  ext = get_ticklabel_extents (get_ztick ().matrix_value (),
6099  get_zticklabel ().all_strings (),
6100  get_zlim ().matrix_value ());
6101 
6102  double wmax = ext(0);
6103  double hmax = ext(1);
6104  double angle = 0;
6105  ColumnVector p;
6106 
6107  if (xySym)
6108  {
6109  p = graphics_xform::xform_vector (xPlaneN, yPlane,
6110  (zpTickN+zpTick)/2);
6111  if (xisinf (fy))
6112  p(0) += (signum (xPlaneN-xPlane)*fx*ztickoffset);
6113  else
6114  p(1) += (signum (yPlane-yPlaneN)*fy*ztickoffset);
6115  }
6116  else
6117  {
6118  p = graphics_xform::xform_vector (xPlane, yPlaneN,
6119  (zpTickN+zpTick)/2);
6120  if (xisinf (fx))
6121  p(1) += (signum (yPlaneN-yPlane)*fy*ztickoffset);
6122  else
6123  p(0) += (signum (xPlane-xPlaneN)*fx*ztickoffset);
6124  }
6125 
6126  p = xform.transform (p(0), p(1), p(2), false);
6127 
6128  switch (zstate)
6129  {
6130  case AXE_ANY_DIR:
6131  if (camAuto)
6132  {
6133  p(0) -= wmax;
6134  angle = 90;
6135  }
6136 
6137  // FIXME: what's the correct offset?
6138  //
6139  // p[0] += (!xySym ? wmax : -wmax);
6140  // p[1] += (zSign ? hmax : -hmax);
6141 
6142  break;
6143 
6144  case AXE_VERT_DIR:
6145  p(0) -= wmax;
6146  angle = 90;
6147  break;
6148 
6149  case AXE_HORZ_DIR:
6150  p(1) += hmax;
6151  break;
6152  }
6153 
6154  if (zlabel_props.positionmode_is ("auto"))
6155  {
6156  p = xform.untransform (p(0), p(1), p(2), true);
6157 
6158  p = convert_label_position (p, zlabel_props, xform,
6159  get_extent (false));
6160 
6161  zlabel_props.set_position (p.extract_n (0, 3).transpose ());
6162  zlabel_props.set_positionmode ("auto");
6163  }
6164 
6165  if (! is_empty && zlabel_props.rotationmode_is ("auto"))
6166  {
6167  zlabel_props.set_rotation (angle);
6168  zlabel_props.set_rotationmode ("auto");
6169  }
6170  }
6171 }
6172 
6173 static bool updating_title_position = false;
6174 
6175 void
6177 {
6178  if (updating_title_position)
6179  return;
6180 
6181  graphics_object obj = gh_manager::get_object (get_title ());
6182 
6183  if (! obj.valid_object ())
6184  return;
6185 
6186  text::properties& title_props
6187  = reinterpret_cast<text::properties&> (obj.get_properties ());
6188 
6189  unwind_protect frame;
6190  frame.protect_var (updating_title_position);
6191  updating_title_position = true;
6192 
6193  if (title_props.positionmode_is ("auto"))
6194  {
6195  graphics_xform xform = get_transform ();
6196 
6197  // FIXME: bbox should be stored in axes::properties
6198  Matrix bbox = get_extent (false);
6199 
6200  ColumnVector p =
6201  graphics_xform::xform_vector (bbox(0)+bbox(2)/2,
6202  bbox(1)-10,
6203  (x_zlim(0)+x_zlim(1))/2);
6204 
6205  if (x2Dtop)
6206  {
6207  Matrix ext (1, 2, 0.0);
6208  ext = get_ticklabel_extents (get_xtick ().matrix_value (),
6209  get_xticklabel ().all_strings (),
6210  get_xlim ().matrix_value ());
6211  p(1) -= ext(1);
6212  }
6213 
6214  p = xform.untransform (p(0), p(1), p(2), true);
6215 
6216  p = convert_label_position (p, title_props, xform, bbox);
6217 
6218  title_props.set_position (p.extract_n (0, 3).transpose ());
6219  title_props.set_positionmode ("auto");
6220  }
6221 }
6222 
6223 void
6224 axes::properties::update_autopos (const std::string& elem_type)
6225 {
6226  if (elem_type == "xlabel")
6227  update_xlabel_position ();
6228  else if (elem_type == "ylabel")
6229  update_ylabel_position ();
6230  else if (elem_type == "zlabel")
6231  update_zlabel_position ();
6232  else if (elem_type == "title")
6233  update_title_position ();
6234  else if (elem_type == "sync")
6235  sync_positions ();
6236 }
6237 
6238 static void
6239 normalized_aspectratios (Matrix& aspectratios, const Matrix& scalefactors,
6240  double xlength, double ylength, double zlength)
6241 {
6242  double xval = xlength/scalefactors(0);
6243  double yval = ylength/scalefactors(1);
6244  double zval = zlength/scalefactors(2);
6245 
6246  double minval = xmin (xmin (xval, yval), zval);
6247 
6248  aspectratios(0) = xval/minval;
6249  aspectratios(1) = yval/minval;
6250  aspectratios(2) = zval/minval;
6251 }
6252 
6253 static void
6254 max_axes_scale (double& s, Matrix& limits, const Matrix& kids,
6255  double pbfactor, double dafactor, char limit_type, bool tight)
6256 {
6257  if (tight)
6258  {
6259  double minval = octave_Inf;
6260  double maxval = -octave_Inf;
6261  double min_pos = octave_Inf;
6262  double max_neg = -octave_Inf;
6263  get_children_limits (minval, maxval, min_pos, max_neg, kids, limit_type);
6264  if (xfinite (minval) && xfinite (maxval))
6265  {
6266  limits(0) = minval;
6267  limits(1) = maxval;
6268  s = xmax(s, (maxval - minval) / (pbfactor * dafactor));
6269  }
6270  }
6271  else
6272  s = xmax(s, (limits(1) - limits(0)) / (pbfactor * dafactor));
6273 }
6274 
6275 static std::set<double> updating_aspectratios;
6276 
6277 void
6279 {
6280  if (updating_aspectratios.find (get___myhandle__ ().value ())
6281  != updating_aspectratios.end ())
6282  return;
6283 
6284  Matrix xlimits = get_xlim ().matrix_value ();
6285  Matrix ylimits = get_ylim ().matrix_value ();
6286  Matrix zlimits = get_zlim ().matrix_value ();
6287 
6288  double dx = (xlimits(1)-xlimits(0));
6289  double dy = (ylimits(1)-ylimits(0));
6290  double dz = (zlimits(1)-zlimits(0));
6291 
6292  Matrix da = get_dataaspectratio ().matrix_value ();
6293  Matrix pba = get_plotboxaspectratio ().matrix_value ();
6294 
6295  if (dataaspectratiomode_is ("auto"))
6296  {
6297  if (plotboxaspectratiomode_is ("auto"))
6298  {
6299  pba = Matrix (1, 3, 1.0);
6300  plotboxaspectratio.set (pba, false);
6301  }
6302 
6303  normalized_aspectratios (da, pba, dx, dy, dz);
6304  dataaspectratio.set (da, false);
6305  }
6306  else if (plotboxaspectratiomode_is ("auto"))
6307  {
6308  normalized_aspectratios (pba, da, dx, dy, dz);
6309  plotboxaspectratio.set (pba, false);
6310  }
6311  else
6312  {
6313  double s = -octave_Inf;
6314  bool modified_limits = false;
6315  Matrix kids;
6316 
6317  if (xlimmode_is ("auto") && ylimmode_is ("auto") && zlimmode_is ("auto"))
6318  {
6319  modified_limits = true;
6320  kids = get_children ();
6321  max_axes_scale (s, xlimits, kids, pba(0), da(0), 'x', true);
6322  max_axes_scale (s, ylimits, kids, pba(1), da(1), 'y', true);
6323  max_axes_scale (s, zlimits, kids, pba(2), da(2), 'z', true);
6324  }
6325  else if (xlimmode_is ("auto") && ylimmode_is ("auto"))
6326  {
6327  modified_limits = true;
6328  max_axes_scale (s, zlimits, kids, pba(2), da(2), 'z', false);
6329  }
6330  else if (ylimmode_is ("auto") && zlimmode_is ("auto"))
6331  {
6332  modified_limits = true;
6333  max_axes_scale (s, xlimits, kids, pba(0), da(0), 'x', false);
6334  }
6335  else if (zlimmode_is ("auto") && xlimmode_is ("auto"))
6336  {
6337  modified_limits = true;
6338  max_axes_scale (s, ylimits, kids, pba(1), da(1), 'y', false);
6339  }
6340 
6341  if (modified_limits)
6342  {
6343 
6344  unwind_protect frame;
6345  frame.protect_var (updating_aspectratios);
6346 
6347  updating_aspectratios.insert (get___myhandle__ ().value ());
6348 
6349  dx = pba(0) *da(0);
6350  dy = pba(1) *da(1);
6351  dz = pba(2) *da(2);
6352  if (xisinf (s))
6353  s = 1 / xmin (xmin (dx, dy), dz);
6354 
6355  if (xlimmode_is ("auto"))
6356  {
6357  dx = s * dx;
6358  xlimits(0) = 0.5 * (xlimits(0) + xlimits(1) - dx);
6359  xlimits(1) = xlimits(0) + dx;
6360  set_xlim (xlimits);
6361  set_xlimmode ("auto");
6362  }
6363 
6364  if (ylimmode_is ("auto"))
6365  {
6366  dy = s * dy;
6367  ylimits(0) = 0.5 * (ylimits(0) + ylimits(1) - dy);
6368  ylimits(1) = ylimits(0) + dy;
6369  set_ylim (ylimits);
6370  set_ylimmode ("auto");
6371  }
6372 
6373  if (zlimmode_is ("auto"))
6374  {
6375  dz = s * dz;
6376  zlimits(0) = 0.5 * (zlimits(0) + zlimits(1) - dz);
6377  zlimits(1) = zlimits(0) + dz;
6378  set_zlim (zlimits);
6379  set_zlimmode ("auto");
6380  }
6381  }
6382  else
6383  {
6384  normalized_aspectratios (pba, da, dx, dy, dz);
6385  plotboxaspectratio.set (pba, false);
6386  }
6387  }
6388 }
6389 
6390 void
6392 {
6393 #ifdef HAVE_FREETYPE
6394 #ifdef HAVE_FONTCONFIG
6395  text_renderer.set_font (get ("fontname").string_value (),
6396  get ("fontweight").string_value (),
6397  get ("fontangle").string_value (),
6398  get ("fontsize_points").double_value ());
6399 #endif
6400 #endif
6401 }
6402 
6403 // The INTERNAL flag defines whether position or outerposition is used.
6404 
6405 Matrix
6407  const Matrix& parent_pix_size) const
6408 {
6409  Matrix pos = internal ? get_position ().matrix_value ()
6410  : get_outerposition ().matrix_value ();
6411  Matrix parent_size (parent_pix_size);
6412 
6413  if (parent_size.numel () == 0)
6414  {
6416 
6417  if (obj.valid_object ())
6418  parent_size =
6419  obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
6420  else
6421  parent_size = default_figure_position ();
6422  }
6423 
6424  pos = convert_position (pos, get_units (), "pixels", parent_size);
6425 
6426  pos(0)--;
6427  pos(1)--;
6428  pos(1) = parent_size(1) - pos(1) - pos(3);
6429 
6430  return pos;
6431 }
6432 
6433 Matrix
6434 axes::properties::get_extent (bool with_text, bool only_text_height) const
6435 {
6436  graphics_xform xform = get_transform ();
6437 
6438  Matrix ext (1, 4, 0.0);
6439  ext(0) = octave_Inf;
6440  ext(1) = octave_Inf;
6441  ext(2) = -octave_Inf;
6442  ext(3) = -octave_Inf;
6443  for (int i = 0; i <= 1; i++)
6444  for (int j = 0; j <= 1; j++)
6445  for (int k = 0; k <= 1; k++)
6446  {
6447  ColumnVector p = xform.transform (i ? xPlaneN : xPlane,
6448  j ? yPlaneN : yPlane,
6449  k ? zPlaneN : zPlane, false);
6450  ext(0) = std::min (ext(0), p(0));
6451  ext(1) = std::min (ext(1), p(1));
6452  ext(2) = std::max (ext(2), p(0));
6453  ext(3) = std::max (ext(3), p(1));
6454  }
6455 
6456  if (with_text)
6457  {
6458  for (int i = 0; i < 4; i++)
6459  {
6460  graphics_handle text_handle;
6461  if (i == 0)
6462  text_handle = get_title ();
6463  else if (i == 1)
6464  text_handle = get_xlabel ();
6465  else if (i == 2)
6466  text_handle = get_ylabel ();
6467  else if (i == 3)
6468  text_handle = get_zlabel ();
6469 
6470  text::properties& text_props
6471  = reinterpret_cast<text::properties&>
6472  (gh_manager::get_object (text_handle).get_properties ());
6473 
6474  Matrix text_pos = text_props.get_data_position ();
6475  text_pos = xform.transform (text_pos(0), text_pos(1), text_pos(2));
6476  if (text_props.get_string ().is_empty ())
6477  {
6478  ext(0) = std::min (ext(0), text_pos(0));
6479  ext(1) = std::min (ext(1), text_pos(1));
6480  ext(2) = std::max (ext(2), text_pos(0));
6481  ext(3) = std::max (ext(3), text_pos(1));
6482  }
6483  else
6484  {
6485  Matrix text_ext = text_props.get_extent_matrix ();
6486 
6487  bool ignore_horizontal = false;
6488  bool ignore_vertical = false;
6489  if (only_text_height)
6490  {
6491  double text_rotation = text_props.get_rotation ();
6492  if (text_rotation == 0. || text_rotation == 180.)
6493  ignore_horizontal = true;
6494  else if (text_rotation == 90. || text_rotation == 270.)
6495  ignore_vertical = true;
6496  }
6497 
6498  if (! ignore_horizontal)
6499  {
6500  ext(0) = std::min (ext(0), text_pos(0)+text_ext(0));
6501  ext(2) = std::max (ext(2),
6502  text_pos(0)+text_ext(0)+text_ext(2));
6503  }
6504 
6505  if (! ignore_vertical)
6506  {
6507  ext(1) = std::min (ext(1),
6508  text_pos(1)-text_ext(1)-text_ext(3));
6509  ext(3) = std::max (ext(3), text_pos(1)-text_ext(1));
6510  }
6511  }
6512  }
6513  }
6514 
6515  ext(2) = ext(2)-ext(0);
6516  ext(3) = ext(3)-ext(1);
6517 
6518  return ext;
6519 }
6520 
6521 static octave_value
6523 {
6524  octave_value retval = val;
6525 
6526  if (val.is_cellstr ())
6527  {
6528  // Always return a column vector for Matlab Compatibility
6529  if (val.columns () > 1)
6530  retval = val.reshape (dim_vector (val.numel (), 1));
6531  }
6532  else
6533  {
6534  string_vector sv;
6535  if (val.is_numeric_type ())
6536  {
6537  NDArray data = val.array_value ();
6538  std::ostringstream oss;
6539  oss.precision (5);
6540  for (octave_idx_type i = 0; i < val.numel (); i++)
6541  {
6542  oss.str ("");
6543  oss << data(i);
6544  sv.append (oss.str ());
6545  }
6546  }
6547  else if (val.is_string () && val.rows () == 1)
6548  {
6549  std::string valstr = val.string_value ();
6550  std::istringstream iss (valstr);
6551  std::string tmpstr;
6552 
6553  // Split string with delimiter '|'
6554  while (std::getline (iss, tmpstr, '|'))
6555  sv.append (tmpstr);
6556 
6557  // If string ends with '|' Matlab appends a null string
6558  if (*valstr.rbegin () == '|')
6559  sv.append (std::string (""));
6560  }
6561  else
6562  return retval;
6563 
6564  charMatrix chmat (sv, ' ');
6565 
6566  retval = octave_value (chmat);
6567  }
6568 
6569  return retval;
6570 }
6571 
6572 void
6574 {
6575  if (!error_state)
6576  {
6577  if (xticklabel.set (convert_ticklabel_string (v), false))
6578  {
6579  set_xticklabelmode ("manual");
6580  xticklabel.run_listeners (POSTSET);
6581  mark_modified ();
6582  }
6583  else
6584  set_xticklabelmode ("manual");
6585 
6586  sync_positions ();
6587  }
6588 }
6589 
6590 void
6592 {
6593  if (!error_state)
6594  {
6595  if (yticklabel.set (convert_ticklabel_string (v), false))
6596  {
6597  set_yticklabelmode ("manual");
6598  yticklabel.run_listeners (POSTSET);
6599  mark_modified ();
6600  }
6601  else
6602  set_yticklabelmode ("manual");
6603 
6604  sync_positions ();
6605  }
6606 }
6607 
6608 void
6610 {
6611  if (!error_state)
6612  {
6613  if (zticklabel.set (convert_ticklabel_string (v), false))
6614  {
6615  set_zticklabelmode ("manual");
6616  zticklabel.run_listeners (POSTSET);
6617  mark_modified ();
6618  }
6619  else
6620  set_zticklabelmode ("manual");
6621 
6622  sync_positions ();
6623  }
6624 }
6625 
6626 // Almost identical to convert_ticklabel_string but it only accepts
6627 // cellstr or string, not numeric input.
6628 static octave_value
6630 {
6631  octave_value retval = val;
6632 
6633  if (val.is_cellstr ())
6634  {
6635  // Always return a column vector for Matlab Compatibility
6636  if (val.columns () > 1)
6637  retval = val.reshape (dim_vector (val.numel (), 1));
6638  }
6639  else
6640  {
6641  string_vector sv;
6642  if (val.is_string () && val.rows () == 1)
6643  {
6644  std::string valstr = val.string_value ();
6645  std::istringstream iss (valstr);
6646  std::string tmpstr;
6647 
6648  // Split string with delimiter '|'
6649  while (std::getline (iss, tmpstr, '|'))
6650  sv.append (tmpstr);
6651 
6652  // If string ends with '|' Matlab appends a null string
6653  if (*valstr.rbegin () == '|')
6654  sv.append (std::string (""));
6655  }
6656  else
6657  return retval;
6658 
6659  charMatrix chmat (sv, ' ');
6660 
6661  retval = octave_value (chmat);
6662  }
6663 
6664  return retval;
6665 }
6666 
6667 void
6669 {
6670  if (!error_state)
6671  {
6672  linestyleorder.set (convert_linestyleorder_string (v), false);
6673  }
6674 }
6675 
6676 void
6678 {
6679  if (! error_state)
6680  {
6681  caseless_str old_units = get_units ();
6682  if (units.set (v, true))
6683  {
6684  update_units (old_units);
6685  mark_modified ();
6686  }
6687  }
6688 }
6689 
6690 void
6692 {
6694  Matrix parent_bb
6695  = obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
6696  caseless_str new_units = get_units ();
6697  position.set (octave_value (convert_position (get_position ().matrix_value (),
6698  old_units, new_units,
6699  parent_bb)),
6700  false);
6701  outerposition.set (octave_value (convert_position (get_outerposition ().matrix_value (),
6702  old_units, new_units,
6703  parent_bb)),
6704  false);
6705  tightinset.set (octave_value (convert_position (get_tightinset ().matrix_value (),
6706  old_units, new_units,
6707  parent_bb)),
6708  false);
6709  looseinset.set (octave_value (convert_position (get_looseinset ().matrix_value (),
6710  old_units, new_units,
6711  parent_bb)),
6712  false);
6713 }
6714 
6715 void
6717 {
6718  if (! error_state)
6719  {
6720  caseless_str old_fontunits = get_fontunits ();
6721  if (fontunits.set (v, true))
6722  {
6723  update_fontunits (old_fontunits);
6724  mark_modified ();
6725  }
6726  }
6727 }
6728 
6729 void
6731 {
6732  caseless_str new_units = get_fontunits ();
6733  double parent_height = get_boundingbox (true).elem (3);
6734  double fsz = get_fontsize ();
6735 
6736  fsz = convert_font_size (fsz, old_units, new_units, parent_height);
6737 
6738  set_fontsize (octave_value (fsz));
6739 }
6740 
6741 double
6742 axes::properties::get_fontsize_points (double box_pix_height) const
6743 {
6744  double fs = get_fontsize ();
6745  double parent_height = box_pix_height;
6746 
6747  if (fontunits_is ("normalized") && parent_height <= 0)
6748  parent_height = get_boundingbox (true).elem (3);
6749 
6750  return convert_font_size (fs, get_fontunits (), "points", parent_height);
6751 }
6752 
6754 graphics_xform::xform_vector (double x, double y, double z)
6755 {
6756  return ::xform_vector (x, y, z);
6757 }
6758 
6759 Matrix
6761 {
6763 }
6764 
6766 graphics_xform::transform (double x, double y, double z,
6767  bool use_scale) const
6768 {
6769  if (use_scale)
6770  {
6771  x = sx.scale (x);
6772  y = sy.scale (y);
6773  z = sz.scale (z);
6774  }
6775 
6776  return ::transform (xform, x, y, z);
6777 }
6778 
6780 graphics_xform::untransform (double x, double y, double z,
6781  bool use_scale) const
6782 {
6783  ColumnVector v = ::transform (xform_inv, x, y, z);
6784 
6785  if (use_scale)
6786  {
6787  v(0) = sx.unscale (v(0));
6788  v(1) = sy.unscale (v(1));
6789  v(2) = sz.unscale (v(2));
6790  }
6791 
6792  return v;
6793 }
6794 
6796 axes::get_default (const caseless_str& name) const
6797 {
6798  octave_value retval = default_properties.lookup (name);
6799 
6800  if (retval.is_undefined ())
6801  {
6802  graphics_handle parent = get_parent ();
6803  graphics_object parent_obj = gh_manager::get_object (parent);
6804 
6805  retval = parent_obj.get_default (name);
6806  }
6807 
6808  return retval;
6809 }
6810 
6811 // FIXME: remove.
6812 // FIXME: maybe this should go into array_property class?
6813 /*
6814 static void
6815 check_limit_vals (double& min_val, double& max_val,
6816  double& min_pos, double& max_neg,
6817  const array_property& data)
6818 {
6819  double val = data.min_val ();
6820  if (xfinite (val) && val < min_val)
6821  min_val = val;
6822  val = data.max_val ();
6823  if (xfinite (val) && val > max_val)
6824  max_val = val;
6825  val = data.min_pos ();
6826  if (xfinite (val) && val > 0 && val < min_pos)
6827  min_pos = val;
6828  val = data.max_neg ();
6829  if (xfinite (val) && val < 0 && val > max_neg)
6830  max_neg = val;
6831 }
6832 */
6833 
6834 static void
6835 check_limit_vals (double& min_val, double& max_val,
6836  double& min_pos, double& max_neg,
6837  const octave_value& data)
6838 {
6839  if (data.is_matrix_type ())
6840  {
6841  Matrix m = data.matrix_value ();
6842 
6843  if (! error_state && m.numel () == 4)
6844  {
6845  double val;
6846 
6847  val = m(0);
6848  if (xfinite (val) && val < min_val)
6849  min_val = val;
6850 
6851  val = m(1);
6852  if (xfinite (val) && val > max_val)
6853  max_val = val;
6854 
6855  val = m(2);
6856  if (xfinite (val) && val > 0 && val < min_pos)
6857  min_pos = val;
6858 
6859  val = m(3);
6860  if (xfinite (val) && val < 0 && val > max_neg)
6861  max_neg = val;
6862  }
6863  }
6864 }
6865 
6866 // magform(x) Returns (a, b), where x = a * 10^b, abs (a) >= 1., and b is
6867 // integer.
6868 
6869 static void
6870 magform (double x, double& a, int& b)
6871 {
6872  if (x == 0)
6873  {
6874  a = 0;
6875  b = 0;
6876  }
6877  else
6878  {
6879  b = static_cast<int> (gnulib::floor (std::log10 (std::abs (x))));
6880  a = x / std::pow (10.0, b);
6881  }
6882 }
6883 
6884 // A translation from Tom Holoryd's python code at
6885 // http://kurage.nimh.nih.gov/tomh/tics.py
6886 // FIXME: add log ticks
6887 
6888 double
6889 axes::properties::calc_tick_sep (double lo, double hi)
6890 {
6891  int ticint = 5;
6892 
6893  // Reference: Lewart, C. R., "Algorithms SCALE1, SCALE2, and
6894  // SCALE3 for Determination of Scales on Computer Generated
6895  // Plots", Communications of the ACM, 10 (1973), 639-640.
6896  // Also cited as ACM Algorithm 463.
6897 
6898  double a;
6899  int b, x;
6900 
6901  magform ((hi-lo)/ticint, a, b);
6902 
6903  static const double sqrt_2 = sqrt (2.0);
6904  static const double sqrt_10 = sqrt (10.0);
6905  static const double sqrt_50 = sqrt (50.0);
6906 
6907  if (a < sqrt_2)
6908  x = 1;
6909  else if (a < sqrt_10)
6910  x = 2;
6911  else if (a < sqrt_50)
6912  x = 5;
6913  else
6914  x = 10;
6915 
6916  return x * std::pow (10., b);
6917 
6918 }
6919 
6920 // Attempt to make "nice" limits from the actual max and min of the
6921 // data. For log plots, we will also use the smallest strictly positive
6922 // value.
6923 
6924 Matrix
6926  double min_pos, double max_neg,
6927  bool logscale)
6928 {
6929  Matrix retval;
6930 
6931  double min_val = xmin;
6932  double max_val = xmax;
6933 
6934  if (xisinf (min_val) && min_val > 0 && xisinf (max_val) && max_val < 0)
6935  {
6936  retval = default_lim (logscale);
6937  return retval;
6938  }
6939  else if (! (xisinf (min_val) || xisinf (max_val)))
6940  {
6941  if (logscale)
6942  {
6943  if (xisinf (min_pos) && xisinf (max_neg))
6944  {
6945  // TODO -- max_neg is needed for "loglog ([0 -Inf])"
6946  // This is the only place where max_neg is needed.
6947  // Is there another way?
6948  retval = default_lim ();
6949  retval(0) = pow (10., retval(0));
6950  retval(1) = pow (10., retval(1));
6951  return retval;
6952  }
6953  if ((min_val <= 0 && max_val > 0))
6954  {
6955  warning ("axis: omitting non-positive data in log plot");
6956  min_val = min_pos;
6957  }
6958  // FIXME: maybe this test should also be relative?
6959  if (std::abs (min_val - max_val)
6960  < sqrt (std::numeric_limits<double>::epsilon ()))
6961  {
6962  // Widen range when too small
6963  if (min_val >= 0)
6964  {
6965  min_val *= 0.9;
6966  max_val *= 1.1;
6967  }
6968  else
6969  {
6970  min_val *= 1.1;
6971  max_val *= 0.9;
6972  }
6973  }
6974  if (min_val > 0)
6975  {
6976  // Log plots with all positive data
6977  min_val = pow (10, gnulib::floor (log10 (min_val)));
6978  max_val = pow (10, std::ceil (log10 (max_val)));
6979  }
6980  else
6981  {
6982  // Log plots with all negative data
6983  min_val = -pow (10, std::ceil (log10 (-min_val)));
6984  max_val = -pow (10, gnulib::floor (log10 (-max_val)));
6985  }
6986  }
6987  else
6988  {
6989  if (min_val == 0 && max_val == 0)
6990  {
6991  min_val = -1;
6992  max_val = 1;
6993  }
6994  // FIXME: maybe this test should also be relative?
6995  else if (std::abs (min_val - max_val)
6996  < sqrt (std::numeric_limits<double>::epsilon ()))
6997  {
6998  min_val -= 0.1 * std::abs (min_val);
6999  max_val += 0.1 * std::abs (max_val);
7000  }
7001 
7002  double tick_sep = calc_tick_sep (min_val , max_val);
7003  double min_tick = gnulib::floor (min_val / tick_sep);
7004  double max_tick = std::ceil (max_val / tick_sep);
7005  // Prevent round-off from cropping ticks
7006  min_val = std::min (min_val, tick_sep * min_tick);
7007  max_val = std::max (max_val, tick_sep * max_tick);
7008  }
7009  }
7010 
7011  retval.resize (1, 2);
7012 
7013  retval(1) = max_val;
7014  retval(0) = min_val;
7015 
7016  return retval;
7017 }
7018 
7019 void
7021  array_property& ticks,
7022  array_property& mticks,
7023  bool limmode_is_auto, bool is_logscale)
7024 {
7025  // FIXME: add log ticks and lims
7026 
7027  if (lims.get ().is_empty ())
7028  return;
7029 
7030  double lo = (lims.get ().matrix_value ()) (0);
7031  double hi = (lims.get ().matrix_value ()) (1);
7032  bool is_negative = lo < 0 && hi < 0;
7033  double tmp;
7034  // FIXME: should this be checked for somewhere else? (i.e. set{x,y,z}lim)
7035  if (hi < lo)
7036  std::swap (hi, lo);
7037 
7038  if (is_logscale)
7039  {
7040  if (is_negative)
7041  {
7042  tmp = hi;
7043  hi = std::log10 (-lo);
7044  lo = std::log10 (-tmp);
7045  }
7046  else
7047  {
7048  hi = std::log10 (hi);
7049  lo = std::log10 (lo);
7050  }
7051  }
7052 
7053  double tick_sep;
7054 
7055  if (is_logscale)
7056  {
7057  if (! (xisinf (hi) || xisinf (lo)))
7058  tick_sep = 1; // Tick is every order of magnitude (bug #39449)
7059  else
7060  tick_sep = 0;
7061  }
7062  else
7063  tick_sep = calc_tick_sep (lo , hi);
7064 
7065  int i1 = static_cast<int> (gnulib::floor (lo / tick_sep));
7066  int i2 = static_cast<int> (std::ceil (hi / tick_sep));
7067 
7068  if (limmode_is_auto)
7069  {
7070  // adjust limits to include min and max tics
7071  Matrix tmp_lims (1,2);
7072  tmp_lims(0) = std::min (tick_sep * i1, lo);
7073  tmp_lims(1) = std::max (tick_sep * i2, hi);
7074 
7075  if (is_logscale)
7076  {
7077  tmp_lims(0) = std::pow (10.,tmp_lims(0));
7078  tmp_lims(1) = std::pow (10.,tmp_lims(1));
7079  if (tmp_lims(0) <= 0)
7080  tmp_lims(0) = std::pow (10., lo);
7081  if (is_negative)
7082  {
7083  tmp = tmp_lims(0);
7084  tmp_lims(0) = -tmp_lims(1);
7085  tmp_lims(1) = -tmp;
7086  }
7087  }
7088  lims = tmp_lims;
7089  }
7090 
7091  Matrix tmp_ticks (1, i2-i1+1);
7092  for (int i = 0; i <= i2-i1; i++)
7093  {
7094  tmp_ticks (i) = tick_sep * (i+i1);
7095  if (is_logscale)
7096  tmp_ticks (i) = std::pow (10., tmp_ticks (i));
7097  }
7098  if (is_logscale && is_negative)
7099  {
7100  Matrix rev_ticks (1, i2-i1+1);
7101  rev_ticks = -tmp_ticks;
7102  for (int i = 0; i <= i2-i1; i++)
7103  tmp_ticks (i) = rev_ticks (i2-i1-i);
7104  }
7105 
7106  ticks = tmp_ticks;
7107 
7108  int n = is_logscale ? 8 : 4;
7109  Matrix tmp_mticks (1, n * (tmp_ticks.numel () - 1));
7110 
7111  for (int i = 0; i < tmp_ticks.numel ()-1; i++)
7112  {
7113  double d = (tmp_ticks (i+1) - tmp_ticks (i)) / (n+1);
7114  for (int j = 0; j < n; j++)
7115  {
7116  tmp_mticks (n*i+j) = tmp_ticks (i) + d * (j+1);
7117  }
7118  }
7119  mticks = tmp_mticks;
7120 }
7121 
7122 void
7124  any_property& labels, bool logscale)
7125 {
7126  Matrix values = ticks.get ().matrix_value ();
7127  Cell c (values.dims ());
7128  std::ostringstream os;
7129 
7130  if (logscale)
7131  {
7132  double significand;
7133  double exponent;
7134  double exp_max = 0.;
7135  double exp_min = 0.;
7136 
7137  for (int i = 0; i < values.numel (); i++)
7138  {
7139  exp_max = std::max (exp_max, std::log10 (values(i)));
7140  exp_min = std::max (exp_min, std::log10 (values(i)));
7141  }
7142 
7143  for (int i = 0; i < values.numel (); i++)
7144  {
7145  if (values(i) < 0.)
7146  exponent = gnulib::floor (std::log10 (-values(i)));
7147  else
7148  exponent = gnulib::floor (std::log10 (values(i)));
7149  significand = values(i) * std::pow (10., -exponent);
7150  os.str (std::string ());
7151  os << significand;
7152  if (exponent < 0.)
7153  {
7154  os << "e-";
7155  exponent = -exponent;
7156  }
7157  else
7158  os << "e+";
7159  if (exponent < 10. && (exp_max > 9 || exp_min < -9))
7160  os << "0";
7161  os << exponent;
7162  c(i) = os.str ();
7163  }
7164  }
7165  else
7166  {
7167  for (int i = 0; i < values.numel (); i++)
7168  {
7169  os.str (std::string ());
7170  os << values(i);
7171  c(i) = os.str ();
7172  }
7173  }
7174 
7175  labels = c;
7176 }
7177 
7178 Matrix
7180  const string_vector& ticklabels,
7181  const Matrix& limits)
7182 {
7183 #ifndef HAVE_FREETYPE
7184  double fontsize = get ("fontsize").double_value ();
7185 #endif
7186 
7187  Matrix ext (1, 2, 0.0);
7188  double wmax, hmax;
7189  wmax = hmax = 0.;
7190  int n = std::min (ticklabels.numel (), ticks.numel ());
7191  for (int i = 0; i < n; i++)
7192  {
7193  double val = ticks(i);
7194  if (limits(0) <= val && val <= limits(1))
7195  {
7196  std::string label (ticklabels(i));
7197  label.erase (0, label.find_first_not_of (" "));
7198  label = label.substr (0, label.find_last_not_of (" ")+1);
7199 #ifdef HAVE_FREETYPE
7200  ext = text_renderer.get_extent (label, 0.0, "none");
7201  wmax = std::max (wmax, ext(0));
7202  hmax = std::max (hmax, ext(1));
7203 #else
7204  // FIXME: find a better approximation
7205  int len = label.length ();
7206  wmax = std::max (wmax, 0.5*fontsize*len);
7207  hmax = fontsize;
7208 #endif
7209  }
7210  }
7211 
7212  ext(0) = wmax;
7213  ext(1) = hmax;
7214  return ext;
7215 }
7216 
7217 void
7218 get_children_limits (double& min_val, double& max_val,
7219  double& min_pos, double& max_neg,
7220  const Matrix& kids, char limit_type)
7221 {
7222  octave_idx_type n = kids.numel ();
7223 
7224  switch (limit_type)
7225  {
7226  case 'x':
7227  for (octave_idx_type i = 0; i < n; i++)
7228  {
7229  graphics_object obj = gh_manager::get_object (kids(i));
7230 
7231  if (obj.is_xliminclude ())
7232  {
7233  octave_value lim = obj.get_xlim ();
7234 
7235  check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
7236  }
7237  }
7238  break;
7239 
7240  case 'y':
7241  for (octave_idx_type i = 0; i < n; i++)
7242  {
7243  graphics_object obj = gh_manager::get_object (kids(i));
7244 
7245  if (obj.is_yliminclude ())
7246  {
7247  octave_value lim = obj.get_ylim ();
7248 
7249  check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
7250  }
7251  }
7252  break;
7253 
7254  case 'z':
7255  for (octave_idx_type i = 0; i < n; i++)
7256  {
7257  graphics_object obj = gh_manager::get_object (kids(i));
7258 
7259  if (obj.is_zliminclude ())
7260  {
7261  octave_value lim = obj.get_zlim ();
7262 
7263  check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
7264  }
7265  }
7266  break;
7267 
7268  case 'c':
7269  for (octave_idx_type i = 0; i < n; i++)
7270  {
7271  graphics_object obj = gh_manager::get_object (kids(i));
7272 
7273  if (obj.is_climinclude ())
7274  {
7275  octave_value lim = obj.get_clim ();
7276 
7277  check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
7278  }
7279  }
7280  break;
7281 
7282  case 'a':
7283  for (octave_idx_type i = 0; i < n; i++)
7284  {
7285  graphics_object obj = gh_manager::get_object (kids(i));
7286 
7287  if (obj.is_aliminclude ())
7288  {
7289  octave_value lim = obj.get_alim ();
7290 
7291  check_limit_vals (min_val, max_val, min_pos, max_neg, lim);
7292  }
7293  }
7294  break;
7295 
7296  default:
7297  break;
7298  }
7299 }
7300 
7301 static std::set<double> updating_axis_limits;
7302 
7303 void
7304 axes::update_axis_limits (const std::string& axis_type,
7305  const graphics_handle& h)
7306 {
7307  if (updating_axis_limits.find (get_handle ().value ())
7308  != updating_axis_limits.end ())
7309  return;
7310 
7311  Matrix kids = Matrix (1, 1, h.value ());
7312 
7313  double min_val = octave_Inf;
7314  double max_val = -octave_Inf;
7315  double min_pos = octave_Inf;
7316  double max_neg = -octave_Inf;
7317 
7318  char update_type = 0;
7319 
7320  Matrix limits;
7321  double val;
7322 
7323 #define FIX_LIMITS \
7324  if (limits.numel () == 4) \
7325  { \
7326  val = limits(0); \
7327  if (xfinite (val)) \
7328  min_val = val; \
7329  val = limits(1); \
7330  if (xfinite (val)) \
7331  max_val = val; \
7332  val = limits(2); \
7333  if (xfinite (val)) \
7334  min_pos = val; \
7335  val = limits(3); \
7336  if (xfinite (val)) \
7337  max_neg = val; \
7338  } \
7339  else \
7340  { \
7341  limits.resize (4, 1); \
7342  limits(0) = min_val; \
7343  limits(1) = max_val; \
7344  limits(2) = min_pos; \
7345  limits(3) = max_neg; \
7346  }
7347 
7348  if (axis_type == "xdata" || axis_type == "xscale"
7349  || axis_type == "xlimmode" || axis_type == "xliminclude"
7350  || axis_type == "xlim")
7351  {
7352  if (xproperties.xlimmode_is ("auto"))
7353  {
7354  limits = xproperties.get_xlim ().matrix_value ();
7355  FIX_LIMITS ;
7356 
7357  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');
7358 
7359  limits = xproperties.get_axis_limits (min_val, max_val,
7360  min_pos, max_neg,
7361  xproperties.xscale_is ("log"));
7362 
7363  update_type = 'x';
7364  }
7365  }
7366  else if (axis_type == "ydata" || axis_type == "yscale"
7367  || axis_type == "ylimmode" || axis_type == "yliminclude"
7368  || axis_type == "ylim")
7369  {
7370  if (xproperties.ylimmode_is ("auto"))
7371  {
7372  limits = xproperties.get_ylim ().matrix_value ();
7373  FIX_LIMITS ;
7374 
7375  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');
7376 
7377  limits = xproperties.get_axis_limits (min_val, max_val,
7378  min_pos, max_neg,
7379  xproperties.yscale_is ("log"));
7380 
7381  update_type = 'y';
7382  }
7383  }
7384  else if (axis_type == "zdata" || axis_type == "zscale"
7385  || axis_type == "zlimmode" || axis_type == "zliminclude"
7386  || axis_type == "zlim")
7387  {
7388  if (xproperties.zlimmode_is ("auto"))
7389  {
7390  limits = xproperties.get_zlim ().matrix_value ();
7391  FIX_LIMITS ;
7392 
7393  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
7394 
7395  limits = xproperties.get_axis_limits (min_val, max_val,
7396  min_pos, max_neg,
7397  xproperties.zscale_is ("log"));
7398 
7399  update_type = 'z';
7400  }
7401  }
7402  else if (axis_type == "cdata" || axis_type == "climmode"
7403  || axis_type == "cdatamapping" || axis_type == "climinclude"
7404  || axis_type == "clim")
7405  {
7406  if (xproperties.climmode_is ("auto"))
7407  {
7408  limits = xproperties.get_clim ().matrix_value ();
7409  FIX_LIMITS ;
7410 
7411  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');
7412 
7413  if (min_val > max_val)
7414  {
7415  min_val = min_pos = 0;
7416  max_val = 1;
7417  }
7418  else if (min_val == max_val)
7419  {
7420  max_val = min_val + 1;
7421  min_val -= 1;
7422  }
7423 
7424  limits.resize (1, 2);
7425 
7426  limits(0) = min_val;
7427  limits(1) = max_val;
7428 
7429  update_type = 'c';
7430  }
7431 
7432  }
7433  else if (axis_type == "alphadata" || axis_type == "alimmode"
7434  || axis_type == "alphadatamapping" || axis_type == "aliminclude"
7435  || axis_type == "alim")
7436  {
7437  if (xproperties.alimmode_is ("auto"))
7438  {
7439  limits = xproperties.get_alim ().matrix_value ();
7440  FIX_LIMITS ;
7441 
7442  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');
7443 
7444  if (min_val > max_val)
7445  {
7446  min_val = min_pos = 0;
7447  max_val = 1;
7448  }
7449  else if (min_val == max_val)
7450  max_val = min_val + 1;
7451 
7452  limits.resize (1, 2);
7453 
7454  limits(0) = min_val;
7455  limits(1) = max_val;
7456 
7457  update_type = 'a';
7458  }
7459 
7460  }
7461 
7462 #undef FIX_LIMITS
7463 
7464  unwind_protect frame;
7465  frame.protect_var (updating_axis_limits);
7466 
7467  updating_axis_limits.insert (get_handle ().value ());
7468 
7469  switch (update_type)
7470  {
7471  case 'x':
7472  xproperties.set_xlim (limits);
7473  xproperties.set_xlimmode ("auto");
7474  xproperties.update_xlim ();
7475  break;
7476 
7477  case 'y':
7478  xproperties.set_ylim (limits);
7479  xproperties.set_ylimmode ("auto");
7480  xproperties.update_ylim ();
7481  break;
7482 
7483  case 'z':
7484  xproperties.set_zlim (limits);
7485  xproperties.set_zlimmode ("auto");
7486  xproperties.update_zlim ();
7487  break;
7488 
7489  case 'c':
7490  xproperties.set_clim (limits);
7491  xproperties.set_climmode ("auto");
7492  break;
7493 
7494  case 'a':
7495  xproperties.set_alim (limits);
7496  xproperties.set_alimmode ("auto");
7497  break;
7498 
7499  default:
7500  break;
7501  }
7502 
7503  xproperties.update_transform ();
7504 
7505 }
7506 
7507 void
7508 axes::update_axis_limits (const std::string& axis_type)
7509 {
7510  if ((updating_axis_limits.find (get_handle ().value ())
7511  != updating_axis_limits.end ())
7512  || (updating_aspectratios.find (get_handle ().value ())
7513  != updating_aspectratios.end ()))
7514  return;
7515 
7516  Matrix kids = xproperties.get_children ();
7517 
7518  double min_val = octave_Inf;
7519  double max_val = -octave_Inf;
7520  double min_pos = octave_Inf;
7521  double max_neg = -octave_Inf;
7522 
7523  char update_type = 0;
7524 
7525  Matrix limits;
7526 
7527  if (axis_type == "xdata" || axis_type == "xscale"
7528  || axis_type == "xlimmode" || axis_type == "xliminclude"
7529  || axis_type == "xlim")
7530  {
7531  if (xproperties.xlimmode_is ("auto"))
7532  {
7533  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');
7534 
7535  limits = xproperties.get_axis_limits (min_val, max_val,
7536  min_pos, max_neg,
7537  xproperties.xscale_is ("log"));
7538 
7539  update_type = 'x';
7540  }
7541  }
7542  else if (axis_type == "ydata" || axis_type == "yscale"
7543  || axis_type == "ylimmode" || axis_type == "yliminclude"
7544  || axis_type == "ylim")
7545  {
7546  if (xproperties.ylimmode_is ("auto"))
7547  {
7548  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');
7549 
7550  limits = xproperties.get_axis_limits (min_val, max_val,
7551  min_pos, max_neg,
7552  xproperties.yscale_is ("log"));
7553 
7554  update_type = 'y';
7555  }
7556  }
7557  else if (axis_type == "zdata" || axis_type == "zscale"
7558  || axis_type == "zlimmode" || axis_type == "zliminclude"
7559  || axis_type == "zlim")
7560  {
7561  if (xproperties.zlimmode_is ("auto"))
7562  {
7563  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
7564 
7565  limits = xproperties.get_axis_limits (min_val, max_val,
7566  min_pos, max_neg,
7567  xproperties.zscale_is ("log"));
7568 
7569  update_type = 'z';
7570  }
7571  }
7572  else if (axis_type == "cdata" || axis_type == "climmode"
7573  || axis_type == "cdatamapping" || axis_type == "climinclude"
7574  || axis_type == "clim")
7575  {
7576  if (xproperties.climmode_is ("auto"))
7577  {
7578  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');
7579 
7580  if (min_val > max_val)
7581  {
7582  min_val = min_pos = 0;
7583  max_val = 1;
7584  }
7585  else if (min_val == max_val)
7586  {
7587  max_val = min_val + 1;
7588  min_val -= 1;
7589  }
7590 
7591  limits.resize (1, 2);
7592 
7593  limits(0) = min_val;
7594  limits(1) = max_val;
7595 
7596  update_type = 'c';
7597  }
7598 
7599  }
7600  else if (axis_type == "alphadata" || axis_type == "alimmode"
7601  || axis_type == "alphadatamapping" || axis_type == "aliminclude"
7602  || axis_type == "alim")
7603  {
7604  if (xproperties.alimmode_is ("auto"))
7605  {
7606  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');
7607 
7608  if (min_val > max_val)
7609  {
7610  min_val = min_pos = 0;
7611  max_val = 1;
7612  }
7613  else if (min_val == max_val)
7614  max_val = min_val + 1;
7615 
7616  limits.resize (1, 2);
7617 
7618  limits(0) = min_val;
7619  limits(1) = max_val;
7620 
7621  update_type = 'a';
7622  }
7623 
7624  }
7625 
7626  unwind_protect frame;
7627  frame.protect_var (updating_axis_limits);
7628 
7629  updating_axis_limits.insert (get_handle ().value ());
7630 
7631  switch (update_type)
7632  {
7633  case 'x':
7634  xproperties.set_xlim (limits);
7635  xproperties.set_xlimmode ("auto");
7636  xproperties.update_xlim ();
7637  break;
7638 
7639  case 'y':
7640  xproperties.set_ylim (limits);
7641  xproperties.set_ylimmode ("auto");
7642  xproperties.update_ylim ();
7643  break;
7644 
7645  case 'z':
7646  xproperties.set_zlim (limits);
7647  xproperties.set_zlimmode ("auto");
7648  xproperties.update_zlim ();
7649  break;
7650 
7651  case 'c':
7652  xproperties.set_clim (limits);
7653  xproperties.set_climmode ("auto");
7654  break;
7655 
7656  case 'a':
7657  xproperties.set_alim (limits);
7658  xproperties.set_alimmode ("auto");
7659  break;
7660 
7661  default:
7662  break;
7663  }
7664 
7665  xproperties.update_transform ();
7666 }
7667 
7668 inline
7669 double force_in_range (double x, double lower, double upper)
7670 {
7671  if (x < lower)
7672  return lower;
7673  else if (x > upper)
7674  return upper;
7675  else
7676  return x;
7677 }
7678 
7679 static Matrix
7680 do_zoom (double val, double factor, const Matrix& lims, bool is_logscale)
7681 {
7682  Matrix new_lims = lims;
7683 
7684  double lo = lims(0);
7685  double hi = lims(1);
7686 
7687  bool is_negative = lo < 0 && hi < 0;
7688 
7689  if (is_logscale)
7690  {
7691  if (is_negative)
7692  {
7693  double tmp = hi;
7694  hi = std::log10 (-lo);
7695  lo = std::log10 (-tmp);
7696  val = std::log10 (-val);
7697  }
7698  else
7699  {
7700  hi = std::log10 (hi);
7701  lo = std::log10 (lo);
7702  val = std::log10 (val);
7703  }
7704  }
7705 
7706  // Perform the zooming
7707  lo = val + (lo - val) / factor;
7708  hi = val + (hi - val) / factor;
7709 
7710  if (is_logscale)
7711  {
7712  if (is_negative)
7713  {
7714  double tmp = -std::pow (10.0, hi);
7715  hi = -std::pow (10.0, lo);
7716  lo = tmp;
7717  }
7718  else
7719  {
7720  lo = std::pow (10.0, lo);
7721  hi = std::pow (10.0, hi);
7722  }
7723  }
7724 
7725  new_lims(0) = lo;
7726  new_lims(1) = hi;
7727 
7728  return new_lims;
7729 }
7730 
7731 void
7732 axes::properties::zoom_about_point (const std::string& mode,
7733  double x, double y, double factor,
7734  bool push_to_zoom_stack)
7735 {
7736  // FIXME: Do we need error checking here?
7737  Matrix xlims = get_xlim ().matrix_value ();
7738  Matrix ylims = get_ylim ().matrix_value ();
7739 
7740  // Get children axes limits
7741  Matrix kids = get_children ();
7742  double minx = octave_Inf;
7743  double maxx = -octave_Inf;
7744  double min_pos_x = octave_Inf;
7745  double max_neg_x = -octave_Inf;
7746  get_children_limits (minx, maxx, min_pos_x, max_neg_x, kids, 'x');
7747 
7748  double miny = octave_Inf;
7749  double maxy = -octave_Inf;
7750  double min_pos_y = octave_Inf;
7751  double max_neg_y = -octave_Inf;
7752  get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y');
7753 
7754  xlims = do_zoom (x, factor, xlims, xscale_is ("log"));
7755  ylims = do_zoom (y, factor, ylims, yscale_is ("log"));
7756 
7757  zoom (mode, xlims, ylims, push_to_zoom_stack);
7758 }
7759 
7760 void
7761 axes::properties::zoom (const std::string& mode, double factor,
7762  bool push_to_zoom_stack)
7763 {
7764  // FIXME: Do we need error checking here?
7765  Matrix xlims = get_xlim ().matrix_value ();
7766  Matrix ylims = get_ylim ().matrix_value ();
7767 
7768  double x = (xlims(0) + xlims(1)) / 2;
7769  double y = (ylims(0) + ylims(1)) / 2;
7770 
7771  zoom_about_point (mode, x, y, factor, push_to_zoom_stack);
7772 }
7773 
7774 void
7776 {
7777  if (zoom_stack.empty ())
7778  {
7779  zoom_stack.push_front (xlimmode.get ());
7780  zoom_stack.push_front (xlim.get ());
7781  zoom_stack.push_front (ylimmode.get ());
7782  zoom_stack.push_front (ylim.get ());
7783  zoom_stack.push_front (zlimmode.get ());
7784  zoom_stack.push_front (zlim.get ());
7785  zoom_stack.push_front (view.get ());
7786  }
7787 }
7788 
7789 void
7790 axes::properties::zoom (const std::string& mode,
7791  const Matrix& xl, const Matrix& yl,
7792  bool push_to_zoom_stack)
7793 {
7794  if (push_to_zoom_stack)
7795  push_zoom_stack ();
7796 
7797  if (mode == "horizontal" || mode == "both")
7798  {
7799  xlim = xl;
7800  xlimmode = "manual";
7801  }
7802 
7803  if (mode == "vertical" || mode == "both")
7804  {
7805  ylim = yl;
7806  ylimmode = "manual";
7807  }
7808 
7809  update_transform ();
7810 
7811  if (mode == "horizontal" || mode == "both")
7812  update_xlim ();
7813 
7814  if (mode == "vertical" || mode == "both")
7815  update_ylim ();
7816 }
7817 
7818 static Matrix
7819 do_translate (double x0, double x1, const Matrix& lims, bool is_logscale)
7820 {
7821  Matrix new_lims = lims;
7822 
7823  double lo = lims(0);
7824  double hi = lims(1);
7825 
7826  bool is_negative = lo < 0 && hi < 0;
7827 
7828  double delta;
7829 
7830  if (is_logscale)
7831  {
7832  if (is_negative)
7833  {
7834  double tmp = hi;
7835  hi = std::log10 (-lo);
7836  lo = std::log10 (-tmp);
7837  x0 = -x0;
7838  x1 = -x1;
7839  }
7840  else
7841  {
7842  hi = std::log10 (hi);
7843  lo = std::log10 (lo);
7844  }
7845 
7846  delta = std::log10 (x0) - std::log10 (x1);
7847  }
7848  else
7849  {
7850  delta = x0 - x1;
7851  }
7852 
7853  // Perform the translation
7854  lo += delta;
7855  hi += delta;
7856 
7857  if (is_logscale)
7858  {
7859  if (is_negative)
7860  {
7861  double tmp = -std::pow (10.0, hi);
7862  hi = -std::pow (10.0, lo);
7863  lo = tmp;
7864  }
7865  else
7866  {
7867  lo = std::pow (10.0, lo);
7868  hi = std::pow (10.0, hi);
7869  }
7870  }
7871 
7872  new_lims(0) = lo;
7873  new_lims(1) = hi;
7874 
7875  return new_lims;
7876 }
7877 
7878 void
7879 axes::properties::translate_view (const std::string& mode,
7880  double x0, double x1, double y0, double y1,
7881  bool push_to_zoom_stack)
7882 {
7883  // FIXME: Do we need error checking here?
7884  Matrix xlims = get_xlim ().matrix_value ();
7885  Matrix ylims = get_ylim ().matrix_value ();
7886 
7887  // Get children axes limits
7888  Matrix kids = get_children ();
7889  double minx = octave_Inf;
7890  double maxx = -octave_Inf;
7891  double min_pos_x = octave_Inf;
7892  double max_neg_x = -octave_Inf;
7893  get_children_limits (minx, maxx, min_pos_x, max_neg_x, kids, 'x');
7894 
7895  double miny = octave_Inf;
7896  double maxy = -octave_Inf;
7897  double min_pos_y = octave_Inf;
7898  double max_neg_y = -octave_Inf;
7899  get_children_limits (miny, maxy, min_pos_y, max_neg_y, kids, 'y');
7900 
7901  xlims = do_translate (x0, x1, xlims, xscale_is ("log"));
7902  ylims = do_translate (y0, y1, ylims, yscale_is ("log"));
7903 
7904  zoom (mode, xlims, ylims, push_to_zoom_stack);
7905 }
7906 
7907 void
7908 axes::properties::pan (const std::string& mode, double factor,
7909  bool push_to_zoom_stack)
7910 {
7911  // FIXME: Do we need error checking here?
7912  Matrix xlims = get_xlim ().matrix_value ();
7913  Matrix ylims = get_ylim ().matrix_value ();
7914 
7915  double x0 = (xlims(0) + xlims(1)) / 2;
7916  double y0 = (ylims(0) + ylims(1)) / 2;
7917 
7918  double x1 = x0 + (xlims(1) - xlims(0)) * factor;
7919  double y1 = y0 + (ylims(1) - ylims(0)) * factor;
7920 
7921  translate_view (mode, x0, x1, y0, y1, push_to_zoom_stack);
7922 }
7923 
7924 void
7925 axes::properties::rotate3d (double x0, double x1, double y0, double y1,
7926  bool push_to_zoom_stack)
7927 {
7928  if (push_to_zoom_stack)
7929  push_zoom_stack ();
7930 
7931  Matrix bb = get_boundingbox (true);
7932  Matrix new_view = get_view ().matrix_value ();
7933 
7934  // Compute new view angles
7935  new_view(0) += ((x0 - x1) * (180.0 / bb(2)));
7936  new_view(1) += ((y1 - y0) * (180.0 / bb(3)));
7937 
7938  // Clipping
7939  new_view(1) = std::min (new_view(1), 90.0);
7940  new_view(1) = std::max (new_view(1), -90.0);
7941  if (new_view(0) > 180.0)
7942  new_view(0) -= 360.0;
7943  else if (new_view(0) < -180.0)
7944  new_view(0) += 360.0;
7945 
7946  // Snapping
7947  double snapMargin = 1.0;
7948  for (int a = -90; a <= 90; a += 90)
7949  {
7950  if ((a - snapMargin) < new_view(1)
7951  && new_view(1) < (a + snapMargin))
7952  {
7953  new_view(1) = a;
7954  break;
7955  }
7956  }
7957 
7958  for (int a = -180; a <= 180; a += 180)
7959  if ((a - snapMargin) < new_view(0)
7960  && new_view(0) < (a + snapMargin))
7961  {
7962  if (a == 180)
7963  new_view(0) = -180;
7964  else
7965  new_view(0) = a;
7966  break;
7967  }
7968 
7969  // Update axes properties
7970  set_view (new_view);
7971 }
7972 
7973 void
7974 axes::properties::rotate_view (double delta_el, double delta_az,
7975  bool push_to_zoom_stack)
7976 {
7977  if (push_to_zoom_stack)
7978  push_zoom_stack ();
7979 
7980  Matrix v = get_view ().matrix_value ();
7981 
7982  v(1) += delta_el;
7983 
7984  if (v(1) > 90)
7985  v(1) = 90;
7986  if (v(1) < -90)
7987  v(1) = -90;
7988 
7989  v(0) = fmod (v(0) - delta_az + 720,360);
7990 
7991  set_view (v);
7992 
7993  update_transform ();
7994 }
7995 
7996 void
7998 {
7999  if (zoom_stack.size () >= 7)
8000  {
8001  view = zoom_stack.front ();
8002  zoom_stack.pop_front ();
8003 
8004  zlim = zoom_stack.front ();
8005  zoom_stack.pop_front ();
8006 
8007  zlimmode = zoom_stack.front ();
8008  zoom_stack.pop_front ();
8009 
8010  ylim = zoom_stack.front ();
8011  zoom_stack.pop_front ();
8012 
8013  ylimmode = zoom_stack.front ();
8014  zoom_stack.pop_front ();
8015 
8016  xlim = zoom_stack.front ();
8017  zoom_stack.pop_front ();
8018 
8019  xlimmode = zoom_stack.front ();
8020  zoom_stack.pop_front ();
8021 
8022  update_transform ();
8023 
8024  update_xlim ();
8025  update_ylim ();
8026  update_zlim ();
8027 
8028  update_view ();
8029  }
8030 }
8031 
8032 void
8034 {
8035  size_t items_to_leave_on_stack = do_unzoom ? 7 : 0;
8036 
8037  while (zoom_stack.size () > items_to_leave_on_stack)
8038  zoom_stack.pop_front ();
8039 
8040  if (do_unzoom)
8041  unzoom ();
8042 }
8043 
8044 void
8046 {
8047  // empty list of local defaults
8049 
8050  // reset factory defaults
8051  set_defaults ("reset");
8052 }
8053 
8054 void
8056 {
8058 
8060  xinitialize (xproperties.get_xlabel ());
8061  xinitialize (xproperties.get_ylabel ());
8062  xinitialize (xproperties.get_zlabel ());
8063 
8064  xproperties.sync_positions ();
8065 }
8066 
8067 // ---------------------------------------------------------------------
8068 
8069 Matrix
8071 {
8072  Matrix m (1, 4);
8073 
8074  m(0) = xdata.min_val ();
8075  m(1) = xdata.max_val ();
8076  m(2) = xdata.min_pos ();
8077  m(3) = xdata.max_neg ();
8078 
8079  return m;
8080 }
8081 
8082 Matrix
8084 {
8085  Matrix m (1, 4);
8086 
8087  m(0) = ydata.min_val ();
8088  m(1) = ydata.max_val ();
8089  m(2) = ydata.min_pos ();
8090  m(3) = ydata.max_neg ();
8091 
8092  return m;
8093 }
8094 
8095 // ---------------------------------------------------------------------
8096 
8097 Matrix
8099 {
8100  Matrix pos = get_position ().matrix_value ();
8101 
8102  if (! units_is ("data"))
8103  pos = convert_text_position (pos, *this, get_units (), "data");
8104 
8105  return pos;
8106 }
8107 
8108 Matrix
8110 {
8111  // FIXME: Should this function also add the (x,y) base position?
8112  return extent.get ().matrix_value ();
8113 }
8114 
8117 {
8118  // FIXME: This doesn't work right for 3D plots.
8119  // (It doesn't in Matlab either, at least not in version 6.5.)
8120  Matrix m = extent.get ().matrix_value ();
8121  Matrix pos = get_position ().matrix_value ();
8122  Matrix p = convert_text_position (pos, *this, get_units (), "pixels");
8123 
8124  m(0) += p(0);
8125  m(1) += p(1);
8126 
8127  return convert_text_position (m, *this, "pixels", get_units ());
8128 }
8129 
8130 void
8132 {
8133  if (! error_state)
8134  {
8135  caseless_str old_fontunits = get_fontunits ();
8136  if (fontunits.set (v, true))
8137  {
8138  update_fontunits (old_fontunits);
8139  mark_modified ();
8140  }
8141  }
8142 }
8143 
8144 void
8146 {
8147  caseless_str new_units = get_fontunits ();
8148  double parent_height = 0;
8149  double fsz = get_fontsize ();
8150 
8151  if (new_units == "normalized")
8152  {
8153  graphics_object go (gh_manager::get_object (get___myhandle__ ()));
8154  graphics_object ax (go.get_ancestor ("axes"));
8155 
8156  parent_height = ax.get_properties ().get_boundingbox (true).elem (3);
8157  }
8158 
8159  fsz = convert_font_size (fsz, old_units, new_units, parent_height);
8160 
8161  set_fontsize (octave_value (fsz));
8162 }
8163 
8164 void
8166 {
8167 #ifdef HAVE_FREETYPE
8168 #ifdef HAVE_FONTCONFIG
8169  renderer.set_font (get ("fontname").string_value (),
8170  get ("fontweight").string_value (),
8171  get ("fontangle").string_value (),
8172  get ("fontsize_points").double_value ());
8173 #endif
8174  renderer.set_color (get_color_rgb ());
8175 #endif
8176 }
8177 
8178 void
8180 {
8181 #ifdef HAVE_FREETYPE
8182 
8183  int halign = 0;
8184  int valign = 0;
8185 
8186  if (horizontalalignment_is ("center"))
8187  halign = 1;
8188  else if (horizontalalignment_is ("right"))
8189  halign = 2;
8190 
8191  if (verticalalignment_is ("middle"))
8192  valign = 1;
8193  else if (verticalalignment_is ("top"))
8194  valign = 2;
8195  else if (verticalalignment_is ("baseline"))
8196  valign = 3;
8197  else if (verticalalignment_is ("cap"))
8198  valign = 4;
8199 
8200  Matrix bbox;
8201 
8202  // FIXME: string should be parsed only when modified, for efficiency
8203 
8204  octave_value string_prop = get_string ();
8205 
8206  string_vector sv = string_prop.all_strings ();
8207 
8208  renderer.text_to_pixels (sv.join ("\n"), pixels, bbox,
8209  halign, valign, get_rotation (),
8210  get_interpreter ());
8211  /* The bbox is relative to the text's position.
8212  We'll leave it that way, because get_position () does not return
8213  valid results when the text is first constructed.
8214  Conversion to proper coordinates is performed in get_extent. */
8215  set_extent (bbox);
8216 
8217 #endif
8218 
8219  if (autopos_tag_is ("xlabel") || autopos_tag_is ("ylabel")
8220  || autopos_tag_is ("zlabel") || autopos_tag_is ("title"))
8221  update_autopos ("sync");
8222 }
8223 
8224 void
8226 {
8227  if (autopos_tag_is ("xlabel") || autopos_tag_is ("ylabel")
8228  || autopos_tag_is ("zlabel") || autopos_tag_is ("title"))
8229  update_autopos (get_autopos_tag ());
8230 }
8231 
8232 void
8234 {
8235  if (! units_is ("data"))
8236  {
8237  set_xliminclude ("off");
8238  set_yliminclude ("off");
8239  set_zliminclude ("off");
8240  }
8241 
8242  Matrix pos = get_position ().matrix_value ();
8243 
8244  pos = convert_text_position (pos, *this, cached_units, get_units ());
8245 
8246  // FIXME: if the current axes view is 2D, then one should
8247  // probably drop the z-component of "pos" and leave "zliminclude"
8248  // to "off".
8249 
8250  bool autopos = positionmode_is ("auto");
8251 
8252  set_position (pos);
8253 
8254  if (autopos)
8255  set_positionmode ("auto");
8256 
8257  if (units_is ("data"))
8258  {
8259  set_xliminclude ("on");
8260  set_yliminclude ("on");
8261  // FIXME: see above
8262  set_zliminclude ("off");
8263  }
8264 
8265  cached_units = get_units ();
8266 }
8267 
8268 double
8269 text::properties::get_fontsize_points (double box_pix_height) const
8270 {
8271  double fs = get_fontsize ();
8272  double parent_height = box_pix_height;
8273 
8274  if (fontunits_is ("normalized") && parent_height <= 0)
8275  {
8276  graphics_object go (gh_manager::get_object (get___myhandle__ ()));
8277  graphics_object ax (go.get_ancestor ("axes"));
8278 
8279  parent_height = ax.get_properties ().get_boundingbox (true).elem (3);
8280  }
8281 
8282  return convert_font_size (fs, get_fontunits (), "points", parent_height);
8283 }
8284 
8285 // ---------------------------------------------------------------------
8286 
8289 {
8290  return convert_cdata (*this, get_cdata (),
8291  cdatamapping_is ("scaled"), 3);
8292 }
8293 
8294 // ---------------------------------------------------------------------
8295 
8298 {
8299  octave_value fvc = get_facevertexcdata ();
8300  if (fvc.is_undefined () || fvc.is_empty ())
8301  return Matrix ();
8302  else
8303  return convert_cdata (*this, fvc,cdatamapping_is ("scaled"), 2);
8304 }
8305 
8306 static bool updating_patch_data = false;
8307 
8308 void
8310 {
8311  if (updating_patch_data)
8312  return;
8313 
8314  Matrix xd = get_xdata ().matrix_value ();
8315  Matrix yd = get_ydata ().matrix_value ();
8316  Matrix zd = get_zdata ().matrix_value ();
8317  NDArray cd = get_cdata ().array_value ();
8318 
8319  bad_data_msg = std::string ();
8320  if (xd.dims () != yd.dims ()
8321  || (xd.dims () != zd.dims () && ! zd.is_empty ()))
8322  {
8323  bad_data_msg = "x/y/zdata should have the same dimensions";
8324  return;
8325  }
8326 
8327  // Faces and Vertices
8328  dim_vector dv;
8329  bool is3D = false;
8330  octave_idx_type nr = xd.rows ();
8331  octave_idx_type nc = xd.columns ();
8332  if (nr == 1 && nc > 1)
8333  {
8334  nr = nc;
8335  nc = 1;
8336  xd = xd.as_column ();
8337  yd = yd.as_column ();
8338  zd = zd.as_column ();
8339  }
8340 
8341  dv(0) = nr * nc;
8342  if (zd.is_empty ())
8343  dv(1) = 2;
8344  else
8345  {
8346  dv(1) = 3;
8347  is3D = true;
8348  }
8349 
8350  Matrix vert (dv);
8351  Matrix idx (nc, nr);
8352 
8353  octave_idx_type kk = 0;
8354  for (octave_idx_type jj = 0; jj < nc; jj++)
8355  {
8356  for (octave_idx_type ii = 0; ii < nr; ii++)
8357  {
8358  vert(kk,0) = xd(ii,jj);
8359  vert(kk,1) = yd(ii,jj);
8360  if (is3D)
8361  vert(kk,2) = zd(ii,jj);
8362 
8363  idx(jj,ii) = static_cast<double> (kk+1);
8364 
8365  kk++;
8366  }
8367  }
8368 
8369  // facevertexcdata
8370  Matrix fvc;
8371  if (cd.ndims () == 3)
8372  {
8373  dv(0) = cd.rows () * cd.columns ();
8374  dv(1) = cd.dims ()(2);
8375  fvc = cd.reshape (dv);
8376  }
8377  else
8378  fvc = cd.as_column ();
8379 
8380  // FIXME: shouldn't we update facevertexalphadata here ?
8381 
8382  unwind_protect frame;
8383  frame.protect_var (updating_patch_data);
8384  updating_patch_data = true;
8385 
8386  faces.set (idx);
8387  vertices.set (vert);
8388  facevertexcdata.set (fvc);
8389 }
8390 
8391 
8392 void
8394 {
8395  if (updating_patch_data)
8396  return;
8397 
8398  Matrix idx = get_faces ().matrix_value ().transpose ();
8399  Matrix vert = get_vertices ().matrix_value ();
8400  NDArray fvc = get_facevertexcdata ().array_value ();
8401 
8402  octave_idx_type nfaces = idx.columns ();
8403  octave_idx_type nvert = vert.rows ();
8404 
8405  // Check all vertices in faces are defined
8406  bad_data_msg = std::string ();
8407  if (static_cast<double> (nvert) < idx.row_max ().max ())
8408  {
8409  bad_data_msg = "some vertices in \"faces\" property are undefined";
8410  return;
8411  }
8412 
8413  // Replace NaNs
8414  if (idx.any_element_is_inf_or_nan ())
8415  {
8416  for (octave_idx_type jj = 0; jj < idx.columns (); jj++)
8417  {
8418  double valid_vert = idx(0,jj);
8419  bool turn_valid = false;
8420  for (octave_idx_type ii = 0; ii < idx.rows (); ii++)
8421  {
8422  if (xisnan (idx(ii,jj)) || turn_valid)
8423  {
8424  idx(ii,jj) = valid_vert;
8425  turn_valid = true;
8426  }
8427  else
8428  valid_vert = idx(ii,jj);
8429  }
8430  }
8431  }
8432 
8433  // Build cdata
8434  dim_vector dv = dim_vector::alloc (3);
8435  NDArray cd;
8436  bool pervertex = false;
8437 
8438  if (fvc.rows () == nfaces || fvc.rows () == 1)
8439  {
8440  dv(0) = 1;
8441  dv(1) = fvc.rows ();
8442  dv(2) = fvc.columns ();
8443  cd = fvc.reshape (dv);
8444  }
8445  else
8446  {
8447  if (! fvc.is_empty ())
8448  {
8449  dv(0) = idx.rows ();
8450  dv(1) = nfaces;
8451  dv(2) = fvc.columns ();
8452  cd.resize (dv);
8453  pervertex = true;
8454  }
8455  }
8456 
8457  // Build x,y,zdata and eventually per vertex cdata
8458  Matrix xd (idx.dims ());
8459  Matrix yd (idx.dims ());
8460  Matrix zd;
8461  bool has_zd = false;
8462  if (vert.columns () > 2)
8463  {
8464  zd = Matrix (idx.dims ());
8465  has_zd = true;
8466  }
8467 
8468 
8469  for (octave_idx_type jj = 0; jj < nfaces; jj++)
8470  {
8471  for (octave_idx_type ii = 0; ii < idx.rows (); ii++)
8472  {
8473  octave_idx_type row = static_cast<octave_idx_type> (idx(ii,jj)-1);
8474  xd(ii,jj) = vert(row,0);
8475  yd(ii,jj) = vert(row,1);
8476 
8477  if (has_zd)
8478  zd(ii,jj) = vert(row,2);
8479 
8480  if (pervertex)
8481  for (int kk = 0; kk < fvc.columns (); kk++)
8482  cd(ii,jj,kk) = fvc(row,kk);
8483  }
8484  }
8485 
8486 
8487  unwind_protect frame;
8488  frame.protect_var (updating_patch_data);
8489  updating_patch_data = true;
8490 
8491  set_xdata (xd);
8492  set_ydata (yd);
8493  set_zdata (zd);
8494  set_cdata (cd);
8495 }
8496 
8497 // ---------------------------------------------------------------------
8498 
8501 {
8502  return convert_cdata (*this, get_cdata (), cdatamapping_is ("scaled"), 3);
8503 }
8504 
8505 inline void
8506 cross_product (double x1, double y1, double z1,
8507  double x2, double y2, double z2,
8508  double& x, double& y, double& z)
8509 {
8510  x += (y1 * z2 - z1 * y2);
8511  y += (z1 * x2 - x1 * z2);
8512  z += (x1 * y2 - y1 * x2);
8513 }
8514 
8515 void
8517 {
8518  if (normalmode_is ("auto"))
8519  {
8520  Matrix x = get_xdata ().matrix_value ();
8521  Matrix y = get_ydata ().matrix_value ();
8522  Matrix z = get_zdata ().matrix_value ();
8523 
8524  int p = z.columns ();
8525  int q = z.rows ();
8526 
8527  // FIXME: There might be a cleaner way to do this. When data is changed
8528  // the update_xdata, update_ydata, update_zdata routines are called in a
8529  // serial fashion. Until the final call to update_zdata the matrices
8530  // will be of mismatched dimensions which can cause an out-of-bound
8531  // indexing in the code below. This one-liner prevents calculating
8532  // normals until dimensions match.
8533  if (x.columns () != p || y.rows () != q)
8534  return;
8535 
8536  NDArray n (dim_vector (q, p, 3), 0.0);
8537 
8538  bool x_mat = (x.rows () == q);
8539  bool y_mat = (y.columns () == p);
8540 
8541  int i1, i2, i3, j1, j2, j3;
8542  i1 = i2 = i3 = 0;
8543  j1 = j2 = j3 = 0;
8544 
8545  for (int i = 0; i < p; i++)
8546  {
8547  if (y_mat)
8548  {
8549  i1 = i - 1;
8550  i2 = i;
8551  i3 = i + 1;
8552  }
8553 
8554  for (int j = 0; j < q; j++)
8555  {
8556  if (x_mat)
8557  {
8558  j1 = j - 1;
8559  j2 = j;
8560  j3 = j + 1;
8561  }
8562 
8563  double& nx = n(j, i, 0);
8564  double& ny = n(j, i, 1);
8565  double& nz = n(j, i, 2);
8566 
8567  if ((j > 0) && (i > 0))
8568  // upper left quadrangle
8570  (x(j1,i-1)-x(j2,i), y(j-1,i1)-y(j,i2), z(j-1,i-1)-z(j,i),
8571  x(j2,i-1)-x(j1,i), y(j,i1)-y(j-1,i2), z(j,i-1)-z(j-1,i),
8572  nx, ny, nz);
8573 
8574  if ((j > 0) && (i < (p -1)))
8575  // upper right quadrangle
8577  (x(j1,i+1)-x(j2,i), y(j-1,i3)-y(j,i2), z(j-1,i+1)-z(j,i),
8578  x(j1,i)-x(j2,i+1), y(j-1,i2)-y(j,i3), z(j-1,i)-z(j,i+1),
8579  nx, ny, nz);
8580 
8581  if ((j < (q - 1)) && (i > 0))
8582  // lower left quadrangle
8584  (x(j2,i-1)-x(j3,i), y(j,i1)-y(j+1,i2), z(j,i-1)-z(j+1,i),
8585  x(j3,i-1)-x(j2,i), y(j+1,i1)-y(j,i2), z(j+1,i-1)-z(j,i),
8586  nx, ny, nz);
8587 
8588  if ((j < (q - 1)) && (i < (p -1)))
8589  // lower right quadrangle
8591  (x(j3,i)-x(j2,i+1), y(j+1,i2)-y(j,i3), z(j+1,i)-z(j,i+1),
8592  x(j3,i+1)-x(j2,i), y(j+1,i3)-y(j,i2), z(j+1,i+1)-z(j,i),
8593  nx, ny, nz);
8594 
8595  double d = -std::max (std::max (fabs (nx), fabs (ny)), fabs (nz));
8596 
8597  nx /= d;
8598  ny /= d;
8599  nz /= d;
8600  }
8601  }
8602  vertexnormals = n;
8603  }
8604 }
8605 
8606 // ---------------------------------------------------------------------
8607 
8608 void
8610 {
8611  graphics_object obj = gh_manager::get_object (__myhandle__);
8612 
8613  if (obj)
8614  {
8615  obj.update_axis_limits ("xlim");
8616  obj.update_axis_limits ("ylim");
8617  obj.update_axis_limits ("zlim");
8618  obj.update_axis_limits ("clim");
8619  obj.update_axis_limits ("alim");
8620  }
8621 }
8622 
8623 void
8625 {
8626  graphics_object obj = gh_manager::get_object (__myhandle__);
8627 
8628  if (obj)
8629  {
8630  obj.update_axis_limits ("xlim", h);
8631  obj.update_axis_limits ("ylim", h);
8632  obj.update_axis_limits ("zlim", h);
8633  obj.update_axis_limits ("clim", h);
8634  obj.update_axis_limits ("alim", h);
8635  }
8636 }
8637 
8638 static bool updating_hggroup_limits = false;
8639 
8640 void
8641 hggroup::update_axis_limits (const std::string& axis_type,
8642  const graphics_handle& h)
8643 {
8644  if (updating_hggroup_limits)
8645  return;
8646 
8647  Matrix kids = Matrix (1, 1, h.value ());
8648 
8649  double min_val = octave_Inf;
8650  double max_val = -octave_Inf;
8651  double min_pos = octave_Inf;
8652  double max_neg = -octave_Inf;
8653 
8654  Matrix limits;
8655  double val;
8656 
8657  char update_type = 0;
8658 
8659  if (axis_type == "xlim" || axis_type == "xliminclude")
8660  {
8661  limits = xproperties.get_xlim ().matrix_value ();
8662  update_type = 'x';
8663  }
8664  else if (axis_type == "ylim" || axis_type == "yliminclude")
8665  {
8666  limits = xproperties.get_ylim ().matrix_value ();
8667  update_type = 'y';
8668  }
8669  else if (axis_type == "zlim" || axis_type == "zliminclude")
8670  {
8671  limits = xproperties.get_zlim ().matrix_value ();
8672  update_type = 'z';
8673  }
8674  else if (axis_type == "clim" || axis_type == "climinclude")
8675  {
8676  limits = xproperties.get_clim ().matrix_value ();
8677  update_type = 'c';
8678  }
8679  else if (axis_type == "alim" || axis_type == "aliminclude")
8680  {
8681  limits = xproperties.get_alim ().matrix_value ();
8682  update_type = 'a';
8683  }
8684 
8685  if (limits.numel () == 4)
8686  {
8687  val = limits(0);
8688  if (xfinite (val))
8689  min_val = val;
8690  val = limits(1);
8691  if (xfinite (val))
8692  max_val = val;
8693  val = limits(2);
8694  if (xfinite (val))
8695  min_pos = val;
8696  val = limits(3);
8697  if (xfinite (val))
8698  max_neg = val;
8699  }
8700  else
8701  {
8702  limits.resize (4,1);
8703  limits(0) = min_val;
8704  limits(1) = max_val;
8705  limits(2) = min_pos;
8706  limits(3) = max_neg;
8707  }
8708 
8709  get_children_limits (min_val, max_val, min_pos, max_neg, kids, update_type);
8710 
8711  unwind_protect frame;
8712  frame.protect_var (updating_hggroup_limits);
8713 
8714  updating_hggroup_limits = true;
8715 
8716  if (limits(0) != min_val || limits(1) != max_val
8717  || limits(2) != min_pos || limits(3) != max_neg)
8718  {
8719  limits(0) = min_val;
8720  limits(1) = max_val;
8721  limits(2) = min_pos;
8722  limits(3) = max_neg;
8723 
8724  switch (update_type)
8725  {
8726  case 'x':
8727  xproperties.set_xlim (limits);
8728  break;
8729 
8730  case 'y':
8731  xproperties.set_ylim (limits);
8732  break;
8733 
8734  case 'z':
8735  xproperties.set_zlim (limits);
8736  break;
8737 
8738  case 'c':
8739  xproperties.set_clim (limits);
8740  break;
8741 
8742  case 'a':
8743  xproperties.set_alim (limits);
8744  break;
8745 
8746  default:
8747  break;
8748  }
8749 
8751  }
8752 }
8753 
8754 void
8755 hggroup::update_axis_limits (const std::string& axis_type)
8756 {
8757  if (updating_hggroup_limits)
8758  return;
8759 
8760  Matrix kids = xproperties.get_children ();
8761 
8762  double min_val = octave_Inf;
8763  double max_val = -octave_Inf;
8764  double min_pos = octave_Inf;
8765  double max_neg = -octave_Inf;
8766 
8767  char update_type = 0;
8768 
8769  if (axis_type == "xlim" || axis_type == "xliminclude")
8770  {
8771  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'x');
8772 
8773  update_type = 'x';
8774  }
8775  else if (axis_type == "ylim" || axis_type == "yliminclude")
8776  {
8777  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'y');
8778 
8779  update_type = 'y';
8780  }
8781  else if (axis_type == "zlim" || axis_type == "zliminclude")
8782  {
8783  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'z');
8784 
8785  update_type = 'z';
8786  }
8787  else if (axis_type == "clim" || axis_type == "climinclude")
8788  {
8789  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'c');
8790 
8791  update_type = 'c';
8792  }
8793  else if (axis_type == "alim" || axis_type == "aliminclude")
8794  {
8795  get_children_limits (min_val, max_val, min_pos, max_neg, kids, 'a');
8796 
8797  update_type = 'a';
8798  }
8799 
8800  unwind_protect frame;
8801  frame.protect_var (updating_hggroup_limits);
8802 
8803  updating_hggroup_limits = true;
8804 
8805  Matrix limits (1, 4, 0.0);
8806 
8807  limits(0) = min_val;
8808  limits(1) = max_val;
8809  limits(2) = min_pos;
8810  limits(3) = max_neg;
8811 
8812  switch (update_type)
8813  {
8814  case 'x':
8815  xproperties.set_xlim (limits);
8816  break;
8817 
8818  case 'y':
8819  xproperties.set_ylim (limits);
8820  break;
8821 
8822  case 'z':
8823  xproperties.set_zlim (limits);
8824  break;
8825 
8826  case 'c':
8827  xproperties.set_clim (limits);
8828  break;
8829 
8830  case 'a':
8831  xproperties.set_alim (limits);
8832  break;
8833 
8834  default:
8835  break;
8836  }
8837 
8839 }
8840 
8841 // ---------------------------------------------------------------------
8842 
8844 {
8845  std::list<graphics_handle> lst = xproperties.get_dependent_obj_list ();
8846  std::list<graphics_handle>::const_iterator it;
8847 
8848  for (it = lst.begin (); it != lst.end (); it++)
8849  {
8851 
8852  if (go.valid_object () &&
8853  go.get ("uicontextmenu") == xproperties.get___myhandle__ ())
8854  go.set ("uicontextmenu", Matrix ());
8855  }
8856 }
8857 
8858 
8859 /*
8860 ## Test deletion/reset of uicontextmenu
8861 %!test
8862 %! hf = figure ("visible", "off");
8863 %! hax = axes ("parent", hf);
8864 %! unwind_protect
8865 %! hctx1 = uicontextmenu ("parent", hf);
8866 %! hctx2 = uicontextmenu ("parent", hf);
8867 %! set (hf, "uicontextmenu", hctx2);
8868 %! set (hax, "uicontextmenu", hctx2);
8869 %! assert (get (hf, "uicontextmenu"), hctx2);
8870 %! assert (get (hax, "uicontextmenu"), hctx2);
8871 %! assert (get (hf, "children"), [hctx2; hctx1; hax]);
8872 %! delete (hctx2);
8873 %! assert (get (hf, "uicontextmenu"), []);
8874 %! assert (get (hax, "uicontextmenu"), []);
8875 %! assert (get (hf, "children"), [hctx1; hax]);
8876 %! set (hf, "uicontextmenu", hctx1);
8877 %! assert (get (hf, "uicontextmenu"), hctx1);
8878 %! set (hf, "uicontextmenu", []);
8879 %! assert (get (hf, "uicontextmenu"), []);
8880 %! assert (get (hf, "children"), [hctx1; hax]);
8881 %! unwind_protect_cleanup
8882 %! close (hf);
8883 %! end_unwind_protect;
8884  */
8885 
8886 // ---------------------------------------------------------------------
8887 
8890 {
8891  Matrix m = extent.get ().matrix_value ();
8892 
8893  graphics_object parent_obj =
8895  Matrix parent_bbox = parent_obj.get_properties ().get_boundingbox (true),
8896  parent_size = parent_bbox.extract_n (0, 2, 1, 2);
8897 
8898  return convert_position (m, "pixels", get_units (), parent_size);
8899 }
8900 
8901 void
8903 {
8904 #ifdef HAVE_FREETYPE
8905 
8906  text_element *elt;
8907  ft_render text_renderer;
8908  Matrix box;
8909 
8910  // FIXME: parsed content should be cached for efficiency
8911  // FIXME: support multiline text
8912 
8913  elt = text_parser::parse (get_string_string (), "none");
8914 #ifdef HAVE_FONTCONFIG
8915  text_renderer.set_font (get_fontname (),
8916  get_fontweight (),
8917  get_fontangle (),
8918  get_fontsize ());
8919 #endif
8920  box = text_renderer.get_extent (elt, 0);
8921  delete elt;
8922 
8923  Matrix ext (1, 4, 0.0);
8924 
8925  // FIXME: also handle left and bottom components
8926 
8927  ext(0) = ext(1) = 1;
8928  ext(2) = box(0);
8929  ext(3) = box(1);
8930 
8931  set_extent (ext);
8932 
8933 #endif
8934 }
8935 
8936 void
8938 {
8939  Matrix pos = get_position ().matrix_value ();
8940 
8942  Matrix parent_bbox = parent_obj.get_properties ().get_boundingbox (true),
8943  parent_size = parent_bbox.extract_n (0, 2, 1, 2);
8944 
8945  pos = convert_position (pos, cached_units, get_units (), parent_size);
8946  set_position (pos);
8947 
8948  cached_units = get_units ();
8949 }
8950 
8951 void
8953 {
8954  if (get___object__ ().is_empty ())
8955  style = st;
8956  else
8957  error ("set: cannot change the style of a uicontrol object after creation.");
8958 }
8959 
8960 Matrix
8962  const Matrix& parent_pix_size) const
8963 {
8964  Matrix pos = get_position ().matrix_value ();
8965  Matrix parent_size (parent_pix_size);
8966 
8967  if (parent_size.numel () == 0)
8968  {
8970 
8971  if (obj.valid_object ())
8972  parent_size =
8973  obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
8974  else
8975  parent_size = default_figure_position ();
8976  }
8977 
8978  pos = convert_position (pos, get_units (), "pixels", parent_size);
8979 
8980  pos(0)--;
8981  pos(1)--;
8982  pos(1) = parent_size(1) - pos(1) - pos(3);
8983 
8984  return pos;
8985 }
8986 
8987 void
8989 {
8990  if (! error_state)
8991  {
8992  caseless_str old_fontunits = get_fontunits ();
8993  if (fontunits.set (v, true))
8994  {
8995  update_fontunits (old_fontunits);
8996  mark_modified ();
8997  }
8998  }
8999 }
9000 
9001 void
9003 {
9004  caseless_str new_units = get_fontunits ();
9005  double parent_height = get_boundingbox (false).elem (3);
9006  double fsz = get_fontsize ();
9007 
9008  fsz = convert_font_size (fsz, old_units, new_units, parent_height);
9009 
9010  fontsize.set (octave_value (fsz), true);
9011 }
9012 
9013 double
9014 uicontrol::properties::get_fontsize_points (double box_pix_height) const
9015 {
9016  double fs = get_fontsize ();
9017  double parent_height = box_pix_height;
9018 
9019  if (fontunits_is ("normalized") && parent_height <= 0)
9020  parent_height = get_boundingbox (false).elem (3);
9021 
9022  return convert_font_size (fs, get_fontunits (), "points", parent_height);
9023 }
9024 
9025 // ---------------------------------------------------------------------
9026 
9027 Matrix
9029  const Matrix& parent_pix_size) const
9030 {
9031  Matrix pos = get_position ().matrix_value ();
9032  Matrix parent_size (parent_pix_size);
9033 
9034  if (parent_size.numel () == 0)
9035  {
9037 
9038  parent_size =
9039  obj.get_properties ().get_boundingbox (true).extract_n (0, 2, 1, 2);
9040  }
9041 
9042  pos = convert_position (pos, get_units (), "pixels", parent_size);
9043 
9044  pos(0)--;
9045  pos(1)--;
9046  pos(1) = parent_size(1) - pos(1) - pos(3);
9047 
9048  if (internal)
9049  {
9050  double outer_height = pos(3);
9051 
9052  pos(0) = pos(1) = 0;
9053 
9054  if (! bordertype_is ("none"))
9055  {
9056  double bw = get_borderwidth ();
9057  double mul = 1.0;
9058 
9059  if (bordertype_is ("etchedin") || bordertype_is ("etchedout"))
9060  mul = 2.0;
9061 
9062  pos(0) += mul * bw;
9063  pos(1) += mul * bw;
9064  pos(2) -= 2 * mul * bw;
9065  pos(3) -= 2 * mul * bw;
9066  }
9067 
9068  if (! get_title ().empty ())
9069  {
9070  double fs = get_fontsize ();
9071 
9072  if (! fontunits_is ("pixels"))
9073  {
9074  double res = xget (0, "screenpixelsperinch").double_value ();
9075 
9076  if (fontunits_is ("points"))
9077  fs *= (res / 72.0);
9078  else if (fontunits_is ("inches"))
9079  fs *= res;
9080  else if (fontunits_is ("centimeters"))
9081  fs *= (res / 2.54);
9082  else if (fontunits_is ("normalized"))
9083  fs *= outer_height;
9084  }
9085 
9086  if (titleposition_is ("lefttop") || titleposition_is ("centertop")
9087  || titleposition_is ("righttop"))
9088  pos(1) += (fs / 2);
9089  pos(3) -= (fs / 2);
9090  }
9091  }
9092 
9093  return pos;
9094 }
9095 
9096 void
9098 {
9099  if (! error_state)
9100  {
9101  caseless_str old_units = get_units ();
9102  if (units.set (v, true))
9103  {
9104  update_units (old_units);
9105  mark_modified ();
9106  }
9107  }
9108 }
9109 
9110 void
9112 {
9113  Matrix pos = get_position ().matrix_value ();
9114 
9116  Matrix parent_bbox = parent_obj.get_properties ().get_boundingbox (true),
9117  parent_size = parent_bbox.extract_n (0, 2, 1, 2);
9118 
9119  pos = convert_position (pos, old_units, get_units (), parent_size);
9120  set_position (pos);
9121 }
9122 
9123 void
9125 {
9126  if (! error_state)
9127  {
9128  caseless_str old_fontunits = get_fontunits ();
9129  if (fontunits.set (v, true))
9130  {
9131  update_fontunits (old_fontunits);
9132  mark_modified ();
9133  }
9134  }
9135 }
9136 
9137 void
9139 {
9140  caseless_str new_units = get_fontunits ();
9141  double parent_height = get_boundingbox (false).elem (3);
9142  double fsz = get_fontsize ();
9143 
9144  fsz = convert_font_size (fsz, old_units, new_units, parent_height);
9145 
9146  set_fontsize (octave_value (fsz));
9147 }
9148 
9149 double
9150 uipanel::properties::get_fontsize_points (double box_pix_height) const
9151 {
9152  double fs = get_fontsize ();
9153  double parent_height = box_pix_height;
9154 
9155  if (fontunits_is ("normalized") && parent_height <= 0)
9156  parent_height = get_boundingbox (false).elem (3);
9157 
9158  return convert_font_size (fs, get_fontunits (), "points", parent_height);
9159 }
9160 
9161 // ---------------------------------------------------------------------
9162 
9165 {
9166  octave_value retval = default_properties.lookup (name);
9167 
9168  if (retval.is_undefined ())
9169  {
9170  graphics_handle parent = get_parent ();
9171  graphics_object parent_obj = gh_manager::get_object (parent);
9172 
9173  retval = parent_obj.get_default (name);
9174  }
9175 
9176  return retval;
9177 }
9178 
9179 void
9181 {
9182  // empty list of local defaults
9184 
9187 }
9188 
9189 // ---------------------------------------------------------------------
9190 
9193 {
9194  graphics_handle parent = get_parent ();
9195  graphics_object parent_obj = gh_manager::get_object (parent);
9196 
9197  return parent_obj.get_default (type () + name);
9198 }
9199 
9202 {
9203  graphics_object parent_obj = gh_manager::get_object (0);
9204 
9205  return parent_obj.get_factory_default (type () + name);
9206 }
9207 
9208 // We use a random value for the handle to avoid issues with plots and
9209 // scalar values for the first argument.
9211  : handle_map (), handle_free_list (),
9212  next_handle (-1.0 - (rand () + 1.0) / (RAND_MAX + 2.0)),
9213  figure_list (), graphics_lock (), event_queue (),
9214  callback_objects (), event_processing (0)
9215 {
9216  handle_map[0] = graphics_object (new root_figure ());
9217 
9218  // Make sure the default graphics toolkit is registered.
9220 }
9221 
9222 void
9224 {
9225  instance = new gh_manager ();
9226 
9227  if (instance)
9229 }
9230 
9232 gh_manager::do_make_graphics_handle (const std::string& go_name,
9233  const graphics_handle& p,
9234  bool integer_figure_handle,
9235  bool do_createfcn,
9236  bool do_notify_toolkit)
9237 {
9238  graphics_handle h = get_handle (integer_figure_handle);
9239 
9240  base_graphics_object *go = 0;
9241 
9242  go = make_graphics_object_from_type (go_name, h, p);
9243 
9244  if (go)
9245  {
9246  graphics_object obj (go);
9247 
9248  handle_map[h] = obj;
9249 
9250  // Overriding defaults will work now because the handle is valid
9251  // and we can find parent objects (not just handles).
9252  obj.override_defaults ();
9253 
9254  if (go_name == "axes")
9255  {
9256  // Handle defaults for labels since overriding defaults for
9257  // them can't work before the axes object is fully
9258  // constructed.
9259 
9260  axes::properties& props =
9261  dynamic_cast<axes::properties&> (obj.get_properties ());
9262 
9263  graphics_object tgo;
9264 
9265  tgo = gh_manager::get_object (props.get_xlabel ());
9266  tgo.override_defaults ();
9267 
9268  tgo = gh_manager::get_object (props.get_ylabel ());
9269  tgo.override_defaults ();
9270 
9271  tgo = gh_manager::get_object (props.get_zlabel ());
9272  tgo.override_defaults ();
9273 
9274  tgo = gh_manager::get_object (props.get_title ());
9275  tgo.override_defaults ();
9276  }
9277 
9278  if (do_createfcn)
9280 
9281  // Notify graphics toolkit.
9282  if (do_notify_toolkit)
9283  obj.initialize ();
9284  }
9285  else
9286  error ("gh_manager::do_make_graphics_handle: invalid object type '%s'",
9287  go_name.c_str ());
9288 
9289  return h;
9290 }
9291 
9293 gh_manager::do_make_figure_handle (double val, bool do_notify_toolkit)
9294 {
9295  graphics_handle h = val;
9296 
9297  base_graphics_object* go = new figure (h, 0);
9298  graphics_object obj (go);
9299 
9300  handle_map[h] = obj;
9301 
9302  // Notify graphics toolkit.
9303  if (do_notify_toolkit)
9304  obj.initialize ();
9305 
9306  obj.override_defaults ();
9307 
9308  return h;
9309 }
9310 
9311 void
9313 {
9314  do_pop_figure (h);
9315 
9316  figure_list.push_front (h);
9317 }
9318 
9319 void
9321 {
9322  for (figure_list_iterator p = figure_list.begin ();
9323  p != figure_list.end ();
9324  p++)
9325  {
9326  if (*p == h)
9327  {
9328  figure_list.erase (p);
9329  break;
9330  }
9331  }
9332 }
9333 
9334 class
9336 {
9337 public:
9338  callback_event (const graphics_handle& h, const std::string& name,
9339  const octave_value& data = Matrix ())
9340  : base_graphics_event (), handle (h), callback_name (name),
9341  callback (), callback_data (data) { }
9342 
9344  const octave_value& data = Matrix ())
9345  : base_graphics_event (), handle (h), callback_name (),
9346  callback (cb), callback_data (data) { }
9347 
9348  void execute (void)
9349  {
9350  if (callback.is_defined ())
9351  gh_manager::execute_callback (handle, callback, callback_data);
9352  else
9353  gh_manager::execute_callback (handle, callback_name, callback_data);
9354  }
9355 
9356 private:
9358  : base_graphics_event (), handle (), callback_name (), callback_data ()
9359  { }
9360 
9361 private:
9363  std::string callback_name;
9366 };
9367 
9368 class
9370 {
9371 public:
9373  : base_graphics_event (), function (fcn), function_data (data)
9374  { }
9375 
9376  void execute (void)
9377  {
9378  function (function_data);
9379  }
9380 
9381 private:
9382 
9384 
9386 
9387  // function_event objects must be created with at least a function.
9388  function_event (void);
9389 
9390  // No copying!
9391 
9392  function_event (const function_event&);
9393 
9394  function_event & operator = (const function_event&);
9395 };
9396 
9397 class
9399 {
9400 public:
9401  set_event (const graphics_handle& h, const std::string& name,
9402  const octave_value& value, bool do_notify_toolkit = true)
9403  : base_graphics_event (), handle (h), property_name (name),
9404  property_value (value), notify_toolkit (do_notify_toolkit) { }
9405 
9406  void execute (void)
9407  {
9408  gh_manager::auto_lock guard;
9409 
9411 
9412  if (go)
9413  {
9414  property p = go.get_properties ().get_property (property_name);
9415 
9416  if (p.ok ())
9417  p.set (property_value, true, notify_toolkit);
9418  }
9419  }
9420 
9421 private:
9422  set_event (void)
9423  : base_graphics_event (), handle (), property_name (), property_value ()
9424  { }
9425 
9426 private:
9428  std::string property_name;
9431 };
9432 
9435  const std::string& name,
9436  const octave_value& data)
9437 {
9438  graphics_event e;
9439 
9440  e.rep = new callback_event (h, name, data);
9441 
9442  return e;
9443 }
9444 
9447  const octave_value& cb,
9448  const octave_value& data)
9449 {
9450  graphics_event e;
9451 
9452  e.rep = new callback_event (h, cb, data);
9453 
9454  return e;
9455 }
9456 
9459  void *data)
9460 {
9461  graphics_event e;
9462 
9463  e.rep = new function_event (fcn, data);
9464 
9465  return e;
9466 }
9467 
9470  const std::string& name,
9471  const octave_value& data,
9472  bool notify_toolkit)
9473 {
9474  graphics_event e;
9475 
9476  e.rep = new set_event (h, name, data, notify_toolkit);
9477 
9478  return e;
9479 }
9480 
9481 static void
9483 {
9485  root_figure::properties& props =
9486  dynamic_cast<root_figure::properties&> (go.get_properties ());
9487 
9488  props.set_callbackobject (h.as_octave_value ());
9489 }
9490 
9491 void
9493 {
9494  gh_manager::auto_lock guard;
9495 
9496  callback_objects.pop_front ();
9497 
9498  xset_gcbo (callback_objects.empty ()
9499  ? graphics_handle ()
9500  : callback_objects.front ().get_handle ());
9501 }
9502 
9503 void
9505  const octave_value& l)
9506 {
9509  else
9510  {
9511  gh_manager::auto_lock guard;
9512 
9514  }
9515 }
9516 
9517 void
9519  const octave_value& cb_arg,
9520  const octave_value& data)
9521 {
9522  if (cb_arg.is_defined () && ! cb_arg.is_empty ())
9523  {
9524  octave_value_list args;
9525  octave_function *fcn = 0;
9526 
9527  args(0) = h.as_octave_value ();
9528  if (data.is_defined ())
9529  args(1) = data;
9530  else
9531  args(1) = Matrix ();
9532 
9533  unwind_protect_safe frame;
9535 
9536  if (true)
9537  {
9538  gh_manager::auto_lock guard;
9539 
9540  callback_objects.push_front (get_object (h));
9541  xset_gcbo (h);
9542  }
9543 
9544  BEGIN_INTERRUPT_WITH_EXCEPTIONS;
9545 
9546  // Copy CB because "function_value" method is non-const.
9547 
9548  octave_value cb = cb_arg;
9549 
9550  if (cb.is_function () || cb.is_function_handle ())
9551  fcn = cb.function_value ();
9552  else if (cb.is_string ())
9553  {
9554  int status;
9555  std::string s = cb.string_value ();
9556 
9557  eval_string (s, false, status, 0);
9558  }
9559  else if (cb.is_cell () && cb.length () > 0
9560  && (cb.rows () == 1 || cb.columns () == 1)
9561  && (cb.cell_value ()(0).is_function ()
9562  || cb.cell_value ()(0).is_function_handle ()))
9563  {
9564  Cell c = cb.cell_value ();
9565 
9566  fcn = c(0).function_value ();
9567  if (! error_state)
9568  {
9569  for (int i = 1; i < c.length () ; i++)
9570  args(1+i) = c(i);
9571  }
9572  }
9573  else
9574  {
9575  std::string nm = cb.class_name ();
9576  error ("trying to execute non-executable object (class = %s)",
9577  nm.c_str ());
9578  }
9579 
9580  if (fcn && ! error_state)
9581  feval (fcn, args);
9582 
9583  END_INTERRUPT_WITH_EXCEPTIONS;
9584  }
9585 }
9586 
9587 void
9589 {
9590  event_queue.push_back (e);
9591 
9593 }
9594 
9595 void
9596 gh_manager::do_post_callback (const graphics_handle& h, const std::string& name,
9597  const octave_value& data)
9598 {
9599  gh_manager::auto_lock guard;
9600 
9601  graphics_object go = get_object (h);
9602 
9603  if (go.valid_object ())
9604  {
9605  if (callback_objects.empty ())
9607  else
9608  {
9609  const graphics_object& current = callback_objects.front ();
9610 
9611  if (current.get_properties ().is_interruptible ())
9613  data));
9614  else
9615  {
9616  caseless_str busy_action (go.get_properties ().get_busyaction ());
9617 
9618  if (busy_action.compare ("queue"))
9620  data));
9621  else
9622  {
9623  caseless_str cname (name);
9624 
9625  if (cname.compare ("deletefcn") || cname.compare ("createfcn")
9626  || (go.isa ("figure")
9627  && (cname.compare ("closerequestfcn")
9628  || cname.compare ("resizefcn"))))
9629  do_post_event (
9630  graphics_event::create_callback_event (h, name, data));
9631  }
9632  }
9633  }
9634  }
9635 }
9636 
9637 void
9639 {
9640  gh_manager::auto_lock guard;
9641 
9643 }
9644 
9645 void
9646 gh_manager::do_post_set (const graphics_handle& h, const std::string& name,
9647  const octave_value& value, bool notify_toolkit)
9648 {
9649  gh_manager::auto_lock guard;
9650 
9652  notify_toolkit));
9653 }
9654 
9655 int
9657 {
9658  graphics_event e;
9659  bool old_Vdrawnow_requested = Vdrawnow_requested;
9660  bool events_executed = false;
9661 
9662  do
9663  {
9664  e = graphics_event ();
9665 
9666  gh_manager::lock ();
9667 
9668  if (! event_queue.empty ())
9669  {
9670  if (callback_objects.empty () || force)
9671  {
9672  e = event_queue.front ();
9673 
9674  event_queue.pop_front ();
9675  }
9676  else
9677  {
9678  const graphics_object& go = callback_objects.front ();
9679 
9680  if (go.get_properties ().is_interruptible ())
9681  {
9682  e = event_queue.front ();
9683 
9684  event_queue.pop_front ();
9685  }
9686  }
9687  }
9688 
9689  gh_manager::unlock ();
9690 
9691  if (e.ok ())
9692  {
9693  e.execute ();
9694  events_executed = true;
9695  }
9696  }
9697  while (e.ok ());
9698 
9699  gh_manager::lock ();
9700 
9701  if (event_queue.empty () && event_processing == 0)
9703 
9704  gh_manager::unlock ();
9705 
9706  if (events_executed)
9708 
9709  if (Vdrawnow_requested && ! old_Vdrawnow_requested)
9710  {
9711  Fdrawnow ();
9712 
9713  Vdrawnow_requested = false;
9714  }
9715 
9716  return 0;
9717 }
9718 
9719 void
9721 {
9722  gh_manager::auto_lock guard;
9723 
9724  if (enable)
9725  {
9726  event_processing++;
9727 
9729  }
9730  else
9731  {
9732  event_processing--;
9733 
9734  if (event_queue.empty () && event_processing == 0)
9736  }
9737 }
9738 
9741 {
9743 
9744  plist_map["figure"] = figure::properties::factory_defaults ();
9745  plist_map["axes"] = axes::properties::factory_defaults ();
9746  plist_map["line"] = line::properties::factory_defaults ();
9747  plist_map["text"] = text::properties::factory_defaults ();
9748  plist_map["image"] = image::properties::factory_defaults ();
9749  plist_map["patch"] = patch::properties::factory_defaults ();
9750  plist_map["surface"] = surface::properties::factory_defaults ();
9751  plist_map["hggroup"] = hggroup::properties::factory_defaults ();
9752  plist_map["uimenu"] = uimenu::properties::factory_defaults ();
9753  plist_map["uicontrol"] = uicontrol::properties::factory_defaults ();
9754  plist_map["uipanel"] = uipanel::properties::factory_defaults ();
9755  plist_map["uicontextmenu"] = uicontextmenu::properties::factory_defaults ();
9756  plist_map["uitoolbar"] = uitoolbar::properties::factory_defaults ();
9757  plist_map["uipushtool"] = uipushtool::properties::factory_defaults ();
9758  plist_map["uitoggletool"] = uitoggletool::properties::factory_defaults ();
9759 
9760  return plist_map;
9761 }
9762 
9763 // ---------------------------------------------------------------------
9764 
9765 DEFUN (ishandle, args, ,
9766  "-*- texinfo -*-\n\
9767 @deftypefn {Built-in Function} {} ishandle (@var{h})\n\
9768 Return true if @var{h} is a graphics handle and false otherwise.\n\
9769 \n\
9770 @var{h} may also be a matrix of handles in which case a logical array is\n\
9771 returned that is true where the elements of @var{h} are graphics handles and\n\
9772 false where they are not.\n\
9773 @seealso{isaxes, isfigure}\n\
9774 @end deftypefn")
9775 {
9776  gh_manager::auto_lock guard;
9777 
9778  octave_value retval;
9779 
9780  if (args.length () == 1)
9781  retval = is_handle (args(0));
9782  else
9783  print_usage ();
9784 
9785  return retval;
9786 }
9787 
9788 static bool
9790 {
9791  return h.ok () && gh_manager::is_handle_visible (h);
9792 }
9793 
9794 static bool
9795 is_handle_visible (double val)
9796 {
9797  return is_handle_visible (gh_manager::lookup (val));
9798 }
9799 
9800 static octave_value
9802 {
9803  octave_value retval = false;
9804 
9805  if (val.is_real_scalar () && is_handle_visible (val.double_value ()))
9806  retval = true;
9807  else if (val.is_numeric_type () && val.is_real_type ())
9808  {
9809  const NDArray handles = val.array_value ();
9810 
9811  if (! error_state)
9812  {
9813  boolNDArray result (handles.dims ());
9814 
9815  for (octave_idx_type i = 0; i < handles.numel (); i++)
9816  result.xelem (i) = is_handle_visible (handles (i));
9817 
9818  retval = result;
9819  }
9820  }
9821 
9822  return retval;
9823 }
9824 
9825 DEFUN (__is_handle_visible__, args, ,
9826  "-*- texinfo -*-\n\
9827 @deftypefn {Built-in Function} {} __is_handle_visible__ (@var{h})\n\
9828 Undocumented internal function.\n\
9829 @end deftypefn")
9830 {
9831  octave_value retval;
9832 
9833  if (args.length () == 1)
9834  retval = is_handle_visible (args(0));
9835  else
9836  print_usage ();
9837 
9838  return retval;
9839 }
9840 
9841 DEFUN (reset, args, ,
9842  "-*- texinfo -*-\n\
9843 @deftypefn {Built-in Function} {} reset (@var{h})\n\
9844 Reset the properties of the graphic object @var{h} to their default values.\n\
9845 \n\
9846 For figures, the properties @qcode{\"position\"}, @qcode{\"units\"},\n\
9847 @qcode{\"windowstyle\"}, and @qcode{\"paperunits\"} are not affected.\n\
9848 For axes, the properties @qcode{\"position\"} and @qcode{\"units\"} are\n\
9849 not affected.\n\
9850 \n\
9851 The input @var{h} may also be a vector of graphic handles in which case\n\
9852 each individual object will be reset.\n\
9853 @seealso{cla, clf, newplot}\n\
9854 @end deftypefn")
9855 {
9856  int nargin = args.length ();
9857 
9858  if (nargin != 1)
9859  print_usage ();
9860  else
9861  {
9862  // get vector of graphics handles
9863  ColumnVector hcv (args(0).vector_value ());
9864 
9865  if (! error_state)
9866  {
9867  // loop over graphics objects
9868  for (octave_idx_type n = 0; n < hcv.length (); n++)
9869  gh_manager::get_object (hcv(n)).reset_default_properties ();
9870 
9871  if (! error_state)
9872  Fdrawnow ();
9873  }
9874  }
9875 
9876  return octave_value ();
9877 }
9878 
9879 /*
9880 
9881 %!test # line object
9882 %! hf = figure ("visible", "off");
9883 %! unwind_protect
9884 %! tol = 20 * eps;
9885 %! hax = axes ("defaultlinelinewidth", 3);
9886 %!
9887 %! hli = line (1:10, 1:10, 1:10, "marker", "o",
9888 %! "markerfacecolor", "b", "linestyle", ":");
9889 %!
9890 %! reset (hli);
9891 %! assert (get (hli, "marker"), get (0, "defaultlinemarker"));
9892 %! assert (get (hli, "markerfacecolor"),
9893 %! get (0, "defaultlinemarkerfacecolor"));
9894 %! assert (get (hli, "linestyle"),
9895 %! get (0, "defaultlinelinestyle"));
9896 %! assert (get (hli, "linewidth"), 3, tol); # parent axes defaults
9897 %!
9898 %! unwind_protect_cleanup
9899 %! close (hf);
9900 %! end_unwind_protect
9901 
9902 %!test # patch object
9903 %! hf = figure ("visible", "off");
9904 %! unwind_protect
9905 %! tol = 20 * eps;
9906 %! t1 = (1/16:1/8:1)' * 2*pi;
9907 %! t2 = ((1/16:1/16:1)' + 1/32) * 2*pi;
9908 %! x1 = sin (t1) - 0.8;
9909 %! y1 = cos (t1);
9910 %! x2 = sin (t2) + 0.8;
9911 %! y2 = cos (t2);
9912 %! vert = [x1, y1; x2, y2];
9913 %! fac = [1:8,NaN(1,8);9:24];
9914 %! hpa = patch ("Faces",fac, "Vertices",vert, "FaceColor","r");
9915 %!
9916 %! reset (hpa);
9917 %! assert (get (hpa, "faces"), get (0, "defaultpatchfaces"), tol);
9918 %! assert (get (hpa, "vertices"), get (0, "defaultpatchvertices"), tol);
9919 %! assert (get (hpa, "facevertexcdata"),
9920 %! get (0, "defaultpatchfacevertexcdata"), tol);
9921 %! unwind_protect_cleanup
9922 %! close (hf);
9923 %! end_unwind_protect
9924 
9925 %!test # surface object
9926 %! hf = figure ("visible", "off");
9927 %! unwind_protect
9928 %! tol = 20 * eps;
9929 %! hsu = surface (peaks, "edgecolor", "none");
9930 %!
9931 %! reset (hsu);
9932 %! assert (get (hsu, "xdata"), get (0, "defaultsurfacexdata"), tol);
9933 %! assert (get (hsu, "ydata"), get (0, "defaultsurfaceydata"), tol);
9934 %! assert (get (hsu, "zdata"), get (0, "defaultsurfacezdata"), tol);
9935 %! assert (get (hsu, "edgecolor"),
9936 %! get (0, "defaultsurfaceedgecolor"), tol);
9937 %! unwind_protect_cleanup
9938 %! close (hf);
9939 %! end_unwind_protect
9940 
9941 %!test # image object
9942 %! hf = figure ("visible", "off");
9943 %! unwind_protect
9944 %! tol = 20 * eps;
9945 %! him = image (rand (10,10), "cdatamapping", "scaled");
9946 %!
9947 %! reset (him);
9948 %! assert (get (him, "cdata"), get (0, "defaultimagecdata"), tol);
9949 %! assert (get (him, "cdatamapping"),
9950 %! get (0, "defaultimagecdatamapping"), tol);
9951 %! unwind_protect_cleanup
9952 %! close (hf);
9953 %! end_unwind_protect
9954 
9955 %!test # text object
9956 %! hf = figure ("visible", "off");
9957 %! unwind_protect
9958 %! tol = 20 * eps;
9959 %! hte = text (5, 5, "Hi!", "fontsize", 20 ,"color", "r");
9960 %!
9961 %! reset (hte);
9962 %! assert (get (hte, "position"), get (0, "defaulttextposition"), tol);
9963 %! assert (get (hte, "fontsize"), get (0, "defaulttextfontsize"), tol);
9964 %! assert (get (hte, "color"), get (0, "defaulttextcolor"), tol);
9965 %! unwind_protect_cleanup
9966 %! close (hf);
9967 %! end_unwind_protect
9968 
9969 %!test # axes object
9970 %! hf = figure ("visible", "off");
9971 %! unwind_protect
9972 %! tol = 20 * eps;
9973 %! pos = get (0, "defaultaxesposition") * .5;
9974 %! hax = axes ("linewidth", 2, "position", pos);
9975 %! title ("Reset me, please!");
9976 %!
9977 %! reset (hax);
9978 %! assert (get (hax, "linewidth"), get (0, "defaultaxeslinewidth"), tol);
9979 %! assert (get (hax, "position"), pos, tol); # axes position is unchanged
9980 %! assert (get (hax, "default"), struct ()); # no more axes' defaults
9981 %! assert (get (get (hax, "title"), "string"), "");
9982 %! unwind_protect_cleanup
9983 %! close (hf);
9984 %! end_unwind_protect
9985 
9986 %!test # root figure object
9987 %! set (0, "defaultfigurevisible", "off");
9988 %! hf = figure ("visible", "off", "paperunits", "centimeters",
9989 %! "papertype", "a4");
9990 %! unwind_protect
9991 %! reset (hf);
9992 %! assert (get (hf, "papertype"), get (0, "defaultfigurepapertype"));
9993 %! assert (get (hf, "paperunits"), "centimeters"); # paperunits is unchanged
9994 %! assert (get (hf, "visible"), get (0, "defaultfigurevisible"));
9995 %! unwind_protect_cleanup
9996 %! close (hf);
9997 %! set (0, "defaultfigurevisible", "remove");
9998 %! end_unwind_protect
9999 
10000 */
10001 
10002 DEFUN (set, args, nargout,
10003  "-*- texinfo -*-\n\
10004 @deftypefn {Built-in Function} {} set (@var{h}, @var{property}, @var{value}, @dots{})\n\
10005 @deftypefnx {Built-in Function} {} set (@var{h}, @var{properties}, @var{values})\n\
10006 @deftypefnx {Built-in Function} {} set (@var{h}, @var{pv})\n\
10007 @deftypefnx {Built-in Function} {@var{value_list} =} set (@var{h}, @var{property})\n\
10008 @deftypefnx {Built-in Function} {@var{all_value_list} =} set (@var{h})\n\
10009 Set named property values for the graphics handle (or vector of graphics\n\
10010 handles) @var{h}.\n\
10011 \n\
10012 There are three ways to give the property names and values:\n\
10013 \n\
10014 @itemize\n\
10015 @item as a comma separated list of @var{property}, @var{value} pairs\n\
10016 \n\
10017 Here, each @var{property} is a string containing the property name, each\n\
10018 @var{value} is a value of the appropriate type for the property.\n\
10019 \n\
10020 @item as a cell array of strings @var{properties} containing property names\n\
10021 and a cell array @var{values} containing property values.\n\
10022 \n\
10023 In this case, the number of columns of @var{values} must match the number of\n\
10024 elements in @var{properties}. The first column of @var{values} contains\n\
10025 values for the first entry in @var{properties}, etc. The number of rows of\n\
10026 @var{values} must be 1 or match the number of elements of @var{h}. In the\n\
10027 first case, each handle in @var{h} will be assigned the same values. In the\n\
10028 latter case, the first handle in @var{h} will be assigned the values from\n\
10029 the first row of @var{values} and so on.\n\
10030 \n\
10031 @item as a structure array @var{pv}\n\
10032 \n\
10033 Here, the field names of @var{pv} represent the property names, and the field\n\
10034 values give the property values. In contrast to the previous case, all\n\
10035 elements of @var{pv} will be set in all handles in @var{h} independent of\n\
10036 the dimensions of @var{pv}.\n\
10037 @end itemize\n\
10038 \n\
10039 @code{set} is also used to query the list of values a named property will\n\
10040 take. @code{@var{clist} = set (@var{h}, \"property\")} will return the list\n\
10041 of possible values for @qcode{\"property\"} in the cell list @var{clist}.\n\
10042 If no output variable is used then the list is formatted and printed to the\n\
10043 screen.\n\
10044 \n\
10045 If no property is specified (@code{@var{slist} = set (@var{h})}) then a\n\
10046 structure @var{slist} is returned where the fieldnames are the properties of\n\
10047 the object @var{h} and the fields are the list of possible values for each\n\
10048 property. If no output variable is used then the list is formatted and\n\
10049 printed to the screen.\n\
10050 \n\
10051 For example,\n\
10052 \n\
10053 @example\n\
10054 @group\n\
10055 hf = figure ();\n\
10056 set (hf, \"paperorientation\")\n\
10057 @result{} paperorientation: [ landscape | @{portrait@} | rotated ]\n\
10058 @end group\n\
10059 @end example\n\
10060 \n\
10061 @noindent\n\
10062 shows the paperorientation property can take three values with the default\n\
10063 being @qcode{\"portrait\"}.\n\
10064 @seealso{get}\n\
10065 @end deftypefn")
10066 {
10067  gh_manager::auto_lock guard;
10068 
10069  octave_value retval;
10070 
10071  int nargin = args.length ();
10072 
10073  if (nargin > 0)
10074  {
10075  // get vector of graphics handles
10076  ColumnVector hcv (args(0).vector_value ());
10077 
10078  if (! error_state)
10079  {
10080  bool request_drawnow = false;
10081 
10082  // loop over graphics objects
10083  for (octave_idx_type n = 0; n < hcv.length (); n++)
10084  {
10085  graphics_object obj = gh_manager::get_object (hcv(n));
10086 
10087  if (obj)
10088  {
10089  if (nargin == 3 && args(1).is_cellstr ()
10090  && args(2).is_cell ())
10091  {
10092  if (args(2).cell_value ().rows () == 1)
10093  {
10094  obj.set (args(1).cellstr_value (),
10095  args(2).cell_value (), 0);
10096  }
10097  else if (hcv.length () == args(2).cell_value ().rows ())
10098  {
10099  obj.set (args(1).cellstr_value (),
10100  args(2).cell_value (), n);
10101  }
10102  else
10103  {
10104  error ("set: number of graphics handles must match number of value rows (%d != %d)",
10105  hcv.length (), args(2).cell_value ().rows ());
10106  break;
10107 
10108  }
10109  }
10110  else if (nargin == 2 && args(1).is_map ())
10111  {
10112  obj.set (args(1).map_value ());
10113  }
10114  else if (nargin == 2 && args(1).is_string ())
10115  {
10116  std::string property = args(1).string_value ();
10117 
10118  octave_map pmap = obj.values_as_struct ();
10119 
10120  if (obj.has_readonly_property (property))
10121  if (nargout != 0)
10122  retval = Matrix ();
10123  else
10124  octave_stdout << "set: " << property
10125  <<" is read-only" << std::endl;
10126  else if (pmap.isfield (property))
10127  {
10128  if (nargout != 0)
10129  retval = pmap.getfield (property)(0);
10130  else
10131  {
10132  std::string s = obj.value_as_string (property);
10133  if (! error_state)
10134  octave_stdout << s;
10135  }
10136  }
10137  else
10138  {
10139  error ("set: unknown property");
10140  break;
10141  }
10142  }
10143  else if (nargin == 1)
10144  {
10145  if (nargout != 0)
10146  retval = obj.values_as_struct ();
10147  else
10148  {
10149  std::string s = obj.values_as_string ();
10150  if (! error_state)
10151  octave_stdout << s;
10152  }
10153  }
10154  else
10155  {
10156  obj.set (args.splice (0, 1));
10157  request_drawnow = true;
10158  }
10159  }
10160  else
10161  {
10162  error ("set: invalid handle (= %g)", hcv(n));
10163  break;
10164  }
10165 
10166  if (error_state)
10167  break;
10168 
10169  request_drawnow = true;
10170  }
10171 
10172  if (! error_state && request_drawnow)
10173  Vdrawnow_requested = true;
10174  }
10175  else
10176  error ("set: expecting graphics handle as first argument");
10177  }
10178  else
10179  print_usage ();
10180 
10181  return retval;
10182 }
10183 
10184 static std::string
10186 {
10187  std::string retval;
10188 
10190 
10191  if (obj)
10192  retval = obj.type ();
10193  else
10194  error ("get: invalid handle (= %g)", val);
10195 
10196  return retval;
10197 }
10198 
10199 DEFUN (get, args, ,
10200  "-*- texinfo -*-\n\
10201 @deftypefn {Built-in Function} {@var{val} =} get (@var{h})\n\
10202 @deftypefnx {Built-in Function} {@var{val} =} get (@var{h}, @var{p})\n\
10203 Return the value of the named property @var{p} from the graphics handle\n\
10204 @var{h}.\n\
10205 \n\
10206 If @var{p} is omitted, return the complete property list for @var{h}.\n\
10207 \n\
10208 If @var{h} is a vector, return a cell array including the property values or\n\
10209 lists respectively.\n\
10210 @seealso{set}\n\
10211 @end deftypefn")
10212 {
10213  gh_manager::auto_lock guard;
10214 
10215  octave_value retval;
10216 
10217  Cell vals;
10218 
10219  int nargin = args.length ();
10220 
10221  bool use_cell_format = false;
10222 
10223  if (nargin == 1 || nargin == 2)
10224  {
10225  if (args(0).is_empty ())
10226  {
10227  retval = Matrix ();
10228  return retval;
10229  }
10230 
10231  ColumnVector hcv (args(0).vector_value ());
10232 
10233  if (! error_state)
10234  {
10235  octave_idx_type len = hcv.length ();
10236 
10237  if (nargin == 1 && len > 1)
10238  {
10239  std::string t0 = get_graphics_object_type (hcv(0));
10240 
10241  if (! error_state)
10242  {
10243  for (octave_idx_type n = 1; n < len; n++)
10244  {
10245  std::string t = get_graphics_object_type (hcv(n));
10246 
10247  if (error_state)
10248  break;
10249 
10250  if (t != t0)
10251  {
10252  error ("get: vector of handles must all have same type");
10253  break;
10254  }
10255  }
10256 
10257  }
10258  }
10259 
10260  if (! error_state)
10261  {
10262  if (nargin > 1 && args(1).is_cellstr ())
10263  {
10264  Array<std::string> plist = args(1).cellstr_value ();
10265 
10266  if (! error_state)
10267  {
10268  octave_idx_type plen = plist.numel ();
10269 
10270  use_cell_format = true;
10271 
10272  vals.resize (dim_vector (len, plen));
10273 
10274  for (octave_idx_type n = 0; ! error_state && n < len; n++)
10275  {
10276  graphics_object obj = gh_manager::get_object (hcv(n));
10277 
10278  if (obj)
10279  {
10280  for (octave_idx_type m = 0;
10281  ! error_state && m < plen;
10282  m++)
10283  {
10284  caseless_str property = plist(m);
10285 
10286  vals(n, m) = obj.get (property);
10287  }
10288  }
10289  else
10290  {
10291  error ("get: invalid handle (= %g)", hcv(n));
10292  break;
10293  }
10294  }
10295  }
10296  else
10297  error ("get: expecting property name or cell array of property names as second argument");
10298  }
10299  else
10300  {
10302 
10303  if (nargin > 1)
10304  {
10305  property = args(1).string_value ();
10306 
10307  if (error_state)
10308  error ("get: expecting property name or cell array of property names as second argument");
10309  }
10310 
10311  vals.resize (dim_vector (len, 1));
10312 
10313  if (! error_state)
10314  {
10315  for (octave_idx_type n = 0; ! error_state && n < len; n++)
10316  {
10317  graphics_object obj = gh_manager::get_object (hcv(n));
10318 
10319  if (obj)
10320  {
10321  if (nargin == 1)
10322  vals(n) = obj.get ();
10323  else
10324  vals(n) = obj.get (property);
10325  }
10326  else
10327  {
10328  error ("get: invalid handle (= %g)", hcv(n));
10329  break;
10330  }
10331  }
10332  }
10333  }
10334  }
10335  }
10336  else
10337  error ("get: expecting graphics handle as first argument");
10338  }
10339  else
10340  print_usage ();
10341 
10342  if (! error_state)
10343  {
10344  if (use_cell_format)
10345  retval = vals;
10346  else
10347  {
10348  octave_idx_type len = vals.numel ();
10349 
10350  if (len == 0)
10351  retval = Matrix ();
10352  else if (len == 1)
10353  retval = vals(0);
10354  else if (len > 1 && nargin == 1)
10355  {
10357 
10358  for (octave_idx_type n = 0; n < len; n++)
10359  tmp[n] = vals(n).scalar_map_value ();
10360 
10361  retval = octave_map::cat (0, len, tmp);
10362  }
10363  else
10364  retval = vals;
10365  }
10366  }
10367 
10368  return retval;
10369 }
10370 
10371 /*
10372 %!assert (get (findobj (0, "Tag", "nonexistenttag"), "nonexistentproperty"), [])
10373 */
10374 
10375 // Return all properties from the graphics handle @var{h}.
10376 // If @var{h} is a vector, return a cell array including the
10377 // property values or lists respectively.
10378 
10379 DEFUN (__get__, args, ,
10380  "-*- texinfo -*-\n\
10381 @deftypefn {Built-in Function} {} __get__ (@var{h})\n\
10382 Undocumented internal function.\n\
10383 @end deftypefn")
10384 {
10385  gh_manager::auto_lock guard;
10386 
10387  octave_value retval;
10388 
10389  Cell vals;
10390 
10391  int nargin = args.length ();
10392 
10393  if (nargin == 1)
10394  {
10395  ColumnVector hcv (args(0).vector_value ());
10396 
10397  if (! error_state)
10398  {
10399  octave_idx_type len = hcv.length ();
10400 
10401  vals.resize (dim_vector (len, 1));
10402 
10403  for (octave_idx_type n = 0; n < len; n++)
10404  {
10405  graphics_object obj = gh_manager::get_object (hcv(n));
10406 
10407  if (obj)
10408  vals(n) = obj.get (true);
10409  else
10410  {
10411  error ("get: invalid handle (= %g)", hcv(n));
10412  break;
10413  }
10414  }
10415  }
10416  else
10417  error ("get: expecting graphics handle as first argument");
10418  }
10419  else
10420  print_usage ();
10421 
10422  if (! error_state)
10423  {
10424  octave_idx_type len = vals.numel ();
10425 
10426  if (len > 1)
10427  retval = vals;
10428  else if (len == 1)
10429  retval = vals(0);
10430  }
10431 
10432  return retval;
10433 }
10434 
10435 static octave_value
10436 make_graphics_object (const std::string& go_name,
10437  bool integer_figure_handle,
10438  const octave_value_list& args)
10439 {
10440  octave_value retval;
10441 
10442  double val = octave_NaN;
10443 
10444  octave_value_list xargs = args.splice (0, 1);
10445 
10446  caseless_str p ("parent");
10447 
10448  for (int i = 0; i < xargs.length (); i++)
10449  if (xargs(i).is_string ()
10450  && p.compare (xargs(i).string_value ()))
10451  {
10452  if (i < (xargs.length () - 1))
10453  {
10454  val = xargs(i+1).double_value ();
10455 
10456  if (! error_state)
10457  {
10458  xargs = xargs.splice (i, 2);
10459  break;
10460  }
10461  }
10462  else
10463  error ("__go_%s__: missing value for parent property",
10464  go_name.c_str ());
10465  }
10466 
10467  if (! error_state && xisnan (val))
10468  val = args(0).double_value ();
10469 
10470  if (! error_state)
10471  {
10472  graphics_handle parent = gh_manager::lookup (val);
10473 
10474  if (parent.ok ())
10475  {
10476  graphics_handle h
10477  = gh_manager::make_graphics_handle (go_name, parent,
10478  integer_figure_handle,
10479  false, false);
10480 
10481  if (! error_state)
10482  {
10483  adopt (parent, h);
10484 
10485  xset (h, xargs);
10486  xcreatefcn (h);
10487  xinitialize (h);
10488 
10489  retval = h.value ();
10490 
10491  if (! error_state)
10492  Vdrawnow_requested = true;
10493  }
10494  else
10495  error ("__go%s__: unable to create graphics handle",
10496  go_name.c_str ());
10497  }
10498  else
10499  error ("__go_%s__: invalid parent", go_name.c_str ());
10500  }
10501  else
10502  error ("__go_%s__: invalid parent", go_name.c_str ());
10503 
10504  return retval;
10505 }
10506 
10507 DEFUN (__go_figure__, args, ,
10508  "-*- texinfo -*-\n\
10509 @deftypefn {Built-in Function} {} __go_figure__ (@var{fignum})\n\
10510 Undocumented internal function.\n\
10511 @end deftypefn")
10512 {
10513  gh_manager::auto_lock guard;
10514 
10515  octave_value retval;
10516 
10517  if (args.length () > 0)
10518  {
10519  double val = args(0).double_value ();
10520 
10521  if (! error_state)
10522  {
10523  if (is_figure (val))
10524  {
10526 
10527  xset (h, args.splice (0, 1));
10528 
10529  retval = h.value ();
10530  }
10531  else
10532  {
10533  bool int_fig_handle = true;
10534 
10535  octave_value_list xargs = args.splice (0, 1);
10536 
10538 
10539  if (xisnan (val))
10540  {
10541  caseless_str p ("integerhandle");
10542 
10543  for (int i = 0; i < xargs.length (); i++)
10544  {
10545  if (xargs(i).is_string ()
10546  && p.compare (xargs(i).string_value ()))
10547  {
10548  if (i < (xargs.length () - 1))
10549  {
10550  std::string pval = xargs(i+1).string_value ();
10551 
10552  if (! error_state)
10553  {
10554  caseless_str on ("on");
10555  int_fig_handle = on.compare (pval);
10556  xargs = xargs.splice (i, 2);
10557  break;
10558  }
10559  }
10560  }
10561  }
10562 
10563  h = gh_manager::make_graphics_handle ("figure", 0,
10564  int_fig_handle,
10565  false, false);
10566 
10567  if (! int_fig_handle)
10568  {
10569  // We need to intiailize the integerhandle
10570  // property without calling the set_integerhandle
10571  // method, because doing that will generate a new
10572  // handle value...
10573 
10575  go.get_properties ().init_integerhandle ("off");
10576  }
10577  }
10578  else if (val > 0 && D_NINT (val) == val)
10579  h = gh_manager::make_figure_handle (val, false);
10580 
10581  if (! error_state && h.ok ())
10582  {
10583  adopt (0, h);
10584 
10586 
10587  xset (h, xargs);
10588  xcreatefcn (h);
10589  xinitialize (h);
10590 
10591  retval = h.value ();
10592  }
10593  else
10594  error ("__go_figure__: failed to create figure handle");
10595  }
10596  }
10597  else
10598  error ("__go_figure__: expecting figure number to be double value");
10599  }
10600  else
10601  print_usage ();
10602 
10603  return retval;
10604 }
10605 
10606 #define GO_BODY(TYPE) \
10607  gh_manager::auto_lock guard; \
10608  \
10609  octave_value retval; \
10610  \
10611  if (args.length () > 0) \
10612  retval = make_graphics_object (#TYPE, false, args); \
10613  else \
10614  print_usage (); \
10615  \
10616  return retval
10617 
10618 int
10620 {
10621 
10622  int nd = 2;
10623 
10624  if (go.isa ("surface"))
10625  nd = 3;
10626  else if ((go.isa ("line") || go.isa ("patch"))
10627  && ! go.get ("zdata").is_empty ())
10628  nd = 3;
10629  else
10630  {
10631  Matrix kids = go.get_properties ().get_children ();
10632 
10633  for (octave_idx_type i = 0; i < kids.length (); i++)
10634  {
10635  graphics_handle hnd = gh_manager::lookup (kids(i));
10636 
10637  if (hnd.ok ())
10638  {
10639  const graphics_object& kid = gh_manager::get_object (hnd);
10640 
10641  if (kid.valid_object ())
10642  nd = calc_dimensions (kid);
10643 
10644  if (nd == 3)
10645  break;
10646  }
10647  }
10648  }
10649 
10650  return nd;
10651 }
10652 
10653 DEFUN (__calc_dimensions__, args, ,
10654  "-*- texinfo -*-\n\
10655 @deftypefn {Built-in Function} {} __calc_dimensions__ (@var{axes})\n\
10656 Internal function.\n\
10657 \n\
10658 Determine the number of dimensions in a graphics object, either 2 or 3.\n\
10659 @end deftypefn")
10660 {
10661  gh_manager::auto_lock guard;
10662 
10663  octave_value retval;
10664 
10665  int nargin = args.length ();
10666 
10667  if (nargin == 1)
10668  {
10669  double h = args(0).double_value ();
10670  if (! error_state)
10671  retval = calc_dimensions (gh_manager::get_object (h));
10672  else
10673  error ("__calc_dimensions__: expecting graphics handle as only argument");
10674  }
10675  else
10676  print_usage ();
10677 
10678  return retval;
10679 }
10680 
10681 DEFUN (__go_axes__, args, ,
10682  "-*- texinfo -*-\n\
10683 @deftypefn {Built-in Function} {} __go_axes__ (@var{parent})\n\
10684 Undocumented internal function.\n\
10685 @end deftypefn")
10686 {
10687  GO_BODY (axes);
10688 }
10689 
10690 DEFUN (__go_line__, args, ,
10691  "-*- texinfo -*-\n\
10692 @deftypefn {Built-in Function} {} __go_line__ (@var{parent})\n\
10693 Undocumented internal function.\n\
10694 @end deftypefn")
10695 {
10696  GO_BODY (line);
10697 }
10698 
10699 DEFUN (__go_text__, args, ,
10700  "-*- texinfo -*-\n\
10701 @deftypefn {Built-in Function} {} __go_text__ (@var{parent})\n\
10702 Undocumented internal function.\n\
10703 @end deftypefn")
10704 {
10705  GO_BODY (text);
10706 }
10707 
10708 DEFUN (__go_image__, args, ,
10709  "-*- texinfo -*-\n\
10710 @deftypefn {Built-in Function} {} __go_image__ (@var{parent})\n\
10711 Undocumented internal function.\n\
10712 @end deftypefn")
10713 {
10714  GO_BODY (image);
10715 }
10716 
10717 DEFUN (__go_surface__, args, ,
10718  "-*- texinfo -*-\n\
10719 @deftypefn {Built-in Function} {} __go_surface__ (@var{parent})\n\
10720 Undocumented internal function.\n\
10721 @end deftypefn")
10722 {
10723  GO_BODY (surface);
10724 }
10725 
10726 DEFUN (__go_patch__, args, ,
10727  "-*- texinfo -*-\n\
10728 @deftypefn {Built-in Function} {} __go_patch__ (@var{parent})\n\
10729 Undocumented internal function.\n\
10730 @end deftypefn")
10731 {
10732  GO_BODY (patch);
10733 }
10734 
10735 DEFUN (__go_hggroup__, args, ,
10736  "-*- texinfo -*-\n\
10737 @deftypefn {Built-in Function} {} __go_hggroup__ (@var{parent})\n\
10738 Undocumented internal function.\n\
10739 @end deftypefn")
10740 {
10741  GO_BODY (hggroup);
10742 }
10743 
10744 DEFUN (__go_uimenu__, args, ,
10745  "-*- texinfo -*-\n\
10746 @deftypefn {Built-in Function} {} __go_uimenu__ (@var{parent})\n\
10747 Undocumented internal function.\n\
10748 @end deftypefn")
10749 {
10750  GO_BODY (uimenu);
10751 }
10752 
10753 DEFUN (__go_uicontrol__, args, ,
10754  "-*- texinfo -*-\n\
10755 @deftypefn {Built-in Function} {} __go_uicontrol__ (@var{parent})\n\
10756 Undocumented internal function.\n\
10757 @end deftypefn")
10758 {
10759  GO_BODY (uicontrol);
10760 }
10761 
10762 DEFUN (__go_uipanel__, args, ,
10763  "-*- texinfo -*-\n\
10764 @deftypefn {Built-in Function} {} __go_uipanel__ (@var{parent})\n\
10765 Undocumented internal function.\n\
10766 @end deftypefn")
10767 {
10768  GO_BODY (uipanel);
10769 }
10770 
10771 DEFUN (__go_uicontextmenu__, args, ,
10772  "-*- texinfo -*-\n\
10773 @deftypefn {Built-in Function} {} __go_uicontextmenu__ (@var{parent})\n\
10774 Undocumented internal function.\n\
10775 @end deftypefn")
10776 {
10778 }
10779 
10780 DEFUN (__go_uitoolbar__, args, ,
10781  "-*- texinfo -*-\n\
10782 @deftypefn {Built-in Function} {} __go_uitoolbar__ (@var{parent})\n\
10783 Undocumented internal function.\n\
10784 @end deftypefn")
10785 {
10786  GO_BODY (uitoolbar);
10787 }
10788 
10789 DEFUN (__go_uipushtool__, args, ,
10790  "-*- texinfo -*-\n\
10791 @deftypefn {Built-in Function} {} __go_uipushtool__ (@var{parent})\n\
10792 Undocumented internal function.\n\
10793 @end deftypefn")
10794 {
10795  GO_BODY (uipushtool);
10796 }
10797 
10798 DEFUN (__go_uitoggletool__, args, ,
10799  "-*- texinfo -*-\n\
10800 @deftypefn {Built-in Function} {} __go_uitoggletool__ (@var{parent})\n\
10801 Undocumented internal function.\n\
10802 @end deftypefn")
10803 {
10805 }
10806 
10807 DEFUN (__go_delete__, args, ,
10808  "-*- texinfo -*-\n\
10809 @deftypefn {Built-in Function} {} __go_delete__ (@var{h})\n\
10810 Undocumented internal function.\n\
10811 @end deftypefn")
10812 {
10813  gh_manager::auto_lock guard;
10814 
10815  octave_value_list retval;
10816 
10817  if (args.length () == 1)
10818  {
10820 
10821  const NDArray vals = args(0).array_value ();
10822 
10823  if (! error_state)
10824  {
10825  // Check is all the handles to delete are valid first
10826  // as callbacks might delete one of the handles we
10827  // later want to delete
10828  for (octave_idx_type i = 0; i < vals.numel (); i++)
10829  {
10830  h = gh_manager::lookup (vals.elem (i));
10831 
10832  if (! h.ok ())
10833  {
10834  error ("delete: invalid graphics object (= %g)",
10835  vals.elem (i));
10836  break;
10837  }
10838  }
10839 
10840  if (! error_state)
10841  delete_graphics_objects (vals);
10842  }
10843  else
10844  error ("delete: invalid graphics object");
10845  }
10846  else
10847  print_usage ();
10848 
10849  return retval;
10850 }
10851 
10852 DEFUN (__go_axes_init__, args, ,
10853  "-*- texinfo -*-\n\
10854 @deftypefn {Built-in Function} {} __go_axes_init__ (@var{h}, @var{mode})\n\
10855 Undocumented internal function.\n\
10856 @end deftypefn")
10857 {
10858  gh_manager::auto_lock guard;
10859 
10860  octave_value retval;
10861 
10862  int nargin = args.length ();
10863 
10864  std::string mode = "";
10865 
10866  if (nargin == 2)
10867  {
10868  mode = args(1).string_value ();
10869 
10870  if (error_state)
10871  return retval;
10872  }
10873 
10874  if (nargin == 1 || nargin == 2)
10875  {
10877 
10878  double val = args(0).double_value ();
10879 
10880  if (! error_state)
10881  {
10882  h = gh_manager::lookup (val);
10883 
10884  if (h.ok ())
10885  {
10887 
10888  obj.set_defaults (mode);
10889 
10890  h = gh_manager::lookup (val);
10891  if (! h.ok ())
10892  error ("__go_axes_init__: axis deleted during initialization (= %g)",
10893  val);
10894  }
10895  else
10896  error ("__go_axes_init__: invalid graphics object (= %g)", val);
10897  }
10898  else
10899  error ("__go_axes_init__: invalid graphics object");
10900  }
10901  else
10902  print_usage ();
10903 
10904  return retval;
10905 }
10906 
10907 DEFUN (__go_handles__, args, ,
10908  "-*- texinfo -*-\n\
10909 @deftypefn {Built-in Function} {} __go_handles__ (@var{show_hidden})\n\
10910 Undocumented internal function.\n\
10911 @end deftypefn")
10912 {
10913  gh_manager::auto_lock guard;
10914 
10915  bool show_hidden = false;
10916 
10917  if (args.length () > 0)
10918  show_hidden = args(0).bool_value ();
10919 
10920  return octave_value (gh_manager::handle_list (show_hidden));
10921 }
10922 
10923 DEFUN (__go_figure_handles__, args, ,
10924  "-*- texinfo -*-\n\
10925 @deftypefn {Built-in Function} {} __go_figure_handles__ (@var{show_hidden})\n\
10926 Undocumented internal function.\n\
10927 @end deftypefn")
10928 {
10929  gh_manager::auto_lock guard;
10930 
10931  bool show_hidden = false;
10932 
10933  if (args.length () > 0)
10934  show_hidden = args(0).bool_value ();
10935 
10936  return octave_value (gh_manager::figure_handle_list (show_hidden));
10937 }
10938 
10939 DEFUN (__go_execute_callback__, args, ,
10940  "-*- texinfo -*-\n\
10941 @deftypefn {Built-in Function} {} __go_execute_callback__ (@var{h}, @var{name})\n\
10942 @deftypefnx {Built-in Function} {} __go_execute_callback__ (@var{h}, @var{name}, @var{param})\n\
10943 Undocumented internal function.\n\
10944 @end deftypefn")
10945 {
10946  octave_value retval;
10947 
10948  int nargin = args.length ();
10949 
10950  if (nargin == 2 || nargin == 3)
10951  {
10952  double val = args(0).double_value ();
10953 
10954  if (! error_state)
10955  {
10957 
10958  if (h.ok ())
10959  {
10960  std::string name = args(1).string_value ();
10961 
10962  if (! error_state)
10963  {
10964  if (nargin == 2)
10965  gh_manager::execute_callback (h, name);
10966  else
10967  gh_manager::execute_callback (h, name, args(2));
10968  }
10969  else
10970  error ("__go_execute_callback__: invalid callback name");
10971  }
10972  else
10973  error ("__go_execute_callback__: invalid graphics object (= %g)",
10974  val);
10975  }
10976  else
10977  error ("__go_execute_callback__: invalid graphics object");
10978  }
10979  else
10980  print_usage ();
10981 
10982  return retval;
10983 }
10984 
10985 DEFUN (__image_pixel_size__, args, ,
10986  "-*- texinfo -*-\n\
10987 @deftypefn {Built-in Function} {@var{px}, @var{py}} __image_pixel_size__ (@var{h})\n\
10988 Internal function: returns the pixel size of the image in normalized units.\n\
10989 @end deftypefn")
10990 {
10991  octave_value retval;
10992 
10993  int nargin = args.length ();
10994 
10995  if (nargin == 1)
10996  {
10997  double h = args(0).double_value ();
10998 
10999  if (! error_state)
11000  {
11002  if (fobj && fobj.isa ("image"))
11003  {
11004  image::properties& ip =
11005  dynamic_cast<image::properties&> (fobj.get_properties ());
11006 
11007  Matrix dp = Matrix (1, 2, 0);
11008  dp(0, 0) = ip.pixel_xsize ();
11009  dp(0, 1) = ip.pixel_ysize ();
11010  retval = dp;
11011  }
11012  else
11013  error ("__image_pixel_size__: object is not an image");
11014  }
11015  else
11016  error ("__image_pixel_size__: argument is not a handle");
11017  }
11018  else
11019  print_usage ();
11020 
11021  return retval;
11022 }
11023 
11025 
11026 void
11028 {
11029  instance = new gtk_manager ();
11030 
11031  if (instance)
11033 }
11034 
11037 {
11038  graphics_toolkit retval;
11039 
11040  if (! dtk.empty ())
11041  {
11043 
11044  if (pl == loaded_toolkits.end ())
11045  {
11047 
11048  if (pa != available_toolkits.end ())
11049  {
11050  octave_value_list args;
11051  args(0) = dtk;
11052  feval ("graphics_toolkit", args);
11053 
11054  if (! error_state)
11055  pl = loaded_toolkits.find (dtk);
11056 
11057  if (error_state || pl == loaded_toolkits.end ())
11058  error ("failed to load %s graphics toolkit", dtk.c_str ());
11059  else
11060  retval = pl->second;
11061  }
11062  else
11063  error ("default graphics toolkit '%s' is not available!",
11064  dtk.c_str ());
11065  }
11066  else
11067  retval = pl->second;
11068  }
11069  else
11070  error ("no graphics toolkits are available!");
11071 
11072  return retval;
11073 }
11074 
11075 void
11076 gtk_manager::do_register_toolkit (const std::string& name)
11077 {
11078  if (dtk.empty () || name == "qt"
11079  || (name == "fltk"
11080  && available_toolkits.find ("qt") == available_toolkits.end ()))
11081  dtk = name;
11082 
11083  available_toolkits.insert (name);
11084 }
11085 
11086 void
11087 gtk_manager::do_unregister_toolkit (const std::string& name)
11088 {
11089  available_toolkits.erase (name);
11090 
11091  if (dtk == name)
11092  {
11093  if (available_toolkits.empty ())
11094  dtk.clear ();
11095  else
11096  {
11098 
11099  dtk = *pa++;
11100 
11101  while (pa != available_toolkits.end ())
11102  {
11103  std::string tk_name = *pa++;
11104 
11105  if (tk_name == "qt"
11106  || (tk_name == "fltk"
11107  && (available_toolkits.find ("qt")
11108  == available_toolkits.end ())))
11109  dtk = tk_name;
11110  }
11111  }
11112  }
11113 }
11114 
11115 DEFUN (available_graphics_toolkits, , ,
11116  "-*- texinfo -*-\n\
11117 @deftypefn {Built-in Function} {} available_graphics_toolkits ()\n\
11118 Return a cell array of registered graphics toolkits.\n\
11119 @seealso{graphics_toolkit, register_graphics_toolkit}\n\
11120 @end deftypefn")
11121 {
11122  gh_manager::auto_lock guard;
11123 
11125 }
11126 
11127 DEFUN (register_graphics_toolkit, args, ,
11128  "-*- texinfo -*-\n\
11129 @deftypefn {Built-in Function} {} register_graphics_toolkit (@var{toolkit})\n\
11130 List @var{toolkit} as an available graphics toolkit.\n\
11131 @seealso{available_graphics_toolkits}\n\
11132 @end deftypefn")
11133 {
11134  octave_value retval;
11135 
11136  gh_manager::auto_lock guard;
11137 
11138  if (args.length () == 1)
11139  {
11140  if (args(0).is_string ())
11141  {
11142  std::string name = args(0).string_value ();
11144  }
11145  else
11146  error ("register_graphics_toolkit: TOOLKIT must be a string");
11147  }
11148  else
11149  print_usage ();
11150 
11151  return retval;
11152 }
11153 
11154 DEFUN (loaded_graphics_toolkits, , ,
11155  "-*- texinfo -*-\n\
11156 @deftypefn {Built-in Function} {} loaded_graphics_toolkits ()\n\
11157 Return a cell array of the currently loaded graphics toolkits.\n\
11158 @seealso{available_graphics_toolkits}\n\
11159 @end deftypefn")
11160 {
11161  gh_manager::auto_lock guard;
11162 
11164 }
11165 
11166 DEFUN (drawnow, args, ,
11167  "-*- texinfo -*-\n\
11168 @deftypefn {Built-in Function} {} drawnow ()\n\
11169 @deftypefnx {Built-in Function} {} drawnow (\"expose\")\n\
11170 @deftypefnx {Built-in Function} {} drawnow (@var{term}, @var{file}, @var{mono}, @var{debug_file})\n\
11171 Update figure windows and their children.\n\
11172 \n\
11173 The event queue is flushed and any callbacks generated are executed.\n\
11174 \n\
11175 With the optional argument @qcode{\"expose\"}, only graphic objects are\n\
11176 updated and no other events or callbacks are processed.\n\
11177 \n\
11178 The third calling form of @code{drawnow} is for debugging and is\n\
11179 undocumented.\n\
11180 @seealso{refresh}\n\
11181 @end deftypefn")
11182 {
11183  static int drawnow_executing = 0;
11184 
11185  octave_value retval;
11186 
11187  gh_manager::lock ();
11188 
11189  unwind_protect frame;
11190  frame.protect_var (Vdrawnow_requested, false);
11191 
11192  frame.protect_var (drawnow_executing);
11193 
11194  if (++drawnow_executing <= 1)
11195  {
11196  if (args.length () == 0 || args.length () == 1)
11197  {
11198  Matrix hlist = gh_manager::figure_handle_list (true);
11199 
11200  for (int i = 0; ! error_state && i < hlist.length (); i++)
11201  {
11202  graphics_handle h = gh_manager::lookup (hlist(i));
11203 
11204  if (h.ok () && h != 0)
11205  {
11207  figure::properties& fprops
11208  = dynamic_cast <figure::properties&> (go.get_properties ());
11209 
11210  if (fprops.is_modified ())
11211  {
11212  if (fprops.is_visible ())
11213  {
11214  gh_manager::unlock ();
11215 
11216  fprops.get_toolkit ().redraw_figure (go);
11217 
11218  gh_manager::lock ();
11219  }
11220 
11221  fprops.set_modified (false);
11222  }
11223  }
11224  }
11225 
11226  bool do_events = true;
11227 
11228  if (args.length () == 1)
11229  {
11230  caseless_str val (args(0).string_value ());
11231 
11232  if (! error_state && val.compare ("expose"))
11233  do_events = false;
11234  else
11235  {
11236  error ("drawnow: invalid argument, expected 'expose' as argument");
11237 
11238  gh_manager::unlock ();
11239 
11240  return retval;
11241  }
11242  }
11243 
11244  if (do_events)
11245  {
11246  gh_manager::unlock ();
11247 
11249 
11250  gh_manager::lock ();
11251  }
11252  }
11253  else if (args.length () >= 2 && args.length () <= 4)
11254  {
11255  std::string term, file, debug_file;
11256  bool mono;
11257 
11258  term = args(0).string_value ();
11259 
11260  if (! error_state)
11261  {
11262  file = args(1).string_value ();
11263 
11264  if (! error_state)
11265  {
11266  size_t pos_p = file.find_first_of ("|");
11267  size_t pos_c = file.find_first_not_of ("| ");
11268 
11269  if (pos_p == std::string::npos &&
11270  pos_c == std::string::npos)
11271  {
11272  error ("drawnow: empty output ''");
11273 
11274  gh_manager::unlock ();
11275 
11276  return retval;
11277  }
11278  else if (pos_c == std::string::npos)
11279  {
11280  error ("drawnow: empty pipe '|'");
11281 
11282  gh_manager::unlock ();
11283 
11284  return retval;
11285  }
11286  else if (pos_p != std::string::npos && pos_p < pos_c)
11287  {
11288  // Strip leading pipe character
11289  file = file.substr (pos_c);
11290  }
11291  else
11292  {
11293  size_t pos = file.find_last_of (file_ops::dir_sep_chars ());
11294 
11295  if (pos != std::string::npos)
11296  {
11297  std::string dirname = file.substr (pos_c, pos+1);
11298 
11299  file_stat fs (dirname);
11300 
11301  if (! (fs && fs.is_dir ()))
11302  {
11303  error ("drawnow: nonexistent directory '%s'",
11304  dirname.c_str ());
11305 
11306  gh_manager::unlock ();
11307 
11308  return retval;
11309  }
11310  }
11311  }
11312 
11313  mono = (args.length () >= 3 ? args(2).bool_value () : false);
11314 
11315  if (! error_state)
11316  {
11317  debug_file = (args.length () > 3 ? args(3).string_value ()
11318  : "");
11319 
11320  if (! error_state)
11321  {
11322  graphics_handle h = gcf ();
11323 
11324  if (h.ok ())
11325  {
11327 
11328  gh_manager::unlock ();
11329 
11330  go.get_toolkit ().print_figure (go, term, file,
11331  mono, debug_file);
11332 
11333  gh_manager::lock ();
11334  }
11335  else
11336  error ("drawnow: nothing to draw");
11337  }
11338  else
11339  error ("drawnow: invalid DEBUG_FILE, expected a string value");
11340  }
11341  else
11342  error ("drawnow: invalid colormode MONO, expected a boolean value");
11343  }
11344  else
11345  error ("drawnow: invalid FILE, expected a string value");
11346  }
11347  else
11348  error ("drawnow: invalid terminal TERM, expected a string value");
11349  }
11350  else
11351  print_usage ();
11352  }
11353 
11354  gh_manager::unlock ();
11355 
11356  return retval;
11357 }
11358 
11359 DEFUN (addlistener, args, ,
11360  "-*- texinfo -*-\n\
11361 @deftypefn {Built-in Function} {} addlistener (@var{h}, @var{prop}, @var{fcn})\n\
11362 Register @var{fcn} as listener for the property @var{prop} of the graphics\n\
11363 object @var{h}.\n\
11364 \n\
11365 Property listeners are executed (in order of registration) when the property\n\
11366 is set. The new value is already available when the listeners are executed.\n\
11367 \n\
11368 @var{prop} must be a string naming a valid property in @var{h}.\n\
11369 \n\
11370 @var{fcn} can be a function handle, a string or a cell array whose first\n\
11371 element is a function handle. If @var{fcn} is a function handle, the\n\
11372 corresponding function should accept at least 2 arguments, that will be\n\
11373 set to the object handle and the empty matrix respectively. If @var{fcn}\n\
11374 is a string, it must be any valid octave expression. If @var{fcn} is a cell\n\
11375 array, the first element must be a function handle with the same signature\n\
11376 as described above. The next elements of the cell array are passed\n\
11377 as additional arguments to the function.\n\
11378 \n\
11379 Example:\n\
11380 \n\
11381 @example\n\
11382 @group\n\
11383 function my_listener (h, dummy, p1)\n\
11384  fprintf (\"my_listener called with p1=%s\\n\", p1);\n\
11385 endfunction\n\
11386 \n\
11387 addlistener (gcf, \"position\", @{@@my_listener, \"my string\"@})\n\
11388 @end group\n\
11389 @end example\n\
11390 \n\
11391 @seealso{addproperty, hggroup}\n\
11392 @end deftypefn")
11393 {
11394  gh_manager::auto_lock guard;
11395 
11396  octave_value retval;
11397 
11398  if (args.length () >= 3 && args.length () <= 4)
11399  {
11400  double h = args(0).double_value ();
11401 
11402  if (! error_state)
11403  {
11404  std::string pname = args(1).string_value ();
11405 
11406  if (! error_state)
11407  {
11409 
11410  if (gh.ok ())
11411  {
11413 
11414  go.add_property_listener (pname, args(2), POSTSET);
11415 
11416  if (args.length () == 4)
11417  {
11418  caseless_str persistent = args(3).string_value ();
11419  if (persistent.compare ("persistent"))
11420  go.add_property_listener (pname, args(2), PERSISTENT);
11421  }
11422  }
11423  else
11424  error ("addlistener: invalid graphics object (= %g)",
11425  h);
11426  }
11427  else
11428  error ("addlistener: invalid property name, expected a string value");
11429  }
11430  else
11431  error ("addlistener: invalid handle");
11432  }
11433  else
11434  print_usage ();
11435 
11436  return retval;
11437 }
11438 
11439 DEFUN (dellistener, args, ,
11440  "-*- texinfo -*-\n\
11441 @deftypefn {Built-in Function} {} dellistener (@var{h}, @var{prop}, @var{fcn})\n\
11442 Remove the registration of @var{fcn} as a listener for the property\n\
11443 @var{prop} of the graphics object @var{h}.\n\
11444 \n\
11445 The function @var{fcn} must be the same variable (not just the same value),\n\
11446 as was passed to the original call to @code{addlistener}.\n\
11447 \n\
11448 If @var{fcn} is not defined then all listener functions of @var{prop}\n\
11449 are removed.\n\
11450 \n\
11451 Example:\n\
11452 \n\
11453 @example\n\
11454 @group\n\
11455 function my_listener (h, dummy, p1)\n\
11456  fprintf (\"my_listener called with p1=%s\\n\", p1);\n\
11457 endfunction\n\
11458 \n\
11459 c = @{@@my_listener, \"my string\"@};\n\
11460 addlistener (gcf, \"position\", c);\n\
11461 dellistener (gcf, \"position\", c);\n\
11462 @end group\n\
11463 @end example\n\
11464 \n\
11465 @end deftypefn")
11466 {
11467  gh_manager::auto_lock guard;
11468 
11469  octave_value retval;
11470 
11471  if (args.length () == 3 || args.length () == 2)
11472  {
11473  double h = args(0).double_value ();
11474 
11475  if (! error_state)
11476  {
11477  std::string pname = args(1).string_value ();
11478 
11479  if (! error_state)
11480  {
11482 
11483  if (gh.ok ())
11484  {
11486 
11487  if (args.length () == 2)
11488  go.delete_property_listener (pname, octave_value (),
11489  POSTSET);
11490  else
11491  {
11492  if (args(2).is_string ()
11493  && args(2).string_value () == "persistent")
11494  {
11495  go.delete_property_listener (pname, octave_value (),
11496  PERSISTENT);
11497  go.delete_property_listener (pname, octave_value (),
11498  POSTSET);
11499  }
11500  else
11501  go.delete_property_listener (pname, args(2), POSTSET);
11502  }
11503  }
11504  else
11505  error ("dellistener: invalid graphics object (= %g)",
11506  h);
11507  }
11508  else
11509  error ("dellistener: invalid property name, expected a string value");
11510  }
11511  else
11512  error ("dellistener: invalid handle");
11513  }
11514  else
11515  print_usage ();
11516 
11517  return retval;
11518 }
11519 
11520 DEFUN (addproperty, args, ,
11521  "-*- texinfo -*-\n\
11522 @deftypefn {Built-in Function} {} addproperty (@var{name}, @var{h}, @var{type})\n\
11523 @deftypefnx {Built-in Function} {} addproperty (@var{name}, @var{h}, @var{type}, @var{arg}, @dots{})\n\
11524 Create a new property named @var{name} in graphics object @var{h}.\n\
11525 \n\
11526 @var{type} determines the type of the property to create. @var{args}\n\
11527 usually contains the default value of the property, but additional\n\
11528 arguments might be given, depending on the type of the property.\n\
11529 \n\
11530 The supported property types are:\n\
11531 \n\
11532 @table @code\n\
11533 @item string\n\
11534 A string property. @var{arg} contains the default string value.\n\
11535 \n\
11536 @item any\n\
11537 An @nospell{un-typed} property. This kind of property can hold any octave\n\
11538 value. @var{args} contains the default value.\n\
11539 \n\
11540 @item radio\n\
11541 A string property with a limited set of accepted values. The first\n\
11542 argument must be a string with all accepted values separated by\n\
11543 a vertical bar ('|'). The default value can be marked by enclosing\n\
11544 it with a '@{' '@}' pair. The default value may also be given as\n\
11545 an optional second string argument.\n\
11546 \n\
11547 @item boolean\n\
11548 A boolean property. This property type is equivalent to a radio\n\
11549 property with \"on|off\" as accepted values. @var{arg} contains\n\
11550 the default property value.\n\
11551 \n\
11552 @item double\n\
11553 A scalar double property. @var{arg} contains the default value.\n\
11554 \n\
11555 @item handle\n\
11556 A handle property. This kind of property holds the handle of a\n\
11557 graphics object. @var{arg} contains the default handle value.\n\
11558 When no default value is given, the property is initialized to\n\
11559 the empty matrix.\n\
11560 \n\
11561 @item data\n\
11562 A data (matrix) property. @var{arg} contains the default data\n\
11563 value. When no default value is given, the data is initialized to\n\
11564 the empty matrix.\n\
11565 \n\
11566 @item color\n\
11567 A color property. @var{arg} contains the default color value.\n\
11568 When no default color is given, the property is set to black.\n\
11569 An optional second string argument may be given to specify an\n\
11570 additional set of accepted string values (like a radio property).\n\
11571 @end table\n\
11572 \n\
11573 @var{type} may also be the concatenation of a core object type and\n\
11574 a valid property name for that object type. The property created\n\
11575 then has the same characteristics as the referenced property (type,\n\
11576 possible values, hidden state@dots{}). This allows one to clone an\n\
11577 existing property into the graphics object @var{h}.\n\
11578 \n\
11579 Examples:\n\
11580 \n\
11581 @example\n\
11582 @group\n\
11583 addproperty (\"my_property\", gcf, \"string\", \"a string value\");\n\
11584 addproperty (\"my_radio\", gcf, \"radio\", \"val_1|val_2|@{val_3@}\");\n\
11585 addproperty (\"my_style\", gcf, \"linelinestyle\", \"--\");\n\
11586 @end group\n\
11587 @end example\n\
11588 \n\
11589 @seealso{addlistener, hggroup}\n\
11590 @end deftypefn")
11591 {
11592  gh_manager::auto_lock guard;
11593 
11594  octave_value retval;
11595 
11596  if (args.length () >= 3)
11597  {
11598  std::string name = args(0).string_value ();
11599 
11600  if (! error_state)
11601  {
11602  double h = args(1).double_value ();
11603 
11604  if (! error_state)
11605  {
11607 
11608  if (gh.ok ())
11609  {
11611 
11612  std::string type = args(2).string_value ();
11613 
11614  if (! error_state)
11615  {
11616  if (! go.get_properties ().has_property (name))
11617  {
11618  property p = property::create (name, gh, type,
11619  args.splice (0, 3));
11620 
11621  if (! error_state)
11622  go.get_properties ().insert_property (name, p);
11623  }
11624  else
11625  error ("addproperty: a '%s' property already exists in the graphics object",
11626  name.c_str ());
11627  }
11628  else
11629  error ("addproperty: invalid property TYPE, expected a string value");
11630  }
11631  else
11632  error ("addproperty: invalid graphics object (= %g)", h);
11633  }
11634  else
11635  error ("addproperty: invalid handle value");
11636  }
11637  else
11638  error ("addproperty: invalid property NAME, expected a string value");
11639  }
11640  else
11641  print_usage ();
11642 
11643  return retval;
11644 }
11645 
11647 get_property_from_handle (double handle, const std::string& property,
11648  const std::string& func)
11649 {
11650  gh_manager::auto_lock guard;
11651 
11652  graphics_object obj = gh_manager::get_object (handle);
11653  octave_value retval;
11654 
11655  if (obj)
11656  retval = obj.get (caseless_str (property));
11657  else
11658  error ("%s: invalid handle (= %g)", func.c_str (), handle);
11659 
11660  return retval;
11661 }
11662 
11663 bool
11664 set_property_in_handle (double handle, const std::string& property,
11665  const octave_value& arg, const std::string& func)
11666 {
11667  gh_manager::auto_lock guard;
11668 
11669  graphics_object obj = gh_manager::get_object (handle);
11670  int ret = false;
11671 
11672  if (obj)
11673  {
11674  obj.set (caseless_str (property), arg);
11675 
11676  if (! error_state)
11677  ret = true;
11678  }
11679  else
11680  error ("%s: invalid handle (= %g)", func.c_str (), handle);
11681 
11682  return ret;
11683 }
11684 
11685 static bool
11687 {
11688  octave_value_list args(2);
11689 
11690  args(0) = o1;
11691  args(1) = o2;
11692 
11693  octave_value_list result = feval ("isequal", args, 1);
11694 
11695  if (! error_state && result.length () > 0)
11696  return result(0).bool_value ();
11697 
11698  return false;
11699 }
11700 
11701 static std::map<uint32_t, bool> waitfor_results;
11702 
11703 static void
11704 cleanup_waitfor_id (uint32_t id)
11705 {
11706  waitfor_results.erase (id);
11707 }
11708 
11709 static void
11711  listener_mode mode = POSTSET)
11712 {
11713  Cell c = listener.cell_value ();
11714 
11715  if (c.numel () >= 4)
11716  {
11717  double h = c(2).double_value ();
11718 
11719  if (! error_state)
11720  {
11721  caseless_str pname = c(3).string_value ();
11722 
11723  if (! error_state)
11724  {
11725  gh_manager::auto_lock guard;
11726 
11727  graphics_handle handle = gh_manager::lookup (h);
11728 
11729  if (handle.ok ())
11730  {
11732 
11733  if (go.get_properties ().has_property (pname))
11734  {
11735  go.get_properties ().delete_listener (pname, listener,
11736  mode);
11737  if (mode == POSTSET)
11738  go.get_properties ().delete_listener (pname, listener,
11739  PERSISTENT);
11740  }
11741  }
11742  }
11743  }
11744  }
11745 }
11746 
11747 static void
11749 { do_cleanup_waitfor_listener (listener, POSTSET); }
11750 
11751 static void
11753 { do_cleanup_waitfor_listener (listener, PREDELETE); }
11754 
11755 static octave_value_list
11757 {
11758  if (args.length () > 3)
11759  {
11760  uint32_t id = args(2).uint32_scalar_value ().value ();
11761 
11762  if (! error_state)
11763  {
11764  if (args.length () > 5)
11765  {
11766  double h = args(0).double_value ();
11767 
11768  if (! error_state)
11769  {
11770  caseless_str pname = args(4).string_value ();
11771 
11772  if (! error_state)
11773  {
11774  gh_manager::auto_lock guard;
11775 
11776  graphics_handle handle = gh_manager::lookup (h);
11777 
11778  if (handle.ok ())
11779  {
11781  octave_value pvalue = go.get (pname);
11782 
11783  if (compare_property_values (pvalue, args(5)))
11784  waitfor_results[id] = true;
11785  }
11786  }
11787  }
11788  }
11789  else
11790  waitfor_results[id] = true;
11791  }
11792  }
11793 
11794  return octave_value_list ();
11795 }
11796 
11797 static octave_value_list
11799 {
11800  if (args.length () > 2)
11801  {
11802  uint32_t id = args(2).uint32_scalar_value ().value ();
11803 
11804  if (! error_state)
11805  waitfor_results[id] = true;
11806  }
11807 
11808  return octave_value_list ();
11809 }
11810 
11811 DEFUN (waitfor, args, ,
11812  "-*- texinfo -*-\n\
11813 @deftypefn {Built-in Function} {} waitfor (@var{h})\n\
11814 @deftypefnx {Built-in Function} {} waitfor (@var{h}, @var{prop})\n\
11815 @deftypefnx {Built-in Function} {} waitfor (@var{h}, @var{prop}, @var{value})\n\
11816 @deftypefnx {Built-in Function} {} waitfor (@dots{}, \"timeout\", @var{timeout})\n\
11817 Suspend the execution of the current program until a condition is\n\
11818 satisfied on the graphics handle @var{h}.\n\
11819 \n\
11820 While the program is suspended graphics events are still processed normally,\n\
11821 allowing callbacks to modify the state of graphics objects. This function\n\
11822 is reentrant and can be called from a callback, while another @code{waitfor}\n\
11823 call is pending at the top-level.\n\
11824 \n\
11825 In the first form, program execution is suspended until the graphics object\n\
11826 @var{h} is destroyed. If the graphics handle is invalid, the function\n\
11827 returns immediately.\n\
11828 \n\
11829 In the second form, execution is suspended until the graphics object is\n\
11830 destroyed or the property named @var{prop} is modified. If the graphics\n\
11831 handle is invalid or the property does not exist, the function returns\n\
11832 immediately.\n\
11833 \n\
11834 In the third form, execution is suspended until the graphics object is\n\
11835 destroyed or the property named @var{prop} is set to @var{value}. The\n\
11836 function @code{isequal} is used to compare property values. If the graphics\n\
11837 handle is invalid, the property does not exist or the property is already\n\
11838 set to @var{value}, the function returns immediately.\n\
11839 \n\
11840 An optional timeout can be specified using the property @code{timeout}.\n\
11841 This timeout value is the number of seconds to wait for the condition to be\n\
11842 true. @var{timeout} must be at least 1. If a smaller value is specified, a\n\
11843 warning is issued and a value of 1 is used instead. If the timeout value is\n\
11844 not an integer, it is truncated towards 0.\n\
11845 \n\
11846 To define a condition on a property named @code{timeout}, use the string\n\
11847 @code{\\timeout} instead.\n\
11848 \n\
11849 In all cases, typing CTRL-C stops program execution immediately.\n\
11850 @seealso{waitforbuttonpress, isequal}\n\
11851 @end deftypefn")
11852 {
11853  if (args.length () > 0)
11854  {
11855  double h = args(0).double_value ();
11856 
11857  if (! error_state)
11858  {
11859  caseless_str pname;
11860 
11861  unwind_protect frame;
11862 
11863  static uint32_t id_counter = 0;
11864  uint32_t id = 0;
11865 
11866  int max_arg_index = 0;
11867  int timeout_index = -1;
11868 
11869  int timeout = 0;
11870 
11871  if (args.length () > 1)
11872  {
11873  pname = args(1).string_value ();
11874  if (! error_state
11875  && ! pname.empty ()
11876  && ! pname.compare ("timeout"))
11877  {
11878  if (pname.compare ("\\timeout"))
11879  pname = "timeout";
11880 
11881  static octave_value wf_listener;
11882 
11883  if (! wf_listener.is_defined ())
11884  wf_listener =
11886  "waitfor_listener"));
11887 
11888  max_arg_index++;
11889  if (args.length () > 2)
11890  {
11891  if (args(2).is_string ())
11892  {
11893  caseless_str s = args(2).string_value ();
11894 
11895  if (s.compare ("timeout"))
11896  timeout_index = 2;
11897  else
11898  max_arg_index++;
11899  }
11900  else
11901  max_arg_index++;
11902  }
11903 
11904  Cell listener (1, max_arg_index >= 2 ? 5 : 4);
11905 
11906  id = id_counter++;
11907  frame.add_fcn (cleanup_waitfor_id, id);
11908  waitfor_results[id] = false;
11909 
11910  listener(0) = wf_listener;
11911  listener(1) = octave_uint32 (id);
11912  listener(2) = h;
11913  listener(3) = pname;
11914 
11915  if (max_arg_index >= 2)
11916  listener(4) = args(2);
11917 
11918  octave_value ov_listener (listener);
11919 
11920  gh_manager::auto_lock guard;
11921 
11922  graphics_handle handle = gh_manager::lookup (h);
11923 
11924  if (handle.ok ())
11925  {
11927 
11928  if (max_arg_index >= 2
11929  && compare_property_values (go.get (pname),
11930  args(2)))
11931  waitfor_results[id] = true;
11932  else
11933  {
11934 
11936  ov_listener);
11937  go.add_property_listener (pname, ov_listener,
11938  POSTSET);
11939  go.add_property_listener (pname, ov_listener,
11940  PERSISTENT);
11941 
11942  if (go.get_properties ()
11943  .has_dynamic_property (pname))
11944  {
11945  static octave_value wf_del_listener;
11946 
11947  if (! wf_del_listener.is_defined ())
11948  wf_del_listener =
11951  "waitfor_del_listener"));
11952 
11953  Cell del_listener (1, 4);
11954 
11955  del_listener(0) = wf_del_listener;
11956  del_listener(1) = octave_uint32 (id);
11957  del_listener(2) = h;
11958  del_listener(3) = pname;
11959 
11960  octave_value ov_del_listener (del_listener);
11961 
11963  ov_del_listener);
11964  go.add_property_listener (pname, ov_del_listener,
11965  PREDELETE);
11966  }
11967  }
11968  }
11969  }
11970  else if (error_state || pname.empty ())
11971  error ("waitfor: invalid property name, expected a non-empty string value");
11972  }
11973 
11974  if (! error_state
11975  && timeout_index < 0
11976  && args.length () > (max_arg_index + 1))
11977  {
11978  caseless_str s = args(max_arg_index + 1).string_value ();
11979 
11980  if (! error_state)
11981  {
11982  if (s.compare ("timeout"))
11983  timeout_index = max_arg_index + 1;
11984  else
11985  error ("waitfor: invalid parameter '%s'", s.c_str ());
11986  }
11987  else
11988  error ("waitfor: invalid parameter, expected 'timeout'");
11989  }
11990 
11991  if (! error_state && timeout_index >= 0)
11992  {
11993  if (args.length () > (timeout_index + 1))
11994  {
11995  timeout = static_cast<int>
11996  (args(timeout_index + 1).scalar_value ());
11997 
11998  if (! error_state)
11999  {
12000  if (timeout < 1)
12001  {
12002  warning ("waitfor: the timeout value must be >= 1, using 1 instead");
12003  timeout = 1;
12004  }
12005  }
12006  else
12007  error ("waitfor: invalid timeout value, expected a value >= 1");
12008  }
12009  else
12010  error ("waitfor: missing timeout value");
12011  }
12012 
12013  // FIXME: There is still a "hole" in the following loop. The code
12014  // assumes that an object handle is unique, which is a fair
12015  // assumption, except for figures. If a figure is destroyed
12016  // then recreated with the same figure ID, within the same
12017  // run of event hooks, then the figure destruction won't be
12018  // caught and the loop will not stop. This is an unlikely
12019  // possibility in practice, though.
12020  //
12021  // Using deletefcn callback is also unreliable as it could be
12022  // modified during a callback execution and the waitfor loop
12023  // would not stop.
12024  //
12025  // The only "good" implementation would require object
12026  // listeners, similar to property listeners.
12027 
12028  time_t start = 0;
12029 
12030  if (timeout > 0)
12031  start = time (0);
12032 
12033  while (! error_state)
12034  {
12035  if (true)
12036  {
12037  gh_manager::auto_lock guard;
12038 
12039  graphics_handle handle = gh_manager::lookup (h);
12040 
12041  if (handle.ok ())
12042  {
12043  if (! pname.empty () && waitfor_results[id])
12044  break;
12045  }
12046  else
12047  break;
12048  }
12049 
12050  octave_usleep (100000);
12051 
12052  OCTAVE_QUIT;
12053 
12055 
12056  if (timeout > 0)
12057  {
12058  if (start + timeout < time (0))
12059  break;
12060  }
12061  }
12062  }
12063  else
12064  error ("waitfor: invalid handle value.");
12065  }
12066  else
12067  print_usage ();
12068 
12069  return octave_value ();
12070 }
12071 
12072 DEFUN (__zoom__, args, ,
12073  "-*- texinfo -*-\n\
12074 @deftypefn {Built-in Function} {} __zoom__ (@var{axes}, @var{mode}, @var{factor})\n\
12075 @deftypefnx {Built-in Function} {} __zoom__ (@var{axes}, \"out\")\n\
12076 @deftypefnx {Built-in Function} {} __zoom__ (@var{axes}, \"reset\")\n\
12077 Undocumented internal function.\n\
12078 @end deftypefn")
12079 {
12080  octave_value retval;
12081 
12082  int nargin = args.length ();
12083 
12084  if (nargin != 2 && nargin != 3)
12085  {
12086  print_usage ();
12087  return retval;
12088  }
12089 
12090  double h = args(0).double_value ();
12091 
12092  if (error_state)
12093  return retval;
12094 
12095  gh_manager::auto_lock guard;
12096 
12097  graphics_handle handle = gh_manager::lookup (h);
12098 
12099  if (! handle.ok ())
12100  {
12101  error ("__zoom__: invalid handle");
12102  return retval;
12103  }
12104 
12106 
12107  axes::properties& ax_props =
12108  dynamic_cast<axes::properties&> (ax.get_properties ());
12109 
12110  if (nargin == 2)
12111  {
12112  std::string opt = args(1).string_value ();
12113 
12114  if (error_state)
12115  return retval;
12116 
12117  if (opt == "out" || opt == "reset")
12118  {
12119  if (opt == "out")
12120  {
12121  ax_props.clear_zoom_stack ();
12122  Vdrawnow_requested = true;
12123  }
12124  else
12125  ax_props.clear_zoom_stack (false);
12126 
12127  }
12128  }
12129  else
12130  {
12131  std::string mode = args(1).string_value ();
12132  double factor = args(2).scalar_value ();
12133 
12134  if (error_state)
12135  return retval;
12136 
12137  ax_props.zoom (mode, factor);
12138  Vdrawnow_requested = true;
12139  }
12140 
12141  return retval;
12142 }
static Matrix default_axes_ticklength(void)
Definition: graphics.cc:386
bool Vdebug_on_error
Definition: error.cc:58
uint8NDArray uint8_array_value(void) const
Definition: ov.h:882
enum double_radio_property::current_enum current_type
void do_register_toolkit(const std::string &name)
Definition: graphics.cc:11076
std::map< graphics_handle, graphics_object >::iterator iterator
Definition: graphics.h:13406
octave_int< uint32_t > octave_uint32
static void pop_figure(const graphics_handle &h)
Definition: graphics.h:13250
std::string get_errormessage(void) const
Definition: graphics.cc:3540
static graphics_event create_set_event(const graphics_handle &h, const std::string &name, const octave_value &value, bool notify_toolkit=true)
Definition: graphics.cc:9469
#define OCTAVE_SAFE_CALL(F, ARGS)
Definition: toplev.h:503
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:696
string_vector keys(void) const
Definition: oct-map.h:339
static bool has_core_property(const caseless_str &pname)
static void clear(octave_shlib &oct_file)
Definition: dynamic-ld.cc:236
octave_value get_default(const caseless_str &name) const
Definition: graphics.h:3320
static void convert_cdata_2(bool is_scaled, bool is_real, double clim_0, double clim_1, const double *cmapv, double x, octave_idx_type lda, octave_idx_type nc, octave_idx_type i, double *av)
Definition: graphics.cc:767
plist_map_iterator find(const std::string &go_name)
Definition: graphics.h:2097
double get_fontsize_points(double box_pix_height=0) const
Definition: graphics.cc:9014
void flush_octave_stdout(void)
Definition: pager.cc:458
const Cell & contents(const_iterator p) const
Definition: oct-map.h:314
radio_values radio_val
Definition: graphics.h:1315
#define OCTAVE_DEFAULT_FONTNAME
Definition: graphics.h:55
bool is_empty(void) const
Definition: Array.h:472
octave_value get_extent(void) const
Definition: graphics.cc:8889
void set_visible(const octave_value &val)
Definition: graphics.cc:3847
graphics_handle get_parent(void) const
Definition: graphics.h:3361
static Matrix default_screensize(void)
Definition: graphics.cc:188
std::string dtk
Definition: graphics.h:2382
static std::set< double > updating_aspectratios
Definition: graphics.cc:6275
octave_value get_color_data(void) const
Definition: graphics.cc:8288
std::string get_busyaction(void) const
Definition: graphics.h:2719
static Matrix default_axes_tick(void)
Definition: graphics.cc:373
void rotate3d(double x0, double x1, double y0, double y1, bool push_to_zoom_stack=true)
Definition: graphics.cc:7925
void delete_listener(const octave_value &v=octave_value(), listener_mode mode=POSTSET)
Definition: graphics.h:1963
OCTINTERP_API octave_value_list F__diaryfile__(const octave_value_list &=octave_value_list(), int=0)
Definition: pager.cc:596
virtual void reparent(const graphics_handle &np)
Definition: graphics.h:3106
Definition: Cell.h:35
void update_axis_limits(const std::string &axis_type)
Definition: graphics.cc:8755
#define GO_BODY(TYPE)
Definition: graphics.cc:10606
OCTINTERP_API octave_value_list Fecho(const octave_value_list &=octave_value_list(), int=0)
Definition: input.cc:971
static double default_screenpixelsperinch(void)
Definition: graphics.cc:199
void set_diary(const octave_value &val)
Definition: graphics.cc:3473
void execute(void)
Definition: graphics.cc:9376
static caseless_str validate_property_name(const std::string &who, const std::string &what, const std::set< std::string > &pnames, const caseless_str &pname)
Definition: graphics.cc:77
static octave_map cat(int dim, octave_idx_type n, const octave_scalar_map *map_list)
Definition: oct-map.cc:662
static Matrix default_axes_outerposition(void)
Definition: graphics.cc:357
std::string values_as_string(void) const
Definition: graphics.cc:1119
static Matrix default_axes_view(void)
Definition: graphics.cc:365
bool Vdebug_on_warning
Definition: error.cc:62
bool is_real_type(void) const
Definition: ov.h:651
void * function_data
Definition: graphics.cc:9385
static Matrix papersize_from_type(const caseless_str punits, const caseless_str typ)
Definition: graphics.cc:4023
void set_fontunits(const octave_value &val)
Definition: graphics.cc:9124
virtual bool do_set(const octave_value &)
Definition: graphics.h:406
octave_idx_type nelem(void) const
Definition: graphics.h:931
std::string get_title(void) const
Definition: graphics.cc:4623
void override_defaults(base_graphics_object &obj)
Definition: graphics.h:4920
std::map< graphics_handle, graphics_object > handle_map
Definition: graphics.h:13417
OCTINTERP_API bool is_equal(const octave_value &v) const
Definition: graphics.cc:1376
enum color_property::current_enum current_type
graphics_handle do_get_handle(bool integer_figure_handle)
Definition: graphics.cc:2423
void update_font(void)
Definition: graphics.cc:6391
void reset_default_properties(void)
Definition: graphics.cc:8045
static bool executing_callback
Definition: graphics.cc:1596
bool is_visible(void) const
Definition: graphics.h:2758
double xround(double x)
Definition: lo-mappers.cc:63
void override_defaults(base_graphics_object &obj)
Definition: graphics.cc:3073
void(* event_fcn)(void *)
Definition: graphics.h:13095
void update_text_extent(void)
Definition: graphics.cc:8179
virtual property get_property(const caseless_str &pname)
void convert_cdata_1(bool is_scaled, bool is_real, double clim_0, double clim_1, const double *cmapv, const T *cv, octave_idx_type lda, octave_idx_type nc, double *av)
Definition: graphics.cc:799
static Matrix default_control_sliderstep(void)
Definition: graphics.cc:439
octave_value reshape(const dim_vector &dv) const
Definition: ov.h:498
octave_idx_type rows(void) const
Definition: ov.h:473
virtual void update(const graphics_object &, int)
Definition: graphics.h:2162
static property_list::pval_map_type factory_defaults(void)
static ColumnVector xform_vector(double x, double y, double z)
Definition: graphics.cc:6754
void do_renumber_figure(const graphics_handle &old_gh, const graphics_handle &new_gh)
Definition: graphics.cc:2512
void update_units(void)
static void register_toolkit(const std::string &name)
Definition: graphics.h:2301
Matrix get_data_position(void) const
Definition: graphics.cc:8098
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition: dMatrix.h:130
graphics_handle gca(void)
Definition: graphics.cc:2620
void erase(const std::string pname)
Definition: graphics.h:2056
static octave_value convert_cdata(const base_properties &props, const octave_value &cdata, bool is_scaled, int cdim)
Definition: graphics.cc:809
bool xisnan(double x)
Definition: lo-mappers.cc:144
static Matrix default_figure_paperposition(void)
Definition: graphics.cc:415
graphics_handle get_xlabel(void) const
Definition: graphics.h:5627
void update_xlabel_position(void)
Definition: graphics.cc:5839
void update_paperorientation(void)
Definition: graphics.cc:4535
void set_horizontalalignmentmode(const octave_value &val)
Definition: graphics.h:8344
static Matrix do_translate(double x0, double x1, const Matrix &lims, bool is_logscale)
Definition: graphics.cc:7819
int8NDArray int8_array_value(void) const
Definition: ov.h:870
static Matrix default_patch_xdata(void)
Definition: graphics.cc:330
static Cell available_toolkits_list(void)
Definition: graphics.h:2331
void set_papertype(const octave_value &val)
Definition: graphics.cc:4000
Matrix get_boundingbox(bool internal=false, const Matrix &parent_pix_size=Matrix()) const
Definition: graphics.cc:8961
void insert_property(const std::string &name, property p)
Definition: graphics.h:2501
static property_list::pval_map_type factory_defaults(void)
void update_limits(void) const
Definition: graphics.cc:8609
void do_execute_listener(const graphics_handle &h, const octave_value &l)
Definition: graphics.cc:9504
static property_list::pval_map_type factory_defaults(void)
bool isa(const std::string &go_name) const
Definition: graphics.h:3375
void update_axes_layout(void)
Definition: graphics.cc:5600
static Matrix default_data(void)
Definition: graphics.cc:248
virtual void init_integerhandle(const octave_value &)
Definition: graphics.h:2491
bool is_uint16_type(void) const
Definition: ov.h:634
graphics_handle get_zlabel(void) const
Definition: graphics.h:5704
int ndims(void) const
Definition: Array.h:487
void set_rotationmode(const octave_value &val)
Definition: graphics.h:8332
void set___mouse_mode__(const octave_value &val)
Definition: graphics.cc:1825
OCTINTERP_API void print_usage(void)
Definition: defun.cc:51
std::set< caseless_str > possible_vals
Definition: graphics.h:936
std::set< std::string >::const_iterator const_available_toolkits_iterator
Definition: graphics.h:2393
bool is_function(void) const
Definition: ov.h:695
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:275
property_list get_defaults_list(void) const
Definition: graphics.h:4964
OCTINTERP_API octave_value box(JNIEnv *jni_env, jobject jobj, jclass jcls=0)
static Matrix default_patch_ydata(void)
Definition: graphics.cc:338
void update_fontunits(void)
Matrix xscale(const Matrix &m) const
Definition: graphics.h:5037
int16NDArray int16_array_value(void) const
Definition: ov.h:873
void set_integerhandle(const octave_value &val)
Definition: graphics.cc:3627
void request_autopos(void)
Definition: graphics.cc:8225
virtual void defaults(void) const
Definition: graphics.h:3114
octave_idx_type length(void) const
Definition: oct-obj.h:89
OCTINTERP_API bool do_set(const octave_value &v)
Definition: graphics.cc:1275
static bool is_octave_thread(void)
std::string value_as_string(const std::string &prop)
Definition: graphics.h:3354
void set_linestyleorder(const octave_value &val)
Definition: graphics.cc:6668
void set_verticalalignmentmode(const octave_value &val)
Definition: graphics.h:8356
void set_currentaxes(const octave_value &val)
Definition: graphics.cc:3773
OCTAVE_EXPORT octave_value_list Fdrawnow(const octave_value_list &args, int)
Definition: graphics.cc:11181
bool is_scalar_type(void) const
Definition: ov.h:657
OCTINTERP_API octave_value_list Fformat(const octave_value_list &=octave_value_list(), int=0)
Definition: pr-output.cc:4064
std::string default_value(void) const
Definition: graphics.h:870
static bool has_core_property(const caseless_str &pname)
bool is_numeric_type(void) const
Definition: ov.h:663
bool is_climinclude(void) const
Definition: graphics.h:3424
bool is_defined(void) const
Definition: ov.h:520
#define CHECK_ARRAY_EQUAL(T, F, A)
static bool updating_zlabel_position
Definition: graphics.cc:6049
static bool updating_axes_layout
Definition: graphics.cc:5597
RowVector xform2cam(const ColumnVector &v)
Definition: graphics.cc:5371
void execute_deletefcn(const octave_value &data=octave_value()) const
Definition: graphics.h:2730
static bool has_core_property(const caseless_str &pname)
virtual void remove_all_listeners(void)
Definition: graphics.cc:3208
static void cleanup_waitfor_postset_listener(const octave_value &listener)
Definition: graphics.cc:11748
std::ostream & list_in_columns(std::ostream &, int width=0, const std::string &prefix=std::string()) const
Definition: str-vec.cc:215
Matrix xform_matrix(void)
Definition: graphics.cc:5234
void do_post_event(const graphics_event &e)
Definition: graphics.cc:9588
bool ok(void) const
Definition: oct-handle.h:105
octave_value get_dynamic(const caseless_str &pname) const
Definition: graphics.cc:2922
void sync_positions(void)
Definition: graphics.cc:4796
std::set< std::string > type_constraints
Definition: graphics.h:1428
void set_parent(const graphics_handle &h)
Definition: graphics.h:1912
const_iterator find(const std::string pname) const
Definition: graphics.h:2009
bool isa(const std::string &go_name) const
Definition: graphics.h:3154
octave_value get_extent(void) const
Definition: graphics.cc:8116
Matrix extract_n(octave_idx_type r1, octave_idx_type c1, octave_idx_type nr, octave_idx_type nc) const
Definition: dMatrix.cc:630
virtual void add_listener(const caseless_str &, const octave_value &, listener_mode=POSTSET)
Definition: graphics.cc:3157
static double y_dpi(void)
Definition: display.h:65
uint64NDArray uint64_array_value(void) const
Definition: ov.h:891
Complex xmax(const Complex &x, const Complex &y)
Definition: lo-mappers.cc:269
static void push_figure(const graphics_handle &h)
Definition: graphics.h:13244
virtual octave_value get_xlim(void) const
Definition: graphics.h:2626
OCTINTERP_API void run_listeners(listener_mode mode=POSTSET)
Definition: graphics.cc:1071
Matrix unit_cube(void)
Definition: graphics.cc:5344
void mark_modified(void)
Definition: graphics.cc:3064
octave_value get_property_from_handle(double handle, const std::string &property, const std::string &func)
Definition: graphics.cc:11647
void protect_var(T &var)
bool positionmode_is(const std::string &v) const
Definition: graphics.h:7979
virtual octave_value get_alim(void) const
Definition: graphics.h:2624
Matrix get_axis_limits(double xmin, double xmax, double min_pos, double max_neg, bool logscale)
Definition: graphics.cc:6925
static bool has_core_property(const caseless_str &pname)
float pixel_ysize(void)
Definition: graphics.h:9001
void do_post_function(graphics_event::event_fcn fcn, void *fcn_data)
Definition: graphics.cc:9638
void set_units(const octave_value &val)
Definition: graphics.cc:6677
graphics_toolkit get_toolkit(void) const
Definition: graphics.h:3439
Matrix get_auto_paperposition(void)
Definition: graphics.cc:4180
virtual std::string graphics_object_name(void) const
Definition: graphics.h:2485
pval_map_type::const_iterator pval_map_const_iterator
Definition: graphics.h:2077
static void execute_listener(const graphics_handle &h, const octave_value &l)
Definition: graphics.h:13294
Matrix get_extent(bool with_text=false, bool only_text_height=false) const
Definition: graphics.cc:6434
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:44
set_event(const graphics_handle &h, const std::string &name, const octave_value &value, bool do_notify_toolkit=true)
Definition: graphics.cc:9401
double get_recursionlimit(void) const
Definition: graphics.cc:3602
void error(const char *fmt,...)
Definition: error.cc:476
void set_dynamic(const caseless_str &pname, const octave_value &val)
Definition: graphics.cc:2968
void finalize(void)
Definition: graphics.h:3451
void reset_default_properties(void)
Definition: graphics.cc:3761
void do_free(const graphics_handle &h)
Definition: graphics.cc:2465
static void add_event_hook(event_hook_fcn f)
Definition: cmd-edit.cc:1440
int32NDArray int32_array_value(void) const
Definition: ov.h:876
void set_fontunits(const octave_value &val)
Definition: graphics.cc:8131
void zoom(const std::string &mode, double factor, bool push_to_zoom_stack=true)
Definition: graphics.cc:7761
double xmaxp
Definition: graphics.h:1427
callback_event(const graphics_handle &h, const std::string &name, const octave_value &data=Matrix())
Definition: graphics.cc:9338
base_graphics_event * rep
Definition: graphics.h:13149
bool valid_object(void) const
Definition: graphics.h:4973
property get_property_dynamic(const caseless_str &pname)
Definition: graphics.cc:2988
void set(const caseless_str &name, const octave_value &val)
Definition: graphics.cc:1888
bool is_int8_type(void) const
Definition: ov.h:619
octave_value_list feval(const std::string &name, const octave_value_list &args, int nargout)
Definition: oct-parse.cc:8625
Matrix zscale(const Matrix &m) const
Definition: graphics.h:5039
std::list< dim_vector > size_constraints
Definition: graphics.h:1429
static void force_close_figure(const graphics_handle &handle)
Definition: graphics.cc:2681
static Matrix default_axes_position(void)
Definition: graphics.cc:346
virtual void update_axis_limits(const std::string &axis_type)
Definition: graphics.cc:3179
virtual Matrix get_boundingbox(bool=false, const Matrix &=Matrix()) const
Definition: graphics.h:2553
static string_vector names(const map_type &lst)
Definition: help.cc:782
pval_map_type::iterator pval_map_iterator
Definition: graphics.h:2076
virtual void initialize(const graphics_object &go)
Definition: graphics.h:3191
static Matrix figure_handle_list(bool show_hidden=false)
Definition: graphics.h:13288
bool xisinf(double x)
Definition: lo-mappers.cc:160
void adopt(const graphics_handle &h)
Definition: graphics.h:3369
OCTINTERP_API bool str2rgb(const std::string &str)
Definition: graphics.cc:1159
bool contains(const std::string &val, std::string &match)
Definition: graphics.h:885
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:171
static void xset_gcbo(const graphics_handle &h)
Definition: graphics.cc:9482
std::set< graphics_handle >::iterator free_list_iterator
Definition: graphics.h:13410
static void restore_gcbo(void)
Definition: graphics.h:13552
void translate_view(const std::string &mode, double x0, double x1, double y0, double y1, bool push_to_zoom_stack=true)
Definition: graphics.cc:7879
static void run_event_hooks(void)
Definition: cmd-edit.cc:1470
static double make_handle_fraction(void)
Definition: graphics.cc:2415
bool verticalalignmentmode_is(const std::string &v) const
Definition: graphics.h:7988
static std::set< double > updating_axis_limits
Definition: graphics.cc:7301
Complex xmin(const Complex &x, const Complex &y)
Definition: lo-mappers.cc:263
void set_diaryfile(const octave_value &val)
Definition: graphics.cc:3496
void do_restore_gcbo(void)
Definition: graphics.cc:9492
bool is_cell(void) const
Definition: ov.h:529
double calc_tick_sep(double minval, double maxval)
Definition: graphics.cc:6889
void set_position(const octave_value &val)
Definition: graphics.h:7751
static graphics_handle make_graphics_handle(const std::string &go_name, const graphics_handle &parent, bool integer_figure_handle=false, bool do_createfcn=true, bool do_notify_toolkit=true)
Definition: graphics.h:13223
T & elem(octave_idx_type n)
Definition: Array.h:380
static property_list::pval_map_type factory_defaults(void)
void update_ticklength(void)
Definition: graphics.cc:5759
color_values color_val
Definition: graphics.h:1184
octave_value_list eval_string(const std::string &eval_str, bool silent, int &parse_status, int nargout)
Definition: oct-parse.cc:8810
bool rotationmode_is(const std::string &v) const
Definition: graphics.h:7982
octave_idx_type numel(void) const
Definition: oct-map.h:372
static int height(void)
Definition: display.h:45
OCTINTERP_API octave_value_list Fmax_recursion_depth(const octave_value_list &=octave_value_list(), int=0)
Definition: pt-eval.cc:1270
const octave_base_value const Array< octave_idx_type > &ra_idx octave_int16_scalar & v1
listener_map listeners
Definition: graphics.h:425
bool is_int32_type(void) const
Definition: ov.h:625
function_event(graphics_event::event_fcn fcn, void *data=0)
Definition: graphics.cc:9372
OCTINTERP_API octave_value_list F__formatstring__(const octave_value_list &=octave_value_list(), int=0)
Definition: pr-output.cc:4094
static bool is_handle_visible(const graphics_handle &h)
Definition: graphics.h:13366
bool has_dynamic_property(const std::string &pname)
Definition: graphics.cc:2957
friend class graphics_object
Definition: graphics.h:2960
virtual void delete_children(bool clear=false)
Definition: graphics.h:2602
static void cleanup_waitfor_predelete_listener(const octave_value &listener)
Definition: graphics.cc:11752
static std::string get_graphics_object_type(double val)
Definition: graphics.cc:10185
void set_rotation(const octave_value &val)
Definition: graphics.h:8186
void set_format(const octave_value &val)
Definition: graphics.cc:3552
void update_axis_limits(const std::string &axis_type)
Definition: graphics.cc:7508
static void max_axes_scale(double &s, Matrix &limits, const Matrix &kids, double pbfactor, double dafactor, char limit_type, bool tight)
Definition: graphics.cc:6254
std::string get_units(void) const
Definition: graphics.h:7959
static Matrix default_surface_xdata(void)
Definition: graphics.cc:274
static octave_value make_graphics_object(const std::string &go_name, bool integer_figure_handle, const octave_value_list &args)
Definition: graphics.cc:10436
static std::string default_toolkit(void)
Definition: graphics.h:2347
Cell getfield(const std::string &key) const
Definition: oct-map.cc:258
static double default_screendepth(void)
Definition: graphics.cc:182
void delete_property_listener(const std::string &nm, const octave_value &v, listener_mode mode=POSTSET)
Definition: graphics.h:3445
callback_event(void)
Definition: graphics.cc:9357
graphics_handle do_make_figure_handle(double val, bool do_notify_toolkit)
Definition: graphics.cc:9293
void set_xlabel(const octave_value &val)
Definition: graphics.cc:4922
static void unlock(void)
Definition: graphics.h:13282
void reset_default_properties(void)
Definition: graphics.cc:4657
void delete_text_child(handle_property &h)
Definition: graphics.cc:5176
graphics_handle current_val
Definition: graphics.h:1590
Matrix yscale(const Matrix &m) const
Definition: graphics.h:5038
const_iterator end(void) const
Definition: oct-map.h:305
virtual graphics_handle get_parent(void) const
Definition: graphics.h:3068
virtual void set(const caseless_str &pname, const octave_value &pval)
Definition: graphics.h:2993
void renumber_child(graphics_handle old_gh, graphics_handle new_gh)
Definition: graphics.h:2607
static Matrix default_lim(bool logscale=false)
Definition: graphics.cc:232
void update_axis_limits(const std::string &axis_type)
Definition: graphics.h:3384
std::string get_formatspacing(void) const
Definition: graphics.cc:3569
any_property __plot_stream__
Definition: graphics.h:4086
bool is_function_handle(void) const
Definition: ov.h:686
octave_idx_type rows(void) const
Definition: Array.h:313
property_list get_factory_defaults_list(void) const
Definition: graphics.h:3342
octave_value get(bool all=false) const
Definition: graphics.h:3300
F77_RET_T const double const double double * d
void build_user_defaults_map(property_list::pval_map_type &def, const std::string go_name) const
Definition: graphics.cc:3237
void calc_ticklabels(const array_property &ticks, any_property &labels, bool is_logscale)
Definition: graphics.cc:7123
string_vector all_strings(bool pad=false) const
Definition: ov.h:894
OCTINTERP_API bool do_set(const octave_value &newval)
Definition: graphics.cc:1201
Matrix compute_xlim(void) const
Definition: graphics.cc:8070
graphics_xform get_transform(void) const
Definition: graphics.h:5127
RowVector transpose(void) const
Definition: dColVector.cc:144
bool has_readonly_property(const caseless_str &pname) const
Definition: graphics.h:3347
static int depth(void)
Definition: display.h:55
virtual void update_boundingbox(void)
Definition: graphics.cc:3134
void init(void)
Definition: graphics.cc:4676
void update_normals(void)
Definition: graphics.cc:8516
static void delete_graphics_object(const graphics_handle &h)
Definition: graphics.cc:2628
bool is_handle_visible(void) const
Definition: graphics.cc:3116
#define CONVERT_CDATA_1(ARRAY_T, VAL_FN, IS_REAL)
void do_post_callback(const graphics_handle &h, const std::string &name, const octave_value &data)
Definition: graphics.cc:9596
octave_value get(void) const
Definition: graphics.h:1350
virtual void adopt(const graphics_handle &h)
Definition: graphics.h:3098
Cell cell_value(void) const
Definition: ov.cc:1566
int64NDArray int64_array_value(void) const
Definition: ov.h:879
static void check_limit_vals(double &min_val, double &max_val, double &min_pos, double &max_neg, const octave_value &data)
Definition: graphics.cc:6835
void update_fontunits(const caseless_str &old_units)
Definition: graphics.cc:9138
Array< T > as_column(void) const
Return the array as a column vector.
Definition: Array.h:279
virtual octave_value get(bool all=false) const
Definition: graphics.h:3006
static property_list::pval_map_type factory_defaults(void)
graphics_handle gcf(void)
Definition: graphics.cc:2611
void set_currentfigure(const octave_value &val)
Definition: graphics.cc:3444
virtual void finalize(const graphics_object &go)
Definition: graphics.h:3197
void update_units(const caseless_str &old_units)
Definition: graphics.cc:9111
std::string current_val
Definition: graphics.h:1186
void update_units(const caseless_str &old_units)
Definition: graphics.cc:4598
OCTINTERP_API octave_value_list F__compactformat__(const octave_value_list &=octave_value_list(), int=0)
Definition: pr-output.cc:4085
void pan(const std::string &mode, double factor, bool push_to_zoom_stack=true)
Definition: graphics.cc:7908
bool is_aliminclude(void) const
Definition: graphics.h:3421
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:337
double signum(double x)
Definition: lo-mappers.cc:80
void set_defaults(const std::string &mode)
Definition: graphics.h:3298
void update_aspectratios(void)
Definition: graphics.cc:6278
property_list default_properties
Definition: graphics.h:4986
static void cleanup_waitfor_id(uint32_t id)
Definition: graphics.cc:11704
static void initialize_r(const graphics_handle &h)
Definition: graphics.cc:1793
void execute_createfcn(const octave_value &data=octave_value()) const
Definition: graphics.h:2727
static void free(const graphics_handle &h)
Definition: graphics.h:13188
callback_event(const graphics_handle &h, const octave_value &cb, const octave_value &data=Matrix())
Definition: graphics.cc:9343
virtual octave_value get_default(const caseless_str &) const
Definition: graphics.cc:9192
ColumnVector row_max(void) const
Definition: dMatrix.cc:2790
static bool updating_xlabel_position
Definition: graphics.cc:5836
void execute(void)
Definition: graphics.h:13125
Matrix xform_translate(double x, double y, double z)
Definition: graphics.cc:5273
void set_zlabel(const octave_value &val)
Definition: graphics.cc:4950
void update_units(void)
Definition: graphics.cc:8937
void initialize(const graphics_object &go)
Definition: graphics.cc:8055
octave_idx_type columns(void) const
Definition: ov.h:475
OCTINTERP_API octave_value_list Flasterr(const octave_value_list &=octave_value_list(), int=0)
Definition: error.cc:1950
static bool has_core_property(const caseless_str &pname)
octave_value data
Definition: graphics.h:1423
static bool has_core_property(const caseless_str &pname)
static bool has_core_property(const caseless_str &pname)
void do_pop_figure(const graphics_handle &h)
Definition: graphics.cc:9320
virtual octave_value get_clim(void) const
Definition: graphics.h:2625
void update_paperunits(const caseless_str &old_paperunits)
Definition: graphics.cc:4295
static bool updating_ylabel_position
Definition: graphics.cc:5938
static bool updating_patch_data
Definition: graphics.cc:8306
octave_fields::const_iterator const_iterator
Definition: oct-map.h:179
void initialize(void)
Definition: graphics.h:3449
void update_text_extent(void)
Definition: graphics.cc:8902
F77_RET_T const double const double * f
void do_enable_event_processing(bool enable=true)
Definition: graphics.cc:9720
void add_fcn(void(*fcn)(void))
static Matrix default_patch_vertices(void)
Definition: graphics.cc:320
bool set_property_in_handle(double handle, const std::string &property, const octave_value &arg, const std::string &func)
Definition: graphics.cc:11664
std::list< double >::iterator children_list_iterator
Definition: graphics.h:1709
double value(void) const
Definition: oct-handle.h:70
std::list< graphics_handle >::iterator figure_list_iterator
Definition: graphics.h:13413
const_iterator begin(void) const
Definition: oct-map.h:182
virtual void update(const graphics_object &go, int id)
Definition: graphics.h:3206
void set_style(const octave_value &val)
Definition: graphics.cc:8952
static bool has_core_property(const caseless_str &pname)
graphics_handle get_parent(void) const
Definition: graphics.h:299
virtual octave_value get_zlim(void) const
Definition: graphics.h:2628
std::set< std::string > dynamic_property_names(void) const
Definition: graphics.cc:2951
bool Vdrawnow_requested
Definition: input.cc:114
Matrix get_children(void) const
Definition: graphics.h:2571
bool isfield(const std::string &name) const
Definition: oct-map.h:330
#define octave_Inf
Definition: lo-ieee.h:31
void update_title_position(void)
Definition: graphics.cc:6176
static bool is_figure(double val)
Definition: graphics.cc:2782
int event_processing
Definition: graphics.h:13439
octave_idx_type nfields(void) const
Definition: oct-map.h:327
graphics_toolkit do_get_toolkit(void) const
Definition: graphics.cc:11036
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:395
bool is_bool_type(void) const
Definition: ov.h:645
bool is_real_scalar(void) const
Definition: ov.h:535
ColumnVector cam2xform(const Array< double > &m)
Definition: graphics.cc:5363
void update_units(void)
Definition: graphics.cc:8233
Matrix xrgb
Definition: graphics.h:1079
bool is_beingdeleted(void) const
Definition: graphics.h:2715
void reset_default_properties(void)
Definition: graphics.cc:9180
#define PERSISTENT
Definition: oct-parse.cc:367
std::string string_value(bool force=false) const
Definition: ov.h:897
plist_map_iterator end(void)
Definition: graphics.h:2094
double force_in_range(double x, double lower, double upper)
Definition: graphics.cc:7669
void print_figure(const graphics_object &go, const std::string &term, const std::string &file, bool mono, const std::string &debug_file="") const
Definition: graphics.h:2247
void mark_modified(void)
Definition: graphics.h:3263
static char default_im_data[]
static void gripe_set_invalid(const std::string &pname)
Definition: graphics.cc:67
virtual void delete_listener(const caseless_str &, const octave_value &, listener_mode=POSTSET)
Definition: graphics.cc:3167
ColumnVector xform_vector(void)
Definition: graphics.cc:5243
static void add(fptr f)
octave_value get_factory_default(const caseless_str &name) const
Definition: graphics.h:3325
virtual void adopt(const graphics_handle &h)
Definition: graphics.h:2543
gtk_manager(void)
Definition: graphics.h:2354
bool set(const octave_value &val, bool do_run=true, bool do_notify_toolkit=true)
Definition: graphics.h:1933
static Matrix default_control_position(void)
Definition: graphics.cc:426
bool is_matrix_type(void) const
Definition: ov.h:660
Matrix get_extent_matrix(void) const
Definition: graphics.cc:8109
void do_delete_children(bool clear)
Definition: graphics.cc:1553
void set_callbackobject(const octave_value &val)
Definition: graphics.cc:3414
std::complex< T > ceil(const std::complex< T > &x)
Definition: lo-mappers.h:275
~uicontextmenu(void)
Definition: graphics.cc:8843
octave_value callback_data
Definition: graphics.cc:9365
bool is_string(void) const
Definition: ov.h:562
std::string get_name(void) const
Definition: graphics.h:2242
virtual void update_autopos(const std::string &elem_type)
Definition: graphics.cc:3148
static bool is_handle(const graphics_handle &h)
Definition: graphics.cc:2743
bool is_double_type(void) const
Definition: ov.h:608
static octave_value_list waitfor_listener(const octave_value_list &args, int)
Definition: graphics.cc:11756
octave_value get_default(const caseless_str &name) const
Definition: graphics.cc:6796
Matrix xform_scale(double x, double y, double z)
Definition: graphics.cc:5265
void rotate_view(double delta_az, double delta_el, bool push_to_zoom_stack=true)
Definition: graphics.cc:7974
void update_font(void)
Definition: graphics.cc:8165
static Matrix xform_eye(void)
Definition: graphics.cc:6760
ColumnVector extract_n(octave_idx_type r1, octave_idx_type n) const
Definition: dColVector.cc:185
const T * data(void) const
Definition: Array.h:479
static Matrix default_figure_position(void)
Definition: graphics.cc:395
Matrix compute_ylim(void) const
Definition: graphics.cc:8083
double norm(const ColumnVector &v)
Definition: graphics.cc:5328
int error_state
Definition: error.cc:101
void unzoom(void)
Definition: graphics.cc:7997
void set_yticklabel(const octave_value &val)
Definition: graphics.cc:6591
string_vector & append(const std::string &s)
Definition: str-vec.cc:140
void set_zticklabel(const octave_value &val)
Definition: graphics.cc:6609
void execute(void)
Definition: graphics.cc:9406
void set_formatspacing(const octave_value &val)
Definition: graphics.cc:3579
static bool updating_hggroup_limits
Definition: graphics.cc:8638
bool is_complex_type(void) const
Definition: ov.h:654
radio_values radio_val
Definition: graphics.h:1185
virtual octave_value get_factory_default(const caseless_str &) const
Definition: graphics.cc:9201
void resize(const dim_vector &dv, const T &rfv)
Definition: Array.cc:1033
Matrix do_get_children(bool return_hidden) const
Definition: graphics.cc:1514
static base_graphics_object * make_graphics_object_from_type(const caseless_str &type, const graphics_handle &h=graphics_handle(), const graphics_handle &p=graphics_handle())
Definition: graphics.cc:1004
octave_value get_clim(void) const
Definition: graphics.h:3409
Cell values_as_cell(void) const
Definition: graphics.cc:1148
octave_int< T > pow(const octave_int< T > &a, const octave_int< T > &b)
std::list< double > children_list
Definition: graphics.h:1711
std::string get_format(void) const
Definition: graphics.cc:3546
double get_fontsize_points(double box_pix_height=0) const
Definition: graphics.cc:8269
bool is_yliminclude(void) const
Definition: graphics.h:3430
octave_value get_alim(void) const
Definition: graphics.h:3406
const_iterator end(void) const
Definition: oct-map.h:183
bool is_int64_type(void) const
Definition: ov.h:628
bool is_cellstr(void) const
Definition: ov.h:532
octave_value_list splice(octave_idx_type offset, octave_idx_type len, const octave_value_list &lst=octave_value_list()) const
Definition: oct-obj.cc:126
static Matrix default_panel_position(void)
Definition: graphics.cc:450
void set_font(const std::string &name, const std::string &weight, const std::string &angle, double size)
Definition: txt-eng-ft.cc:322
void set_defaults(base_graphics_object &obj, const std::string &mode)
Definition: graphics.cc:4978
Matrix transpose(void) const
Definition: dMatrix.h:114
void update_data(void)
Definition: graphics.cc:8393
virtual base_properties & get_properties(void)
Definition: graphics.h:3125
std::map< std::string, graphics_toolkit >::const_iterator const_loaded_toolkits_iterator
Definition: graphics.h:2399
static bool has_core_property(const caseless_str &pname)
static bool has_core_property(const caseless_str &pname)
void set_toolkit(const graphics_toolkit &b)
Definition: graphics.cc:1809
static octave_value convert_linestyleorder_string(const octave_value &val)
Definition: graphics.cc:6629
static Matrix default_figure_papersize(void)
Definition: graphics.cc:406
base_properties & get_properties(void)
Definition: graphics.h:3377
virtual void remove_child(const graphics_handle &h)
Definition: graphics.h:2534
static void get_array_limits(const Array< T > &m, double &emin, double &emax, double &eminp, double &emaxp)
Definition: graphics.cc:897
static bool lookup_object_name(const caseless_str &name, caseless_str &go_name, caseless_str &rest)
Definition: graphics.cc:926
static void xset(const graphics_handle &h, const caseless_str &name, const octave_value &val)
Definition: graphics.cc:2546
void reset_default_properties(void)
Definition: graphics.h:3455
virtual text_element * parse(const std::string &s)=0
octave_value get_default(const caseless_str &name) const
Definition: graphics.cc:9164
octave_idx_type length(void) const
Definition: ov.cc:1525
static Matrix handle_list(bool show_hidden=false)
Definition: graphics.h:13262
void update_camera(void)
Definition: graphics.cc:5377
graphics_toolkit toolkit
Definition: graphics.h:4907
Definition: dMatrix.h:35
void zoom_about_point(const std::string &mode, double x, double y, double factor, bool push_to_zoom_stack=true)
Definition: graphics.cc:7732
void renumber_parent(graphics_handle new_gh)
Definition: graphics.h:2612
void do_unregister_toolkit(const std::string &name)
Definition: graphics.cc:11087
OCTAVE_API double D_NINT(double x)
Definition: lo-mappers.h:240
octave_value lookup(const caseless_str &name) const
Definition: graphics.cc:2025
static Matrix default_surface_ydata(void)
Definition: graphics.cc:285
static graphics_event create_function_event(event_fcn fcn, void *data=0)
Definition: graphics.cc:9458
static Matrix convert_text_position(const Matrix &pos, const text::properties &props, const caseless_str &from_units, const caseless_str &to_units)
Definition: graphics.cc:666
OCTINTERP_API octave_value_list F__diarystate__(const octave_value_list &=octave_value_list(), int=0)
Definition: pager.cc:605
ColumnVector cross(const ColumnVector &v1, const ColumnVector &v2)
Definition: graphics.cc:5334
graphics_object get_ancestor(const std::string &type) const
Definition: graphics.cc:3394
const_iterator begin(void) const
Definition: oct-map.h:304
octave_value get_zlim(void) const
Definition: graphics.h:3418
static dim_vector alloc(int n)
Definition: dim-vector.h:256
static Matrix default_colororder(void)
Definition: graphics.cc:205
void update_fontunits(const caseless_str &old_units)
Definition: graphics.cc:9002
void override_defaults(base_graphics_object &obj)
Definition: graphics.h:3265
dim_vector dims(void) const
Definition: ov.h:470
double get_fontsize_points(double box_pix_height=0) const
Definition: graphics.cc:6742
octave_value property_value
Definition: graphics.cc:9429
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:773
#define FIX_LIMITS
std::string get_diary(void) const
Definition: graphics.cc:3463
int calc_dimensions(const graphics_object &go)
Definition: graphics.cc:10619
Matrix map_to_boundingbox(double x, double y) const
Definition: graphics.cc:3913
void set(const caseless_str &name, const octave_value &val)
Definition: graphics.h:3283
void update_zlabel_position(void)
Definition: graphics.cc:6052
static graphics_event create_callback_event(const graphics_handle &h, const std::string &name, const octave_value &data=Matrix())
Definition: graphics.cc:9434
graphics_handle parent
Definition: graphics.h:423
OCTINTERP_API void execute(const octave_value &data=octave_value()) const
Definition: graphics.cc:1599
virtual void reset_default_properties(void)
Definition: graphics.cc:3263
set_event(void)
Definition: graphics.cc:9422
static void execute_callback(const graphics_handle &h, const std::string &name, const octave_value &data=Matrix())
Definition: graphics.h:13301
std::list< double >::const_iterator const_children_list_iterator
Definition: graphics.h:1710
static void cleanup_instance(void)
Definition: graphics.h:13179
static void remove_event_hook(event_hook_fcn f)
Definition: cmd-edit.cc:1453
void remove_child(const graphics_handle &h)
Definition: graphics.cc:5207
void set_position(const octave_value &val, bool do_notify_toolkit=true)
Definition: graphics.cc:3930
static gh_manager * instance
Definition: graphics.h:13404
double arg(double x)
Definition: lo-mappers.h:37
graphics_handle do_make_graphics_handle(const std::string &go_name, const graphics_handle &p, bool integer_figure_handle, bool do_createfcn, bool do_notify_toolkit)
Definition: graphics.cc:9232
void add_dependent_obj(graphics_handle gh)
Definition: graphics.h:11415
static Matrix convert_position(const Matrix &pos, const caseless_str &from_units, const caseless_str &to_units, const Matrix &parent_dim)
Definition: graphics.cc:521
std::set< std::string > available_toolkits
Definition: graphics.h:2385
octave_value get_string(void) const
Definition: graphics.h:7956
static octave_idx_type find(octave_idx_type i, octave_idx_type *pp)
Definition: colamd.cc:111
octave_function * function_value(bool silent=false) const
Definition: ov.cc:1597
T & xelem(octave_idx_type n)
Definition: Array.h:353
graphics_toolkit get_toolkit(void) const
Definition: graphics.h:3917
virtual void set_defaults(const std::string &)
Definition: graphics.h:3001
double get_fontsize_points(double box_pix_height=0) const
Definition: graphics.cc:9150
bool is_int16_type(void) const
Definition: ov.h:622
static Matrix default_surface_cdata(void)
Definition: graphics.cc:305
octave_value get_deletefcn(void) const
Definition: graphics.h:2731
graphics_handle get_title(void) const
Definition: graphics.h:5606
void set_units(const octave_value &val)
Definition: graphics.cc:4584
static void magform(double x, double &a, int &b)
Definition: graphics.cc:6870
octave_value get_default(const caseless_str &name) const
Definition: graphics.cc:4641
void warning(const char *fmt,...)
Definition: error.cc:681
void do_post_set(const graphics_handle &h, const std::string &name, const octave_value &value, bool notify_toolkit=true)
Definition: graphics.cc:9646
static std::map< caseless_str, graphics_object > dprop_obj_map
Definition: graphics.cc:1624
virtual void finalize(const graphics_object &)
Definition: graphics.h:2178
string_property __graphics_toolkit__
Definition: graphics.h:4084
void update_ylabel_position(void)
Definition: graphics.cc:5941
Matrix get_boundingbox(bool internal=false, const Matrix &parent_pix_size=Matrix()) const
Definition: graphics.cc:9028
double xminp
Definition: graphics.h:1426
void set_xticklabel(const octave_value &val)
Definition: graphics.cc:6573
std::string type(void) const
Definition: graphics.h:3397
ColumnVector untransform(double x, double y, double z, bool use_scale=true) const
Definition: graphics.cc:6780
static std::string dir_sep_chars(void)
Definition: file-ops.h:68
bool valid_object(void) const
Definition: graphics.h:3395
std::string current_val
Definition: graphics.h:1316
Handles the reference counting for all the derived classes.
Definition: Array.h:45
void get_children_limits(double &min_val, double &max_val, double &min_pos, double &max_neg, const Matrix &kids, char limit_type)
Definition: graphics.cc:7218
std::string type_name(void) const
Definition: ov.h:1047
std::string property_name
Definition: graphics.cc:9428
double get_rotation(void) const
Definition: graphics.h:7954
OCTINTERP_API bool validate(const octave_value &v)
Definition: graphics.cc:1319
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
static graphics_handle make_figure_handle(double val, bool do_notify_toolkit=true)
Definition: graphics.h:13236
bool is_empty(void) const
Definition: ov.h:526
bool is_bool_scalar(void) const
Definition: ov.h:547
static bool has_core_property(const caseless_str &pname)
static void close_figure(const graphics_handle &handle)
Definition: graphics.cc:2673
#define octave_stdout
Definition: pager.h:144
const octave_char_matrix & v2
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:779
static property_list::pval_map_type factory_defaults(void)
void update_autopos(const std::string &elem_type)
Definition: graphics.cc:6224
octave_value_list ovl(const octave_value &a0)
Definition: oct-obj.h:178
octave_value callback
Definition: graphics.cc:9364
bool xfinite(double x)
Definition: lo-mappers.cc:152
static void cleanup_instance(void)
Definition: graphics.h:2377
std::string values_as_string(void) const
Definition: graphics.h:1937
void do_close_all_figures(void)
Definition: graphics.cc:2693
double max(void) const
Definition: dColVector.cc:284
void do_push_figure(const graphics_handle &h)
Definition: graphics.cc:9312
static void do_cleanup_waitfor_listener(const octave_value &listener, listener_mode mode=POSTSET)
Definition: graphics.cc:11710
std::string default_val
Definition: graphics.h:935
bool ok(void) const
Definition: graphics.h:13128
#define octave_NaN
Definition: lo-ieee.h:37
double dot(const ColumnVector &v1, const ColumnVector &v2)
Definition: graphics.cc:5322
void set_outerposition(const octave_value &val, bool do_notify_toolkit=true)
Definition: graphics.cc:3963
virtual std::string value_as_string(const std::string &prop)
Definition: graphics.cc:3311
void set_title(const octave_value &val)
Definition: graphics.cc:4964
virtual bool initialize(const graphics_object &)
Definition: graphics.h:2170
static octave_value xget(const graphics_handle &h, const caseless_str &name)
Definition: graphics.cc:2564
std::map< std::string, pval_map_type > plist_map_type
Definition: graphics.h:2074
static octave_value convert_ticklabel_string(const octave_value &val)
Definition: graphics.cc:6522
void calc_ticks_and_lims(array_property &lims, array_property &ticks, array_property &mticks, bool limmode_is_auto, bool is_logscale)
Definition: graphics.cc:7020
properties xproperties
Definition: graphics.h:4911
void cross_product(double x1, double y1, double z1, double x2, double y2, double z2, double &x, double &y, double &z)
Definition: graphics.cc:8506
void set_fontunits(const octave_value &val)
Definition: graphics.cc:8988
static void xinitialize(const graphics_handle &h)
Definition: graphics.cc:2797
void remove_child(const graphics_handle &h)
Definition: graphics.h:3367
bool is_uint8_type(void) const
Definition: ov.h:631
void push_zoom_stack(void)
Definition: graphics.cc:7775
static Matrix default_image_cdata(void)
Definition: graphics.cc:259
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:225
static property_list::pval_map_type factory_defaults(void)
static graphics_handle lookup(double val)
Definition: graphics.h:13201
virtual graphics_toolkit get_toolkit(void) const
Definition: graphics.cc:3123
static OCTINTERP_API property create(const std::string &name, const graphics_handle &parent, const caseless_str &type, const octave_value_list &args)
Definition: graphics.cc:1627
bool is_interruptible(void) const
Definition: graphics.h:2739
void set_fontunits(const octave_value &val)
Definition: graphics.cc:6716
octave_value get_xlim(void) const
Definition: graphics.h:3412
octave_handle graphics_handle
Definition: graphics.h:58
void add_property_listener(const std::string &nm, const octave_value &v, listener_mode mode=POSTSET)
Definition: graphics.h:3441
void normalize(ColumnVector &v)
Definition: graphics.cc:5315
OCTINTERP_API bool set(const octave_value &v, bool do_run=true, bool do_notify_toolkit=true)
Definition: graphics.cc:1046
octave_map values_as_struct(void)
Definition: graphics.h:3359
octave_value get_ylim(void) const
Definition: graphics.h:3415
int do_process_events(bool force=false)
Definition: graphics.cc:9656
static bool compare_property_values(const octave_value &o1, const octave_value &o2)
Definition: graphics.cc:11686
static void adopt(const graphics_handle &p, const graphics_handle &h)
Definition: graphics.cc:2736
void set_value_or_default(const caseless_str &name, const octave_value &val)
Definition: graphics.cc:2354
static OCTINTERP_API void create_instance(void)
Definition: graphics.cc:11027
void remove_child(const graphics_handle &h)
Definition: graphics.cc:3787
OCTINTERP_API octave_value_list F__echostate__(const octave_value_list &=octave_value_list(), int=0)
Definition: input.cc:1035
virtual octave_value get_ylim(void) const
Definition: graphics.h:2627
property(void)
Definition: graphics.h:1883
Matrix map_from_boundingbox(double x, double y) const
Definition: graphics.cc:3896
virtual void mark_modified(void)
Definition: graphics.h:2966
static graphics_handle get_handle(bool integer_figure_handle)
Definition: graphics.h:13181
Matrix get_all_children(void) const
Definition: graphics.h:2576
void update_papertype(void)
Definition: graphics.cc:4350
void adopt(const graphics_handle &h)
Definition: graphics.cc:3815
std::string callback_name
Definition: graphics.cc:9363
void set_units(const octave_value &val)
Definition: graphics.cc:9097
bool is_dir(void) const
Definition: file-stat.cc:56
static property_list::pval_map_type factory_defaults(void)
void remove_child(const graphics_handle &h)
Definition: graphics.cc:3746
bool compare(const std::string &s, size_t limit=std::string::npos) const
Definition: caseless-str.h:76
bool is_modified(void) const
Definition: graphics.h:2532
static void normalized_aspectratios(Matrix &aspectratios, const Matrix &scalefactors, double xlength, double ylength, double zlength)
Definition: graphics.cc:6239
std::string class_name(void) const
Definition: ov.h:1049
Matrix get_extent(text_element *elt, double rotation=0.0)
Definition: txt-eng-ft.cc:919
static void renumber_figure(const graphics_handle &old_gh, const graphics_handle &new_gh)
Definition: graphics.h:13194
OCTINTERP_API octave_value_list Fdiary(const octave_value_list &=octave_value_list(), int=0)
Definition: pager.cc:540
array_property Matrix() callback_property closerequestfcn
static property_list::pval_map_type factory_defaults(void)
void scale(Matrix &m, double x, double y, double z)
Definition: graphics.cc:5281
void set_horizontalalignment(const octave_value &val)
Definition: graphics.h:8125
void clear_zoom_stack(bool do_unzoom=true)
Definition: graphics.cc:8033
bool any_element_is_inf_or_nan(void) const
Definition: dNDArray.cc:570
void set_verticalalignment(const octave_value &val)
Definition: graphics.h:8226
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:197
ColumnVector row_min(void) const
Definition: dMatrix.cc:2735
graphics_handle handle
Definition: graphics.cc:9427
static graphics_object get_object(double val)
Definition: graphics.h:13212
bool is_undefined(void) const
Definition: ov.h:523
bool is_uint64_type(void) const
Definition: ov.h:640
void set_paperunits(const octave_value &val)
Definition: graphics.cc:3976
void set_boundingbox(const Matrix &bb, bool internal=false, bool do_notify_toolkit=true)
Definition: graphics.cc:3878
bool empty(void) const
static property_list::pval_map_type factory_defaults(void)
static property_list factory_properties
Definition: graphics.h:3895
std::string values_as_string(void)
Definition: graphics.h:3352
ColumnVector transform(const Matrix &m, double x, double y, double z)
Definition: graphics.cc:5259
static void xreset_default_properties(graphics_handle gh, property_list::pval_map_type factory_pval)
Definition: graphics.cc:2832
void do_execute_callback(const graphics_handle &h, const octave_value &cb, const octave_value &data)
Definition: graphics.cc:9518
virtual void update_axis_limits(const std::string &axis_type) const
Definition: graphics.cc:3082
listener_mode
Definition: graphics.h:270
float pixel_xsize(void)
Definition: graphics.h:8996
void set_echo(const octave_value &val)
Definition: graphics.cc:3523
void set_text_child(handle_property &h, const std::string &who, const octave_value &v)
Definition: graphics.cc:4884
static property_list::pval_map_type factory_defaults(void)
static bool match(const std::string &filename_arg, const std::string &path_elt_arg)
Definition: kpse.cc:1738
octave_value getfield(const std::string &key) const
Definition: oct-map.cc:164
void set_beingdeleted(const octave_value &val)
Definition: graphics.h:2767
octave_value get_color_data(void) const
Definition: graphics.cc:8297
static Matrix do_zoom(double val, double factor, const Matrix &lims, bool is_logscale)
Definition: graphics.cc:7680
void execute(void)
Definition: graphics.cc:9348
void set_ylabel(const octave_value &val)
Definition: graphics.cc:4936
void reparent(const graphics_handle &h)
Definition: graphics.h:3371
std::list< graphics_object > callback_objects
Definition: graphics.h:13436
graphics_handle handle
Definition: graphics.cc:9362
void update_fvc(void)
Definition: graphics.cc:8309
virtual void update_uicontextmenu(void) const
Definition: graphics.cc:3101
std::complex< T > floor(const std::complex< T > &x)
Definition: lo-mappers.h:282
property clone(void) const
Definition: graphics.h:1975
graphics_handle get_handle(void) const
Definition: graphics.h:3363
void update(int id)
Definition: graphics.h:3453
static property_list::pval_map_type factory_defaults(void)
std::map< std::string, graphics_toolkit > loaded_toolkits
Definition: graphics.h:2388
static property_list::pval_map_type factory_defaults(void)
static Cell loaded_toolkits_list(void)
Definition: graphics.h:2336
bool notify_toolkit
Definition: graphics.cc:9430
static std::map< uint32_t, bool > waitfor_results
Definition: graphics.cc:11701
octave_value get_color_data(void) const
Definition: graphics.cc:8500
std::list< graphics_handle > figure_list
Definition: graphics.h:13427
graphics_handle get___myhandle__(void) const
Definition: graphics.h:2764
void set_modified(const octave_value &val)
Definition: graphics.h:2586
OCTINTERP_API radio_values(const std::string &opt_string=std::string())
Definition: graphics.cc:1084
void redraw_figure(const graphics_object &go) const
Definition: graphics.h:2244
const T * fortran_vec(void) const
Definition: Array.h:481
static OCTINTERP_API gtk_manager * instance
Definition: graphics.h:2379
octave_fields::const_iterator const_iterator
Definition: oct-map.h:301
bool is_single_type(void) const
Definition: ov.h:611
MArray< T > reshape(const dim_vector &new_dims) const
Definition: MArray.h:71
std::string get_echo(void) const
Definition: graphics.cc:3513
Matrix calc_tightbox(const Matrix &init_pos)
Definition: graphics.cc:4766
bool is_showhiddenhandles(void) const
Definition: graphics.h:3619
ColumnVector transform(double x, double y, double z, bool use_scale=true) const
Definition: graphics.cc:6766
std::string get_diaryfile(void) const
Definition: graphics.cc:3490
octave_scalar_map as_struct(const std::string &prefix_arg) const
Definition: graphics.cc:2118
static double convert_font_size(double font_size, const caseless_str &from_units, const caseless_str &to_units, double parent_height=0)
Definition: graphics.cc:463
void set_positionmode(const octave_value &val)
Definition: graphics.h:8320
#define OCTAVE_QUIT
Definition: quit.h:130
double double_value(bool frc_str_conv=false) const
Definition: ov.h:759
static Matrix screen_size_pixels(void)
Definition: graphics.cc:758
void set_recursionlimit(const octave_value &val)
Definition: graphics.cc:3608
static octave_value_list waitfor_del_listener(const octave_value_list &args, int)
Definition: graphics.cc:11798
gh_manager(void)
Definition: graphics.cc:9210
graphics_handle get_handle(void) const
Definition: graphics.h:3079
bool is_uint32_type(void) const
Definition: ov.h:637
virtual octave_scalar_map values_as_struct(void)
Definition: graphics.cc:3340
void octave_usleep(unsigned int useconds)
Definition: cutils.c:42
std::string get_name(void) const
Definition: graphics.h:295
base_properties & get_properties(void)
Definition: graphics.h:4969
OCTINTERP_API bool validate(const octave_value &v) const
Definition: graphics.cc:1570
bool discard_error_messages
Definition: error.cc:118
virtual bool has_property(const caseless_str &) const
Definition: graphics.h:2526
std::string join(const std::string &sep=std::string()) const
Definition: str-vec.cc:167
static bool has_core_property(const caseless_str &pname)
octave_value as_octave_value(void) const
Definition: oct-handle.h:72
Matrix get_ticklabel_extents(const Matrix &ticks, const string_vector &ticklabels, const Matrix &limits)
Definition: graphics.cc:7179
uint32NDArray uint32_array_value(void) const
Definition: ov.h:888
octave_value callback
Definition: graphics.h:1872
bool is_zliminclude(void) const
Definition: graphics.h:3433
T abs(T x)
Definition: pr-output.cc:3062
void build_user_defaults_map(property_list::pval_map_type &def, const std::string go_name) const
Definition: graphics.h:3275
Matrix get_boundingbox(bool internal=false, const Matrix &parent_pix_size=Matrix()) const
Definition: graphics.cc:3861
static bool updating_title_position
Definition: graphics.cc:6173
virtual std::string values_as_string(void)
Definition: graphics.cc:3276
int length(void) const
Definition: dim-vector.h:281
static property_list::pval_map_type factory_defaults(void)
static Matrix default_surface_zdata(void)
Definition: graphics.cc:296
Complex atan(const Complex &x)
Definition: lo-mappers.cc:231
static int width(void)
Definition: display.h:50
static void lock(void)
Definition: graphics.h:13268
uint16NDArray uint16_array_value(void) const
Definition: ov.h:885
Matrix get_boundingbox(bool internal=false, const Matrix &parent_pix_size=Matrix()) const
Definition: graphics.cc:3714
static void xcreatefcn(const graphics_handle &h)
Definition: graphics.cc:2790
octave_idx_type columns(void) const
Definition: Array.h:322
static bool is_handle_visible(const graphics_handle &h)
Definition: graphics.cc:9789
static bool has_core_property(const caseless_str &pname)
void update_fontunits(void)
bool is_xliminclude(void) const
Definition: graphics.h:3427
plist_map_type::const_iterator plist_map_const_iterator
Definition: graphics.h:2080
void set_parent(const octave_value &val)
Definition: graphics.cc:3003
void xform(ColumnVector &v, const Matrix &m)
Definition: graphics.cc:5293
static graphics_handle current_figure(void)
Definition: graphics.h:13256
static void finalize_r(const graphics_handle &h)
Definition: graphics.cc:1777
void set_from_list(base_graphics_object &obj, property_list &defaults)
Definition: graphics.cc:2877
void translate(Matrix &m, double x, double y, double z)
Definition: graphics.cc:5287
graphics_handle get_ylabel(void) const
Definition: graphics.h:5667
static double x_dpi(void)
Definition: display.h:60
graphics_handle handle_value(void) const
Definition: graphics.h:1568
static ColumnVector convert_label_position(const ColumnVector &p, const text::properties &props, const graphics_xform &xform, const Matrix &bbox)
Definition: graphics.cc:5808
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
Matrix inverse(void) const
Definition: dMatrix.cc:651
static void delete_graphics_objects(const NDArray vals)
Definition: graphics.cc:2666
bool horizontalalignmentmode_is(const std::string &v) const
Definition: graphics.h:7985
F77_RET_T const double * x
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:210
static property_list::pval_map_type factory_defaults(void)
void update_papersize(void)
Definition: graphics.cc:4368
static Matrix default_patch_faces(void)
Definition: graphics.cc:311
static void create_instance(void)
Definition: graphics.cc:9223
void resize(octave_idx_type n, const double &rfv=0)
Definition: dColVector.h:106
OCTINTERP_API bool do_set(const octave_value &v)
Definition: graphics.cc:1474
OCTINTERP_API void get_data_limits(void)
Definition: graphics.cc:1434
Matrix get_boundingbox(bool internal=false, const Matrix &parent_pix_size=Matrix()) const
Definition: graphics.cc:6406
void F(const TSRC *v, TRES *r, octave_idx_type m, octave_idx_type n)
Definition: mx-inlines.cc:527
static bool has_core_property(const caseless_str &pname)
static int process_events(void)
Definition: graphics.h:13350
static Matrix jet_colormap(void)
Definition: graphics.cc:137
bool is_integer_type(void) const
Definition: ov.h:648
static property_list::plist_map_type init_factory_properties(void)
Definition: graphics.cc:9740