GNU Octave  3.8.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.in.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2007-2013 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 #if !defined (octave_graphics_h)
24 #define octave_graphics_h 1
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #include <cctype>
31 
32 #include <algorithm>
33 #include <list>
34 #include <map>
35 #include <set>
36 #include <sstream>
37 #include <string>
38 
39 #include "caseless-str.h"
40 
41 #include "gripes.h"
42 #include "oct-handle.h"
43 #include "oct-map.h"
44 #include "oct-mutex.h"
45 #include "oct-refcount.h"
46 #include "ov.h"
47 #include "txt-eng-ft.h"
48 
49 // FIXME: maybe this should be a configure option?
50 // Matlab defaults to "Helvetica", but that causes problems for many
51 // gnuplot users.
52 #if !defined (OCTAVE_DEFAULT_FONTNAME)
53 #define OCTAVE_DEFAULT_FONTNAME "*"
54 #endif
55 
57 
58 // ---------------------------------------------------------------------
59 
60 class base_scaler
61 {
62 public:
63  base_scaler (void) { }
64 
65  virtual ~base_scaler (void) { }
66 
67  virtual Matrix scale (const Matrix& m) const
68  {
69  error ("invalid axis scale");
70  return m;
71  }
72 
73  virtual NDArray scale (const NDArray& m) const
74  {
75  error ("invalid axis scale");
76  return m;
77  }
78 
79  virtual double scale (double d) const
80  {
81  error ("invalid axis scale");
82  return d;
83  }
84 
85  virtual double unscale (double d) const
86  {
87  error ("invalid axis scale");
88  return d;
89  }
90 
91  virtual base_scaler* clone () const
92  { return new base_scaler (); }
93 
94  virtual bool is_linear (void) const
95  { return false; }
96 };
97 
98 class lin_scaler : public base_scaler
99 {
100 public:
101  lin_scaler (void) { }
102 
103  Matrix scale (const Matrix& m) const { return m; }
104 
105  NDArray scale (const NDArray& m) const { return m; }
106 
107  double scale (double d) const { return d; }
108 
109  double unscale (double d) const { return d; }
110 
111  base_scaler* clone (void) const { return new lin_scaler (); }
112 
113  bool is_linear (void) const { return true; }
114 };
115 
116 class log_scaler : public base_scaler
117 {
118 public:
119  log_scaler (void) { }
120 
121  Matrix scale (const Matrix& m) const
122  {
123  Matrix retval (m.rows (), m.cols ());
124 
125  do_scale (m.data (), retval.fortran_vec (), m.numel ());
126 
127  return retval;
128  }
129 
130  NDArray scale (const NDArray& m) const
131  {
132  NDArray retval (m.dims ());
133 
134  do_scale (m.data (), retval.fortran_vec (), m.numel ());
135 
136  return retval;
137  }
138 
139  double scale (double d) const
140  { return log10 (d); }
141 
142  double unscale (double d) const
143  { return pow (10.0, d); }
144 
145  base_scaler* clone (void) const
146  { return new log_scaler (); }
147 
148 private:
149  void do_scale (const double *src, double *dest, int n) const
150  {
151  for (int i = 0; i < n; i++)
152  dest[i] = log10 (src[i]);
153  }
154 };
155 
156 class neg_log_scaler : public base_scaler
157 {
158 public:
159  neg_log_scaler (void) { }
160 
161  Matrix scale (const Matrix& m) const
162  {
163  Matrix retval (m.rows (), m.cols ());
164 
165  do_scale (m.data (), retval.fortran_vec (), m.numel ());
166 
167  return retval;
168  }
169 
170  NDArray scale (const NDArray& m) const
171  {
172  NDArray retval (m.dims ());
173 
174  do_scale (m.data (), retval.fortran_vec (), m.numel ());
175 
176  return retval;
177  }
178 
179  double scale (double d) const
180  { return -log10 (-d); }
181 
182  double unscale (double d) const
183  { return -pow (10.0, -d); }
184 
185  base_scaler* clone (void) const
186  { return new neg_log_scaler (); }
187 
188 private:
189  void do_scale (const double *src, double *dest, int n) const
190  {
191  for (int i = 0; i < n; i++)
192  dest[i] = -log10 (-src[i]);
193  }
194 };
195 
196 class scaler
197 {
198 public:
199  scaler (void) : rep (new base_scaler ()) { }
200 
201  scaler (const scaler& s) : rep (s.rep->clone ()) { }
202 
203  scaler (const std::string& s)
204  : rep (s == "log"
205  ? new log_scaler ()
206  : (s == "neglog" ? new neg_log_scaler ()
207  : (s == "linear" ? new lin_scaler () : new base_scaler ())))
208  { }
209 
210  ~scaler (void) { delete rep; }
211 
212  Matrix scale (const Matrix& m) const
213  { return rep->scale (m); }
214 
215  NDArray scale (const NDArray& m) const
216  { return rep->scale (m); }
217 
218  double scale (double d) const
219  { return rep->scale (d); }
220 
221  double unscale (double d) const
222  { return rep->unscale (d); }
223 
224  bool is_linear (void) const
225  { return rep->is_linear (); }
226 
228  {
229  if (rep)
230  {
231  delete rep;
232  rep = 0;
233  }
234 
235  rep = s.rep->clone ();
236 
237  return *this;
238  }
239 
240  scaler& operator = (const std::string& s)
241  {
242  if (rep)
243  {
244  delete rep;
245  rep = 0;
246  }
247 
248  if (s == "log")
249  rep = new log_scaler ();
250  else if (s == "neglog")
251  rep = new neg_log_scaler ();
252  else if (s == "linear")
253  rep = new lin_scaler ();
254  else
255  rep = new base_scaler ();
256 
257  return *this;
258  }
259 
260 private:
261  base_scaler *rep;
262 };
263 
264 // ---------------------------------------------------------------------
265 
266 class property;
267 
269 
270 class base_property
271 {
272 public:
273  friend class property;
274 
275 public:
277  : id (-1), count (1), name (), parent (), hidden (), listeners ()
278  { }
279 
280  base_property (const std::string& s, const graphics_handle& h)
281  : id (-1), count (1), name (s), parent (h), hidden (false), listeners ()
282  { }
283 
285  : id (-1), count (1), name (p.name), parent (p.parent),
286  hidden (p.hidden), listeners ()
287  { }
288 
289  virtual ~base_property (void) { }
290 
291  bool ok (void) const { return parent.ok (); }
292 
293  std::string get_name (void) const { return name; }
294 
295  void set_name (const std::string& s) { name = s; }
296 
297  graphics_handle get_parent (void) const { return parent; }
298 
299  void set_parent (const graphics_handle &h) { parent = h; }
300 
301  bool is_hidden (void) const { return hidden; }
302 
303  void set_hidden (bool flag) { hidden = flag; }
304 
305  virtual bool is_radio (void) const { return false; }
306 
307  int get_id (void) const { return id; }
308 
309  void set_id (int d) { id = d; }
310 
311  // Sets property value, notifies graphics toolkit.
312  // If do_run is true, runs associated listeners.
313  OCTINTERP_API bool set (const octave_value& v, bool do_run = true,
314  bool do_notify_toolkit = true);
315 
316  virtual octave_value get (void) const
317  {
318  error ("get: invalid property \"%s\"", name.c_str ());
319  return octave_value ();
320  }
321 
322 
323  virtual std::string values_as_string (void) const
324  {
325  error ("values_as_string: invalid property \"%s\"", name.c_str ());
326  return std::string ();
327  }
328 
329  virtual Cell values_as_cell (void) const
330  {
331  error ("values_as_cell: invalid property \"%s\"", name.c_str ());
332  return Cell ();
333  }
334 
336  {
337  set (val);
338  return *this;
339  }
340 
342  {
343  octave_value_list& l = listeners[mode];
344  l.resize (l.length () + 1, v);
345  }
346 
348  listener_mode mode = POSTSET)
349  {
350  octave_value_list& l = listeners[mode];
351 
352  if (v.is_defined ())
353  {
354  bool found = false;
355  int i;
356 
357  for (i = 0; i < l.length (); i++)
358  {
359  if (v.internal_rep () == l(i).internal_rep ())
360  {
361  found = true;
362  break;
363  }
364  }
365  if (found)
366  {
367  for (int j = i; j < l.length () - 1; j++)
368  l(j) = l(j + 1);
369 
370  l.resize (l.length () - 1);
371  }
372  }
373  else
374  {
375  if (mode == PERSISTENT)
376  l.resize (0);
377  else
378  {
379  octave_value_list lnew (0);
381  for (int i = l.length () - 1; i >= 0 ; i--)
382  {
383  for (int j = 0; j < lp.length (); j++)
384  {
385  if (l(i).internal_rep () == lp(j).internal_rep ())
386  {
387  lnew.resize (lnew.length () + 1, l(i));
388  break;
389  }
390  }
391  }
392  l = lnew;
393  }
394  }
395 
396  }
397 
399 
400  virtual base_property* clone (void) const
401  { return new base_property (*this); }
402 
403 protected:
404  virtual bool do_set (const octave_value&)
405  {
406  error ("set: invalid property \"%s\"", name.c_str ());
407  return false;
408  }
409 
410 private:
411  typedef std::map<listener_mode, octave_value_list> listener_map;
412  typedef std::map<listener_mode, octave_value_list>::iterator
414  typedef std::map<listener_mode, octave_value_list>::const_iterator
416 
417 private:
418  int id;
420  std::string name;
422  bool hidden;
424 };
425 
426 // ---------------------------------------------------------------------
427 
428 class string_property : public base_property
429 {
430 public:
431  string_property (const std::string& s, const graphics_handle& h,
432  const std::string& val = "")
433  : base_property (s, h), str (val) { }
434 
436  : base_property (p), str (p.str) { }
437 
438  octave_value get (void) const
439  { return octave_value (str); }
440 
441  std::string string_value (void) const { return str; }
442 
444  {
445  set (val);
446  return *this;
447  }
448 
449  base_property* clone (void) const { return new string_property (*this); }
450 
451 protected:
452  bool do_set (const octave_value& val)
453  {
454  if (val.is_string ())
455  {
456  std::string new_str = val.string_value ();
457 
458  if (new_str != str)
459  {
460  str = new_str;
461  return true;
462  }
463  }
464  else
465  error ("set: invalid string property value for \"%s\"",
466  get_name ().c_str ());
467  return false;
468  }
469 
470 private:
471  std::string str;
472 };
473 
474 // ---------------------------------------------------------------------
475 
477 {
478 public:
480 
481  string_array_property (const std::string& s, const graphics_handle& h,
482  const std::string& val = "", const char& sep = '|',
483  const desired_enum& typ = string_t)
484  : base_property (s, h), desired_type (typ), separator (sep), str ()
485  {
486  size_t pos = 0;
487 
488  while (true)
489  {
490  size_t new_pos = val.find_first_of (separator, pos);
491 
492  if (new_pos == std::string::npos)
493  {
494  str.append (val.substr (pos));
495  break;
496  }
497  else
498  str.append (val.substr (pos, new_pos - pos));
499 
500  pos = new_pos + 1;
501  }
502  }
503 
504  string_array_property (const std::string& s, const graphics_handle& h,
505  const Cell& c, const char& sep = '|',
506  const desired_enum& typ = string_t)
507  : base_property (s, h), desired_type (typ), separator (sep), str ()
508  {
509  if (c.is_cellstr ())
510  {
511  string_vector strings (c.numel ());
512 
513  for (octave_idx_type i = 0; i < c.numel (); i++)
514  strings[i] = c(i).string_value ();
515 
516  str = strings;
517  }
518  else
519  error ("set: invalid order property value for \"%s\"",
520  get_name ().c_str ());
521  }
522 
525  separator (p.separator), str (p.str) { }
526 
527  octave_value get (void) const
528  {
529  if (desired_type == string_t)
530  return octave_value (string_value ());
531  else
532  return octave_value (cell_value ());
533  }
534 
535  std::string string_value (void) const
536  {
537  std::string s;
538 
539  for (octave_idx_type i = 0; i < str.length (); i++)
540  {
541  s += str[i];
542  if (i != str.length () - 1)
543  s += separator;
544  }
545 
546  return s;
547  }
548 
549  Cell cell_value (void) const {return Cell (str);}
550 
551  string_vector string_vector_value (void) const { return str; }
552 
554  {
555  set (val);
556  return *this;
557  }
558 
559  base_property* clone (void) const
560  { return new string_array_property (*this); }
561 
562 protected:
563  bool do_set (const octave_value& val)
564  {
565  if (val.is_string () && val.rows () == 1)
566  {
567  bool replace = false;
568  std::string new_str = val.string_value ();
569  string_vector strings;
570  size_t pos = 0;
571 
572  // Split single string on delimiter (usually '|')
573  while (pos != std::string::npos)
574  {
575  size_t new_pos = new_str.find_first_of (separator, pos);
576 
577  if (new_pos == std::string::npos)
578  {
579  strings.append (new_str.substr (pos));
580  break;
581  }
582  else
583  strings.append (new_str.substr (pos, new_pos - pos));
584 
585  pos = new_pos + 1;
586  }
587 
588  if (str.numel () == strings.numel ())
589  {
590  for (octave_idx_type i = 0; i < str.numel (); i++)
591  if (strings[i] != str[i])
592  {
593  replace = true;
594  break;
595  }
596  }
597  else
598  replace = true;
599 
601 
602  if (replace)
603  {
604  str = strings;
605  return true;
606  }
607  }
608  else if (val.is_string ()) // multi-row character matrix
609  {
610  bool replace = false;
611  charMatrix chm = val.char_matrix_value ();
612  octave_idx_type nel = chm.rows ();
613  string_vector strings (nel);
614 
615  if (nel != str.numel ())
616  replace = true;
617  for (octave_idx_type i = 0; i < nel; i++)
618  {
619  strings[i] = chm.row_as_string (i);
620  if (!replace && strings[i] != str[i])
621  replace = true;
622  }
623 
625 
626  if (replace)
627  {
628  str = strings;
629  return true;
630  }
631  }
632  else if (val.is_cellstr ())
633  {
634  bool replace = false;
635  Cell new_cell = val.cell_value ();
636 
637  string_vector strings = new_cell.cellstr_value ();
638 
639  octave_idx_type nel = strings.length ();
640 
641  if (nel != str.length ())
642  replace = true;
643  else
644  {
645  for (octave_idx_type i = 0; i < nel; i++)
646  {
647  if (strings[i] != str[i])
648  {
649  replace = true;
650  break;
651  }
652  }
653  }
654 
656 
657  if (replace)
658  {
659  str = strings;
660  return true;
661  }
662  }
663  else
664  error ("set: invalid string property value for \"%s\"",
665  get_name ().c_str ());
666  return false;
667  }
668 
669 private:
671  char separator;
673 };
674 
675 // ---------------------------------------------------------------------
676 
677 class text_label_property : public base_property
678 {
679 public:
680  enum type { char_t, cellstr_t };
681 
682  text_label_property (const std::string& s, const graphics_handle& h,
683  const std::string& val = "")
684  : base_property (s, h), value (val), stored_type (char_t)
685  { }
686 
687  text_label_property (const std::string& s, const graphics_handle& h,
688  const NDArray& nda)
689  : base_property (s, h), stored_type (char_t)
690  {
691  octave_idx_type nel = nda.numel ();
692 
693  value.resize (nel);
694 
695  for (octave_idx_type i = 0; i < nel; i++)
696  {
697  std::ostringstream buf;
698  buf << nda(i);
699  value[i] = buf.str ();
700  }
701  }
702 
703  text_label_property (const std::string& s, const graphics_handle& h,
704  const Cell& c)
706  {
707  octave_idx_type nel = c.numel ();
708 
709  value.resize (nel);
710 
711  for (octave_idx_type i = 0; i < nel; i++)
712  {
713  octave_value tmp = c(i);
714 
715  if (tmp.is_string ())
716  value[i] = c(i).string_value ();
717  else
718  {
719  double d = c(i).double_value ();
720 
721  if (! error_state)
722  {
723  std::ostringstream buf;
724  buf << d;
725  value[i] = buf.str ();
726  }
727  else
728  break;
729  }
730  }
731  }
732 
735  { }
736 
737  bool empty (void) const
738  {
739  octave_value tmp = get ();
740  return tmp.is_empty ();
741  }
742 
743  octave_value get (void) const
744  {
745  if (stored_type == char_t)
746  return octave_value (char_value ());
747  else
748  return octave_value (cell_value ());
749  }
750 
751  std::string string_value (void) const
752  {
753  return value.empty () ? std::string () : value[0];
754  }
755 
756  string_vector string_vector_value (void) const { return value; }
757 
758  charMatrix char_value (void) const { return charMatrix (value, ' '); }
759 
760  Cell cell_value (void) const {return Cell (value); }
761 
763  {
764  set (val);
765  return *this;
766  }
767 
768  base_property* clone (void) const { return new text_label_property (*this); }
769 
770 protected:
771 
772  bool do_set (const octave_value& val)
773  {
774  if (val.is_string ())
775  {
776  value = val.all_strings ();
777 
779  }
780  else if (val.is_cell ())
781  {
782  Cell c = val.cell_value ();
783 
784  octave_idx_type nel = c.numel ();
785 
786  value.resize (nel);
787 
788  for (octave_idx_type i = 0; i < nel; i++)
789  {
790  octave_value tmp = c(i);
791 
792  if (tmp.is_string ())
793  value[i] = c(i).string_value ();
794  else
795  {
796  double d = c(i).double_value ();
797 
798  if (! error_state)
799  {
800  std::ostringstream buf;
801  buf << d;
802  value[i] = buf.str ();
803  }
804  else
805  return false;
806  }
807  }
808 
810  }
811  else
812  {
813  NDArray nda = val.array_value ();
814 
815  if (! error_state)
816  {
817  octave_idx_type nel = nda.numel ();
818 
819  value.resize (nel);
820 
821  for (octave_idx_type i = 0; i < nel; i++)
822  {
823  std::ostringstream buf;
824  buf << nda(i);
825  value[i] = buf.str ();
826  }
827 
829  }
830  else
831  {
832  error ("set: invalid string property value for \"%s\"",
833  get_name ().c_str ());
834 
835  return false;
836  }
837  }
838 
839  return true;
840  }
841 
842 private:
845 };
846 
847 // ---------------------------------------------------------------------
848 
849 class radio_values
850 {
851 public:
852  OCTINTERP_API radio_values (const std::string& opt_string = std::string ());
853 
856 
858  {
859  if (&a != this)
860  {
863  }
864 
865  return *this;
866  }
867 
868  std::string default_value (void) const { return default_val; }
869 
870  bool validate (const std::string& val, std::string& match)
871  {
872  bool retval = true;
873 
874  if (! contains (val, match))
875  {
876  error ("invalid value = %s", val.c_str ());
877  retval = false;
878  }
879 
880  return retval;
881  }
882 
883  bool contains (const std::string& val, std::string& match)
884  {
885  size_t k = 0;
886 
887  size_t len = val.length ();
888 
889  std::string first_match;
890 
891  for (std::set<caseless_str>::const_iterator p = possible_vals.begin ();
892  p != possible_vals.end (); p++)
893  {
894  if (p->compare (val, len))
895  {
896  if (len == p->length ())
897  {
898  // We found a full match (consider the case of val ==
899  // "replace" with possible values "replace" and
900  // "replacechildren"). Any other matches are
901  // irrelevant, so set match and return now.
902 
903  match = *p;
904  return true;
905  }
906  else
907  {
908  if (k == 0)
909  first_match = *p;
910 
911  k++;
912  }
913  }
914  }
915 
916  if (k == 1)
917  {
918  match = first_match;
919  return true;
920  }
921  else
922  return false;
923  }
924 
925  std::string values_as_string (void) const;
926 
927  Cell values_as_cell (void) const;
928 
929  octave_idx_type nelem (void) const { return possible_vals.size (); }
930 
931 private:
932  // Might also want to cache
933  std::string default_val;
934  std::set<caseless_str> possible_vals;
935 };
936 
937 class radio_property : public base_property
938 {
939 public:
940  radio_property (const std::string& nm, const graphics_handle& h,
941  const radio_values& v = radio_values ())
942  : base_property (nm, h),
943  vals (v), current_val (v.default_value ()) { }
944 
945  radio_property (const std::string& nm, const graphics_handle& h,
946  const std::string& v)
947  : base_property (nm, h),
948  vals (v), current_val (vals.default_value ()) { }
949 
950  radio_property (const std::string& nm, const graphics_handle& h,
951  const radio_values& v, const std::string& def)
952  : base_property (nm, h),
953  vals (v), current_val (def) { }
954 
956  : base_property (p), vals (p.vals), current_val (p.current_val) { }
957 
958  octave_value get (void) const { return octave_value (current_val); }
959 
960  const std::string& current_value (void) const { return current_val; }
961 
962  std::string values_as_string (void) const { return vals.values_as_string (); }
963 
964  Cell values_as_cell (void) const { return vals.values_as_cell (); }
965 
966  bool is (const caseless_str& v) const
967  { return v.compare (current_val); }
968 
969  bool is_radio (void) const { return true; }
970 
972  {
973  set (val);
974  return *this;
975  }
976 
977  base_property* clone (void) const { return new radio_property (*this); }
978 
979 protected:
980  bool do_set (const octave_value& newval)
981  {
982  if (newval.is_string ())
983  {
984  std::string s = newval.string_value ();
985 
986  std::string match;
987 
988  if (vals.validate (s, match))
989  {
990  if (match != current_val)
991  {
992  if (s.length () != match.length ())
993  warning_with_id ("Octave:abbreviated-property-match",
994  "%s: allowing %s to match %s value %s",
995  "set", s.c_str (), get_name ().c_str (),
996  match.c_str ());
997  current_val = match;
998  return true;
999  }
1000  }
1001  else
1002  error ("set: invalid value for radio property \"%s\" (value = %s)",
1003  get_name ().c_str (), s.c_str ());
1004  }
1005  else
1006  error ("set: invalid value for radio property \"%s\"",
1007  get_name ().c_str ());
1008  return false;
1009  }
1010 
1011 private:
1013  std::string current_val;
1014 };
1015 
1016 // ---------------------------------------------------------------------
1017 
1018 class color_values
1019 {
1020 public:
1021  color_values (double r = 0, double g = 0, double b = 1)
1022  : xrgb (1, 3)
1023  {
1024  xrgb(0) = r;
1025  xrgb(1) = g;
1026  xrgb(2) = b;
1027 
1028  validate ();
1029  }
1030 
1031  color_values (std::string str)
1032  : xrgb (1, 3)
1033  {
1034  if (! str2rgb (str))
1035  error ("invalid color specification: %s", str.c_str ());
1036  }
1037 
1039  : xrgb (c.xrgb)
1040  { }
1041 
1043  {
1044  if (&c != this)
1045  xrgb = c.xrgb;
1046 
1047  return *this;
1048  }
1049 
1050  bool operator == (const color_values& c) const
1051  {
1052  return (xrgb(0) == c.xrgb(0)
1053  && xrgb(1) == c.xrgb(1)
1054  && xrgb(2) == c.xrgb(2));
1055  }
1056 
1057  bool operator != (const color_values& c) const
1058  { return ! (*this == c); }
1059 
1060  Matrix rgb (void) const { return xrgb; }
1061 
1062  operator octave_value (void) const { return xrgb; }
1063 
1064  void validate (void) const
1065  {
1066  for (int i = 0; i < 3; i++)
1067  {
1068  if (xrgb(i) < 0 || xrgb(i) > 1)
1069  {
1070  error ("invalid RGB color specification");
1071  break;
1072  }
1073  }
1074  }
1075 
1076 private:
1077  Matrix xrgb;
1078 
1079  OCTINTERP_API bool str2rgb (std::string str);
1080 };
1081 
1082 class color_property : public base_property
1083 {
1084 public:
1086  : base_property ("", graphics_handle ()),
1088  current_val (v.default_value ())
1089  { }
1090 
1092  : base_property ("", graphics_handle ()),
1094  current_val (v.default_value ())
1095  { }
1096 
1097  color_property (const std::string& nm, const graphics_handle& h,
1098  const color_values& c = color_values (),
1099  const radio_values& v = radio_values ())
1100  : base_property (nm, h),
1102  current_val (v.default_value ())
1103  { }
1104 
1105  color_property (const std::string& nm, const graphics_handle& h,
1106  const radio_values& v)
1107  : base_property (nm, h),
1109  current_val (v.default_value ())
1110  { }
1111 
1112  color_property (const std::string& nm, const graphics_handle& h,
1113  const std::string& v)
1114  : base_property (nm, h),
1116  current_val (radio_val.default_value ())
1117  { }
1118 
1119  color_property (const std::string& nm, const graphics_handle& h,
1120  const color_property& v)
1121  : base_property (nm, h),
1124  { }
1125 
1129  current_val (p.current_val) { }
1130 
1131  octave_value get (void) const
1132  {
1133  if (current_type == color_t)
1134  return color_val.rgb ();
1135 
1136  return current_val;
1137  }
1138 
1139  bool is_rgb (void) const { return (current_type == color_t); }
1140 
1141  bool is_radio (void) const { return (current_type == radio_t); }
1142 
1143  bool is (const std::string& v) const
1144  { return (is_radio () && current_val == v); }
1145 
1146  Matrix rgb (void) const
1147  {
1148  if (current_type != color_t)
1149  error ("color has no rgb value");
1150 
1151  return color_val.rgb ();
1152  }
1153 
1154  const std::string& current_value (void) const
1155  {
1156  if (current_type != radio_t)
1157  error ("color has no radio value");
1158 
1159  return current_val;
1160  }
1161 
1163  {
1164  set (val);
1165  return *this;
1166  }
1167 
1168  operator octave_value (void) const { return get (); }
1169 
1170  base_property* clone (void) const { return new color_property (*this); }
1171 
1172  std::string values_as_string (void) const
1173  { return radio_val.values_as_string (); }
1174 
1175  Cell values_as_cell (void) const { return radio_val.values_as_cell (); }
1176 
1177 protected:
1178  OCTINTERP_API bool do_set (const octave_value& newval);
1179 
1180 private:
1184  std::string current_val;
1185 };
1186 
1187 // ---------------------------------------------------------------------
1188 
1189 class double_property : public base_property
1190 {
1191 public:
1192  double_property (const std::string& nm, const graphics_handle& h,
1193  double d = 0)
1194  : base_property (nm, h),
1195  current_val (d) { }
1196 
1198  : base_property (p), current_val (p.current_val) { }
1199 
1200  octave_value get (void) const { return octave_value (current_val); }
1201 
1202  double double_value (void) const { return current_val; }
1203 
1205  {
1206  set (val);
1207  return *this;
1208  }
1209 
1210  base_property* clone (void) const { return new double_property (*this); }
1211 
1212 protected:
1213  bool do_set (const octave_value& v)
1214  {
1215  if (v.is_scalar_type () && v.is_real_type ())
1216  {
1217  double new_val = v.double_value ();
1218 
1219  if (new_val != current_val)
1220  {
1221  current_val = new_val;
1222  return true;
1223  }
1224  }
1225  else
1226  error ("set: invalid value for double property \"%s\"",
1227  get_name ().c_str ());
1228  return false;
1229  }
1230 
1231 private:
1232  double current_val;
1233 };
1234 
1235 // ---------------------------------------------------------------------
1236 
1237 class double_radio_property : public base_property
1238 {
1239 public:
1241  : base_property ("", graphics_handle ()),
1242  current_type (double_t), dval (d), radio_val (v),
1243  current_val (v.default_value ())
1244  { }
1245 
1246  double_radio_property (const std::string& nm, const graphics_handle& h,
1247  const std::string& v)
1248  : base_property (nm, h),
1249  current_type (radio_t), dval (0), radio_val (v),
1250  current_val (radio_val.default_value ())
1251  { }
1252 
1253  double_radio_property (const std::string& nm, const graphics_handle& h,
1254  const double_radio_property& v)
1255  : base_property (nm, h),
1258  { }
1259 
1262  dval (p.dval), radio_val (p.radio_val),
1263  current_val (p.current_val) { }
1264 
1265  octave_value get (void) const
1266  {
1267  if (current_type == double_t)
1268  return dval;
1269 
1270  return current_val;
1271  }
1272 
1273  bool is_double (void) const { return (current_type == double_t); }
1274 
1275  bool is_radio (void) const { return (current_type == radio_t); }
1276 
1277  bool is (const std::string& v) const
1278  { return (is_radio () && current_val == v); }
1279 
1280  double double_value (void) const
1281  {
1282  if (current_type != double_t)
1283  error ("%s: property has no double", get_name ().c_str ());
1284 
1285  return dval;
1286  }
1287 
1288  const std::string& current_value (void) const
1289  {
1290  if (current_type != radio_t)
1291  error ("%s: property has no radio value");
1292 
1293  return current_val;
1294  }
1295 
1297  {
1298  set (val);
1299  return *this;
1300  }
1301 
1302  operator octave_value (void) const { return get (); }
1303 
1304  base_property* clone (void) const
1305  { return new double_radio_property (*this); }
1306 
1307 protected:
1308  OCTINTERP_API bool do_set (const octave_value& v);
1309 
1310 private:
1312  double dval;
1314  std::string current_val;
1315 };
1316 
1317 // ---------------------------------------------------------------------
1318 
1319 class array_property : public base_property
1320 {
1321 public:
1323  : base_property ("", graphics_handle ()), data (Matrix ()),
1324  xmin (), xmax (), xminp (), xmaxp (),
1326  {
1327  get_data_limits ();
1328  }
1329 
1330  array_property (const std::string& nm, const graphics_handle& h,
1331  const octave_value& m)
1332  : base_property (nm, h), data (m.is_sparse_type () ? m.full_value () : m),
1333  xmin (), xmax (), xminp (), xmaxp (),
1335  {
1336  get_data_limits ();
1337  }
1338 
1339  // This copy constructor is only intended to be used
1340  // internally to access min/max values; no need to
1341  // copy constraints.
1343  : base_property (p), data (p.data),
1344  xmin (p.xmin), xmax (p.xmax), xminp (p.xminp), xmaxp (p.xmaxp),
1346  { }
1347 
1348  octave_value get (void) const { return data; }
1349 
1350  void add_constraint (const std::string& type)
1351  { type_constraints.insert (type); }
1352 
1353  void add_constraint (const dim_vector& dims)
1354  { size_constraints.push_back (dims); }
1355 
1356  double min_val (void) const { return xmin; }
1357  double max_val (void) const { return xmax; }
1358  double min_pos (void) const { return xminp; }
1359  double max_neg (void) const { return xmaxp; }
1360 
1361  Matrix get_limits (void) const
1362  {
1363  Matrix m (1, 4);
1364 
1365  m(0) = min_val ();
1366  m(1) = max_val ();
1367  m(2) = min_pos ();
1368  m(3) = max_neg ();
1369 
1370  return m;
1371  }
1372 
1374  {
1375  set (val);
1376  return *this;
1377  }
1378 
1379  base_property* clone (void) const
1380  {
1381  array_property *p = new array_property (*this);
1382 
1385 
1386  return p;
1387  }
1388 
1389 protected:
1390  bool do_set (const octave_value& v)
1391  {
1392  octave_value tmp = v.is_sparse_type () ? v.full_value () : v;
1393 
1394  if (validate (tmp))
1395  {
1396  // FIXME: should we check for actual data change?
1397  if (! is_equal (tmp))
1398  {
1399  data = tmp;
1400 
1401  get_data_limits ();
1402 
1403  return true;
1404  }
1405  }
1406  else
1407  error ("invalid value for array property \"%s\"",
1408  get_name ().c_str ());
1409 
1410  return false;
1411  }
1412 
1413 private:
1414  OCTINTERP_API bool validate (const octave_value& v);
1415 
1416  OCTINTERP_API bool is_equal (const octave_value& v) const;
1417 
1418  OCTINTERP_API void get_data_limits (void);
1419 
1420 protected:
1422  double xmin;
1423  double xmax;
1424  double xminp;
1425  double xmaxp;
1426  std::set<std::string> type_constraints;
1427  std::list<dim_vector> size_constraints;
1428 };
1429 
1430 class row_vector_property : public array_property
1431 {
1432 public:
1433  row_vector_property (const std::string& nm, const graphics_handle& h,
1434  const octave_value& m)
1435  : array_property (nm, h, m)
1436  {
1437  add_constraint (dim_vector (-1, 1));
1438  add_constraint (dim_vector (1, -1));
1439  add_constraint (dim_vector (0, 0));
1440  }
1441 
1443  : array_property (p)
1444  {
1445  add_constraint (dim_vector (-1, 1));
1446  add_constraint (dim_vector (1, -1));
1447  add_constraint (dim_vector (0, 0));
1448  }
1449 
1450  void add_constraint (const std::string& type)
1451  {
1453  }
1454 
1455  void add_constraint (const dim_vector& dims)
1456  {
1458  }
1459 
1461  {
1462  size_constraints.remove (dim_vector (1, -1));
1463  size_constraints.remove (dim_vector (-1, 1));
1464 
1465  add_constraint (dim_vector (1, len));
1466  add_constraint (dim_vector (len, 1));
1467  }
1468 
1470  {
1471  set (val);
1472  return *this;
1473  }
1474 
1475  base_property* clone (void) const
1476  {
1477  row_vector_property *p = new row_vector_property (*this);
1478 
1481 
1482  return p;
1483  }
1484 
1485 protected:
1486  bool do_set (const octave_value& v)
1487  {
1488  bool retval = array_property::do_set (v);
1489 
1490  if (! error_state)
1491  {
1492  dim_vector dv = data.dims ();
1493 
1494  if (dv(0) > 1 && dv(1) == 1)
1495  {
1496  int tmp = dv(0);
1497  dv(0) = dv(1);
1498  dv(1) = tmp;
1499 
1500  data = data.reshape (dv);
1501  }
1502 
1503  return retval;
1504  }
1505 
1506  return false;
1507  }
1508 
1509 private:
1510  OCTINTERP_API bool validate (const octave_value& v);
1511 };
1512 
1513 // ---------------------------------------------------------------------
1514 
1515 class bool_property : public radio_property
1516 {
1517 public:
1518  bool_property (const std::string& nm, const graphics_handle& h,
1519  bool val)
1520  : radio_property (nm, h, radio_values (val ? "{on}|off" : "on|{off}"))
1521  { }
1522 
1523  bool_property (const std::string& nm, const graphics_handle& h,
1524  const char* val)
1525  : radio_property (nm, h, radio_values ("on|off"), val)
1526  { }
1527 
1529  : radio_property (p) { }
1530 
1531  bool is_on (void) const { return is ("on"); }
1532 
1534  {
1535  set (val);
1536  return *this;
1537  }
1538 
1539  base_property* clone (void) const { return new bool_property (*this); }
1540 
1541 protected:
1542  bool do_set (const octave_value& val)
1543  {
1544  if (val.is_bool_scalar ())
1545  return radio_property::do_set (val.bool_value () ? "on" : "off");
1546  else
1547  return radio_property::do_set (val);
1548  }
1549 };
1550 
1551 // ---------------------------------------------------------------------
1552 
1553 class handle_property : public base_property
1554 {
1555 public:
1556  handle_property (const std::string& nm, const graphics_handle& h,
1557  const graphics_handle& val = graphics_handle ())
1558  : base_property (nm, h),
1559  current_val (val) { }
1560 
1562  : base_property (p), current_val (p.current_val) { }
1563 
1564  octave_value get (void) const { return current_val.as_octave_value (); }
1565 
1566  graphics_handle handle_value (void) const { return current_val; }
1567 
1569  {
1570  set (val);
1571  return *this;
1572  }
1573 
1575  {
1576  set (octave_value (h.value ()));
1577  return *this;
1578  }
1579 
1580  base_property* clone (void) const { return new handle_property (*this); }
1581 
1582 protected:
1583  OCTINTERP_API bool do_set (const octave_value& v);
1584 
1585 private:
1587 };
1588 
1589 // ---------------------------------------------------------------------
1590 
1591 class any_property : public base_property
1592 {
1593 public:
1594  any_property (const std::string& nm, const graphics_handle& h,
1595  const octave_value& m = Matrix ())
1596  : base_property (nm, h), data (m) { }
1597 
1599  : base_property (p), data (p.data) { }
1600 
1601  octave_value get (void) const { return data; }
1602 
1604  {
1605  set (val);
1606  return *this;
1607  }
1608 
1609  base_property* clone (void) const { return new any_property (*this); }
1610 
1611 protected:
1612  bool do_set (const octave_value& v)
1613  {
1614  data = v;
1615  return true;
1616  }
1617 
1618 private:
1620 };
1621 
1622 // ---------------------------------------------------------------------
1623 
1624 class children_property : public base_property
1625 {
1626 public:
1629  {
1630  do_init_children (Matrix ());
1631  }
1632 
1633  children_property (const std::string& nm, const graphics_handle& h,
1634  const Matrix &val)
1635  : base_property (nm, h), children_list ()
1636  {
1637  do_init_children (val);
1638  }
1639 
1641  : base_property (p), children_list ()
1642  {
1644  }
1645 
1647  {
1648  set (val);
1649  return *this;
1650  }
1651 
1652  base_property* clone (void) const { return new children_property (*this); }
1653 
1654  bool remove_child (const double &val)
1655  {
1656  return do_remove_child (val);
1657  }
1658 
1659  void adopt (const double &val)
1660  {
1661  do_adopt_child (val);
1662  }
1663 
1664  Matrix get_children (void) const
1665  {
1666  return do_get_children (false);
1667  }
1668 
1669  Matrix get_hidden (void) const
1670  {
1671  return do_get_children (true);
1672  }
1673 
1674  Matrix get_all (void) const
1675  {
1676  return do_get_all_children ();
1677  }
1678 
1679  octave_value get (void) const
1680  {
1681  return octave_value (get_children ());
1682  }
1683 
1684  void delete_children (bool clear = false)
1685  {
1687  }
1688 
1690  {
1691  for (children_list_iterator p = children_list.begin ();
1692  p != children_list.end (); p++)
1693  {
1694  if (*p == old_gh)
1695  {
1696  *p = new_gh.value ();
1697  return;
1698  }
1699  }
1700 
1701  error ("children_list::renumber: child not found!");
1702  }
1703 
1704 private:
1705  typedef std::list<double>::iterator children_list_iterator;
1706  typedef std::list<double>::const_iterator const_children_list_iterator;
1707  std::list<double> children_list;
1708 
1709 protected:
1710  bool do_set (const octave_value& val)
1711  {
1712  const Matrix new_kids = val.matrix_value ();
1713 
1714  octave_idx_type nel = new_kids.numel ();
1715 
1716  const Matrix new_kids_column = new_kids.reshape (dim_vector (nel, 1));
1717 
1718  bool is_ok = true;
1719 
1720  if (! error_state)
1721  {
1722  const Matrix visible_kids = do_get_children (false);
1723 
1724  if (visible_kids.numel () == new_kids.numel ())
1725  {
1726  Matrix t1 = visible_kids.sort ();
1727  Matrix t2 = new_kids_column.sort ();
1728 
1729  if (t1 != t2)
1730  is_ok = false;
1731  }
1732  else
1733  is_ok = false;
1734 
1735  if (! is_ok)
1736  error ("set: new children must be a permutation of existing children");
1737  }
1738  else
1739  {
1740  is_ok = false;
1741  error ("set: expecting children to be array of graphics handles");
1742  }
1743 
1744  if (is_ok)
1745  {
1746  Matrix tmp = new_kids_column.stack (get_hidden ());
1747 
1748  children_list.clear ();
1749 
1750  // Don't use do_init_children here, as that reverses the
1751  // order of the list, and we don't want to do that if setting
1752  // the child list directly.
1753 
1754  for (octave_idx_type i = 0; i < tmp.numel (); i++)
1755  children_list.push_back (tmp.xelem (i));
1756  }
1757 
1758  return is_ok;
1759  }
1760 
1761 private:
1762  void do_init_children (const Matrix &val)
1763  {
1764  children_list.clear ();
1765  for (octave_idx_type i = 0; i < val.numel (); i++)
1766  children_list.push_front (val.xelem (i));
1767  }
1768 
1769  void do_init_children (const std::list<double> &val)
1770  {
1771  children_list.clear ();
1772  for (const_children_list_iterator p = val.begin (); p != val.end (); p++)
1773  children_list.push_front (*p);
1774  }
1775 
1776  Matrix do_get_children (bool return_hidden) const;
1777 
1779  {
1780  Matrix retval (children_list.size (), 1);
1781  octave_idx_type i = 0;
1782 
1783  for (const_children_list_iterator p = children_list.begin ();
1784  p != children_list.end (); p++)
1785  retval(i++) = *p;
1786  return retval;
1787  }
1788 
1789  bool do_remove_child (double child)
1790  {
1791  for (children_list_iterator p = children_list.begin ();
1792  p != children_list.end (); p++)
1793  {
1794  if (*p == child)
1795  {
1796  children_list.erase (p);
1797  return true;
1798  }
1799  }
1800  return false;
1801  }
1802 
1803  void do_adopt_child (const double &val)
1804  {
1805  children_list.push_front (val);
1806  }
1807 
1808  void do_delete_children (bool clear);
1809 };
1810 
1811 
1812 
1813 // ---------------------------------------------------------------------
1814 
1815 class callback_property : public base_property
1816 {
1817 public:
1818  callback_property (const std::string& nm, const graphics_handle& h,
1819  const octave_value& m)
1820  : base_property (nm, h), callback (m), executing (false) { }
1821 
1823  : base_property (p), callback (p.callback), executing (false) { }
1824 
1825  octave_value get (void) const { return callback; }
1826 
1827  OCTINTERP_API void execute (const octave_value& data = octave_value ()) const;
1828 
1829  bool is_defined (void) const
1830  {
1831  return (callback.is_defined () && ! callback.is_empty ());
1832  }
1833 
1835  {
1836  set (val);
1837  return *this;
1838  }
1839 
1840  base_property* clone (void) const { return new callback_property (*this); }
1841 
1842 protected:
1843  bool do_set (const octave_value& v)
1844  {
1845  if (validate (v))
1846  {
1847  callback = v;
1848  return true;
1849  }
1850  else
1851  error ("invalid value for callback property \"%s\"",
1852  get_name ().c_str ());
1853  return false;
1854  }
1855 
1856 private:
1857  OCTINTERP_API bool validate (const octave_value& v) const;
1858 
1859 private:
1861 
1862  // If TRUE, we are executing this callback.
1863  mutable bool executing;
1864 };
1865 
1866 // ---------------------------------------------------------------------
1867 
1868 class property
1869 {
1870 public:
1871  property (void) : rep (new base_property ("", graphics_handle ()))
1872  { }
1873 
1874  property (base_property *bp, bool persist = false) : rep (bp)
1875  { if (persist) rep->count++; }
1876 
1877  property (const property& p) : rep (p.rep)
1878  {
1879  rep->count++;
1880  }
1881 
1882  ~property (void)
1883  {
1884  if (--rep->count == 0)
1885  delete rep;
1886  }
1887 
1888  bool ok (void) const
1889  { return rep->ok (); }
1890 
1891  std::string get_name (void) const
1892  { return rep->get_name (); }
1893 
1894  void set_name (const std::string& name)
1895  { rep->set_name (name); }
1896 
1898  { return rep->get_parent (); }
1899 
1900  void set_parent (const graphics_handle& h)
1901  { rep->set_parent (h); }
1902 
1903  bool is_hidden (void) const
1904  { return rep->is_hidden (); }
1905 
1906  void set_hidden (bool flag)
1907  { rep->set_hidden (flag); }
1908 
1909  bool is_radio (void) const
1910  { return rep->is_radio (); }
1911 
1912  int get_id (void) const
1913  { return rep->get_id (); }
1914 
1915  void set_id (int d)
1916  { rep->set_id (d); }
1917 
1918  octave_value get (void) const
1919  { return rep->get (); }
1920 
1921  bool set (const octave_value& val, bool do_run = true,
1922  bool do_notify_toolkit = true)
1923  { return rep->set (val, do_run, do_notify_toolkit); }
1924 
1925  std::string values_as_string (void) const
1926  { return rep->values_as_string (); }
1927 
1928  Cell values_as_cell (void) const
1929  { return rep->values_as_cell (); }
1930 
1931  property& operator = (const octave_value& val)
1932  {
1933  *rep = val;
1934  return *this;
1935  }
1936 
1937  property& operator = (const property& p)
1938  {
1939  if (rep && --rep->count == 0)
1940  delete rep;
1941 
1942  rep = p.rep;
1943  rep->count++;
1944 
1945  return *this;
1946  }
1947 
1949  { rep->add_listener (v, mode); }
1950 
1952  listener_mode mode = POSTSET)
1953  { rep->delete_listener (v, mode); }
1954 
1956  { rep->run_listeners (mode); }
1957 
1958  OCTINTERP_API static
1959  property create (const std::string& name, const graphics_handle& parent,
1960  const caseless_str& type,
1961  const octave_value_list& args);
1962 
1963  property clone (void) const
1964  { return property (rep->clone ()); }
1965 
1966  /*
1967  const string_property& as_string_property (void) const
1968  { return *(dynamic_cast<string_property*> (rep)); }
1969 
1970  const radio_property& as_radio_property (void) const
1971  { return *(dynamic_cast<radio_property*> (rep)); }
1972 
1973  const color_property& as_color_property (void) const
1974  { return *(dynamic_cast<color_property*> (rep)); }
1975 
1976  const double_property& as_double_property (void) const
1977  { return *(dynamic_cast<double_property*> (rep)); }
1978 
1979  const bool_property& as_bool_property (void) const
1980  { return *(dynamic_cast<bool_property*> (rep)); }
1981 
1982  const handle_property& as_handle_property (void) const
1983  { return *(dynamic_cast<handle_property*> (rep)); }
1984  */
1985 
1986 private:
1987  base_property *rep;
1988 };
1989 
1990 // ---------------------------------------------------------------------
1991 
1992 class property_list
1993 {
1994 public:
1995  typedef std::map<std::string, octave_value> pval_map_type;
1996  typedef std::map<std::string, pval_map_type> plist_map_type;
1997 
1998  typedef pval_map_type::iterator pval_map_iterator;
1999  typedef pval_map_type::const_iterator pval_map_const_iterator;
2000 
2001  typedef plist_map_type::iterator plist_map_iterator;
2002  typedef plist_map_type::const_iterator plist_map_const_iterator;
2003 
2005  : plist_map (m) { }
2006 
2007  ~property_list (void) { }
2008 
2009  void set (const caseless_str& name, const octave_value& val);
2010 
2011  octave_value lookup (const caseless_str& name) const;
2012 
2013  plist_map_iterator begin (void) { return plist_map.begin (); }
2014  plist_map_const_iterator begin (void) const { return plist_map.begin (); }
2015 
2016  plist_map_iterator end (void) { return plist_map.end (); }
2017  plist_map_const_iterator end (void) const { return plist_map.end (); }
2018 
2019  plist_map_iterator find (const std::string& go_name)
2020  {
2021  return plist_map.find (go_name);
2022  }
2023 
2024  plist_map_const_iterator find (const std::string& go_name) const
2025  {
2026  return plist_map.find (go_name);
2027  }
2028 
2029  octave_scalar_map as_struct (const std::string& prefix_arg) const;
2030 
2031 private:
2033 };
2034 
2035 // ---------------------------------------------------------------------
2036 
2037 class graphics_toolkit;
2038 class graphics_object;
2039 
2041 {
2042 public:
2043  friend class graphics_toolkit;
2044 
2045 public:
2046  base_graphics_toolkit (const std::string& nm)
2047  : name (nm), count (0) { }
2048 
2049  virtual ~base_graphics_toolkit (void) { }
2050 
2051  std::string get_name (void) const { return name; }
2052 
2053  virtual bool is_valid (void) const { return false; }
2054 
2055  virtual void redraw_figure (const graphics_object&) const
2056  { gripe_invalid ("redraw_figure"); }
2057 
2058  virtual void print_figure (const graphics_object&, const std::string&,
2059  const std::string&, bool,
2060  const std::string& = "") const
2061  { gripe_invalid ("print_figure"); }
2062 
2063  virtual Matrix get_canvas_size (const graphics_handle&) const
2064  {
2065  gripe_invalid ("get_canvas_size");
2066  return Matrix (1, 2, 0.0);
2067  }
2068 
2069  virtual double get_screen_resolution (void) const
2070  {
2071  gripe_invalid ("get_screen_resolution");
2072  return 72.0;
2073  }
2074 
2075  virtual Matrix get_screen_size (void) const
2076  {
2077  gripe_invalid ("get_screen_size");
2078  return Matrix (1, 2, 0.0);
2079  }
2080 
2081  // Callback function executed when the given graphics object
2082  // changes. This allows the graphics toolkit to act on property
2083  // changes if needed.
2084  virtual void update (const graphics_object&, int)
2085  { gripe_invalid ("base_graphics_toolkit::update"); }
2086 
2087  void update (const graphics_handle&, int);
2088 
2089  // Callback function executed when the given graphics object is
2090  // created. This allows the graphics toolkit to do toolkit-specific
2091  // initializations for a newly created object.
2092  virtual bool initialize (const graphics_object&)
2093  { gripe_invalid ("base_graphics_toolkit::initialize"); return false; }
2094 
2095  bool initialize (const graphics_handle&);
2096 
2097  // Callback function executed just prior to deleting the given
2098  // graphics object. This allows the graphics toolkit to perform
2099  // toolkit-specific cleanup operations before an object is deleted.
2100  virtual void finalize (const graphics_object&)
2101  { gripe_invalid ("base_graphics_toolkit::finalize"); }
2102 
2103  void finalize (const graphics_handle&);
2104 
2105  // Close the graphics toolkit.
2106  virtual void close (void)
2107  { gripe_invalid ("base_graphics_toolkit::close"); }
2108 
2109 private:
2110  std::string name;
2112 
2113 private:
2114  void gripe_invalid (const std::string& fname) const
2115  {
2116  if (! is_valid ())
2117  error ("%s: invalid graphics toolkit", fname.c_str ());
2118  }
2119 };
2120 
2121 class graphics_toolkit
2122 {
2123 public:
2125  : rep (new base_graphics_toolkit ("unknown"))
2126  {
2127  rep->count++;
2128  }
2129 
2131  : rep (b)
2132  {
2133  rep->count++;
2134  }
2135 
2137  : rep (b.rep)
2138  {
2139  rep->count++;
2140  }
2141 
2143  {
2144  if (--rep->count == 0)
2145  delete rep;
2146  }
2147 
2149  {
2150  if (rep != b.rep)
2151  {
2152  if (--rep->count == 0)
2153  delete rep;
2154 
2155  rep = b.rep;
2156  rep->count++;
2157  }
2158 
2159  return *this;
2160  }
2161 
2162  operator bool (void) const { return rep->is_valid (); }
2163 
2164  std::string get_name (void) const { return rep->get_name (); }
2165 
2166  void redraw_figure (const graphics_object& go) const
2167  { rep->redraw_figure (go); }
2168 
2169  void print_figure (const graphics_object& go, const std::string& term,
2170  const std::string& file, bool mono,
2171  const std::string& debug_file = "") const
2172  { rep->print_figure (go, term, file, mono, debug_file); }
2173 
2175  { return rep->get_canvas_size (fh); }
2176 
2177  double get_screen_resolution (void) const
2178  { return rep->get_screen_resolution (); }
2179 
2181  { return rep->get_screen_size (); }
2182 
2183  // Notifies graphics toolkit that object't property has changed.
2184  void update (const graphics_object& go, int id)
2185  { rep->update (go, id); }
2186 
2187  void update (const graphics_handle& h, int id)
2188  { rep->update (h, id); }
2189 
2190  // Notifies graphics toolkit that new object was created.
2191  bool initialize (const graphics_object& go)
2192  { return rep->initialize (go); }
2193 
2194  bool initialize (const graphics_handle& h)
2195  { return rep->initialize (h); }
2196 
2197  // Notifies graphics toolkit that object was destroyed.
2198  // This is called only for explicitly deleted object. Children are
2199  // deleted implicitly and graphics toolkit isn't notified.
2200  void finalize (const graphics_object& go)
2201  { rep->finalize (go); }
2202 
2203  void finalize (const graphics_handle& h)
2204  { rep->finalize (h); }
2205 
2206  // Close the graphics toolkit.
2207  void close (void) { rep->close (); }
2208 
2209 private:
2210 
2212 };
2213 
2214 class gtk_manager
2215 {
2216 public:
2217 
2219  {
2220  return instance_ok () ? instance->do_get_toolkit () : graphics_toolkit ();
2221  }
2222 
2223  static void register_toolkit (const std::string& name)
2224  {
2225  if (instance_ok ())
2226  instance->do_register_toolkit (name);
2227  }
2228 
2229  static void unregister_toolkit (const std::string& name)
2230  {
2231  if (instance_ok ())
2233  }
2234 
2235  static void load_toolkit (const graphics_toolkit& tk)
2236  {
2237  if (instance_ok ())
2238  instance->do_load_toolkit (tk);
2239  }
2240 
2241  static void unload_toolkit (const std::string& name)
2242  {
2243  if (instance_ok ())
2244  instance->do_unload_toolkit (name);
2245  }
2246 
2247  static graphics_toolkit find_toolkit (const std::string& name)
2248  {
2249  return instance_ok ()
2250  ? instance->do_find_toolkit (name) : graphics_toolkit ();
2251  }
2252 
2254  {
2255  return instance_ok () ? instance->do_available_toolkits_list () : Cell ();
2256  }
2257 
2259  {
2260  return instance_ok () ? instance->do_loaded_toolkits_list () : Cell ();
2261  }
2262 
2263  static void unload_all_toolkits (void)
2264  {
2265  if (instance_ok ())
2267  }
2268 
2269  static std::string default_toolkit (void)
2270  {
2271  return instance_ok () ? instance->do_default_toolkit () : std::string ();
2272  }
2273 
2274 private:
2275 
2276  gtk_manager (void);
2277 
2278  ~gtk_manager (void) { }
2279 
2280  OCTINTERP_API static void create_instance (void);
2281 
2282  static bool instance_ok (void)
2283  {
2284  bool retval = true;
2285 
2286  if (! instance)
2287  create_instance ();
2288 
2289  if (! instance)
2290  {
2291  ::error ("unable to create gh_manager!");
2292 
2293  retval = false;
2294  }
2295 
2296  return retval;
2297  }
2298 
2299  static void cleanup_instance (void) { delete instance; instance = 0; }
2300 
2302 
2303  // The name of the default toolkit.
2304  std::string dtk;
2305 
2306  // The list of toolkits that we know about.
2307  std::set<std::string> available_toolkits;
2308 
2309  // The list of toolkits we have actually loaded.
2310  std::map<std::string, graphics_toolkit> loaded_toolkits;
2311 
2312  typedef std::set<std::string>::iterator available_toolkits_iterator;
2313 
2314  typedef std::set<std::string>::const_iterator
2316 
2317  typedef std::map<std::string, graphics_toolkit>::iterator
2319 
2320  typedef std::map<std::string, graphics_toolkit>::const_iterator
2322 
2323  graphics_toolkit do_get_toolkit (void) const;
2324 
2325  void do_register_toolkit (const std::string& name)
2326  {
2327  available_toolkits.insert (name);
2328  }
2329 
2330  void do_unregister_toolkit (const std::string& name)
2331  {
2332  available_toolkits.erase (name);
2333  }
2334 
2336  {
2337  loaded_toolkits[tk.get_name ()] = tk;
2338  }
2339 
2340  void do_unload_toolkit (const std::string& name)
2341  {
2342  loaded_toolkits.erase (name);
2343  }
2344 
2345  graphics_toolkit do_find_toolkit (const std::string& name) const
2346  {
2348 
2349  if (p != loaded_toolkits.end ())
2350  return p->second;
2351  else
2352  return graphics_toolkit ();
2353  }
2354 
2356  {
2357  Cell m (1 , available_toolkits.size ());
2358 
2359  octave_idx_type i = 0;
2361  p != available_toolkits.end (); p++)
2362  m(i++) = *p;
2363 
2364  return m;
2365  }
2366 
2368  {
2369  Cell m (1 , loaded_toolkits.size ());
2370 
2371  octave_idx_type i = 0;
2373  p != loaded_toolkits.end (); p++)
2374  m(i++) = p->first;
2375 
2376  return m;
2377  }
2378 
2380  {
2381  while (! loaded_toolkits.empty ())
2382  {
2384 
2385  std::string name = p->first;
2386 
2387  p->second.close ();
2388 
2389  // The toolkit may have unloaded itself. If not, we'll do
2390  // it here.
2391  if (loaded_toolkits.find (name) != loaded_toolkits.end ())
2392  unload_toolkit (name);
2393  }
2394  }
2395 
2396  std::string do_default_toolkit (void) { return dtk; }
2397 };
2398 
2399 // ---------------------------------------------------------------------
2400 
2401 class base_graphics_object;
2402 class graphics_object;
2403 
2405 {
2406 public:
2407  base_properties (const std::string& ty = "unknown",
2408  const graphics_handle& mh = graphics_handle (),
2409  const graphics_handle& p = graphics_handle ());
2410 
2411  virtual ~base_properties (void) { }
2412 
2413  virtual std::string graphics_object_name (void) const { return "unknown"; }
2414 
2415  void mark_modified (void);
2416 
2417  void override_defaults (base_graphics_object& obj);
2418 
2419  virtual void init_integerhandle (const octave_value&)
2420  {
2421  panic_impossible ();
2422  }
2423 
2424  // Look through DEFAULTS for properties with given CLASS_NAME, and
2425  // apply them to the current object with set (virtual method).
2426 
2427  void set_from_list (base_graphics_object& obj, property_list& defaults);
2428 
2429  void insert_property (const std::string& name, property p)
2430  {
2431  p.set_name (name);
2432  p.set_parent (__myhandle__);
2433  all_props[name] = p;
2434  }
2435 
2436  virtual void set (const caseless_str&, const octave_value&);
2437 
2438  virtual octave_value get (const caseless_str& pname) const;
2439 
2440  virtual octave_value get (const std::string& pname) const
2441  {
2442  return get (caseless_str (pname));
2443  }
2444 
2445  virtual octave_value get (const char *pname) const
2446  {
2447  return get (caseless_str (pname));
2448  }
2449 
2450  virtual octave_value get (bool all = false) const;
2451 
2452  virtual property get_property (const caseless_str& pname);
2453 
2454  virtual bool has_property (const caseless_str&) const
2455  {
2456  panic_impossible ();
2457  return false;
2458  }
2459 
2460  bool is_modified (void) const { return is___modified__ (); }
2461 
2462  virtual void remove_child (const graphics_handle& h)
2463  {
2464  if (children.remove_child (h.value ()))
2465  mark_modified ();
2466  }
2467 
2468  virtual void adopt (const graphics_handle& h)
2469  {
2470  children.adopt (h.value ());
2471  mark_modified ();
2472  }
2473 
2474  virtual graphics_toolkit get_toolkit (void) const;
2475 
2476  virtual Matrix
2477  get_boundingbox (bool /*internal*/ = false,
2478  const Matrix& /*parent_pix_size*/ = Matrix ()) const
2479  { return Matrix (1, 4, 0.0); }
2480 
2481  virtual void update_boundingbox (void);
2482 
2483  virtual void update_autopos (const std::string& elem_type);
2484 
2485  virtual void add_listener (const caseless_str&, const octave_value&,
2487 
2488  virtual void delete_listener (const caseless_str&, const octave_value&,
2490 
2491  void set_tag (const octave_value& val) { tag = val; }
2492 
2493  void set_parent (const octave_value& val);
2494 
2495  Matrix get_children (void) const
2496  {
2497  return children.get_children ();
2498  }
2499 
2500  Matrix get_all_children (void) const
2501  {
2502  return children.get_all ();
2503  }
2504 
2505  Matrix get_hidden_children (void) const
2506  {
2507  return children.get_hidden ();
2508  }
2509 
2510  void set_modified (const octave_value& val) { set___modified__ (val); }
2511 
2512  void set___modified__ (const octave_value& val) { __modified__ = val; }
2513 
2514  void reparent (const graphics_handle& new_parent) { parent = new_parent; }
2515 
2516  // Update data limits for AXIS_TYPE (xdata, ydata, etc.) in the parent
2517  // axes object.
2518 
2519  virtual void update_axis_limits (const std::string& axis_type) const;
2520 
2521  virtual void update_axis_limits (const std::string& axis_type,
2522  const graphics_handle& h) const;
2523 
2524  virtual void delete_children (bool clear = false)
2525  {
2526  children.delete_children (clear);
2527  }
2528 
2529  void renumber_child (graphics_handle old_gh, graphics_handle new_gh)
2530  {
2531  children.renumber (old_gh, new_gh);
2532  }
2533 
2534  void renumber_parent (graphics_handle new_gh)
2535  {
2536  parent = new_gh;
2537  }
2538 
2539  static property_list::pval_map_type factory_defaults (void);
2540 
2541  // FIXME: these functions should be generated automatically by the
2542  // genprops.awk script.
2543  //
2544  // EMIT_BASE_PROPERTIES_GET_FUNCTIONS
2545 
2546  virtual octave_value get_alim (void) const { return octave_value (); }
2547  virtual octave_value get_clim (void) const { return octave_value (); }
2548  virtual octave_value get_xlim (void) const { return octave_value (); }
2549  virtual octave_value get_ylim (void) const { return octave_value (); }
2550  virtual octave_value get_zlim (void) const { return octave_value (); }
2551 
2552  virtual bool is_aliminclude (void) const { return false; }
2553  virtual bool is_climinclude (void) const { return false; }
2554  virtual bool is_xliminclude (void) const { return false; }
2555  virtual bool is_yliminclude (void) const { return false; }
2556  virtual bool is_zliminclude (void) const { return false; }
2557 
2558  bool is_handle_visible (void) const;
2559 
2560  std::set<std::string> dynamic_property_names (void) const;
2561 
2562  bool has_dynamic_property (const std::string& pname);
2563 
2564 protected:
2565  std::set<std::string> dynamic_properties;
2566 
2567  void set_dynamic (const caseless_str& pname, const octave_value& val);
2568 
2569  octave_value get_dynamic (const caseless_str& pname) const;
2570 
2571  octave_value get_dynamic (bool all = false) const;
2572 
2573  property get_property_dynamic (const caseless_str& pname);
2574 
2575  BEGIN_BASE_PROPERTIES
2576  // properties common to all objects
2577  bool_property beingdeleted , "off"
2578  radio_property busyaction , "{queue}|cancel"
2580  children_property children gf , Matrix ()
2581  bool_property clipping , "on"
2582  callback_property createfcn , Matrix ()
2583  callback_property deletefcn , Matrix ()
2584  radio_property handlevisibility , "{on}|callback|off"
2585  bool_property hittest , "on"
2586  bool_property interruptible , "on"
2587  handle_property parent fs , p
2588  bool_property selected , "off"
2589  bool_property selectionhighlight , "on"
2590  string_property tag s , ""
2591  string_property type frs , ty
2592  handle_property uicontextmenu , graphics_handle ()
2593  any_property userdata , Matrix ()
2594  bool_property visible , "on"
2595  // additional (Octave-specific) properties
2596  bool_property __modified__ s , "on"
2597  graphics_handle __myhandle__ fhrs , mh
2598  END_PROPERTIES
2599 
2600 protected:
2601  struct cmp_caseless_str
2602  {
2603  bool operator () (const caseless_str &a, const caseless_str &b) const
2604  {
2605  std::string a1 = a;
2606  std::transform (a1.begin (), a1.end (), a1.begin (), tolower);
2607  std::string b1 = b;
2608  std::transform (b1.begin (), b1.end (), b1.begin (), tolower);
2609 
2610  return a1 < b1;
2611  }
2612  };
2613 
2614  std::map<caseless_str, property, cmp_caseless_str> all_props;
2615 
2616 protected:
2617  void insert_static_property (const std::string& name, base_property& p)
2618  { insert_property (name, property (&p, true)); }
2619 
2620  virtual void init (void) { }
2621 };
2622 
2623 class OCTINTERP_API base_graphics_object
2624 {
2625 public:
2626  friend class graphics_object;
2627 
2628  base_graphics_object (void) : count (1), toolkit_flag (false) { }
2629 
2630  virtual ~base_graphics_object (void) { }
2631 
2632  virtual void mark_modified (void)
2633  {
2634  if (valid_object ())
2635  get_properties ().mark_modified ();
2636  else
2637  error ("base_graphics_object::mark_modified: invalid graphics object");
2638  }
2639 
2640  virtual void override_defaults (base_graphics_object& obj)
2641  {
2642  if (valid_object ())
2643  get_properties ().override_defaults (obj);
2644  else
2645  error ("base_graphics_object::override_defaults: invalid graphics object");
2646  }
2647 
2648  virtual void set_from_list (property_list& plist)
2649  {
2650  if (valid_object ())
2651  get_properties ().set_from_list (*this, plist);
2652  else
2653  error ("base_graphics_object::set_from_list: invalid graphics object");
2654  }
2655 
2656  virtual void set (const caseless_str& pname, const octave_value& pval)
2657  {
2658  if (valid_object ())
2659  get_properties ().set (pname, pval);
2660  else
2661  error ("base_graphics_object::set: invalid graphics object");
2662  }
2663 
2664  virtual void set_defaults (const std::string&)
2665  {
2666  error ("base_graphics_object::set_defaults: invalid graphics object");
2667  }
2668 
2669  virtual octave_value get (bool all = false) const
2670  {
2671  if (valid_object ())
2672  return get_properties ().get (all);
2673  else
2674  {
2675  error ("base_graphics_object::get: invalid graphics object");
2676  return octave_value ();
2677  }
2678  }
2679 
2680  virtual octave_value get (const caseless_str& pname) const
2681  {
2682  if (valid_object ())
2683  return get_properties ().get (pname);
2684  else
2685  {
2686  error ("base_graphics_object::get: invalid graphics object");
2687  return octave_value ();
2688  }
2689  }
2690 
2691  virtual octave_value get_default (const caseless_str&) const;
2692 
2693  virtual octave_value get_factory_default (const caseless_str&) const;
2694 
2695  virtual octave_value get_defaults (void) const
2696  {
2697  error ("base_graphics_object::get_defaults: invalid graphics object");
2698  return octave_value ();
2699  }
2700 
2701  virtual octave_value get_factory_defaults (void) const
2702  {
2703  error ("base_graphics_object::get_factory_defaults: invalid graphics object");
2704  return octave_value ();
2705  }
2706 
2707  virtual std::string values_as_string (void);
2708 
2709  virtual octave_scalar_map values_as_struct (void);
2710 
2711  virtual graphics_handle get_parent (void) const
2712  {
2713  if (valid_object ())
2714  return get_properties ().get_parent ();
2715  else
2716  {
2717  error ("base_graphics_object::get_parent: invalid graphics object");
2718  return graphics_handle ();
2719  }
2720  }
2721 
2722  graphics_handle get_handle (void) const
2723  {
2724  if (valid_object ())
2725  return get_properties ().get___myhandle__ ();
2726  else
2727  {
2728  error ("base_graphics_object::get_handle: invalid graphics object");
2729  return graphics_handle ();
2730  }
2731  }
2732 
2733  virtual void remove_child (const graphics_handle& h)
2734  {
2735  if (valid_object ())
2736  get_properties ().remove_child (h);
2737  else
2738  error ("base_graphics_object::remove_child: invalid graphics object");
2739  }
2740 
2741  virtual void adopt (const graphics_handle& h)
2742  {
2743  if (valid_object ())
2744  get_properties ().adopt (h);
2745  else
2746  error ("base_graphics_object::adopt: invalid graphics object");
2747  }
2748 
2749  virtual void reparent (const graphics_handle& np)
2750  {
2751  if (valid_object ())
2752  get_properties ().reparent (np);
2753  else
2754  error ("base_graphics_object::reparent: invalid graphics object");
2755  }
2756 
2757  virtual void defaults (void) const
2758  {
2759  if (valid_object ())
2760  {
2761  std::string msg = (type () + "::defaults");
2762  gripe_not_implemented (msg.c_str ());
2763  }
2764  else
2765  error ("base_graphics_object::default: invalid graphics object");
2766  }
2767 
2768  virtual base_properties& get_properties (void)
2769  {
2770  static base_properties properties;
2771  error ("base_graphics_object::get_properties: invalid graphics object");
2772  return properties;
2773  }
2774 
2775  virtual const base_properties& get_properties (void) const
2776  {
2777  static base_properties properties;
2778  error ("base_graphics_object::get_properties: invalid graphics object");
2779  return properties;
2780  }
2781 
2782  virtual void update_axis_limits (const std::string& axis_type);
2783 
2784  virtual void update_axis_limits (const std::string& axis_type,
2785  const graphics_handle& h);
2786 
2787  virtual bool valid_object (void) const { return false; }
2788 
2789  bool valid_toolkit_object (void) const { return toolkit_flag; }
2790 
2791  virtual std::string type (void) const
2792  {
2793  return (valid_object () ? get_properties ().graphics_object_name ()
2794  : "unknown");
2795  }
2796 
2797  bool isa (const std::string& go_name) const
2798  {
2799  return type () == go_name;
2800  }
2801 
2802  virtual graphics_toolkit get_toolkit (void) const
2803  {
2804  if (valid_object ())
2805  return get_properties ().get_toolkit ();
2806  else
2807  {
2808  error ("base_graphics_object::get_toolkit: invalid graphics object");
2809  return graphics_toolkit ();
2810  }
2811  }
2812 
2813  virtual void add_property_listener (const std::string& nm,
2814  const octave_value& v,
2815  listener_mode mode = POSTSET)
2816  {
2817  if (valid_object ())
2818  get_properties ().add_listener (nm, v, mode);
2819  }
2820 
2821  virtual void delete_property_listener (const std::string& nm,
2822  const octave_value& v,
2823  listener_mode mode = POSTSET)
2824  {
2825  if (valid_object ())
2826  get_properties ().delete_listener (nm, v, mode);
2827  }
2828 
2829  virtual void remove_all_listeners (void);
2830 
2831  virtual void reset_default_properties (void)
2832  {
2833  if (valid_object ())
2834  {
2835  std::string msg = (type () + "::reset_default_properties");
2836  gripe_not_implemented (msg.c_str ());
2837  }
2838  else
2839  error ("base_graphics_object::default: invalid graphics object");
2840  }
2841 
2842 protected:
2843  virtual void initialize (const graphics_object& go)
2844  {
2845  if (! toolkit_flag)
2846  toolkit_flag = get_toolkit ().initialize (go);
2847  }
2848 
2849  virtual void finalize (const graphics_object& go)
2850  {
2851  if (toolkit_flag)
2852  {
2853  get_toolkit ().finalize (go);
2854  toolkit_flag = false;
2855  }
2856  }
2857 
2858  virtual void update (const graphics_object& go, int id)
2859  {
2860  if (toolkit_flag)
2861  get_toolkit ().update (go, id);
2862  }
2863 
2864 protected:
2865  // A reference count.
2866  octave_refcount<int> count;
2867 
2868  // A flag telling whether this object is a valid object
2869  // in the backend context.
2870  bool toolkit_flag;
2871 
2872  // No copying!
2873 
2874  base_graphics_object (const base_graphics_object&) : count (0) { }
2875 
2876  base_graphics_object& operator = (const base_graphics_object&)
2877  {
2878  return *this;
2879  }
2880 };
2881 
2882 class OCTINTERP_API graphics_object
2883 {
2884 public:
2885  graphics_object (void) : rep (new base_graphics_object ()) { }
2886 
2887  graphics_object (base_graphics_object *new_rep)
2888  : rep (new_rep) { }
2889 
2890  graphics_object (const graphics_object& obj) : rep (obj.rep)
2891  {
2892  rep->count++;
2893  }
2894 
2895  graphics_object& operator = (const graphics_object& obj)
2896  {
2897  if (rep != obj.rep)
2898  {
2899  if (--rep->count == 0)
2900  delete rep;
2901 
2902  rep = obj.rep;
2903  rep->count++;
2904  }
2905 
2906  return *this;
2907  }
2908 
2909  ~graphics_object (void)
2910  {
2911  if (--rep->count == 0)
2912  delete rep;
2913  }
2914 
2915  void mark_modified (void) { rep->mark_modified (); }
2916 
2917  void override_defaults (base_graphics_object& obj)
2918  {
2919  rep->override_defaults (obj);
2920  }
2921 
2922  void set_from_list (property_list& plist) { rep->set_from_list (plist); }
2923 
2924  void set (const caseless_str& name, const octave_value& val)
2925  {
2926  rep->set (name, val);
2927  }
2928 
2929  void set (const octave_value_list& args);
2930 
2931  void set (const Array<std::string>& names, const Cell& values,
2932  octave_idx_type row);
2933 
2934  void set (const octave_map& m);
2935 
2936  void set_value_or_default (const caseless_str& name,
2937  const octave_value& val);
2938 
2939  void set_defaults (const std::string& mode) { rep->set_defaults (mode); }
2940 
2941  octave_value get (bool all = false) const { return rep->get (all); }
2942 
2943  octave_value get (const caseless_str& name) const
2944  {
2945  return name.compare ("default")
2946  ? get_defaults ()
2947  : (name.compare ("factory")
2948  ? get_factory_defaults () : rep->get (name));
2949  }
2950 
2951  octave_value get (const std::string& name) const
2952  {
2953  return get (caseless_str (name));
2954  }
2955 
2956  octave_value get (const char *name) const
2957  {
2958  return get (caseless_str (name));
2959  }
2960 
2961  octave_value get_default (const caseless_str& name) const
2962  {
2963  return rep->get_default (name);
2964  }
2965 
2966  octave_value get_factory_default (const caseless_str& name) const
2967  {
2968  return rep->get_factory_default (name);
2969  }
2970 
2971  octave_value get_defaults (void) const { return rep->get_defaults (); }
2972 
2973  octave_value get_factory_defaults (void) const
2974  {
2975  return rep->get_factory_defaults ();
2976  }
2977 
2978  std::string values_as_string (void) { return rep->values_as_string (); }
2979 
2980  octave_map values_as_struct (void) { return rep->values_as_struct (); }
2981 
2982  graphics_handle get_parent (void) const { return rep->get_parent (); }
2983 
2984  graphics_handle get_handle (void) const { return rep->get_handle (); }
2985 
2986  graphics_object get_ancestor (const std::string& type) const;
2987 
2988  void remove_child (const graphics_handle& h) { rep->remove_child (h); }
2989 
2990  void adopt (const graphics_handle& h) { rep->adopt (h); }
2991 
2992  void reparent (const graphics_handle& h) { rep->reparent (h); }
2993 
2994  void defaults (void) const { rep->defaults (); }
2995 
2996  bool isa (const std::string& go_name) const { return rep->isa (go_name); }
2997 
2998  base_properties& get_properties (void) { return rep->get_properties (); }
2999 
3000  const base_properties& get_properties (void) const
3001  {
3002  return rep->get_properties ();
3003  }
3004 
3005  void update_axis_limits (const std::string& axis_type)
3006  {
3007  rep->update_axis_limits (axis_type);
3008  }
3009 
3010  void update_axis_limits (const std::string& axis_type,
3011  const graphics_handle& h)
3012  {
3013  rep->update_axis_limits (axis_type, h);
3014  }
3015 
3016  bool valid_object (void) const { return rep->valid_object (); }
3017 
3018  std::string type (void) const { return rep->type (); }
3019 
3020  operator bool (void) const { return rep->valid_object (); }
3021 
3022  // FIXME: these functions should be generated automatically by the
3023  // genprops.awk script.
3024  //
3025  // EMIT_GRAPHICS_OBJECT_GET_FUNCTIONS
3026 
3027  octave_value get_alim (void) const
3028  { return get_properties ().get_alim (); }
3029 
3030  octave_value get_clim (void) const
3031  { return get_properties ().get_clim (); }
3032 
3033  octave_value get_xlim (void) const
3034  { return get_properties ().get_xlim (); }
3035 
3036  octave_value get_ylim (void) const
3037  { return get_properties ().get_ylim (); }
3038 
3039  octave_value get_zlim (void) const
3040  { return get_properties ().get_zlim (); }
3041 
3042  bool is_aliminclude (void) const
3043  { return get_properties ().is_aliminclude (); }
3044 
3045  bool is_climinclude (void) const
3046  { return get_properties ().is_climinclude (); }
3047 
3048  bool is_xliminclude (void) const
3049  { return get_properties ().is_xliminclude (); }
3050 
3051  bool is_yliminclude (void) const
3052  { return get_properties ().is_yliminclude (); }
3053 
3054  bool is_zliminclude (void) const
3055  { return get_properties ().is_zliminclude (); }
3056 
3057  bool is_handle_visible (void) const
3058  { return get_properties ().is_handle_visible (); }
3059 
3060  graphics_toolkit get_toolkit (void) const { return rep->get_toolkit (); }
3061 
3062  void add_property_listener (const std::string& nm, const octave_value& v,
3063  listener_mode mode = POSTSET)
3064  { rep->add_property_listener (nm, v, mode); }
3065 
3066  void delete_property_listener (const std::string& nm, const octave_value& v,
3067  listener_mode mode = POSTSET)
3068  { rep->delete_property_listener (nm, v, mode); }
3069 
3070  void initialize (void) { rep->initialize (*this); }
3071 
3072  void finalize (void) { rep->finalize (*this); }
3073 
3074  void update (int id) { rep->update (*this, id); }
3075 
3076  void reset_default_properties (void)
3077  { rep->reset_default_properties (); }
3078 
3079 private:
3080  base_graphics_object *rep;
3081 };
3082 
3083 // ---------------------------------------------------------------------
3084 
3085 class OCTINTERP_API root_figure : public base_graphics_object
3086 {
3087 public:
3088  class OCTINTERP_API properties : public base_properties
3089  {
3090  public:
3091  void remove_child (const graphics_handle& h);
3092 
3093  Matrix get_boundingbox (bool internal = false,
3094  const Matrix& parent_pix_size = Matrix ()) const;
3095 
3096  // See the genprops.awk script for an explanation of the
3097  // properties declarations.
3098 
3099  // FIXME: it seems strange to me that the diary, diaryfile,
3100  // echo, errormessage, format, formatspacing, language, and
3101  // recursionlimit properties are here.
3102  // WTF do they have to do with graphics?
3103  // Also note that these properties (and the monitorpositions,
3104  // pointerlocation, and pointerwindow properties) are not yet used
3105  // by Octave, so setting them will have no effect, and changes
3106  // made elswhere (say, the diary or format functions) will not
3107  // cause these properties to be updated.
3108  // ANSWER: Matlab defines these properties and uses them in
3109  // the same way that Octave uses an internal static variable to
3110  // keep track of state. set (0, "echo", "on") is equivalent
3111  // to Octave's echo ("on"). Maybe someday we can connect callbacks
3112  // that actually call Octave's own functions for this.
3113 
3114  // Programming note: Keep property list sorted if new ones are added.
3115 
3116  BEGIN_PROPERTIES (root_figure, root)
3117  handle_property callbackobject Sr , graphics_handle ()
3118  array_property commandwindowsize r , Matrix (1, 2, 0)
3119  handle_property currentfigure S , graphics_handle ()
3120  bool_property diary , "off"
3121  string_property diaryfile , "diary"
3122  bool_property echo , "off"
3123  string_property errormessage , ""
3124  string_property fixedwidthfontname , "Courier"
3125  radio_property format , "+|bank|bit|hex|long|longe|longeng|longg|native-bit|native-hex|none|rational|{short}|shorte|shorteng|shortg"
3126  radio_property formatspacing , "compact|{loose}"
3127  string_property language , "ascii"
3128  array_property monitorpositions , Matrix (1, 4, 0)
3129  array_property pointerlocation , Matrix (1, 2, 0)
3130  double_property pointerwindow r , 0.0
3131  double_property recursionlimit , 256.0
3132  double_property screendepth r , default_screendepth ()
3133  double_property screenpixelsperinch r , default_screenpixelsperinch ()
3134  array_property screensize r , default_screensize ()
3135  bool_property showhiddenhandles , "off"
3136  radio_property units U , "inches|centimeters|normalized|points|{pixels}"
3137  END_PROPERTIES
3138 
3139  private:
3140  std::list<graphics_handle> cbo_stack;
3141  };
3142 
3143 private:
3144  properties xproperties;
3145 
3146 public:
3147 
3148  root_figure (void)
3149  : xproperties (0, graphics_handle ()), default_properties () { }
3150 
3151  ~root_figure (void) { }
3152 
3153  void mark_modified (void) { }
3154 
3155  void override_defaults (base_graphics_object& obj)
3156  {
3157  // Now override with our defaults. If the default_properties
3158  // list includes the properties for all defaults (line,
3159  // surface, etc.) then we don't have to know the type of OBJ
3160  // here, we just call its set function and let it decide which
3161  // properties from the list to use.
3162  obj.set_from_list (default_properties);
3163  }
3164 
3165  void set (const caseless_str& name, const octave_value& value)
3166  {
3167  if (name.compare ("default", 7))
3168  // strip "default", pass rest to function that will
3169  // parse the remainder and add the element to the
3170  // default_properties map.
3171  default_properties.set (name.substr (7), value);
3172  else
3173  xproperties.set (name, value);
3174  }
3175 
3176  octave_value get (const caseless_str& name) const
3177  {
3178  octave_value retval;
3179 
3180  if (name.compare ("default", 7))
3181  return get_default (name.substr (7));
3182  else if (name.compare ("factory", 7))
3183  return get_factory_default (name.substr (7));
3184  else
3185  retval = xproperties.get (name);
3186 
3187  return retval;
3188  }
3189 
3190  octave_value get_default (const caseless_str& name) const
3191  {
3192  octave_value retval = default_properties.lookup (name);
3193 
3194  if (retval.is_undefined ())
3195  {
3196  // no default property found, use factory default
3197  retval = factory_properties.lookup (name);
3198 
3199  if (retval.is_undefined ())
3200  error ("get: invalid default property '%s'", name.c_str ());
3201  }
3202 
3203  return retval;
3204  }
3205 
3206  octave_value get_factory_default (const caseless_str& name) const
3207  {
3208  octave_value retval = factory_properties.lookup (name);
3209 
3210  if (retval.is_undefined ())
3211  error ("get: invalid factory default property '%s'", name.c_str ());
3212 
3213  return retval;
3214  }
3215 
3216  octave_value get_defaults (void) const
3217  {
3218  return default_properties.as_struct ("default");
3219  }
3220 
3221  octave_value get_factory_defaults (void) const
3222  {
3223  return factory_properties.as_struct ("factory");
3224  }
3225 
3226  base_properties& get_properties (void) { return xproperties; }
3227 
3228  const base_properties& get_properties (void) const { return xproperties; }
3229 
3230  bool valid_object (void) const { return true; }
3231 
3232  void reset_default_properties (void);
3233 
3234 private:
3235  property_list default_properties;
3236 
3237  static property_list factory_properties;
3238 
3239  static property_list::plist_map_type init_factory_properties (void);
3240 };
3241 
3242 // ---------------------------------------------------------------------
3243 
3244 class OCTINTERP_API figure : public base_graphics_object
3245 {
3246 public:
3247  class OCTINTERP_API properties : public base_properties
3248  {
3249  public:
3250  void init_integerhandle (const octave_value& val)
3251  {
3252  integerhandle = val;
3253  }
3254 
3255  void remove_child (const graphics_handle& h);
3256 
3257  void set_visible (const octave_value& val);
3258 
3259  graphics_toolkit get_toolkit (void) const
3260  {
3261  if (! toolkit)
3262  toolkit = gtk_manager::get_toolkit ();
3263 
3264  return toolkit;
3265  }
3266 
3267  void set_toolkit (const graphics_toolkit& b);
3268 
3269  void set___graphics_toolkit__ (const octave_value& val)
3270  {
3271  if (! error_state)
3272  {
3273  if (val.is_string ())
3274  {
3275  std::string nm = val.string_value ();
3276  graphics_toolkit b = gtk_manager::find_toolkit (nm);
3277  if (b.get_name () != nm)
3278  {
3279  error ("set___graphics_toolkit__: invalid graphics toolkit");
3280  }
3281  else
3282  {
3283  set_toolkit (b);
3284  mark_modified ();
3285  }
3286  }
3287  else
3288  error ("set___graphics_toolkit__ must be a string");
3289  }
3290  }
3291 
3292  void set_position (const octave_value& val,
3293  bool do_notify_toolkit = true);
3294 
3295  void set_outerposition (const octave_value& val,
3296  bool do_notify_toolkit = true);
3297 
3298  Matrix get_boundingbox (bool internal = false,
3299  const Matrix& parent_pix_size = Matrix ()) const;
3300 
3301  void set_boundingbox (const Matrix& bb, bool internal = false,
3302  bool do_notify_toolkit = true);
3303 
3304  Matrix map_from_boundingbox (double x, double y) const;
3305 
3306  Matrix map_to_boundingbox (double x, double y) const;
3307 
3308  void update_units (const caseless_str& old_units);
3309 
3310  void update_paperunits (const caseless_str& old_paperunits);
3311 
3312  std::string get_title (void) const;
3313 
3314  // See the genprops.awk script for an explanation of the
3315  // properties declarations.
3316  // Programming note: Keep property list sorted if new ones are added.
3317 
3318  BEGIN_PROPERTIES (figure)
3319  array_property alphamap , Matrix (64, 1, 1)
3320  callback_property buttondownfcn , Matrix ()
3321  callback_property closerequestfcn , "closereq"
3322  color_property color , color_property (color_values (1, 1, 1), radio_values ("none"))
3323  array_property colormap , jet_colormap ()
3324  handle_property currentaxes S , graphics_handle ()
3325  string_property currentcharacter r , ""
3326  handle_property currentobject r , graphics_handle ()
3327  array_property currentpoint r , Matrix (2, 1, 0)
3328  bool_property dockcontrols , "off"
3329  bool_property doublebuffer , "on"
3330  string_property filename , ""
3331  bool_property integerhandle S , "on"
3332  bool_property inverthardcopy , "off"
3333  callback_property keypressfcn , Matrix ()
3334  callback_property keyreleasefcn , Matrix ()
3335  radio_property menubar , "none|{figure}"
3336  double_property mincolormap , 64
3337  string_property name , ""
3338  radio_property nextplot , "new|{add}|replacechildren|replace"
3339  bool_property numbertitle , "on"
3340  array_property outerposition s , Matrix (1, 4, -1.0)
3341  radio_property paperorientation U , "{portrait}|landscape|rotated"
3342  array_property paperposition , default_figure_paperposition ()
3343  radio_property paperpositionmode , "auto|{manual}"
3344  array_property papersize U , default_figure_papersize ()
3345  radio_property papertype SU , "{usletter}|uslegal|a0|a1|a2|a3|a4|a5|b0|b1|b2|b3|b4|b5|arch-a|arch-b|arch-c|arch-d|arch-e|a|b|c|d|e|tabloid|<custom>"
3346  radio_property paperunits Su , "{inches}|centimeters|normalized|points"
3347  radio_property pointer , "crosshair|fullcrosshair|{arrow}|ibeam|watch|topl|topr|botl|botr|left|top|right|bottom|circle|cross|fleur|custom|hand"
3348  array_property pointershapecdata , Matrix (16, 16, 0)
3349  array_property pointershapehotspot , Matrix (1, 2, 0)
3350  array_property position s , default_figure_position ()
3351  radio_property renderer , "{painters}|zbuffer|opengl|none"
3352  radio_property renderermode , "{auto}|manual"
3353  bool_property resize , "on"
3354  callback_property resizefcn , Matrix ()
3355  radio_property selectiontype , "{normal}|open|alt|extend"
3356  radio_property toolbar , "none|{auto}|figure"
3357  radio_property units Su , "inches|centimeters|normalized|points|{pixels}|characters"
3358  callback_property windowbuttondownfcn , Matrix ()
3359  callback_property windowbuttonmotionfcn , Matrix ()
3360  callback_property windowbuttonupfcn , Matrix ()
3361  callback_property windowkeypressfcn , Matrix ()
3362  callback_property windowkeyreleasefcn , Matrix ()
3363  callback_property windowscrollwheelfcn , Matrix ()
3364  radio_property windowstyle , "{normal}|modal|docked"
3365  string_property wvisual , ""
3366  radio_property wvisualmode , "{auto}|manual"
3367  string_property xdisplay , ""
3368  string_property xvisual , ""
3369  radio_property xvisualmode , "{auto}|manual"
3370  // Octave-specific properties
3371  bool_property __enhanced__ h , "on"
3372  string_property __graphics_toolkit__ s , gtk_manager::default_toolkit ()
3373  any_property __guidata__ h , Matrix ()
3374  any_property __plot_stream__ h , Matrix ()
3375  END_PROPERTIES
3376 
3377  protected:
3378  void init (void)
3379  {
3380  alphamap.add_constraint (dim_vector (-1, 1));
3381  colormap.add_constraint (dim_vector (-1, 3));
3382  outerposition.add_constraint (dim_vector (1, 4));
3383  paperposition.add_constraint (dim_vector (1, 4));
3384  papersize.add_constraint (dim_vector (1, 2));
3385  pointershapecdata.add_constraint (dim_vector (16, 16));
3386  pointershapehotspot.add_constraint (dim_vector (1, 2));
3387  position.add_constraint (dim_vector (1, 4));
3388  }
3389 
3390  private:
3391  mutable graphics_toolkit toolkit;
3392  };
3393 
3394 private:
3395  properties xproperties;
3396 
3397 public:
3398  figure (const graphics_handle& mh, const graphics_handle& p)
3399  : base_graphics_object (), xproperties (mh, p), default_properties ()
3400  {
3401  xproperties.override_defaults (*this);
3402  }
3403 
3404  ~figure (void) { }
3405 
3406  void override_defaults (base_graphics_object& obj)
3407  {
3408  // Allow parent (root figure) to override first (properties knows how
3409  // to find the parent object).
3410  xproperties.override_defaults (obj);
3411 
3412  // Now override with our defaults. If the default_properties
3413  // list includes the properties for all defaults (line,
3414  // surface, etc.) then we don't have to know the type of OBJ
3415  // here, we just call its set function and let it decide which
3416  // properties from the list to use.
3417  obj.set_from_list (default_properties);
3418  }
3419 
3420  void set (const caseless_str& name, const octave_value& value)
3421  {
3422  if (name.compare ("default", 7))
3423  // strip "default", pass rest to function that will
3424  // parse the remainder and add the element to the
3425  // default_properties map.
3426  default_properties.set (name.substr (7), value);
3427  else
3428  xproperties.set (name, value);
3429  }
3430 
3431  octave_value get (const caseless_str& name) const
3432  {
3433  octave_value retval;
3434 
3435  if (name.compare ("default", 7))
3436  retval = get_default (name.substr (7));
3437  else
3438  retval = xproperties.get (name);
3439 
3440  return retval;
3441  }
3442 
3443  octave_value get_default (const caseless_str& name) const;
3444 
3445  octave_value get_defaults (void) const
3446  {
3447  return default_properties.as_struct ("default");
3448  }
3449 
3450  base_properties& get_properties (void) { return xproperties; }
3451 
3452  const base_properties& get_properties (void) const { return xproperties; }
3453 
3454  bool valid_object (void) const { return true; }
3455 
3456  void reset_default_properties (void);
3457 
3458 private:
3459  property_list default_properties;
3460 };
3461 
3462 // ---------------------------------------------------------------------
3463 
3464 class OCTINTERP_API graphics_xform
3465 {
3466 public:
3467  graphics_xform (void)
3468  : xform (xform_eye ()), xform_inv (xform_eye ()),
3469  sx ("linear"), sy ("linear"), sz ("linear"), zlim (1, 2, 0.0)
3470  {
3471  zlim(1) = 1.0;
3472  }
3473 
3474  graphics_xform (const Matrix& xm, const Matrix& xim,
3475  const scaler& x, const scaler& y, const scaler& z,
3476  const Matrix& zl)
3477  : xform (xm), xform_inv (xim), sx (x), sy (y), sz (z), zlim (zl) { }
3478 
3479  graphics_xform (const graphics_xform& g)
3480  : xform (g.xform), xform_inv (g.xform_inv), sx (g.sx),
3481  sy (g.sy), sz (g.sz), zlim (g.zlim) { }
3482 
3483  ~graphics_xform (void) { }
3484 
3485  graphics_xform& operator = (const graphics_xform& g)
3486  {
3487  xform = g.xform;
3488  xform_inv = g.xform_inv;
3489  sx = g.sx;
3490  sy = g.sy;
3491  sz = g.sz;
3492  zlim = g.zlim;
3493 
3494  return *this;
3495  }
3496 
3497  static ColumnVector xform_vector (double x, double y, double z);
3498 
3499  static Matrix xform_eye (void);
3500 
3501  ColumnVector transform (double x, double y, double z,
3502  bool use_scale = true) const;
3503 
3504  ColumnVector untransform (double x, double y, double z,
3505  bool use_scale = true) const;
3506 
3507  ColumnVector untransform (double x, double y, bool use_scale = true) const
3508  { return untransform (x, y, (zlim(0)+zlim(1))/2, use_scale); }
3509 
3510  Matrix xscale (const Matrix& m) const { return sx.scale (m); }
3511  Matrix yscale (const Matrix& m) const { return sy.scale (m); }
3512  Matrix zscale (const Matrix& m) const { return sz.scale (m); }
3513 
3514  Matrix scale (const Matrix& m) const
3515  {
3516  bool has_z = (m.columns () > 2);
3517 
3518  if (sx.is_linear () && sy.is_linear ()
3519  && (! has_z || sz.is_linear ()))
3520  return m;
3521 
3522  Matrix retval (m.dims ());
3523 
3524  int r = m.rows ();
3525 
3526  for (int i = 0; i < r; i++)
3527  {
3528  retval(i,0) = sx.scale (m(i,0));
3529  retval(i,1) = sy.scale (m(i,1));
3530  if (has_z)
3531  retval(i,2) = sz.scale (m(i,2));
3532  }
3533 
3534  return retval;
3535  }
3536 
3537 private:
3538  Matrix xform;
3539  Matrix xform_inv;
3540  scaler sx, sy, sz;
3541  Matrix zlim;
3542 };
3543 
3544 enum
3545 {
3546  AXE_ANY_DIR = 0,
3547  AXE_DEPTH_DIR = 1,
3548  AXE_HORZ_DIR = 2,
3549  AXE_VERT_DIR = 3
3550 };
3551 
3552 class OCTINTERP_API axes : public base_graphics_object
3553 {
3554 public:
3555  class OCTINTERP_API properties : public base_properties
3556  {
3557  public:
3558  void set_defaults (base_graphics_object& obj, const std::string& mode);
3559 
3560  void remove_child (const graphics_handle& h);
3561 
3562  const scaler& get_x_scaler (void) const { return sx; }
3563  const scaler& get_y_scaler (void) const { return sy; }
3564  const scaler& get_z_scaler (void) const { return sz; }
3565 
3566  Matrix get_boundingbox (bool internal = false,
3567  const Matrix& parent_pix_size = Matrix ()) const;
3568  Matrix get_extent (bool with_text = false,
3569  bool only_text_height=false) const;
3570 
3571  double get_fontsize_points (double box_pix_height = 0) const;
3572 
3573  void update_boundingbox (void)
3574  {
3575  if (units_is ("normalized"))
3576  {
3577  sync_positions ();
3578  base_properties::update_boundingbox ();
3579  }
3580  }
3581 
3582  void update_camera (void);
3583  void update_axes_layout (void);
3584  void update_aspectratios (void);
3585  void update_transform (void)
3586  {
3587  update_aspectratios ();
3588  update_camera ();
3589  update_axes_layout ();
3590  }
3591 
3592  void sync_positions (void);
3593 
3594  void update_autopos (const std::string& elem_type);
3595  void update_xlabel_position (void);
3596  void update_ylabel_position (void);
3597  void update_zlabel_position (void);
3598  void update_title_position (void);
3599 
3600  graphics_xform get_transform (void) const
3601  { return graphics_xform (x_render, x_render_inv, sx, sy, sz, x_zlim); }
3602 
3603  Matrix get_transform_matrix (void) const { return x_render; }
3604  Matrix get_inverse_transform_matrix (void) const { return x_render_inv; }
3605  Matrix get_opengl_matrix_1 (void) const { return x_gl_mat1; }
3606  Matrix get_opengl_matrix_2 (void) const { return x_gl_mat2; }
3607  Matrix get_transform_zlim (void) const { return x_zlim; }
3608 
3609  int get_xstate (void) const { return xstate; }
3610  int get_ystate (void) const { return ystate; }
3611  int get_zstate (void) const { return zstate; }
3612  double get_xPlane (void) const { return xPlane; }
3613  double get_xPlaneN (void) const { return xPlaneN; }
3614  double get_yPlane (void) const { return yPlane; }
3615  double get_yPlaneN (void) const { return yPlaneN; }
3616  double get_zPlane (void) const { return zPlane; }
3617  double get_zPlaneN (void) const { return zPlaneN; }
3618  double get_xpTick (void) const { return xpTick; }
3619  double get_xpTickN (void) const { return xpTickN; }
3620  double get_ypTick (void) const { return ypTick; }
3621  double get_ypTickN (void) const { return ypTickN; }
3622  double get_zpTick (void) const { return zpTick; }
3623  double get_zpTickN (void) const { return zpTickN; }
3624  double get_x_min (void) const { return std::min (xPlane, xPlaneN); }
3625  double get_x_max (void) const { return std::max (xPlane, xPlaneN); }
3626  double get_y_min (void) const { return std::min (yPlane, yPlaneN); }
3627  double get_y_max (void) const { return std::max (yPlane, yPlaneN); }
3628  double get_z_min (void) const { return std::min (zPlane, zPlaneN); }
3629  double get_z_max (void) const { return std::max (zPlane, zPlaneN); }
3630  double get_fx (void) const { return fx; }
3631  double get_fy (void) const { return fy; }
3632  double get_fz (void) const { return fz; }
3633  double get_xticklen (void) const { return xticklen; }
3634  double get_yticklen (void) const { return yticklen; }
3635  double get_zticklen (void) const { return zticklen; }
3636  double get_xtickoffset (void) const { return xtickoffset; }
3637  double get_ytickoffset (void) const { return ytickoffset; }
3638  double get_ztickoffset (void) const { return ztickoffset; }
3639  bool get_x2Dtop (void) const { return x2Dtop; }
3640  bool get_y2Dright (void) const { return y2Dright; }
3641  bool get_layer2Dtop (void) const { return layer2Dtop; }
3642  bool get_xySym (void) const { return xySym; }
3643  bool get_xyzSym (void) const { return xyzSym; }
3644  bool get_zSign (void) const { return zSign; }
3645  bool get_nearhoriz (void) const { return nearhoriz; }
3646 
3647  ColumnVector pixel2coord (double px, double py) const
3648  { return get_transform ().untransform (px, py, (x_zlim(0)+x_zlim(1))/2); }
3649 
3650  ColumnVector coord2pixel (double x, double y, double z) const
3651  { return get_transform ().transform (x, y, z); }
3652 
3653  void zoom_about_point (double x, double y, double factor,
3654  bool push_to_zoom_stack = true);
3655  void zoom (const Matrix& xl, const Matrix& yl,
3656  bool push_to_zoom_stack = true);
3657  void translate_view (double x0, double x1, double y0, double y1);
3658  void rotate_view (double delta_az, double delta_el);
3659  void unzoom (void);
3660  void clear_zoom_stack (void);
3661 
3662  void update_units (const caseless_str& old_units);
3663 
3664  void update_fontunits (const caseless_str& old_fontunits);
3665 
3666  private:
3667  scaler sx, sy, sz;
3668  Matrix x_render, x_render_inv;
3669  Matrix x_gl_mat1, x_gl_mat2;
3670  Matrix x_zlim;
3671  std::list<octave_value> zoom_stack;
3672 
3673  // Axes layout data
3674  int xstate, ystate, zstate;
3675  double xPlane, xPlaneN, yPlane, yPlaneN, zPlane, zPlaneN;
3676  double xpTick, xpTickN, ypTick, ypTickN, zpTick, zpTickN;
3677  double fx, fy, fz;
3678  double xticklen, yticklen, zticklen;
3679  double xtickoffset, ytickoffset, ztickoffset;
3680  bool x2Dtop, y2Dright, layer2Dtop;
3681  bool xySym, xyzSym, zSign, nearhoriz;
3682 
3683 #if HAVE_FREETYPE
3684  // freetype renderer, used for calculation of text (tick labels) size
3685  ft_render text_renderer;
3686 #endif
3687 
3688  void set_text_child (handle_property& h, const std::string& who,
3689  const octave_value& v);
3690 
3691  void delete_text_child (handle_property& h);
3692 
3693  // See the genprops.awk script for an explanation of the
3694  // properties declarations.
3695  // Programming note: Keep property list sorted if new ones are added.
3696 
3697  BEGIN_PROPERTIES (axes)
3698  radio_property activepositionproperty , "{outerposition}|position"
3699  row_vector_property alim m , default_lim ()
3700  radio_property alimmode , "{auto}|manual"
3701  color_property ambientlightcolor , color_values (1, 1, 1)
3702  bool_property box , "on"
3703  array_property cameraposition m , Matrix (1, 3, 0.0)
3704  radio_property camerapositionmode , "{auto}|manual"
3705  array_property cameratarget m , Matrix (1, 3, 0.0)
3706  radio_property cameratargetmode , "{auto}|manual"
3707  array_property cameraupvector m , Matrix ()
3708  radio_property cameraupvectormode , "{auto}|manual"
3709  double_property cameraviewangle m , 10.0
3710  radio_property cameraviewanglemode , "{auto}|manual"
3711  row_vector_property clim m , default_lim ()
3712  radio_property climmode al , "{auto}|manual"
3713  color_property color , color_property (color_values (1, 1, 1), radio_values ("none"))
3714  array_property colororder , default_colororder ()
3715  array_property currentpoint , Matrix (2, 3, 0.0)
3716  array_property dataaspectratio mu , Matrix (1, 3, 1.0)
3717  radio_property dataaspectratiomode u , "{auto}|manual"
3718  radio_property drawmode , "{normal}|fast"
3719  radio_property fontangle u , "{normal}|italic|oblique"
3720  string_property fontname u , OCTAVE_DEFAULT_FONTNAME
3721  double_property fontsize u , 10
3722  radio_property fontunits SU , "{points}|normalized|inches|centimeters|pixels"
3723  radio_property fontweight u , "{normal}|light|demi|bold"
3724  radio_property gridlinestyle , "-|--|{:}|-.|none"
3725  // NOTE: interpreter is not a Matlab axis property, but it makes
3726  // more sense to have it so that axis ticklabels can use it.
3727  radio_property interpreter , "tex|{none}|latex"
3728  radio_property layer u , "{bottom}|top"
3729  // FIXME: should be kind of string array.
3730  any_property linestyleorder S , "-"
3731  double_property linewidth , 0.5
3732  radio_property minorgridlinestyle , "-|--|{:}|-.|none"
3733  radio_property nextplot , "add|replacechildren|{replace}"
3734  array_property outerposition u , default_axes_outerposition ()
3735  array_property plotboxaspectratio mu , Matrix (1, 3, 1.0)
3736  radio_property plotboxaspectratiomode u , "{auto}|manual"
3737  array_property position u , default_axes_position ()
3738  radio_property projection , "{orthographic}|perpective"
3739  radio_property tickdir mu , "{in}|out"
3740  radio_property tickdirmode u , "{auto}|manual"
3741  array_property ticklength u , default_axes_ticklength ()
3742  array_property tightinset r , Matrix (1, 4, 0.0)
3743  handle_property title SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
3744  // FIXME: uicontextmenu should be moved here.
3745  radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters"
3746  array_property view u , Matrix ()
3747  radio_property xaxislocation u , "{bottom}|top|zero"
3748  color_property xcolor , color_values (0, 0, 0)
3749  radio_property xdir u , "{normal}|reverse"
3750  bool_property xgrid , "off"
3751  handle_property xlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
3752  row_vector_property xlim mu , default_lim ()
3753  radio_property xlimmode al , "{auto}|manual"
3754  bool_property xminorgrid , "off"
3755  bool_property xminortick , "off"
3756  radio_property xscale alu , "{linear}|log"
3757  row_vector_property xtick mu , default_axes_tick ()
3758  // FIXME: should be kind of string array.
3759  any_property xticklabel S , ""
3760  radio_property xticklabelmode u , "{auto}|manual"
3761  radio_property xtickmode u , "{auto}|manual"
3762  radio_property yaxislocation u , "{left}|right|zero"
3763  color_property ycolor , color_values (0, 0, 0)
3764  radio_property ydir u , "{normal}|reverse"
3765  bool_property ygrid , "off"
3766  handle_property ylabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
3767  row_vector_property ylim mu , default_lim ()
3768  radio_property ylimmode al , "{auto}|manual"
3769  bool_property yminorgrid , "off"
3770  bool_property yminortick , "off"
3771  radio_property yscale alu , "{linear}|log"
3772  row_vector_property ytick mu , default_axes_tick ()
3773  any_property yticklabel S , ""
3774  radio_property yticklabelmode u , "{auto}|manual"
3775  radio_property ytickmode u , "{auto}|manual"
3776  color_property zcolor , color_values (0, 0, 0)
3777  radio_property zdir u , "{normal}|reverse"
3778  bool_property zgrid , "off"
3779  handle_property zlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
3780  row_vector_property zlim mu , default_lim ()
3781  radio_property zlimmode al , "{auto}|manual"
3782  bool_property zminorgrid , "off"
3783  bool_property zminortick , "off"
3784  radio_property zscale alu , "{linear}|log"
3785  row_vector_property ztick mu , default_axes_tick ()
3786  any_property zticklabel S , ""
3787  radio_property zticklabelmode u , "{auto}|manual"
3788  radio_property ztickmode u , "{auto}|manual"
3789  // Octave-specific properties
3790  bool_property __hold_all__ h , "off"
3791  // hidden properties for alignment of subplots
3792  radio_property autopos_tag h , "{none}|subplot"
3793  // hidden properties for inset
3794  array_property looseinset hu , Matrix (1, 4, 0.0)
3795  // hidden properties for transformation computation
3796  array_property x_viewtransform h , Matrix (4, 4, 0.0)
3797  array_property x_projectiontransform h , Matrix (4, 4, 0.0)
3798  array_property x_viewporttransform h , Matrix (4, 4, 0.0)
3799  array_property x_normrendertransform h , Matrix (4, 4, 0.0)
3800  array_property x_rendertransform h , Matrix (4, 4, 0.0)
3801  // hidden properties for minor ticks
3802  row_vector_property xmtick h , Matrix ()
3803  row_vector_property ymtick h , Matrix ()
3804  row_vector_property zmtick h , Matrix ()
3805  END_PROPERTIES
3806 
3807  protected:
3808  void init (void);
3809 
3810  private:
3811 
3812  std::string
3813  get_scale (const std::string& scale, const Matrix& lims)
3814  {
3815  std::string retval = scale;
3816 
3817  if (scale == "log" && lims.numel () > 1 && lims(0) < 0 && lims(1) < 0)
3818  retval = "neglog";
3819 
3820  return retval;
3821  }
3822 
3823  void update_xscale (void)
3824  {
3825  sx = get_scale (get_xscale (), xlim.get ().matrix_value ());
3826  }
3827 
3828  void update_yscale (void)
3829  {
3830  sy = get_scale (get_yscale (), ylim.get ().matrix_value ());
3831  }
3832 
3833  void update_zscale (void)
3834  {
3835  sz = get_scale (get_zscale (), zlim.get ().matrix_value ());
3836  }
3837 
3838  void update_view (void) { sync_positions (); }
3839  void update_dataaspectratio (void) { sync_positions (); }
3840  void update_dataaspectratiomode (void) { sync_positions (); }
3841  void update_plotboxaspectratio (void) { sync_positions (); }
3842  void update_plotboxaspectratiomode (void) { sync_positions (); }
3843 
3844  void update_layer (void) { update_axes_layout (); }
3845  void update_yaxislocation (void)
3846  {
3847  update_axes_layout ();
3848  update_ylabel_position ();
3849  }
3850  void update_xaxislocation (void)
3851  {
3852  update_axes_layout ();
3853  update_xlabel_position ();
3854  }
3855 
3856  void update_xdir (void) { update_camera (); update_axes_layout (); }
3857  void update_ydir (void) { update_camera (); update_axes_layout (); }
3858  void update_zdir (void) { update_camera (); update_axes_layout (); }
3859 
3860  void update_ticklength (void);
3861  void update_tickdir (void) { update_ticklength (); }
3862  void update_tickdirmode (void) { update_ticklength (); }
3863 
3864  void update_xtick (void)
3865  {
3866  if (xticklabelmode.is ("auto"))
3867  calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
3868  }
3869  void update_ytick (void)
3870  {
3871  if (yticklabelmode.is ("auto"))
3872  calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
3873  }
3874  void update_ztick (void)
3875  {
3876  if (zticklabelmode.is ("auto"))
3877  calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
3878  }
3879 
3880  void update_xtickmode (void)
3881  {
3882  if (xtickmode.is ("auto"))
3883  {
3884  calc_ticks_and_lims (xlim, xtick, xmtick, xlimmode.is ("auto"),
3885  xscale.is ("log"));
3886  update_xtick ();
3887  }
3888  }
3889  void update_ytickmode (void)
3890  {
3891  if (ytickmode.is ("auto"))
3892  {
3893  calc_ticks_and_lims (ylim, ytick, ymtick, ylimmode.is ("auto"),
3894  yscale.is ("log"));
3895  update_ytick ();
3896  }
3897  }
3898  void update_ztickmode (void)
3899  {
3900  if (ztickmode.is ("auto"))
3901  {
3902  calc_ticks_and_lims (zlim, ztick, zmtick, zlimmode.is ("auto"),
3903  zscale.is ("log"));
3904  update_ztick ();
3905  }
3906  }
3907 
3908  void update_xticklabelmode (void)
3909  {
3910  if (xticklabelmode.is ("auto"))
3911  calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
3912  }
3913  void update_yticklabelmode (void)
3914  {
3915  if (yticklabelmode.is ("auto"))
3916  calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
3917  }
3918  void update_zticklabelmode (void)
3919  {
3920  if (zticklabelmode.is ("auto"))
3921  calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
3922  }
3923 
3924  void update_font (void);
3925  void update_fontname (void) { update_font (); }
3926  void update_fontsize (void) { update_font (); }
3927  void update_fontangle (void) { update_font (); }
3928  void update_fontweight (void) { update_font (); }
3929 
3930  void update_outerposition (void)
3931  {
3932  set_activepositionproperty ("outerposition");
3933  caseless_str old_units = get_units ();
3934  set_units ("normalized");
3935  Matrix outerbox = outerposition.get ().matrix_value ();
3936  Matrix innerbox = position.get ().matrix_value ();
3937  Matrix linset = looseinset.get ().matrix_value ();
3938  Matrix tinset = tightinset.get ().matrix_value ();
3939  outerbox(2) = outerbox(2) + outerbox(0);
3940  outerbox(3) = outerbox(3) + outerbox(1);
3941  innerbox(0) = outerbox(0) + std::max (linset(0), tinset(0));
3942  innerbox(1) = outerbox(1) + std::max (linset(1), tinset(1));
3943  innerbox(2) = outerbox(2) - std::max (linset(2), tinset(2));
3944  innerbox(3) = outerbox(3) - std::max (linset(3), tinset(3));
3945  innerbox(2) = innerbox(2) - innerbox(0);
3946  innerbox(3) = innerbox(3) - innerbox(1);
3947  position = innerbox;
3948  set_units (old_units);
3949  update_transform ();
3950  }
3951 
3952  void update_position (void)
3953  {
3954  set_activepositionproperty ("position");
3955  caseless_str old_units = get_units ();
3956  set_units ("normalized");
3957  Matrix outerbox = outerposition.get ().matrix_value ();
3958  Matrix innerbox = position.get ().matrix_value ();
3959  Matrix linset = looseinset.get ().matrix_value ();
3960  Matrix tinset = tightinset.get ().matrix_value ();
3961  innerbox(2) = innerbox(2) + innerbox(0);
3962  innerbox(3) = innerbox(3) + innerbox(1);
3963  outerbox(0) = innerbox(0) - std::max (linset(0), tinset(0));
3964  outerbox(1) = innerbox(1) - std::max (linset(1), tinset(1));
3965  outerbox(2) = innerbox(2) + std::max (linset(2), tinset(2));
3966  outerbox(3) = innerbox(3) + std::max (linset(3), tinset(3));
3967  outerbox(2) = outerbox(2) - outerbox(0);
3968  outerbox(3) = outerbox(3) - outerbox(1);
3969  outerposition = outerbox;
3970  set_units (old_units);
3971  update_transform ();
3972  }
3973 
3974  void update_looseinset (void)
3975  {
3976  caseless_str old_units = get_units ();
3977  set_units ("normalized");
3978  Matrix innerbox = position.get ().matrix_value ();
3979  innerbox(2) = innerbox(2) + innerbox(0);
3980  innerbox(3) = innerbox(3) + innerbox(1);
3981  Matrix outerbox = outerposition.get ().matrix_value ();
3982  outerbox(2) = outerbox(2) + outerbox(0);
3983  outerbox(3) = outerbox(3) + outerbox(1);
3984  Matrix linset = looseinset.get ().matrix_value ();
3985  Matrix tinset = tightinset.get ().matrix_value ();
3986  if (activepositionproperty.is ("position"))
3987  {
3988  outerbox(0) = innerbox(0) - std::max (linset(0), tinset(0));
3989  outerbox(1) = innerbox(1) - std::max (linset(1), tinset(1));
3990  outerbox(2) = innerbox(2) + std::max (linset(2), tinset(2));
3991  outerbox(3) = innerbox(3) + std::max (linset(3), tinset(3));
3992  outerbox(2) = outerbox(2) - outerbox(0);
3993  outerbox(3) = outerbox(3) - outerbox(1);
3994  outerposition = outerbox;
3995  }
3996  else
3997  {
3998  innerbox(0) = outerbox(0) + std::max (linset(0), tinset(0));
3999  innerbox(1) = outerbox(1) + std::max (linset(1), tinset(1));
4000  innerbox(2) = outerbox(2) - std::max (linset(2), tinset(2));
4001  innerbox(3) = outerbox(3) - std::max (linset(3), tinset(3));
4002  innerbox(2) = innerbox(2) - innerbox(0);
4003  innerbox(3) = innerbox(3) - innerbox(1);
4004  position = innerbox;
4005  }
4006  set_units (old_units);
4007  update_transform ();
4008  }
4009 
4010  double calc_tick_sep (double minval, double maxval);
4011  void calc_ticks_and_lims (array_property& lims, array_property& ticks,
4012  array_property& mticks,
4013  bool limmode_is_auto, bool is_logscale);
4014  void calc_ticklabels (const array_property& ticks, any_property& labels,
4015  bool is_logscale);
4016  Matrix get_ticklabel_extents (const Matrix& ticks,
4017  const string_vector& ticklabels,
4018  const Matrix& limits);
4019 
4020  void fix_limits (array_property& lims)
4021  {
4022  if (lims.get ().is_empty ())
4023  return;
4024 
4025  Matrix l = lims.get ().matrix_value ();
4026  if (l(0) > l(1))
4027  {
4028  l(0) = 0;
4029  l(1) = 1;
4030  lims = l;
4031  }
4032  else if (l(0) == l(1))
4033  {
4034  l(0) -= 0.5;
4035  l(1) += 0.5;
4036  lims = l;
4037  }
4038  }
4039 
4040  Matrix calc_tightbox (const Matrix& init_pos);
4041 
4042  public:
4043  Matrix get_axis_limits (double xmin, double xmax,
4044  double min_pos, double max_neg,
4045  bool logscale);
4046 
4047  void update_xlim (bool do_clr_zoom = true)
4048  {
4049  if (xtickmode.is ("auto"))
4050  calc_ticks_and_lims (xlim, xtick, xmtick, xlimmode.is ("auto"),
4051  xscale.is ("log"));
4052  if (xticklabelmode.is ("auto"))
4053  calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
4054 
4055  fix_limits (xlim);
4056 
4057  update_xscale ();
4058 
4059  if (do_clr_zoom)
4060  zoom_stack.clear ();
4061 
4062  update_axes_layout ();
4063  }
4064 
4065  void update_ylim (bool do_clr_zoom = true)
4066  {
4067  if (ytickmode.is ("auto"))
4068  calc_ticks_and_lims (ylim, ytick, ymtick, ylimmode.is ("auto"),
4069  yscale.is ("log"));
4070  if (yticklabelmode.is ("auto"))
4071  calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
4072 
4073  fix_limits (ylim);
4074 
4075  update_yscale ();
4076 
4077  if (do_clr_zoom)
4078  zoom_stack.clear ();
4079 
4080  update_axes_layout ();
4081  }
4082 
4083  void update_zlim (void)
4084  {
4085  if (ztickmode.is ("auto"))
4086  calc_ticks_and_lims (zlim, ztick, zmtick, zlimmode.is ("auto"),
4087  zscale.is ("log"));
4088  if (zticklabelmode.is ("auto"))
4089  calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
4090 
4091  fix_limits (zlim);
4092 
4093  update_zscale ();
4094 
4095  zoom_stack.clear ();
4096 
4097  update_axes_layout ();
4098  }
4099 
4100  };
4101 
4102 private:
4103  properties xproperties;
4104 
4105 public:
4106  axes (const graphics_handle& mh, const graphics_handle& p)
4107  : base_graphics_object (), xproperties (mh, p), default_properties ()
4108  {
4109  xproperties.override_defaults (*this);
4110  xproperties.update_transform ();
4111  }
4112 
4113  ~axes (void) { }
4114 
4115  void override_defaults (base_graphics_object& obj)
4116  {
4117  // Allow parent (figure) to override first (properties knows how
4118  // to find the parent object).
4119  xproperties.override_defaults (obj);
4120 
4121  // Now override with our defaults. If the default_properties
4122  // list includes the properties for all defaults (line,
4123  // surface, etc.) then we don't have to know the type of OBJ
4124  // here, we just call its set function and let it decide which
4125  // properties from the list to use.
4126  obj.set_from_list (default_properties);
4127  }
4128 
4129  void set (const caseless_str& name, const octave_value& value)
4130  {
4131  if (name.compare ("default", 7))
4132  // strip "default", pass rest to function that will
4133  // parse the remainder and add the element to the
4134  // default_properties map.
4135  default_properties.set (name.substr (7), value);
4136  else
4137  xproperties.set (name, value);
4138  }
4139 
4140  void set_defaults (const std::string& mode)
4141  {
4142  remove_all_listeners ();
4143  xproperties.set_defaults (*this, mode);
4144  }
4145 
4146  octave_value get (const caseless_str& name) const
4147  {
4148  octave_value retval;
4149 
4150  // FIXME: finish this.
4151  if (name.compare ("default", 7))
4152  retval = get_default (name.substr (7));
4153  else
4154  retval = xproperties.get (name);
4155 
4156  return retval;
4157  }
4158 
4159  octave_value get_default (const caseless_str& name) const;
4160 
4161  octave_value get_defaults (void) const
4162  {
4163  return default_properties.as_struct ("default");
4164  }
4165 
4166  base_properties& get_properties (void) { return xproperties; }
4167 
4168  const base_properties& get_properties (void) const { return xproperties; }
4169 
4170  void update_axis_limits (const std::string& axis_type);
4171 
4172  void update_axis_limits (const std::string& axis_type,
4173  const graphics_handle& h);
4174 
4175  bool valid_object (void) const { return true; }
4176 
4177  void reset_default_properties (void);
4178 
4179 protected:
4180  void initialize (const graphics_object& go);
4181 
4182 private:
4183  property_list default_properties;
4184 };
4185 
4186 // ---------------------------------------------------------------------
4187 
4188 class OCTINTERP_API line : public base_graphics_object
4189 {
4190 public:
4191  class OCTINTERP_API properties : public base_properties
4192  {
4193  public:
4194  // See the genprops.awk script for an explanation of the
4195  // properties declarations.
4196  // Programming note: Keep property list sorted if new ones are added.
4197 
4198  BEGIN_PROPERTIES (line)
4199  color_property color , color_values (0, 0, 0)
4200  string_property displayname , ""
4201  radio_property erasemode , "{normal}|none|xor|background"
4202  // FIXME: interpreter is not a property of Matlab line objects.
4203  // Octave uses this for legend() with the string displayname.
4204  radio_property interpreter , "{tex}|none|latex"
4205  radio_property linestyle , "{-}|--|:|-.|none"
4206  double_property linewidth , 0.5
4207  radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram"
4208  color_property markeredgecolor , color_property (radio_values ("{auto}|none"), color_values (0, 0, 0))
4209  color_property markerfacecolor , color_property (radio_values ("auto|{none}"), color_values (0, 0, 0))
4210  double_property markersize , 6
4211  row_vector_property xdata u , default_data ()
4212  string_property xdatasource , ""
4213  row_vector_property ydata u , default_data ()
4214  string_property ydatasource , ""
4215  row_vector_property zdata u , Matrix ()
4216  string_property zdatasource , ""
4217 
4218  // hidden properties for limit computation
4219  row_vector_property xlim hlr , Matrix ()
4220  row_vector_property ylim hlr , Matrix ()
4221  row_vector_property zlim hlr , Matrix ()
4222  bool_property xliminclude hl , "on"
4223  bool_property yliminclude hl , "on"
4224  bool_property zliminclude hl , "off"
4225  END_PROPERTIES
4226 
4227  private:
4228  Matrix compute_xlim (void) const;
4229  Matrix compute_ylim (void) const;
4230 
4231  void update_xdata (void) { set_xlim (compute_xlim ()); }
4232 
4233  void update_ydata (void) { set_ylim (compute_ylim ()); }
4234 
4235  void update_zdata (void)
4236  {
4237  set_zlim (zdata.get_limits ());
4238  set_zliminclude (get_zdata ().numel () > 0);
4239  }
4240  };
4241 
4242 private:
4243  properties xproperties;
4244 
4245 public:
4246  line (const graphics_handle& mh, const graphics_handle& p)
4247  : base_graphics_object (), xproperties (mh, p)
4248  {
4249  xproperties.override_defaults (*this);
4250  }
4251 
4252  ~line (void) { }
4253 
4254  base_properties& get_properties (void) { return xproperties; }
4255 
4256  const base_properties& get_properties (void) const { return xproperties; }
4257 
4258  bool valid_object (void) const { return true; }
4259 };
4260 
4261 // ---------------------------------------------------------------------
4262 
4263 class OCTINTERP_API text : public base_graphics_object
4264 {
4265 public:
4266  class OCTINTERP_API properties : public base_properties
4267  {
4268  public:
4269  double get_fontsize_points (double box_pix_height = 0) const;
4270 
4271  void set_position (const octave_value& val)
4272  {
4273  if (! error_state)
4274  {
4275  octave_value new_val (val);
4276 
4277  if (new_val.numel () == 2)
4278  {
4279  dim_vector dv (1, 3);
4280 
4281  new_val = new_val.resize (dv, true);
4282  }
4283 
4284  if (position.set (new_val, false))
4285  {
4286  set_positionmode ("manual");
4287  update_position ();
4288  position.run_listeners (POSTSET);
4289  mark_modified ();
4290  }
4291  else
4292  set_positionmode ("manual");
4293  }
4294  }
4295 
4296  // See the genprops.awk script for an explanation of the
4297  // properties declarations.
4298 
4299  BEGIN_PROPERTIES (text)
4300  color_property backgroundcolor , color_property (radio_values ("{none}"), color_values (1, 1, 1))
4301  color_property color u , color_values (0, 0, 0)
4302  string_property displayname , ""
4303  color_property edgecolor , color_property (radio_values ("{none}"), color_values (0, 0, 0))
4304  bool_property editing , "off"
4305  radio_property erasemode , "{normal}|none|xor|background"
4306  array_property extent rG , Matrix (1, 4, 0.0)
4307  radio_property fontangle u , "{normal}|italic|oblique"
4308  string_property fontname u , OCTAVE_DEFAULT_FONTNAME
4309  double_property fontsize u , 10
4310  radio_property fontunits , "inches|centimeters|normalized|{points}|pixels"
4311  radio_property fontweight u , "light|{normal}|demi|bold"
4312  radio_property horizontalalignment mu , "{left}|center|right"
4313  radio_property interpreter u , "{tex}|none|latex"
4314  radio_property linestyle , "{-}|--|:|-.|none"
4315  double_property linewidth , 0.5
4316  double_property margin , 1
4317  array_property position smu , Matrix (1, 3, 0.0)
4318  double_property rotation mu , 0
4319  text_label_property string u , ""
4320  radio_property units u , "{data}|pixels|normalized|inches|centimeters|points"
4321  radio_property verticalalignment mu , "top|cap|{middle}|baseline|bottom"
4322 
4323  // hidden properties for limit computation
4324  row_vector_property xlim hlr , Matrix ()
4325  row_vector_property ylim hlr , Matrix ()
4326  row_vector_property zlim hlr , Matrix ()
4327  bool_property xliminclude hl , "off"
4328  bool_property yliminclude hl , "off"
4329  bool_property zliminclude hl , "off"
4330  // hidden properties for auto-positioning
4331  radio_property positionmode hu , "{auto}|manual"
4332  radio_property rotationmode hu , "{auto}|manual"
4333  radio_property horizontalalignmentmode hu , "{auto}|manual"
4334  radio_property verticalalignmentmode hu , "{auto}|manual"
4335  radio_property autopos_tag h , "{none}|xlabel|ylabel|zlabel|title"
4336  END_PROPERTIES
4337 
4338  Matrix get_data_position (void) const;
4339  Matrix get_extent_matrix (void) const;
4340  const uint8NDArray& get_pixels (void) const { return pixels; }
4341 #if HAVE_FREETYPE
4342  // freetype renderer, used for calculation of text size
4343  ft_render renderer;
4344 #endif
4345 
4346  protected:
4347  void init (void)
4348  {
4349  position.add_constraint (dim_vector (1, 3));
4350  cached_units = get_units ();
4351  update_font ();
4352  }
4353 
4354  private:
4355  void update_position (void)
4356  {
4357  Matrix pos = get_data_position ();
4358  Matrix lim;
4359 
4360  lim = Matrix (1, 3, pos(0));
4361  lim(2) = (lim(2) <= 0 ? octave_Inf : lim(2));
4362  set_xlim (lim);
4363 
4364  lim = Matrix (1, 3, pos(1));
4365  lim(2) = (lim(2) <= 0 ? octave_Inf : lim(2));
4366  set_ylim (lim);
4367 
4368  if (pos.numel () == 3)
4369  {
4370  lim = Matrix (1, 3, pos(2));
4371  lim(2) = (lim(2) <= 0 ? octave_Inf : lim(2));
4372  set_zliminclude ("on");
4373  set_zlim (lim);
4374  }
4375  else
4376  set_zliminclude ("off");
4377  }
4378 
4379  void update_text_extent (void);
4380 
4381  void request_autopos (void);
4382  void update_positionmode (void) { request_autopos (); }
4383  void update_rotationmode (void) { request_autopos (); }
4384  void update_horizontalalignmentmode (void) { request_autopos (); }
4385  void update_verticalalignmentmode (void) { request_autopos (); }
4386 
4387  void update_font (void);
4388  void update_string (void) { request_autopos (); update_text_extent (); }
4389  void update_rotation (void) { update_text_extent (); }
4390  void update_color (void) { update_font (); update_text_extent (); }
4391  void update_fontname (void) { update_font (); update_text_extent (); }
4392  void update_fontsize (void) { update_font (); update_text_extent (); }
4393  void update_fontangle (void) { update_font (); update_text_extent (); }
4394  void update_fontweight (void) { update_font (); update_text_extent (); }
4395  void update_interpreter (void) { update_text_extent (); }
4396  void update_horizontalalignment (void) { update_text_extent (); }
4397  void update_verticalalignment (void) { update_text_extent (); }
4398 
4399  void update_units (void);
4400 
4401  private:
4402  std::string cached_units;
4403  uint8NDArray pixels;
4404  };
4405 
4406 private:
4407  properties xproperties;
4408 
4409 public:
4410  text (const graphics_handle& mh, const graphics_handle& p)
4411  : base_graphics_object (), xproperties (mh, p)
4412  {
4413  xproperties.set_clipping ("off");
4414  xproperties.override_defaults (*this);
4415  }
4416 
4417  ~text (void) { }
4418 
4419  base_properties& get_properties (void) { return xproperties; }
4420 
4421  const base_properties& get_properties (void) const { return xproperties; }
4422 
4423  bool valid_object (void) const { return true; }
4424 };
4425 
4426 // ---------------------------------------------------------------------
4427 
4428 class OCTINTERP_API image : public base_graphics_object
4429 {
4430 public:
4431  class OCTINTERP_API properties : public base_properties
4432  {
4433  public:
4434  bool is_aliminclude (void) const
4435  { return (aliminclude.is_on () && alphadatamapping.is ("scaled")); }
4436  std::string get_aliminclude (void) const
4437  { return aliminclude.current_value (); }
4438 
4439  bool is_climinclude (void) const
4440  { return (climinclude.is_on () && cdatamapping.is ("scaled")); }
4441  std::string get_climinclude (void) const
4442  { return climinclude.current_value (); }
4443 
4444  octave_value get_color_data (void) const;
4445 
4446  // See the genprops.awk script for an explanation of the
4447  // properties declarations.
4448  // Programming note: Keep property list sorted if new ones are added.
4449 
4450  BEGIN_PROPERTIES (image)
4451  array_property alphadata u , Matrix ()
4452  radio_property alphadatamapping al , "none|direct|{scaled}"
4453  array_property cdata u , Matrix ()
4454  radio_property cdatamapping al , "scaled|{direct}"
4455  radio_property erasemode , "{normal}|none|xor|background"
4456  row_vector_property xdata u , Matrix ()
4457  row_vector_property ydata u , Matrix ()
4458  // hidden properties for limit computation
4459  row_vector_property alim hlr , Matrix ()
4460  row_vector_property clim hlr , Matrix ()
4461  row_vector_property xlim hlr , Matrix ()
4462  row_vector_property ylim hlr , Matrix ()
4463  bool_property aliminclude hlg , "on"
4464  bool_property climinclude hlg , "on"
4465  bool_property xliminclude hl , "on"
4466  bool_property yliminclude hl , "on"
4467  END_PROPERTIES
4468 
4469  protected:
4470  void init (void)
4471  {
4472  xdata.add_constraint (2);
4473  ydata.add_constraint (2);
4474  cdata.add_constraint ("double");
4475  cdata.add_constraint ("single");
4476  cdata.add_constraint ("logical");
4477  cdata.add_constraint ("uint8");
4478  cdata.add_constraint ("uint16");
4479  cdata.add_constraint ("int16");
4480  cdata.add_constraint ("real");
4481  cdata.add_constraint (dim_vector (-1, -1));
4482  cdata.add_constraint (dim_vector (-1, -1, 3));
4483  alphadata.add_constraint (dim_vector (-1, -1));
4484  alphadata.add_constraint ("double");
4485  alphadata.add_constraint ("uint8");
4486  }
4487 
4488  private:
4489  void update_alphadata (void)
4490  {
4491  if (alphadatamapping_is ("scaled"))
4492  set_alim (alphadata.get_limits ());
4493  else
4494  alim = alphadata.get_limits ();
4495  }
4496 
4497  void update_cdata (void)
4498  {
4499  if (cdatamapping_is ("scaled"))
4500  set_clim (cdata.get_limits ());
4501  else
4502  clim = cdata.get_limits ();
4503  }
4504 
4505  void update_xdata (void)
4506  {
4507  Matrix limits = xdata.get_limits ();
4508  float dp = pixel_xsize ();
4509 
4510  limits(0) = limits(0) - dp;
4511  limits(1) = limits(1) + dp;
4512  set_xlim (limits);
4513  }
4514 
4515  void update_ydata (void)
4516  {
4517  Matrix limits = ydata.get_limits ();
4518  float dp = pixel_ysize ();
4519 
4520  limits(0) = limits(0) - dp;
4521  limits(1) = limits(1) + dp;
4522  set_ylim (limits);
4523  }
4524 
4525  float pixel_size (octave_idx_type dim, const Matrix limits)
4526  {
4527  octave_idx_type l = dim - 1;
4528  float dp;
4529 
4530  if (l > 0 && limits(0) != limits(1))
4531  dp = (limits(1) - limits(0))/(2*l);
4532  else
4533  {
4534  if (limits(1) == limits(2))
4535  dp = 0.5;
4536  else
4537  dp = (limits(1) - limits(0))/2;
4538  }
4539  return dp;
4540  }
4541 
4542  public:
4543  float pixel_xsize (void)
4544  {
4545  return pixel_size ((get_cdata ().dims ())(1), xdata.get_limits ());
4546  }
4547 
4548  float pixel_ysize (void)
4549  {
4550  return pixel_size ((get_cdata ().dims ())(0), ydata.get_limits ());
4551  }
4552  };
4553 
4554 private:
4555  properties xproperties;
4556 
4557 public:
4558  image (const graphics_handle& mh, const graphics_handle& p)
4559  : base_graphics_object (), xproperties (mh, p)
4560  {
4561  xproperties.override_defaults (*this);
4562  }
4563 
4564  ~image (void) { }
4565 
4566  base_properties& get_properties (void) { return xproperties; }
4567 
4568  const base_properties& get_properties (void) const { return xproperties; }
4569 
4570  bool valid_object (void) const { return true; }
4571 };
4572 
4573 // ---------------------------------------------------------------------
4574 
4575 class OCTINTERP_API patch : public base_graphics_object
4576 {
4577 public:
4578  class OCTINTERP_API properties : public base_properties
4579  {
4580  public:
4581  octave_value get_color_data (void) const;
4582 
4583  bool is_aliminclude (void) const
4584  { return (aliminclude.is_on () && alphadatamapping.is ("scaled")); }
4585  std::string get_aliminclude (void) const
4586  { return aliminclude.current_value (); }
4587 
4588  bool is_climinclude (void) const
4589  { return (climinclude.is_on () && cdatamapping.is ("scaled")); }
4590  std::string get_climinclude (void) const
4591  { return climinclude.current_value (); }
4592 
4593  // See the genprops.awk script for an explanation of the
4594  // properties declarations.
4595  // Programming note: Keep property list sorted if new ones are added.
4596 
4597  BEGIN_PROPERTIES (patch)
4598  radio_property alphadatamapping l , "none|{scaled}|direct"
4599  double_property ambientstrength , 0.3
4600  radio_property backfacelighting , "unlit|lit|{reverselit}"
4601  array_property cdata u , Matrix ()
4602  radio_property cdatamapping l , "{scaled}|direct"
4603  double_property diffusestrength , 0.6
4604  string_property displayname , ""
4605  double_radio_property edgealpha , double_radio_property (1.0, radio_values ("flat|interp"))
4606  color_property edgecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
4607  radio_property edgelighting , "{none}|flat|gouraud|phong"
4608  radio_property erasemode , "{normal}|background|xor|none"
4609  double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp"))
4610  color_property facecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
4611  radio_property facelighting , "{none}|flat|gouraud|phong"
4612  array_property faces , Matrix ()
4613  array_property facevertexalphadata , Matrix ()
4614  array_property facevertexcdata , Matrix ()
4615  // FIXME: interpreter is not a property of a Matlab patch.
4616  // Octave uses this for legend() with the string displayname.
4617  radio_property interpreter , "{tex}|none|latex"
4618  radio_property linestyle , "{-}|--|:|-.|none"
4619  double_property linewidth , 0.5
4620  radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram"
4621  color_property markeredgecolor , color_property (radio_values ("none|{auto}|flat"), color_values (0, 0, 0))
4622  color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0))
4623  double_property markersize , 6
4624  radio_property normalmode , "{auto}|manual"
4625  double_property specularcolorreflectance , 1.0
4626  double_property specularexponent , 10.0
4627  double_property specularstrength , 0.6
4628  array_property vertexnormals , Matrix ()
4629  array_property vertices , Matrix ()
4630  array_property xdata u , Matrix ()
4631  array_property ydata u , Matrix ()
4632  array_property zdata u , Matrix ()
4633 
4634  // hidden properties for limit computation
4635  row_vector_property alim hlr , Matrix ()
4636  row_vector_property clim hlr , Matrix ()
4637  row_vector_property xlim hlr , Matrix ()
4638  row_vector_property ylim hlr , Matrix ()
4639  row_vector_property zlim hlr , Matrix ()
4640  bool_property aliminclude hlg , "on"
4641  bool_property climinclude hlg , "on"
4642  bool_property xliminclude hl , "on"
4643  bool_property yliminclude hl , "on"
4644  bool_property zliminclude hl , "on"
4645  END_PROPERTIES
4646 
4647  protected:
4648  void init (void)
4649  {
4650  xdata.add_constraint (dim_vector (-1, -1));
4651  ydata.add_constraint (dim_vector (-1, -1));
4652  zdata.add_constraint (dim_vector (-1, -1));
4653  faces.add_constraint (dim_vector (-1, -1));
4654  vertices.add_constraint (dim_vector (-1, 2));
4655  vertices.add_constraint (dim_vector (-1, 3));
4656  cdata.add_constraint (dim_vector (-1, -1));
4657  cdata.add_constraint (dim_vector (-1, -1, 3));
4658  facevertexcdata.add_constraint (dim_vector (-1, 1));
4659  facevertexcdata.add_constraint (dim_vector (-1, 3));
4660  facevertexalphadata.add_constraint (dim_vector (-1, 1));
4661  vertexnormals.add_constraint (dim_vector (-1, -1));
4662  }
4663 
4664  private:
4665  void update_xdata (void) { set_xlim (xdata.get_limits ()); }
4666  void update_ydata (void) { set_ylim (ydata.get_limits ()); }
4667  void update_zdata (void) { set_zlim (zdata.get_limits ()); }
4668 
4669  void update_cdata (void)
4670  {
4671  if (cdatamapping_is ("scaled"))
4672  set_clim (cdata.get_limits ());
4673  else
4674  clim = cdata.get_limits ();
4675  }
4676  };
4677 
4678 private:
4679  properties xproperties;
4680 
4681 public:
4682  patch (const graphics_handle& mh, const graphics_handle& p)
4683  : base_graphics_object (), xproperties (mh, p)
4684  {
4685  xproperties.override_defaults (*this);
4686  }
4687 
4688  ~patch (void) { }
4689 
4690  base_properties& get_properties (void) { return xproperties; }
4691 
4692  const base_properties& get_properties (void) const { return xproperties; }
4693 
4694  bool valid_object (void) const { return true; }
4695 };
4696 
4697 // ---------------------------------------------------------------------
4698 
4699 class OCTINTERP_API surface : public base_graphics_object
4700 {
4701 public:
4702  class OCTINTERP_API properties : public base_properties
4703  {
4704  public:
4705  octave_value get_color_data (void) const;
4706 
4707  bool is_aliminclude (void) const
4708  { return (aliminclude.is_on () && alphadatamapping.is ("scaled")); }
4709  std::string get_aliminclude (void) const
4710  { return aliminclude.current_value (); }
4711 
4712  bool is_climinclude (void) const
4713  { return (climinclude.is_on () && cdatamapping.is ("scaled")); }
4714  std::string get_climinclude (void) const
4715  { return climinclude.current_value (); }
4716 
4717  // See the genprops.awk script for an explanation of the
4718  // properties declarations.
4719  // Programming note: Keep property list sorted if new ones are added.
4720 
4721  BEGIN_PROPERTIES (surface)
4722  array_property alphadata u , Matrix ()
4723  radio_property alphadatamapping l , "none|direct|{scaled}"
4724  double_property ambientstrength , 0.3
4725  radio_property backfacelighting , "unlit|lit|{reverselit}"
4726  array_property cdata u , Matrix ()
4727  radio_property cdatamapping al , "{scaled}|direct"
4728  string_property cdatasource , ""
4729  double_property diffusestrength , 0.6
4730  string_property displayname , ""
4731  double_radio_property edgealpha , double_radio_property (1.0, radio_values ("flat|interp"))
4732  color_property edgecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
4733  radio_property edgelighting , "{none}|flat|gouraud|phong"
4734  radio_property erasemode , "{normal}|none|xor|background"
4735  double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp|texturemap"))
4736  color_property facecolor , color_property (radio_values ("none|{flat}|interp|texturemap"), color_values (0, 0, 0))
4737  radio_property facelighting , "{none}|flat|gouraud|phong"
4738  // FIXME: interpreter is not a Matlab surface property
4739  // Octave uses this for legend() with the string displayname.
4740  radio_property interpreter , "{tex}|none|latex"
4741  radio_property linestyle , "{-}|--|:|-.|none"
4742  double_property linewidth , 0.5
4743  radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram"
4744  color_property markeredgecolor , color_property (radio_values ("none|{auto}|flat"), color_values (0, 0, 0))
4745  color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0))
4746  double_property markersize , 6
4747  radio_property meshstyle , "{both}|row|column"
4748  radio_property normalmode u , "{auto}|manual"
4749  double_property specularcolorreflectance , 1
4750  double_property specularexponent , 10
4751  double_property specularstrength , 0.9
4752  array_property vertexnormals u , Matrix ()
4753  array_property xdata u , Matrix ()
4754  string_property xdatasource , ""
4755  array_property ydata u , Matrix ()
4756  string_property ydatasource , ""
4757  array_property zdata u , Matrix ()
4758  string_property zdatasource , ""
4759 
4760  // hidden properties for limit computation
4761  row_vector_property alim hlr , Matrix ()
4762  row_vector_property clim hlr , Matrix ()
4763  row_vector_property xlim hlr , Matrix ()
4764  row_vector_property ylim hlr , Matrix ()
4765  row_vector_property zlim hlr , Matrix ()
4766  bool_property aliminclude hlg , "on"
4767  bool_property climinclude hlg , "on"
4768  bool_property xliminclude hl , "on"
4769  bool_property yliminclude hl , "on"
4770  bool_property zliminclude hl , "on"
4771  END_PROPERTIES
4772 
4773  protected:
4774  void init (void)
4775  {
4776  xdata.add_constraint (dim_vector (-1, -1));
4777  ydata.add_constraint (dim_vector (-1, -1));
4778  zdata.add_constraint (dim_vector (-1, -1));
4779  cdata.add_constraint ("double");
4780  cdata.add_constraint ("single");
4781  cdata.add_constraint (dim_vector (-1, -1));
4782  cdata.add_constraint (dim_vector (-1, -1, 3));
4783  alphadata.add_constraint ("double");
4784  alphadata.add_constraint ("uint8");
4785  alphadata.add_constraint (dim_vector (-1, -1));
4786  vertexnormals.add_constraint (dim_vector (-1, -1, 3));
4787  }
4788 
4789  private:
4790  void update_alphadata (void)
4791  {
4792  if (alphadatamapping_is ("scaled"))
4793  set_alim (alphadata.get_limits ());
4794  else
4795  alim = alphadata.get_limits ();
4796  }
4797 
4798  void update_cdata (void)
4799  {
4800  if (cdatamapping_is ("scaled"))
4801  set_clim (cdata.get_limits ());
4802  else
4803  clim = cdata.get_limits ();
4804  }
4805 
4806  void update_xdata (void)
4807  {
4808  update_normals ();
4809  set_xlim (xdata.get_limits ());
4810  }
4811 
4812  void update_ydata (void)
4813  {
4814  update_normals ();
4815  set_ylim (ydata.get_limits ());
4816  }
4817 
4818  void update_zdata (void)
4819  {
4820  update_normals ();
4821  set_zlim (zdata.get_limits ());
4822  }
4823 
4824  void update_normals (void);
4825 
4826  void update_normalmode (void)
4827  { update_normals (); }
4828 
4829  void update_vertexnormals (void)
4830  { set_normalmode ("manual"); }
4831  };
4832 
4833 private:
4834  properties xproperties;
4835 
4836 public:
4837  surface (const graphics_handle& mh, const graphics_handle& p)
4838  : base_graphics_object (), xproperties (mh, p)
4839  {
4840  xproperties.override_defaults (*this);
4841  }
4842 
4843  ~surface (void) { }
4844 
4845  base_properties& get_properties (void) { return xproperties; }
4846 
4847  const base_properties& get_properties (void) const { return xproperties; }
4848 
4849  bool valid_object (void) const { return true; }
4850 };
4851 
4852 // ---------------------------------------------------------------------
4853 
4854 class OCTINTERP_API hggroup : public base_graphics_object
4855 {
4856 public:
4857  class OCTINTERP_API properties : public base_properties
4858  {
4859  public:
4860  void remove_child (const graphics_handle& h)
4861  {
4862  base_properties::remove_child (h);
4863  update_limits ();
4864  }
4865 
4866  void adopt (const graphics_handle& h)
4867  {
4868 
4869  base_properties::adopt (h);
4870  update_limits (h);
4871  }
4872 
4873  // See the genprops.awk script for an explanation of the
4874  // properties declarations.
4875  // Programming note: Keep property list sorted if new ones are added.
4876 
4877  BEGIN_PROPERTIES (hggroup)
4878  string_property displayname , ""
4879  radio_property erasemode , "{normal}|none|xor|background"
4880 
4881  // hidden properties for limit computation
4882  row_vector_property alim hr , Matrix ()
4883  row_vector_property clim hr , Matrix ()
4884  row_vector_property xlim hr , Matrix ()
4885  row_vector_property ylim hr , Matrix ()
4886  row_vector_property zlim hr , Matrix ()
4887  bool_property aliminclude h , "on"
4888  bool_property climinclude h , "on"
4889  bool_property xliminclude h , "on"
4890  bool_property yliminclude h , "on"
4891  bool_property zliminclude h , "on"
4892  END_PROPERTIES
4893 
4894  private:
4895  void update_limits (void) const;
4896 
4897  void update_limits (const graphics_handle& h) const;
4898 
4899  protected:
4900  void init (void)
4901  { }
4902 
4903  };
4904 
4905 private:
4906  properties xproperties;
4907 
4908 public:
4909  hggroup (const graphics_handle& mh, const graphics_handle& p)
4910  : base_graphics_object (), xproperties (mh, p)
4911  {
4912  xproperties.override_defaults (*this);
4913  }
4914 
4915  ~hggroup (void) { }
4916 
4917  base_properties& get_properties (void) { return xproperties; }
4918 
4919  const base_properties& get_properties (void) const { return xproperties; }
4920 
4921  bool valid_object (void) const { return true; }
4922 
4923  void update_axis_limits (const std::string& axis_type);
4924 
4925  void update_axis_limits (const std::string& axis_type,
4926  const graphics_handle& h);
4927 
4928 };
4929 
4930 // ---------------------------------------------------------------------
4931 
4932 class OCTINTERP_API uimenu : public base_graphics_object
4933 {
4934 public:
4935  class OCTINTERP_API properties : public base_properties
4936  {
4937  public:
4938  void remove_child (const graphics_handle& h)
4939  {
4940  base_properties::remove_child (h);
4941  }
4942 
4943  void adopt (const graphics_handle& h)
4944  {
4945  base_properties::adopt (h);
4946  }
4947 
4948  // See the genprops.awk script for an explanation of the
4949  // properties declarations.
4950  // Programming note: Keep property list sorted if new ones are added.
4951 
4952  BEGIN_PROPERTIES (uimenu)
4953  any_property __object__ , Matrix ()
4954  string_property accelerator , ""
4955  callback_property callback , Matrix ()
4956  bool_property checked , "off"
4957  bool_property enable , "on"
4958  color_property foregroundcolor , color_values (0, 0, 0)
4959  string_property label , ""
4960  double_property position , 9
4961  bool_property separator , "off"
4962  // Octave-specific properties
4963  string_property fltk_label h , ""
4964  END_PROPERTIES
4965 
4966  protected:
4967  void init (void)
4968  { }
4969  };
4970 
4971 private:
4972  properties xproperties;
4973 
4974 public:
4975  uimenu (const graphics_handle& mh, const graphics_handle& p)
4976  : base_graphics_object (), xproperties (mh, p)
4977  {
4978  xproperties.override_defaults (*this);
4979  }
4980 
4981  ~uimenu (void) { }
4982 
4983  base_properties& get_properties (void) { return xproperties; }
4984 
4985  const base_properties& get_properties (void) const { return xproperties; }
4986 
4987  bool valid_object (void) const { return true; }
4988 
4989 };
4990 
4991 // ---------------------------------------------------------------------
4992 
4993 class OCTINTERP_API uicontextmenu : public base_graphics_object
4994 {
4995 public:
4996  class OCTINTERP_API properties : public base_properties
4997  {
4998  public:
4999  // See the genprops.awk script for an explanation of the
5000  // properties declarations.
5001  // Programming note: Keep property list sorted if new ones are added.
5002 
5003  BEGIN_PROPERTIES (uicontextmenu)
5004  any_property __object__ , Matrix ()
5005  callback_property callback , Matrix ()
5006  array_property position , Matrix (1, 2, 0.0)
5007  END_PROPERTIES
5008 
5009  protected:
5010  void init (void)
5011  {
5012  position.add_constraint (dim_vector (1, 2));
5013  position.add_constraint (dim_vector (2, 1));
5014  visible.set (octave_value (true));
5015  }
5016  };
5017 
5018 private:
5019  properties xproperties;
5020 
5021 public:
5022  uicontextmenu (const graphics_handle& mh, const graphics_handle& p)
5023  : base_graphics_object (), xproperties (mh, p)
5024  {
5025  xproperties.override_defaults (*this);
5026  }
5027 
5028  ~uicontextmenu (void) { }
5029 
5030  base_properties& get_properties (void) { return xproperties; }
5031 
5032  const base_properties& get_properties (void) const { return xproperties; }
5033 
5034  bool valid_object (void) const { return true; }
5035 
5036 };
5037 
5038 // ---------------------------------------------------------------------
5039 
5040 class OCTINTERP_API uicontrol : public base_graphics_object
5041 {
5042 public:
5043  class OCTINTERP_API properties : public base_properties
5044  {
5045  public:
5046  Matrix get_boundingbox (bool internal = false,
5047  const Matrix& parent_pix_size = Matrix ()) const;
5048 
5049  double get_fontsize_points (double box_pix_height = 0) const;
5050 
5051  // See the genprops.awk script for an explanation of the
5052  // properties declarations.
5053  // Programming note: Keep property list sorted if new ones are added.
5054 
5055  BEGIN_PROPERTIES (uicontrol)
5056  any_property __object__ , Matrix ()
5057  color_property backgroundcolor , color_values (1, 1, 1)
5058  callback_property callback , Matrix ()
5059  array_property cdata , Matrix ()
5060  bool_property clipping , "on"
5061  radio_property enable , "{on}|inactive|off"
5062  array_property extent rG , Matrix (1, 4, 0.0)
5063  radio_property fontangle u , "{normal}|italic|oblique"
5064  string_property fontname u , OCTAVE_DEFAULT_FONTNAME
5065  double_property fontsize u , 10
5066  radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
5067  radio_property fontweight u , "light|{normal}|demi|bold"
5068  color_property foregroundcolor , color_values (0, 0, 0)
5069  radio_property horizontalalignment , "left|{center}|right"
5070  callback_property keypressfcn , Matrix ()
5071  double_property listboxtop , 1
5072  double_property max , 1
5073  double_property min , 0
5074  array_property position , default_control_position ()
5075  array_property sliderstep , default_control_sliderstep ()
5076  string_array_property string u , ""
5077  radio_property style S , "{pushbutton}|togglebutton|radiobutton|checkbox|edit|text|slider|frame|listbox|popupmenu"
5078  string_property tooltipstring , ""
5079  radio_property units u , "normalized|inches|centimeters|points|{pixels}|characters"
5080  row_vector_property value , Matrix (1, 1, 1.0)
5081  radio_property verticalalignment , "top|{middle}|bottom"
5082  END_PROPERTIES
5083 
5084  private:
5085  std::string cached_units;
5086 
5087  protected:
5088  void init (void)
5089  {
5090  cdata.add_constraint ("double");
5091  cdata.add_constraint ("single");
5092  cdata.add_constraint (dim_vector (-1, -1, 3));
5093  position.add_constraint (dim_vector (1, 4));
5094  sliderstep.add_constraint (dim_vector (1, 2));
5095  cached_units = get_units ();
5096  }
5097 
5098  void update_text_extent (void);
5099 
5100  void update_string (void) { update_text_extent (); }
5101  void update_fontname (void) { update_text_extent (); }
5102  void update_fontsize (void) { update_text_extent (); }
5103  void update_fontangle (void) { update_text_extent (); }
5104  void update_fontweight (void) { update_text_extent (); }
5105  void update_fontunits (const caseless_str& old_units);
5106 
5107  void update_units (void);
5108 
5109  };
5110 
5111 private:
5112  properties xproperties;
5113 
5114 public:
5115  uicontrol (const graphics_handle& mh, const graphics_handle& p)
5116  : base_graphics_object (), xproperties (mh, p)
5117  {
5118  xproperties.override_defaults (*this);
5119  }
5120 
5121  ~uicontrol (void) { }
5122 
5123  base_properties& get_properties (void) { return xproperties; }
5124 
5125  const base_properties& get_properties (void) const { return xproperties; }
5126 
5127  bool valid_object (void) const { return true; }
5128 };
5129 
5130 // ---------------------------------------------------------------------
5131 
5132 class OCTINTERP_API uipanel : public base_graphics_object
5133 {
5134 public:
5135  class OCTINTERP_API properties : public base_properties
5136  {
5137  public:
5138  Matrix get_boundingbox (bool internal = false,
5139  const Matrix& parent_pix_size = Matrix ()) const;
5140 
5141  double get_fontsize_points (double box_pix_height = 0) const;
5142 
5143  // See the genprops.awk script for an explanation of the
5144  // properties declarations.
5145  // Programming note: Keep property list sorted if new ones are added.
5146 
5147  BEGIN_PROPERTIES (uipanel)
5148  any_property __object__ , Matrix ()
5149  color_property backgroundcolor , color_values (1, 1, 1)
5150  radio_property bordertype , "none|{etchedin}|etchedout|beveledin|beveledout|line"
5151  double_property borderwidth , 1
5152  radio_property fontangle , "{normal}|italic|oblique"
5153  string_property fontname , OCTAVE_DEFAULT_FONTNAME
5154  double_property fontsize , 10
5155  radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
5156  radio_property fontweight , "light|{normal}|demi|bold"
5157  color_property foregroundcolor , color_values (0, 0, 0)
5158  color_property highlightcolor , color_values (1, 1, 1)
5159  array_property position , default_panel_position ()
5160  callback_property resizefcn , Matrix ()
5161  color_property shadowcolor , color_values (0, 0, 0)
5162  string_property title , ""
5163  radio_property titleposition , "{lefttop}|centertop|righttop|leftbottom|centerbottom|rightbottom"
5164  radio_property units S , "{normalized}|inches|centimeters|points|pixels|characters"
5165  END_PROPERTIES
5166 
5167  protected:
5168  void init (void)
5169  {
5170  position.add_constraint (dim_vector (1, 4));
5171  }
5172 
5173  void update_units (const caseless_str& old_units);
5174  void update_fontunits (const caseless_str& old_units);
5175 
5176  };
5177 
5178 private:
5179  properties xproperties;
5180 
5181 public:
5182  uipanel (const graphics_handle& mh, const graphics_handle& p)
5183  : base_graphics_object (), xproperties (mh, p)
5184  {
5185  xproperties.override_defaults (*this);
5186  }
5187 
5188  ~uipanel (void) { }
5189 
5190  base_properties& get_properties (void) { return xproperties; }
5191 
5192  const base_properties& get_properties (void) const { return xproperties; }
5193 
5194  bool valid_object (void) const { return true; }
5195 };
5196 
5197 // ---------------------------------------------------------------------
5198 
5199 class OCTINTERP_API uitoolbar : public base_graphics_object
5200 {
5201 public:
5202  class OCTINTERP_API properties : public base_properties
5203  {
5204  public:
5205  // See the genprops.awk script for an explanation of the
5206  // properties declarations.
5207  // Programming note: Keep property list sorted if new ones are added.
5208 
5209  BEGIN_PROPERTIES (uitoolbar)
5210  any_property __object__ , Matrix ()
5211  END_PROPERTIES
5212 
5213  protected:
5214  void init (void)
5215  { }
5216  };
5217 
5218 private:
5219  properties xproperties;
5220 
5221 public:
5222  uitoolbar (const graphics_handle& mh, const graphics_handle& p)
5223  : base_graphics_object (), xproperties (mh, p), default_properties ()
5224  {
5225  xproperties.override_defaults (*this);
5226  }
5227 
5228  ~uitoolbar (void) { }
5229 
5230  void override_defaults (base_graphics_object& obj)
5231  {
5232  // Allow parent (figure) to override first (properties knows how
5233  // to find the parent object).
5234  xproperties.override_defaults (obj);
5235 
5236  // Now override with our defaults. If the default_properties
5237  // list includes the properties for all defaults (line,
5238  // surface, etc.) then we don't have to know the type of OBJ
5239  // here, we just call its set function and let it decide which
5240  // properties from the list to use.
5241  obj.set_from_list (default_properties);
5242  }
5243 
5244  void set (const caseless_str& name, const octave_value& value)
5245  {
5246  if (name.compare ("default", 7))
5247  // strip "default", pass rest to function that will
5248  // parse the remainder and add the element to the
5249  // default_properties map.
5250  default_properties.set (name.substr (7), value);
5251  else
5252  xproperties.set (name, value);
5253  }
5254 
5255  octave_value get (const caseless_str& name) const
5256  {
5257  octave_value retval;
5258 
5259  if (name.compare ("default", 7))
5260  retval = get_default (name.substr (7));
5261  else
5262  retval = xproperties.get (name);
5263 
5264  return retval;
5265  }
5266 
5267  octave_value get_default (const caseless_str& name) const;
5268 
5269  octave_value get_defaults (void) const
5270  {
5271  return default_properties.as_struct ("default");
5272  }
5273 
5274  base_properties& get_properties (void) { return xproperties; }
5275 
5276  const base_properties& get_properties (void) const { return xproperties; }
5277 
5278  bool valid_object (void) const { return true; }
5279 
5280  void reset_default_properties (void);
5281 
5282 private:
5283  property_list default_properties;
5284 };
5285 
5286 // ---------------------------------------------------------------------
5287 
5288 class OCTINTERP_API uipushtool : public base_graphics_object
5289 {
5290 public:
5291  class OCTINTERP_API properties : public base_properties
5292  {
5293  public:
5294  // See the genprops.awk script for an explanation of the
5295  // properties declarations.
5296  // Programming note: Keep property list sorted if new ones are added.
5297 
5298  BEGIN_PROPERTIES (uipushtool)
5299  any_property __object__ , Matrix ()
5300  array_property cdata , Matrix ()
5301  callback_property clickedcallback , Matrix ()
5302  bool_property enable , "on"
5303  bool_property separator , "off"
5304  string_property tooltipstring , ""
5305  END_PROPERTIES
5306 
5307  protected:
5308  void init (void)
5309  {
5310  cdata.add_constraint ("double");
5311  cdata.add_constraint ("single");
5312  cdata.add_constraint (dim_vector (-1, -1, 3));
5313  }
5314  };
5315 
5316 private:
5317  properties xproperties;
5318 
5319 public:
5320  uipushtool (const graphics_handle& mh, const graphics_handle& p)
5321  : base_graphics_object (), xproperties (mh, p)
5322  {
5323  xproperties.override_defaults (*this);
5324  }
5325 
5326  ~uipushtool (void) { }
5327 
5328  base_properties& get_properties (void) { return xproperties; }
5329 
5330  const base_properties& get_properties (void) const { return xproperties; }
5331 
5332  bool valid_object (void) const { return true; }
5333 
5334 };
5335 
5336 // ---------------------------------------------------------------------
5337 
5338 class OCTINTERP_API uitoggletool : public base_graphics_object
5339 {
5340 public:
5341  class OCTINTERP_API properties : public base_properties
5342  {
5343  public:
5344  // See the genprops.awk script for an explanation of the
5345  // properties declarations.
5346  // Programming note: Keep property list sorted if new ones are added.
5347 
5348  BEGIN_PROPERTIES (uitoggletool)
5349  any_property __object__ , Matrix ()
5350  array_property cdata , Matrix ()
5351  callback_property clickedcallback , Matrix ()
5352  bool_property enable , "on"
5353  callback_property offcallback , Matrix ()
5354  callback_property oncallback , Matrix ()
5355  bool_property separator , "off"
5356  bool_property state , "off"
5357  string_property tooltipstring , ""
5358  END_PROPERTIES
5359 
5360  protected:
5361  void init (void)
5362  {
5363  cdata.add_constraint ("double");
5364  cdata.add_constraint ("single");
5365  cdata.add_constraint (dim_vector (-1, -1, 3));
5366  }
5367  };
5368 
5369 private:
5370  properties xproperties;
5371 
5372 public:
5373  uitoggletool (const graphics_handle& mh, const graphics_handle& p)
5374  : base_graphics_object (), xproperties (mh, p)
5375  {
5376  xproperties.override_defaults (*this);
5377  }
5378 
5379  ~uitoggletool (void) { }
5380 
5381  base_properties& get_properties (void) { return xproperties; }
5382 
5383  const base_properties& get_properties (void) const { return xproperties; }
5384 
5385  bool valid_object (void) const { return true; }
5386 
5387 };
5388 
5389 // ---------------------------------------------------------------------
5390 
5391 octave_value
5392 get_property_from_handle (double handle, const std::string &property,
5393  const std::string &func);
5394 bool
5395 set_property_in_handle (double handle, const std::string &property,
5396  const octave_value &arg, const std::string &func);
5397 
5398 // ---------------------------------------------------------------------
5399 
5400 class graphics_event;
5401 
5402 class
5403 base_graphics_event
5404 {
5405 public:
5406  friend class graphics_event;
5407 
5408  base_graphics_event (void) : count (1) { }
5409 
5410  virtual ~base_graphics_event (void) { }
5411 
5412  virtual void execute (void) = 0;
5413 
5414 private:
5415  octave_refcount<int> count;
5416 };
5417 
5418 class
5419 graphics_event
5420 {
5421 public:
5422  typedef void (*event_fcn) (void*);
5423 
5424  graphics_event (void) : rep (0) { }
5425 
5426  graphics_event (const graphics_event& e) : rep (e.rep)
5427  {
5428  rep->count++;
5429  }
5430 
5431  ~graphics_event (void)
5432  {
5433  if (rep && --rep->count == 0)
5434  delete rep;
5435  }
5436 
5437  graphics_event& operator = (const graphics_event& e)
5438  {
5439  if (rep != e.rep)
5440  {
5441  if (rep && --rep->count == 0)
5442  delete rep;
5443 
5444  rep = e.rep;
5445  if (rep)
5446  rep->count++;
5447  }
5448 
5449  return *this;
5450  }
5451 
5452  void execute (void)
5453  { if (rep) rep->execute (); }
5454 
5455  bool ok (void) const
5456  { return (rep != 0); }
5457 
5458  static graphics_event
5459  create_callback_event (const graphics_handle& h,
5460  const std::string& name,
5461  const octave_value& data = Matrix ());
5462 
5463  static graphics_event
5464  create_callback_event (const graphics_handle& h,
5465  const octave_value& cb,
5466  const octave_value& data = Matrix ());
5467 
5468  static graphics_event
5469  create_function_event (event_fcn fcn, void *data = 0);
5470 
5471  static graphics_event
5472  create_set_event (const graphics_handle& h, const std::string& name,
5473  const octave_value& value,
5474  bool notify_toolkit = true);
5475 private:
5476  base_graphics_event *rep;
5477 };
5478 
5479 class OCTINTERP_API gh_manager
5480 {
5481 protected:
5482 
5483  gh_manager (void);
5484 
5485 public:
5486 
5487  static void create_instance (void);
5488 
5489  static bool instance_ok (void)
5490  {
5491  bool retval = true;
5492 
5493  if (! instance)
5494  create_instance ();
5495 
5496  if (! instance)
5497  {
5498  ::error ("unable to create gh_manager!");
5499 
5500  retval = false;
5501  }
5502 
5503  return retval;
5504  }
5505 
5506  static void cleanup_instance (void) { delete instance; instance = 0; }
5507 
5508  static graphics_handle get_handle (bool integer_figure_handle)
5509  {
5510  return instance_ok ()
5511  ? instance->do_get_handle (integer_figure_handle)
5512  : graphics_handle ();
5513  }
5514 
5515  static void free (const graphics_handle& h)
5516  {
5517  if (instance_ok ())
5518  instance->do_free (h);
5519  }
5520 
5521  static void renumber_figure (const graphics_handle& old_gh,
5522  const graphics_handle& new_gh)
5523  {
5524  if (instance_ok ())
5525  instance->do_renumber_figure (old_gh, new_gh);
5526  }
5527 
5528  static graphics_handle lookup (double val)
5529  {
5530  return instance_ok () ? instance->do_lookup (val) : graphics_handle ();
5531  }
5532 
5533  static graphics_handle lookup (const octave_value& val)
5534  {
5535  return val.is_real_scalar ()
5536  ? lookup (val.double_value ()) : graphics_handle ();
5537  }
5538 
5539  static graphics_object get_object (double val)
5540  {
5541  return get_object (lookup (val));
5542  }
5543 
5544  static graphics_object get_object (const graphics_handle& h)
5545  {
5546  return instance_ok () ? instance->do_get_object (h) : graphics_object ();
5547  }
5548 
5549  static graphics_handle
5550  make_graphics_handle (const std::string& go_name,
5551  const graphics_handle& parent,
5552  bool integer_figure_handle = false,
5553  bool do_createfcn = true,
5554  bool do_notify_toolkit = true)
5555  {
5556  return instance_ok ()
5557  ? instance->do_make_graphics_handle (go_name, parent,
5558  integer_figure_handle,
5559  do_createfcn, do_notify_toolkit)
5560  : graphics_handle ();
5561  }
5562 
5563  static graphics_handle make_figure_handle (double val,
5564  bool do_notify_toolkit = true)
5565  {
5566  return instance_ok ()
5567  ? instance->do_make_figure_handle (val, do_notify_toolkit)
5568  : graphics_handle ();
5569  }
5570 
5571  static void push_figure (const graphics_handle& h)
5572  {
5573  if (instance_ok ())
5574  instance->do_push_figure (h);
5575  }
5576 
5577  static void pop_figure (const graphics_handle& h)
5578  {
5579  if (instance_ok ())
5580  instance->do_pop_figure (h);
5581  }
5582 
5583  static graphics_handle current_figure (void)
5584  {
5585  return instance_ok ()
5586  ? instance->do_current_figure () : graphics_handle ();
5587  }
5588 
5589  static Matrix handle_list (bool show_hidden = false)
5590  {
5591  return instance_ok ()
5592  ? instance->do_handle_list (show_hidden) : Matrix ();
5593  }
5594 
5595  static void lock (void)
5596  {
5597  if (instance_ok ())
5598  instance->do_lock ();
5599  }
5600 
5601  static bool try_lock (void)
5602  {
5603  if (instance_ok ())
5604  return instance->do_try_lock ();
5605  else
5606  return false;
5607  }
5608 
5609  static void unlock (void)
5610  {
5611  if (instance_ok ())
5612  instance->do_unlock ();
5613  }
5614 
5615  static Matrix figure_handle_list (bool show_hidden = false)
5616  {
5617  return instance_ok ()
5618  ? instance->do_figure_handle_list (show_hidden) : Matrix ();
5619  }
5620 
5621  static void execute_listener (const graphics_handle& h,
5622  const octave_value& l)
5623  {
5624  if (instance_ok ())
5625  instance->do_execute_listener (h, l);
5626  }
5627 
5628  static void execute_callback (const graphics_handle& h,
5629  const std::string& name,
5630  const octave_value& data = Matrix ())
5631  {
5632  octave_value cb;
5633 
5634  if (true)
5635  {
5636  gh_manager::auto_lock lock;
5637 
5638  graphics_object go = get_object (h);
5639 
5640  if (go.valid_object ())
5641  cb = go.get (name);
5642  }
5643 
5644  if (! error_state)
5645  execute_callback (h, cb, data);
5646  }
5647 
5648  static void execute_callback (const graphics_handle& h,
5649  const octave_value& cb,
5650  const octave_value& data = Matrix ())
5651  {
5652  if (instance_ok ())
5653  instance->do_execute_callback (h, cb, data);
5654  }
5655 
5656  static void post_callback (const graphics_handle& h,
5657  const std::string& name,
5658  const octave_value& data = Matrix ())
5659  {
5660  if (instance_ok ())
5661  instance->do_post_callback (h, name, data);
5662  }
5663 
5664  static void post_function (graphics_event::event_fcn fcn, void* data = 0)
5665  {
5666  if (instance_ok ())
5667  instance->do_post_function (fcn, data);
5668  }
5669 
5670  static void post_set (const graphics_handle& h, const std::string& name,
5671  const octave_value& value, bool notify_toolkit = true)
5672  {
5673  if (instance_ok ())
5674  instance->do_post_set (h, name, value, notify_toolkit);
5675  }
5676 
5677  static int process_events (void)
5678  {
5679  return (instance_ok () ? instance->do_process_events () : 0);
5680  }
5681 
5682  static int flush_events (void)
5683  {
5684  return (instance_ok () ? instance->do_process_events (true) : 0);
5685  }
5686 
5687  static void enable_event_processing (bool enable = true)
5688  {
5689  if (instance_ok ())
5690  instance->do_enable_event_processing (enable);
5691  }
5692 
5693  static bool is_handle_visible (const graphics_handle& h)
5694  {
5695  bool retval = false;
5696 
5697  graphics_object go = get_object (h);
5698 
5699  if (go.valid_object ())
5700  retval = go.is_handle_visible ();
5701 
5702  return retval;
5703  }
5704 
5705  static void close_all_figures (void)
5706  {
5707  if (instance_ok ())
5708  instance->do_close_all_figures ();
5709  }
5710 
5711 public:
5712  class auto_lock : public octave_autolock
5713  {
5714  public:
5715  auto_lock (bool wait = true)
5716  : octave_autolock (instance_ok ()
5717  ? instance->graphics_lock
5718  : octave_mutex (),
5719  wait)
5720  { }
5721 
5722  private:
5723 
5724  // No copying!
5725  auto_lock (const auto_lock&);
5726  auto_lock& operator = (const auto_lock&);
5727  };
5728 
5729 private:
5730 
5731  static gh_manager *instance;
5732 
5733  typedef std::map<graphics_handle, graphics_object>::iterator iterator;
5734  typedef std::map<graphics_handle, graphics_object>::const_iterator
5735  const_iterator;
5736 
5737  typedef std::set<graphics_handle>::iterator free_list_iterator;
5738  typedef std::set<graphics_handle>::const_iterator const_free_list_iterator;
5739 
5740  typedef std::list<graphics_handle>::iterator figure_list_iterator;
5741  typedef std::list<graphics_handle>::const_iterator const_figure_list_iterator;
5742 
5743  // A map of handles to graphics objects.
5744  std::map<graphics_handle, graphics_object> handle_map;
5745 
5746  // The available graphics handles.
5747  std::set<graphics_handle> handle_free_list;
5748 
5749  // The next handle available if handle_free_list is empty.
5750  double next_handle;
5751 
5752  // The allocated figure handles. Top of the stack is most recently
5753  // created.
5754  std::list<graphics_handle> figure_list;
5755 
5756  // The lock for accessing the graphics sytsem.
5757  octave_mutex graphics_lock;
5758 
5759  // The list of events queued by graphics toolkits.
5760  std::list<graphics_event> event_queue;
5761 
5762  // The stack of callback objects.
5763  std::list<graphics_object> callback_objects;
5764 
5765  // A flag telling whether event processing must be constantly on.
5766  int event_processing;
5767 
5768  graphics_handle do_get_handle (bool integer_figure_handle);
5769 
5770  void do_free (const graphics_handle& h);
5771 
5772  void do_renumber_figure (const graphics_handle& old_gh,
5773  const graphics_handle& new_gh);
5774 
5775  graphics_handle do_lookup (double val)
5776  {
5777  iterator p = (xisnan (val) ? handle_map.end () : handle_map.find (val));
5778 
5779  return (p != handle_map.end ()) ? p->first : graphics_handle ();
5780  }
5781 
5782  graphics_object do_get_object (const graphics_handle& h)
5783  {
5784  iterator p = (h.ok () ? handle_map.find (h) : handle_map.end ());
5785 
5786  return (p != handle_map.end ()) ? p->second : graphics_object ();
5787  }
5788 
5789  graphics_handle do_make_graphics_handle (const std::string& go_name,
5790  const graphics_handle& p,
5791  bool integer_figure_handle,
5792  bool do_createfcn,
5793  bool do_notify_toolkit);
5794 
5795  graphics_handle do_make_figure_handle (double val, bool do_notify_toolkit);
5796 
5797  Matrix do_handle_list (bool show_hidden)
5798  {
5799  Matrix retval (1, handle_map.size ());
5800 
5801  octave_idx_type i = 0;
5802  for (const_iterator p = handle_map.begin (); p != handle_map.end (); p++)
5803  {
5804  graphics_handle h = p->first;
5805 
5806  if (show_hidden || is_handle_visible (h))
5807  retval(i++) = h.value ();
5808  }
5809 
5810  retval.resize (1, i);
5811 
5812  return retval;
5813  }
5814 
5815  Matrix do_figure_handle_list (bool show_hidden)
5816  {
5817  Matrix retval (1, figure_list.size ());
5818 
5819  octave_idx_type i = 0;
5820  for (const_figure_list_iterator p = figure_list.begin ();
5821  p != figure_list.end ();
5822  p++)
5823  {
5824  graphics_handle h = *p;
5825 
5826  if (show_hidden || is_handle_visible (h))
5827  retval(i++) = h.value ();
5828  }
5829 
5830  retval.resize (1, i);
5831 
5832  return retval;
5833  }
5834 
5835  void do_push_figure (const graphics_handle& h);
5836 
5837  void do_pop_figure (const graphics_handle& h);
5838 
5839  graphics_handle do_current_figure (void) const
5840  {
5841  graphics_handle retval;
5842 
5843  for (const_figure_list_iterator p = figure_list.begin ();
5844  p != figure_list.end ();
5845  p++)
5846  {
5847  graphics_handle h = *p;
5848 
5849  if (is_handle_visible (h))
5850  retval = h;
5851  }
5852 
5853  return retval;
5854  }
5855 
5856  void do_lock (void) { graphics_lock.lock (); }
5857 
5858  bool do_try_lock (void) { return graphics_lock.try_lock (); }
5859 
5860  void do_unlock (void) { graphics_lock.unlock (); }
5861 
5862  void do_execute_listener (const graphics_handle& h, const octave_value& l);
5863 
5864  void do_execute_callback (const graphics_handle& h, const octave_value& cb,
5865  const octave_value& data);
5866 
5867  void do_post_callback (const graphics_handle& h, const std::string name,
5868  const octave_value& data);
5869 
5870  void do_post_function (graphics_event::event_fcn fcn, void* fcn_data);
5871 
5872  void do_post_set (const graphics_handle& h, const std::string name,
5873  const octave_value& value, bool notify_toolkit = true);
5874 
5875  int do_process_events (bool force = false);
5876 
5877  void do_close_all_figures (void);
5878 
5879  static void restore_gcbo (void)
5880  {
5881  if (instance_ok ())
5882  instance->do_restore_gcbo ();
5883  }
5884 
5885  void do_restore_gcbo (void);
5886 
5887  void do_post_event (const graphics_event& e);
5888 
5889  void do_enable_event_processing (bool enable = true);
5890 };
5891 
5892 void get_children_limits (double& min_val, double& max_val,
5893  double& min_pos, double& max_neg,
5894  const Matrix& kids, char limit_type);
5895 
5896 OCTINTERP_API int calc_dimensions (const graphics_object& gh);
5897 
5898 // This function is NOT equivalent to the scripting language function gcf.
5899 OCTINTERP_API graphics_handle gcf (void);
5900 
5901 // This function is NOT equivalent to the scripting language function gca.
5902 OCTINTERP_API graphics_handle gca (void);
5903 
5904 OCTINTERP_API void close_all_figures (void);
5905 
5906 #endif