GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
graphics.in.h
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2007-2015 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #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;
423  listener_map listeners;
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 (const 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 (const 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  void invalidate (void) { current_val = octave_NaN; }
1581 
1582  base_property* clone (void) const { return new handle_property (*this); }
1583 
1584 protected:
1585  OCTINTERP_API bool do_set (const octave_value& v);
1586 
1587 private:
1589 };
1590 
1591 // ---------------------------------------------------------------------
1592 
1593 class any_property : public base_property
1594 {
1595 public:
1596  any_property (const std::string& nm, const graphics_handle& h,
1597  const octave_value& m = Matrix ())
1598  : base_property (nm, h), data (m) { }
1599 
1601  : base_property (p), data (p.data) { }
1602 
1603  octave_value get (void) const { return data; }
1604 
1606  {
1607  set (val);
1608  return *this;
1609  }
1610 
1611  base_property* clone (void) const { return new any_property (*this); }
1612 
1613 protected:
1614  bool do_set (const octave_value& v)
1615  {
1616  data = v;
1617  return true;
1618  }
1619 
1620 private:
1622 };
1623 
1624 // ---------------------------------------------------------------------
1625 
1626 class children_property : public base_property
1627 {
1628 public:
1631  {
1632  do_init_children (Matrix ());
1633  }
1634 
1635  children_property (const std::string& nm, const graphics_handle& h,
1636  const Matrix& val)
1637  : base_property (nm, h), children_list ()
1638  {
1639  do_init_children (val);
1640  }
1641 
1643  : base_property (p), children_list ()
1644  {
1646  }
1647 
1649  {
1650  set (val);
1651  return *this;
1652  }
1653 
1654  base_property* clone (void) const { return new children_property (*this); }
1655 
1656  bool remove_child (double val)
1657  {
1658  return do_remove_child (val);
1659  }
1660 
1661  void adopt (double val)
1662  {
1663  do_adopt_child (val);
1664  }
1665 
1666  Matrix get_children (void) const
1667  {
1668  return do_get_children (false);
1669  }
1670 
1671  Matrix get_hidden (void) const
1672  {
1673  return do_get_children (true);
1674  }
1675 
1676  Matrix get_all (void) const
1677  {
1678  return do_get_all_children ();
1679  }
1680 
1681  octave_value get (void) const
1682  {
1683  return octave_value (get_children ());
1684  }
1685 
1686  void delete_children (bool clear = false)
1687  {
1689  }
1690 
1692  {
1693  for (children_list_iterator p = children_list.begin ();
1694  p != children_list.end (); p++)
1695  {
1696  if (*p == old_gh)
1697  {
1698  *p = new_gh.value ();
1699  return;
1700  }
1701  }
1702 
1703  error ("children_list::renumber: child not found!");
1704  }
1705 
1706 private:
1707  typedef std::list<double>::iterator children_list_iterator;
1708  typedef std::list<double>::const_iterator const_children_list_iterator;
1709  std::list<double> children_list;
1710 
1711 protected:
1712  bool do_set (const octave_value& val)
1713  {
1714  const Matrix new_kids = val.matrix_value ();
1715 
1716  octave_idx_type nel = new_kids.numel ();
1717 
1718  const Matrix new_kids_column = new_kids.reshape (dim_vector (nel, 1));
1719 
1720  bool is_ok = true;
1721  bool add_hidden = true;
1722 
1723  if (! error_state)
1724  {
1725  const Matrix visible_kids = do_get_children (false);
1726 
1727  if (visible_kids.numel () == new_kids.numel ())
1728  {
1729  Matrix t1 = visible_kids.sort ();
1730  Matrix t2 = new_kids_column.sort ();
1731  Matrix t3 = get_hidden ().sort ();
1732 
1733  if (t1 != t2)
1734  is_ok = false;
1735 
1736  if (t1 == t3)
1737  add_hidden = false;
1738  }
1739  else
1740  is_ok = false;
1741 
1742  if (! is_ok)
1743  error ("set: new children must be a permutation of existing children");
1744  }
1745  else
1746  {
1747  is_ok = false;
1748  error ("set: expecting children to be array of graphics handles");
1749  }
1750 
1751  if (is_ok)
1752  {
1753  Matrix tmp = new_kids_column;
1754 
1755  if (add_hidden)
1756  tmp.stack (get_hidden ());
1757 
1758  children_list.clear ();
1759 
1760  // Don't use do_init_children here, as that reverses the
1761  // order of the list, and we don't want to do that if setting
1762  // the child list directly.
1763 
1764  for (octave_idx_type i = 0; i < tmp.numel (); i++)
1765  children_list.push_back (tmp.xelem (i));
1766  }
1767 
1768  return is_ok;
1769  }
1770 
1771 private:
1772  void do_init_children (const Matrix& val)
1773  {
1774  children_list.clear ();
1775  for (octave_idx_type i = 0; i < val.numel (); i++)
1776  children_list.push_front (val.xelem (i));
1777  }
1778 
1779  void do_init_children (const std::list<double>& val)
1780  {
1781  children_list.clear ();
1782  for (const_children_list_iterator p = val.begin (); p != val.end (); p++)
1783  children_list.push_front (*p);
1784  }
1785 
1786  Matrix do_get_children (bool return_hidden) const;
1787 
1789  {
1790  Matrix retval (children_list.size (), 1);
1791  octave_idx_type i = 0;
1792 
1793  for (const_children_list_iterator p = children_list.begin ();
1794  p != children_list.end (); p++)
1795  retval(i++) = *p;
1796  return retval;
1797  }
1798 
1799  bool do_remove_child (double child)
1800  {
1801  for (children_list_iterator p = children_list.begin ();
1802  p != children_list.end (); p++)
1803  {
1804  if (*p == child)
1805  {
1806  children_list.erase (p);
1807  return true;
1808  }
1809  }
1810  return false;
1811  }
1812 
1813  void do_adopt_child (double val)
1814  {
1815  children_list.push_front (val);
1816  }
1817 
1818  void do_delete_children (bool clear);
1819 };
1820 
1821 
1822 
1823 // ---------------------------------------------------------------------
1824 
1825 class callback_property : public base_property
1826 {
1827 public:
1828  callback_property (const std::string& nm, const graphics_handle& h,
1829  const octave_value& m)
1830  : base_property (nm, h), callback (m), executing (false) { }
1831 
1833  : base_property (p), callback (p.callback), executing (false) { }
1834 
1835  octave_value get (void) const { return callback; }
1836 
1837  OCTINTERP_API void execute (const octave_value& data = octave_value ()) const;
1838 
1839  bool is_defined (void) const
1840  {
1841  return (callback.is_defined () && ! callback.is_empty ());
1842  }
1843 
1845  {
1846  set (val);
1847  return *this;
1848  }
1849 
1850  base_property* clone (void) const { return new callback_property (*this); }
1851 
1852 protected:
1853  bool do_set (const octave_value& v)
1854  {
1855  if (validate (v))
1856  {
1857  callback = v;
1858  return true;
1859  }
1860  else
1861  error ("invalid value for callback property \"%s\"",
1862  get_name ().c_str ());
1863  return false;
1864  }
1865 
1866 private:
1867  OCTINTERP_API bool validate (const octave_value& v) const;
1868 
1869 private:
1871 
1872  // If TRUE, we are executing this callback.
1873  mutable bool executing;
1874 };
1875 
1876 // ---------------------------------------------------------------------
1877 
1878 class property
1879 {
1880 public:
1881  property (void) : rep (new base_property ("", graphics_handle ()))
1882  { }
1883 
1884  property (base_property *bp, bool persist = false) : rep (bp)
1885  { if (persist) rep->count++; }
1886 
1887  property (const property& p) : rep (p.rep)
1888  {
1889  rep->count++;
1890  }
1891 
1892  ~property (void)
1893  {
1894  if (--rep->count == 0)
1895  delete rep;
1896  }
1897 
1898  bool ok (void) const
1899  { return rep->ok (); }
1900 
1901  std::string get_name (void) const
1902  { return rep->get_name (); }
1903 
1904  void set_name (const std::string& name)
1905  { rep->set_name (name); }
1906 
1908  { return rep->get_parent (); }
1909 
1910  void set_parent (const graphics_handle& h)
1911  { rep->set_parent (h); }
1912 
1913  bool is_hidden (void) const
1914  { return rep->is_hidden (); }
1915 
1916  void set_hidden (bool flag)
1917  { rep->set_hidden (flag); }
1918 
1919  bool is_radio (void) const
1920  { return rep->is_radio (); }
1921 
1922  int get_id (void) const
1923  { return rep->get_id (); }
1924 
1925  void set_id (int d)
1926  { rep->set_id (d); }
1927 
1928  octave_value get (void) const
1929  { return rep->get (); }
1930 
1931  bool set (const octave_value& val, bool do_run = true,
1932  bool do_notify_toolkit = true)
1933  { return rep->set (val, do_run, do_notify_toolkit); }
1934 
1935  std::string values_as_string (void) const
1936  { return rep->values_as_string (); }
1937 
1938  Cell values_as_cell (void) const
1939  { return rep->values_as_cell (); }
1940 
1941  property& operator = (const octave_value& val)
1942  {
1943  *rep = val;
1944  return *this;
1945  }
1946 
1947  property& operator = (const property& p)
1948  {
1949  if (rep && --rep->count == 0)
1950  delete rep;
1951 
1952  rep = p.rep;
1953  rep->count++;
1954 
1955  return *this;
1956  }
1957 
1959  { rep->add_listener (v, mode); }
1960 
1962  listener_mode mode = POSTSET)
1963  { rep->delete_listener (v, mode); }
1964 
1966  { rep->run_listeners (mode); }
1967 
1968  OCTINTERP_API static
1969  property create (const std::string& name, const graphics_handle& parent,
1970  const caseless_str& type,
1971  const octave_value_list& args);
1972 
1973  property clone (void) const
1974  { return property (rep->clone ()); }
1975 
1976  /*
1977  const string_property& as_string_property (void) const
1978  { return *(dynamic_cast<string_property*> (rep)); }
1979 
1980  const radio_property& as_radio_property (void) const
1981  { return *(dynamic_cast<radio_property*> (rep)); }
1982 
1983  const color_property& as_color_property (void) const
1984  { return *(dynamic_cast<color_property*> (rep)); }
1985 
1986  const double_property& as_double_property (void) const
1987  { return *(dynamic_cast<double_property*> (rep)); }
1988 
1989  const bool_property& as_bool_property (void) const
1990  { return *(dynamic_cast<bool_property*> (rep)); }
1991 
1992  const handle_property& as_handle_property (void) const
1993  { return *(dynamic_cast<handle_property*> (rep)); }
1994  */
1995 
1996 private:
1997  base_property *rep;
1998 };
1999 
2000 // ---------------------------------------------------------------------
2001 
2002 typedef std::pair <std::string, octave_value> pval_pair;
2003 
2004 class pval_vector : public std::vector <pval_pair>
2005 {
2006 public:
2007  const_iterator find (const std::string pname) const
2008  {
2009  const_iterator it;
2010 
2011  for (it = (*this).begin (); it != (*this).end (); it++)
2012  if (pname.compare ((*it).first) == 0)
2013  return it;
2014 
2015  return (*this).end ();
2016  }
2017 
2018  iterator find (const std::string pname)
2019  {
2020  iterator it;
2021 
2022  for (it = (*this).begin (); it != (*this).end (); it++)
2023  if (pname.compare ((*it).first) == 0)
2024  return it;
2025 
2026  return (*this).end ();
2027  }
2028 
2029  octave_value lookup (const std::string pname) const
2030  {
2031  octave_value retval;
2032 
2033  const_iterator it = find (pname);
2034 
2035  if (it != (*this).end ())
2036  retval = (*it).second;
2037 
2038  return retval;
2039  }
2040 
2041  octave_value& operator [] (const std::string pname)
2042  {
2043  iterator it = find (pname);
2044 
2045  if (it == (*this).end ())
2046  {
2047  push_back (pval_pair (pname, octave_value ()));
2048  return (*this).back ().second;
2049  }
2050 
2051  return (*it).second;
2052  }
2053 
2054  void erase (const std::string pname)
2055  {
2056  iterator it = find (pname);
2057  if (it != (*this).end ())
2058  erase (it);
2059  }
2060 
2061  void erase (iterator it)
2062  {
2063  std::vector <pval_pair>::erase (it);
2064  }
2065 
2066 };
2067 
2068 class property_list
2069 {
2070 public:
2072  typedef std::map<std::string, pval_map_type> plist_map_type;
2073 
2074  typedef pval_map_type::iterator pval_map_iterator;
2075  typedef pval_map_type::const_iterator pval_map_const_iterator;
2076 
2077  typedef plist_map_type::iterator plist_map_iterator;
2078  typedef plist_map_type::const_iterator plist_map_const_iterator;
2079 
2080  property_list (const plist_map_type& m = plist_map_type ())
2081  : plist_map (m) { }
2082 
2083  ~property_list (void) { }
2084 
2085  void set (const caseless_str& name, const octave_value& val);
2086 
2087  octave_value lookup (const caseless_str& name) const;
2088 
2089  plist_map_iterator begin (void) { return plist_map.begin (); }
2090  plist_map_const_iterator begin (void) const { return plist_map.begin (); }
2091 
2092  plist_map_iterator end (void) { return plist_map.end (); }
2093  plist_map_const_iterator end (void) const { return plist_map.end (); }
2094 
2095  plist_map_iterator find (const std::string& go_name)
2096  {
2097  return plist_map.find (go_name);
2098  }
2099 
2100  plist_map_const_iterator find (const std::string& go_name) const
2101  {
2102  return plist_map.find (go_name);
2103  }
2104 
2105  octave_scalar_map as_struct (const std::string& prefix_arg) const;
2106 
2107 private:
2108  plist_map_type plist_map;
2109 };
2110 
2111 // ---------------------------------------------------------------------
2112 
2113 class graphics_toolkit;
2114 class graphics_object;
2115 
2117 {
2118 public:
2119  friend class graphics_toolkit;
2120 
2121 public:
2122  base_graphics_toolkit (const std::string& nm)
2123  : name (nm), count (0) { }
2124 
2125  virtual ~base_graphics_toolkit (void) { }
2126 
2127  std::string get_name (void) const { return name; }
2128 
2129  virtual bool is_valid (void) const { return false; }
2130 
2131  virtual void redraw_figure (const graphics_object&) const
2132  { gripe_invalid ("redraw_figure"); }
2133 
2134  virtual void print_figure (const graphics_object&, const std::string&,
2135  const std::string&, bool,
2136  const std::string& = "") const
2137  { gripe_invalid ("print_figure"); }
2138 
2139  virtual Matrix get_canvas_size (const graphics_handle&) const
2140  {
2141  gripe_invalid ("get_canvas_size");
2142  return Matrix (1, 2, 0.0);
2143  }
2144 
2145  virtual double get_screen_resolution (void) const
2146  {
2147  gripe_invalid ("get_screen_resolution");
2148  return 72.0;
2149  }
2150 
2151  virtual Matrix get_screen_size (void) const
2152  {
2153  gripe_invalid ("get_screen_size");
2154  return Matrix (1, 2, 0.0);
2155  }
2156 
2157  // Callback function executed when the given graphics object
2158  // changes. This allows the graphics toolkit to act on property
2159  // changes if needed.
2160  virtual void update (const graphics_object&, int)
2161  { gripe_invalid ("base_graphics_toolkit::update"); }
2162 
2163  void update (const graphics_handle&, int);
2164 
2165  // Callback function executed when the given graphics object is
2166  // created. This allows the graphics toolkit to do toolkit-specific
2167  // initializations for a newly created object.
2168  virtual bool initialize (const graphics_object&)
2169  { gripe_invalid ("base_graphics_toolkit::initialize"); return false; }
2170 
2171  bool initialize (const graphics_handle&);
2172 
2173  // Callback function executed just prior to deleting the given
2174  // graphics object. This allows the graphics toolkit to perform
2175  // toolkit-specific cleanup operations before an object is deleted.
2176  virtual void finalize (const graphics_object&)
2177  { gripe_invalid ("base_graphics_toolkit::finalize"); }
2178 
2179  void finalize (const graphics_handle&);
2180 
2181  // Close the graphics toolkit.
2182  virtual void close (void)
2183  { gripe_invalid ("base_graphics_toolkit::close"); }
2184 
2185 private:
2186  std::string name;
2188 
2189 private:
2190  void gripe_invalid (const std::string& fname) const
2191  {
2192  if (! is_valid ())
2193  error ("%s: invalid graphics toolkit", fname.c_str ());
2194  }
2195 };
2196 
2197 class graphics_toolkit
2198 {
2199 public:
2201  : rep (new base_graphics_toolkit ("unknown"))
2202  {
2203  rep->count++;
2204  }
2205 
2207  : rep (b)
2208  {
2209  rep->count++;
2210  }
2211 
2213  : rep (b.rep)
2214  {
2215  rep->count++;
2216  }
2217 
2219  {
2220  if (--rep->count == 0)
2221  delete rep;
2222  }
2223 
2225  {
2226  if (rep != b.rep)
2227  {
2228  if (--rep->count == 0)
2229  delete rep;
2230 
2231  rep = b.rep;
2232  rep->count++;
2233  }
2234 
2235  return *this;
2236  }
2237 
2238  operator bool (void) const { return rep->is_valid (); }
2239 
2240  std::string get_name (void) const { return rep->get_name (); }
2241 
2242  void redraw_figure (const graphics_object& go) const
2243  { rep->redraw_figure (go); }
2244 
2245  void print_figure (const graphics_object& go, const std::string& term,
2246  const std::string& file, bool mono,
2247  const std::string& debug_file = "") const
2248  { rep->print_figure (go, term, file, mono, debug_file); }
2249 
2251  { return rep->get_canvas_size (fh); }
2252 
2253  double get_screen_resolution (void) const
2254  { return rep->get_screen_resolution (); }
2255 
2257  { return rep->get_screen_size (); }
2258 
2259  // Notifies graphics toolkit that object't property has changed.
2260  void update (const graphics_object& go, int id)
2261  { rep->update (go, id); }
2262 
2263  void update (const graphics_handle& h, int id)
2264  { rep->update (h, id); }
2265 
2266  // Notifies graphics toolkit that new object was created.
2267  bool initialize (const graphics_object& go)
2268  { return rep->initialize (go); }
2269 
2270  bool initialize (const graphics_handle& h)
2271  { return rep->initialize (h); }
2272 
2273  // Notifies graphics toolkit that object was destroyed.
2274  // This is called only for explicitly deleted object. Children are
2275  // deleted implicitly and graphics toolkit isn't notified.
2276  void finalize (const graphics_object& go)
2277  { rep->finalize (go); }
2278 
2279  void finalize (const graphics_handle& h)
2280  { rep->finalize (h); }
2281 
2282  // Close the graphics toolkit.
2283  void close (void) { rep->close (); }
2284 
2285 private:
2286 
2288 };
2289 
2290 class gtk_manager
2291 {
2292 public:
2293 
2295  {
2296  return instance_ok () ? instance->do_get_toolkit () : graphics_toolkit ();
2297  }
2298 
2299  static void register_toolkit (const std::string& name)
2300  {
2301  if (instance_ok ())
2302  instance->do_register_toolkit (name);
2303  }
2304 
2305  static void unregister_toolkit (const std::string& name)
2306  {
2307  if (instance_ok ())
2309  }
2310 
2311  static void load_toolkit (const graphics_toolkit& tk)
2312  {
2313  if (instance_ok ())
2314  instance->do_load_toolkit (tk);
2315  }
2316 
2317  static void unload_toolkit (const std::string& name)
2318  {
2319  if (instance_ok ())
2320  instance->do_unload_toolkit (name);
2321  }
2322 
2323  static graphics_toolkit find_toolkit (const std::string& name)
2324  {
2325  return instance_ok ()
2326  ? instance->do_find_toolkit (name) : graphics_toolkit ();
2327  }
2328 
2330  {
2331  return instance_ok () ? instance->do_available_toolkits_list () : Cell ();
2332  }
2333 
2335  {
2336  return instance_ok () ? instance->do_loaded_toolkits_list () : Cell ();
2337  }
2338 
2339  static void unload_all_toolkits (void)
2340  {
2341  if (instance_ok ())
2343  }
2344 
2345  static std::string default_toolkit (void)
2346  {
2347  return instance_ok () ? instance->do_default_toolkit () : std::string ();
2348  }
2349 
2350 private:
2351 
2352  gtk_manager (void) { }
2353 
2354  ~gtk_manager (void) { }
2355 
2356  OCTINTERP_API static void create_instance (void);
2357 
2358  static bool instance_ok (void)
2359  {
2360  bool retval = true;
2361 
2362  if (! instance)
2363  create_instance ();
2364 
2365  if (! instance)
2366  {
2367  ::error ("unable to create gh_manager!");
2368 
2369  retval = false;
2370  }
2371 
2372  return retval;
2373  }
2374 
2375  static void cleanup_instance (void) { delete instance; instance = 0; }
2376 
2378 
2379  // The name of the default toolkit.
2380  std::string dtk;
2381 
2382  // The list of toolkits that we know about.
2383  std::set<std::string> available_toolkits;
2384 
2385  // The list of toolkits we have actually loaded.
2386  std::map<std::string, graphics_toolkit> loaded_toolkits;
2387 
2388  typedef std::set<std::string>::iterator available_toolkits_iterator;
2389 
2390  typedef std::set<std::string>::const_iterator
2392 
2393  typedef std::map<std::string, graphics_toolkit>::iterator
2395 
2396  typedef std::map<std::string, graphics_toolkit>::const_iterator
2398 
2399  graphics_toolkit do_get_toolkit (void) const;
2400 
2401  void do_register_toolkit (const std::string& name);
2402 
2403  void do_unregister_toolkit (const std::string& name);
2404 
2406  {
2407  loaded_toolkits[tk.get_name ()] = tk;
2408  }
2409 
2410  void do_unload_toolkit (const std::string& name)
2411  {
2412  loaded_toolkits.erase (name);
2413  }
2414 
2415  graphics_toolkit do_find_toolkit (const std::string& name) const
2416  {
2417  const_loaded_toolkits_iterator p = loaded_toolkits.find (name);
2418 
2419  if (p != loaded_toolkits.end ())
2420  return p->second;
2421  else
2422  return graphics_toolkit ();
2423  }
2424 
2426  {
2427  Cell m (1 , available_toolkits.size ());
2428 
2429  octave_idx_type i = 0;
2430  for (const_available_toolkits_iterator p = available_toolkits.begin ();
2431  p != available_toolkits.end (); p++)
2432  m(i++) = *p;
2433 
2434  return m;
2435  }
2436 
2438  {
2439  Cell m (1 , loaded_toolkits.size ());
2440 
2441  octave_idx_type i = 0;
2442  for (const_loaded_toolkits_iterator p = loaded_toolkits.begin ();
2443  p != loaded_toolkits.end (); p++)
2444  m(i++) = p->first;
2445 
2446  return m;
2447  }
2448 
2450  {
2451  while (! loaded_toolkits.empty ())
2452  {
2453  loaded_toolkits_iterator p = loaded_toolkits.begin ();
2454 
2455  std::string name = p->first;
2456 
2457  p->second.close ();
2458 
2459  // The toolkit may have unloaded itself. If not, we'll do
2460  // it here.
2461  if (loaded_toolkits.find (name) != loaded_toolkits.end ())
2462  unload_toolkit (name);
2463  }
2464  }
2465 
2466  std::string do_default_toolkit (void) { return dtk; }
2467 };
2468 
2469 // ---------------------------------------------------------------------
2470 
2471 class base_graphics_object;
2472 class graphics_object;
2473 
2475 {
2476 public:
2477  base_properties (const std::string& ty = "unknown",
2478  const graphics_handle& mh = graphics_handle (),
2479  const graphics_handle& p = graphics_handle ());
2480 
2481  virtual ~base_properties (void) { }
2482 
2483  virtual std::string graphics_object_name (void) const { return "unknown"; }
2484 
2485  void mark_modified (void);
2486 
2487  void override_defaults (base_graphics_object& obj);
2488 
2489  virtual void init_integerhandle (const octave_value&)
2490  {
2491  panic_impossible ();
2492  }
2493 
2494  // Look through DEFAULTS for properties with given CLASS_NAME, and
2495  // apply them to the current object with set (virtual method).
2496 
2497  void set_from_list (base_graphics_object& obj, property_list& defaults);
2498 
2499  void insert_property (const std::string& name, property p)
2500  {
2501  p.set_name (name);
2502  p.set_parent (__myhandle__);
2503  all_props[name] = p;
2504  }
2505 
2506  virtual void set (const caseless_str&, const octave_value&);
2507 
2508  virtual octave_value get (const caseless_str& pname) const;
2509 
2510  virtual octave_value get (const std::string& pname) const
2511  {
2512  return get (caseless_str (pname));
2513  }
2514 
2515  virtual octave_value get (const char *pname) const
2516  {
2517  return get (caseless_str (pname));
2518  }
2519 
2520  virtual octave_value get (bool all = false) const;
2521 
2522  virtual property get_property (const caseless_str& pname);
2523 
2524  virtual bool has_property (const caseless_str&) const
2525  {
2526  panic_impossible ();
2527  return false;
2528  }
2529 
2530  bool is_modified (void) const { return is___modified__ (); }
2531 
2532  virtual void remove_child (const graphics_handle& h)
2533  {
2534  if (children.remove_child (h.value ()))
2535  {
2536  children.run_listeners ();
2537  mark_modified ();
2538  }
2539  }
2540 
2541  virtual void adopt (const graphics_handle& h)
2542  {
2543  children.adopt (h.value ());
2544  children.run_listeners ();
2545  mark_modified ();
2546  }
2547 
2548  virtual graphics_toolkit get_toolkit (void) const;
2549 
2550  virtual Matrix
2551  get_boundingbox (bool /*internal*/ = false,
2552  const Matrix& /*parent_pix_size*/ = Matrix ()) const
2553  { return Matrix (1, 4, 0.0); }
2554 
2555  virtual void update_boundingbox (void);
2556 
2557  virtual void update_autopos (const std::string& elem_type);
2558 
2559  virtual void add_listener (const caseless_str&, const octave_value&,
2561 
2562  virtual void delete_listener (const caseless_str&, const octave_value&,
2564 
2565  void set_tag (const octave_value& val) { tag = val; }
2566 
2567  void set_parent (const octave_value& val);
2568 
2569  Matrix get_children (void) const
2570  {
2571  return children.get_children ();
2572  }
2573 
2575  {
2576  return children.get_all ();
2577  }
2578 
2580  {
2581  return children.get_hidden ();
2582  }
2583 
2584  void set_modified (const octave_value& val) { set___modified__ (val); }
2585 
2586  void set___modified__ (const octave_value& val) { __modified__ = val; }
2587 
2588  void reparent (const graphics_handle& new_parent) { parent = new_parent; }
2589 
2590  // Update data limits for AXIS_TYPE (xdata, ydata, etc.) in the parent
2591  // axes object.
2592 
2593  virtual void update_axis_limits (const std::string& axis_type) const;
2594 
2595  virtual void update_axis_limits (const std::string& axis_type,
2596  const graphics_handle& h) const;
2597 
2598  virtual void update_uicontextmenu (void) const;
2599 
2600  virtual void delete_children (bool clear = false)
2601  {
2602  children.delete_children (clear);
2603  }
2604 
2606  {
2607  children.renumber (old_gh, new_gh);
2608  }
2609 
2611  {
2612  parent = new_gh;
2613  }
2614 
2615  static property_list::pval_map_type factory_defaults (void);
2616 
2617  // FIXME: these functions should be generated automatically by the
2618  // genprops.awk script.
2619  //
2620  // EMIT_BASE_PROPERTIES_GET_FUNCTIONS
2621 
2622  virtual octave_value get_alim (void) const { return octave_value (); }
2623  virtual octave_value get_clim (void) const { return octave_value (); }
2624  virtual octave_value get_xlim (void) const { return octave_value (); }
2625  virtual octave_value get_ylim (void) const { return octave_value (); }
2626  virtual octave_value get_zlim (void) const { return octave_value (); }
2627 
2628  virtual bool is_aliminclude (void) const { return false; }
2629  virtual bool is_climinclude (void) const { return false; }
2630  virtual bool is_xliminclude (void) const { return false; }
2631  virtual bool is_yliminclude (void) const { return false; }
2632  virtual bool is_zliminclude (void) const { return false; }
2633 
2634  bool is_handle_visible (void) const;
2635 
2636  std::set<std::string> dynamic_property_names (void) const;
2637 
2638  bool has_dynamic_property (const std::string& pname);
2639 
2640 protected:
2641  std::set<std::string> dynamic_properties;
2642 
2643  void set_dynamic (const caseless_str& pname, const octave_value& val);
2644 
2645  octave_value get_dynamic (const caseless_str& pname) const;
2646 
2647  octave_value get_dynamic (bool all = false) const;
2648 
2649  property get_property_dynamic (const caseless_str& pname);
2650 
2651  BEGIN_BASE_PROPERTIES
2652  // properties common to all objects
2653  bool_property beingdeleted , "off"
2654  radio_property busyaction , "{queue}|cancel"
2656  children_property children gf , Matrix ()
2657  bool_property clipping , "on"
2658  callback_property createfcn , Matrix ()
2659  callback_property deletefcn , Matrix ()
2660  radio_property handlevisibility , "{on}|callback|off"
2661  bool_property hittest , "on"
2662  bool_property interruptible , "on"
2663  handle_property parent fs , p
2664  bool_property selected , "off"
2665  bool_property selectionhighlight , "on"
2666  string_property tag s , ""
2667  string_property type frs , ty
2668  handle_property uicontextmenu u , graphics_handle ()
2669  any_property userdata , Matrix ()
2670  bool_property visible , "on"
2671  // additional (Octave-specific) properties
2672  bool_property __modified__ s , "on"
2673  graphics_handle __myhandle__ fhrs , mh
2674  END_PROPERTIES
2675 
2676 protected:
2677  struct cmp_caseless_str
2678  {
2679  bool operator () (const caseless_str& a, const caseless_str& b) const
2680  {
2681  std::string a1 = a;
2682  std::transform (a1.begin (), a1.end (), a1.begin (), tolower);
2683  std::string b1 = b;
2684  std::transform (b1.begin (), b1.end (), b1.begin (), tolower);
2685 
2686  return a1 < b1;
2687  }
2688  };
2689 
2690  std::map<caseless_str, property, cmp_caseless_str> all_props;
2691 
2692 protected:
2693  void insert_static_property (const std::string& name, base_property& p)
2694  { insert_property (name, property (&p, true)); }
2695 
2696  virtual void init (void) { }
2697 };
2698 
2699 class OCTINTERP_API base_graphics_object
2700 {
2701 public:
2702  friend class graphics_object;
2703 
2704  base_graphics_object (void) : count (1), toolkit_flag (false) { }
2705 
2706  virtual ~base_graphics_object (void) { }
2707 
2708  virtual void mark_modified (void)
2709  {
2710  if (valid_object ())
2711  get_properties ().mark_modified ();
2712  else
2713  error ("base_graphics_object::mark_modified: invalid graphics object");
2714  }
2715 
2716  virtual void override_defaults (base_graphics_object& obj)
2717  {
2718  if (valid_object ())
2719  get_properties ().override_defaults (obj);
2720  else
2721  error ("base_graphics_object::override_defaults: invalid graphics object");
2722  }
2723 
2724  void build_user_defaults_map (property_list::pval_map_type &def,
2725  const std::string go_name) const;
2726 
2727  virtual void set_from_list (property_list& plist)
2728  {
2729  if (valid_object ())
2730  get_properties ().set_from_list (*this, plist);
2731  else
2732  error ("base_graphics_object::set_from_list: invalid graphics object");
2733  }
2734 
2735  virtual void set (const caseless_str& pname, const octave_value& pval)
2736  {
2737  if (valid_object ())
2738  get_properties ().set (pname, pval);
2739  else
2740  error ("base_graphics_object::set: invalid graphics object");
2741  }
2742 
2743  virtual void set_defaults (const std::string&)
2744  {
2745  error ("base_graphics_object::set_defaults: invalid graphics object");
2746  }
2747 
2748  virtual octave_value get (bool all = false) const
2749  {
2750  if (valid_object ())
2751  return get_properties ().get (all);
2752  else
2753  {
2754  error ("base_graphics_object::get: invalid graphics object");
2755  return octave_value ();
2756  }
2757  }
2758 
2759  virtual octave_value get (const caseless_str& pname) const
2760  {
2761  if (valid_object ())
2762  return get_properties ().get (pname);
2763  else
2764  {
2765  error ("base_graphics_object::get: invalid graphics object");
2766  return octave_value ();
2767  }
2768  }
2769 
2770  virtual octave_value get_default (const caseless_str&) const;
2771 
2772  virtual octave_value get_factory_default (const caseless_str&) const;
2773 
2774  virtual octave_value get_defaults (void) const
2775  {
2776  error ("base_graphics_object::get_defaults: invalid graphics object");
2777  return octave_value ();
2778  }
2779 
2780  virtual property_list get_defaults_list (void) const
2781  {
2782  if (! valid_object ())
2783  error ("base_graphics_object::get_defaults_list: invalid graphics object");
2784  return property_list ();
2785  }
2786 
2787  virtual octave_value get_factory_defaults (void) const
2788  {
2789  error ("base_graphics_object::get_factory_defaults: invalid graphics object");
2790  return octave_value ();
2791  }
2792 
2793  virtual property_list get_factory_defaults_list (void) const
2794  {
2795  error ("base_graphics_object::get_factory_defaults_list: invalid graphics object");
2796  return property_list ();
2797  }
2798 
2799  virtual bool has_readonly_property (const caseless_str& pname) const
2800  {
2801  return base_properties::has_readonly_property (pname);
2802  }
2803 
2804  virtual std::string values_as_string (void);
2805 
2806  virtual std::string value_as_string (const std::string& prop);
2807 
2808  virtual octave_scalar_map values_as_struct (void);
2809 
2810  virtual graphics_handle get_parent (void) const
2811  {
2812  if (valid_object ())
2813  return get_properties ().get_parent ();
2814  else
2815  {
2816  error ("base_graphics_object::get_parent: invalid graphics object");
2817  return graphics_handle ();
2818  }
2819  }
2820 
2821  graphics_handle get_handle (void) const
2822  {
2823  if (valid_object ())
2824  return get_properties ().get___myhandle__ ();
2825  else
2826  {
2827  error ("base_graphics_object::get_handle: invalid graphics object");
2828  return graphics_handle ();
2829  }
2830  }
2831 
2832  virtual void remove_child (const graphics_handle& h)
2833  {
2834  if (valid_object ())
2835  get_properties ().remove_child (h);
2836  else
2837  error ("base_graphics_object::remove_child: invalid graphics object");
2838  }
2839 
2840  virtual void adopt (const graphics_handle& h)
2841  {
2842  if (valid_object ())
2843  get_properties ().adopt (h);
2844  else
2845  error ("base_graphics_object::adopt: invalid graphics object");
2846  }
2847 
2848  virtual void reparent (const graphics_handle& np)
2849  {
2850  if (valid_object ())
2851  get_properties ().reparent (np);
2852  else
2853  error ("base_graphics_object::reparent: invalid graphics object");
2854  }
2855 
2856  virtual void defaults (void) const
2857  {
2858  if (valid_object ())
2859  {
2860  std::string msg = (type () + "::defaults");
2861  gripe_not_implemented (msg.c_str ());
2862  }
2863  else
2864  error ("base_graphics_object::default: invalid graphics object");
2865  }
2866 
2867  virtual base_properties& get_properties (void)
2868  {
2869  static base_properties properties;
2870  error ("base_graphics_object::get_properties: invalid graphics object");
2871  return properties;
2872  }
2873 
2874  virtual const base_properties& get_properties (void) const
2875  {
2876  static base_properties properties;
2877  error ("base_graphics_object::get_properties: invalid graphics object");
2878  return properties;
2879  }
2880 
2881  virtual void update_axis_limits (const std::string& axis_type);
2882 
2883  virtual void update_axis_limits (const std::string& axis_type,
2884  const graphics_handle& h);
2885 
2886  virtual bool valid_object (void) const { return false; }
2887 
2888  bool valid_toolkit_object (void) const { return toolkit_flag; }
2889 
2890  virtual std::string type (void) const
2891  {
2892  return (valid_object () ? get_properties ().graphics_object_name ()
2893  : "unknown");
2894  }
2895 
2896  bool isa (const std::string& go_name) const
2897  {
2898  return type () == go_name;
2899  }
2900 
2901  virtual graphics_toolkit get_toolkit (void) const
2902  {
2903  if (valid_object ())
2904  return get_properties ().get_toolkit ();
2905  else
2906  {
2907  error ("base_graphics_object::get_toolkit: invalid graphics object");
2908  return graphics_toolkit ();
2909  }
2910  }
2911 
2912  virtual void add_property_listener (const std::string& nm,
2913  const octave_value& v,
2914  listener_mode mode = POSTSET)
2915  {
2916  if (valid_object ())
2917  get_properties ().add_listener (nm, v, mode);
2918  }
2919 
2920  virtual void delete_property_listener (const std::string& nm,
2921  const octave_value& v,
2922  listener_mode mode = POSTSET)
2923  {
2924  if (valid_object ())
2925  get_properties ().delete_listener (nm, v, mode);
2926  }
2927 
2928  virtual void remove_all_listeners (void);
2929 
2930  virtual void reset_default_properties (void);
2931 
2932 protected:
2933  virtual void initialize (const graphics_object& go)
2934  {
2935  if (! toolkit_flag)
2936  toolkit_flag = get_toolkit ().initialize (go);
2937  }
2938 
2939  virtual void finalize (const graphics_object& go)
2940  {
2941  if (toolkit_flag)
2942  {
2943  get_toolkit ().finalize (go);
2944  toolkit_flag = false;
2945  }
2946  }
2947 
2948  virtual void update (const graphics_object& go, int id)
2949  {
2950  if (toolkit_flag)
2951  get_toolkit ().update (go, id);
2952  }
2953 
2954 protected:
2955  // A reference count.
2956  octave_refcount<int> count;
2957 
2958  // A flag telling whether this object is a valid object
2959  // in the backend context.
2960  bool toolkit_flag;
2961 
2962  // No copying!
2963 
2964  base_graphics_object (const base_graphics_object&) : count (0) { }
2965 
2966  base_graphics_object& operator = (const base_graphics_object&)
2967  {
2968  return *this;
2969  }
2970 };
2971 
2972 class OCTINTERP_API graphics_object
2973 {
2974 public:
2975  graphics_object (void) : rep (new base_graphics_object ()) { }
2976 
2977  graphics_object (base_graphics_object *new_rep)
2978  : rep (new_rep) { }
2979 
2980  graphics_object (const graphics_object& obj) : rep (obj.rep)
2981  {
2982  rep->count++;
2983  }
2984 
2985  graphics_object& operator = (const graphics_object& obj)
2986  {
2987  if (rep != obj.rep)
2988  {
2989  if (--rep->count == 0)
2990  delete rep;
2991 
2992  rep = obj.rep;
2993  rep->count++;
2994  }
2995 
2996  return *this;
2997  }
2998 
2999  ~graphics_object (void)
3000  {
3001  if (--rep->count == 0)
3002  delete rep;
3003  }
3004 
3005  void mark_modified (void) { rep->mark_modified (); }
3006 
3007  void override_defaults (base_graphics_object& obj)
3008  {
3009  rep->override_defaults (obj);
3010  }
3011 
3012  void override_defaults (void)
3013  {
3014  rep->override_defaults (*rep);
3015  }
3016 
3017  void build_user_defaults_map (property_list::pval_map_type &def,
3018  const std::string go_name) const
3019  {
3020  rep->build_user_defaults_map (def, go_name);
3021  }
3022 
3023  void set_from_list (property_list& plist) { rep->set_from_list (plist); }
3024 
3025  void set (const caseless_str& name, const octave_value& val)
3026  {
3027  rep->set (name, val);
3028  }
3029 
3030  void set (const octave_value_list& args);
3031 
3032  void set (const Array<std::string>& names, const Cell& values,
3033  octave_idx_type row);
3034 
3035  void set (const octave_map& m);
3036 
3037  void set_value_or_default (const caseless_str& name,
3038  const octave_value& val);
3039 
3040  void set_defaults (const std::string& mode) { rep->set_defaults (mode); }
3041 
3042  octave_value get (bool all = false) const { return rep->get (all); }
3043 
3044  octave_value get (const caseless_str& name) const
3045  {
3046  return name.compare ("default")
3047  ? get_defaults ()
3048  : (name.compare ("factory")
3049  ? get_factory_defaults () : rep->get (name));
3050  }
3051 
3052  octave_value get (const std::string& name) const
3053  {
3054  return get (caseless_str (name));
3055  }
3056 
3057  octave_value get (const char *name) const
3058  {
3059  return get (caseless_str (name));
3060  }
3061 
3062  octave_value get_default (const caseless_str& name) const
3063  {
3064  return rep->get_default (name);
3065  }
3066 
3067  octave_value get_factory_default (const caseless_str& name) const
3068  {
3069  return rep->get_factory_default (name);
3070  }
3071 
3072  octave_value get_defaults (void) const { return rep->get_defaults (); }
3073 
3074  property_list get_defaults_list (void) const
3075  {
3076  return rep->get_defaults_list ();
3077  }
3078 
3079  octave_value get_factory_defaults (void) const
3080  {
3081  return rep->get_factory_defaults ();
3082  }
3083 
3084  property_list get_factory_defaults_list (void) const
3085  {
3086  return rep->get_factory_defaults_list ();
3087  }
3088 
3089  bool has_readonly_property (const caseless_str& pname) const
3090  {
3091  return rep->has_readonly_property (pname);
3092  }
3093 
3094  std::string values_as_string (void) { return rep->values_as_string (); }
3095 
3096  std::string value_as_string (const std::string& prop)
3097  {
3098  return rep->value_as_string (prop);
3099  }
3100 
3101  octave_map values_as_struct (void) { return rep->values_as_struct (); }
3102 
3103  graphics_handle get_parent (void) const { return rep->get_parent (); }
3104 
3105  graphics_handle get_handle (void) const { return rep->get_handle (); }
3106 
3107  graphics_object get_ancestor (const std::string& type) const;
3108 
3109  void remove_child (const graphics_handle& h) { rep->remove_child (h); }
3110 
3111  void adopt (const graphics_handle& h) { rep->adopt (h); }
3112 
3113  void reparent (const graphics_handle& h) { rep->reparent (h); }
3114 
3115  void defaults (void) const { rep->defaults (); }
3116 
3117  bool isa (const std::string& go_name) const { return rep->isa (go_name); }
3118 
3119  base_properties& get_properties (void) { return rep->get_properties (); }
3120 
3121  const base_properties& get_properties (void) const
3122  {
3123  return rep->get_properties ();
3124  }
3125 
3126  void update_axis_limits (const std::string& axis_type)
3127  {
3128  rep->update_axis_limits (axis_type);
3129  }
3130 
3131  void update_axis_limits (const std::string& axis_type,
3132  const graphics_handle& h)
3133  {
3134  rep->update_axis_limits (axis_type, h);
3135  }
3136 
3137  bool valid_object (void) const { return rep->valid_object (); }
3138 
3139  std::string type (void) const { return rep->type (); }
3140 
3141  operator bool (void) const { return rep->valid_object (); }
3142 
3143  // FIXME: these functions should be generated automatically by the
3144  // genprops.awk script.
3145  //
3146  // EMIT_GRAPHICS_OBJECT_GET_FUNCTIONS
3147 
3148  octave_value get_alim (void) const
3149  { return get_properties ().get_alim (); }
3150 
3151  octave_value get_clim (void) const
3152  { return get_properties ().get_clim (); }
3153 
3154  octave_value get_xlim (void) const
3155  { return get_properties ().get_xlim (); }
3156 
3157  octave_value get_ylim (void) const
3158  { return get_properties ().get_ylim (); }
3159 
3160  octave_value get_zlim (void) const
3161  { return get_properties ().get_zlim (); }
3162 
3163  bool is_aliminclude (void) const
3164  { return get_properties ().is_aliminclude (); }
3165 
3166  bool is_climinclude (void) const
3167  { return get_properties ().is_climinclude (); }
3168 
3169  bool is_xliminclude (void) const
3170  { return get_properties ().is_xliminclude (); }
3171 
3172  bool is_yliminclude (void) const
3173  { return get_properties ().is_yliminclude (); }
3174 
3175  bool is_zliminclude (void) const
3176  { return get_properties ().is_zliminclude (); }
3177 
3178  bool is_handle_visible (void) const
3179  { return get_properties ().is_handle_visible (); }
3180 
3181  graphics_toolkit get_toolkit (void) const { return rep->get_toolkit (); }
3182 
3183  void add_property_listener (const std::string& nm, const octave_value& v,
3184  listener_mode mode = POSTSET)
3185  { rep->add_property_listener (nm, v, mode); }
3186 
3187  void delete_property_listener (const std::string& nm, const octave_value& v,
3188  listener_mode mode = POSTSET)
3189  { rep->delete_property_listener (nm, v, mode); }
3190 
3191  void initialize (void) { rep->initialize (*this); }
3192 
3193  void finalize (void) { rep->finalize (*this); }
3194 
3195  void update (int id) { rep->update (*this, id); }
3196 
3197  void reset_default_properties (void)
3198  { rep->reset_default_properties (); }
3199 
3200 private:
3201  base_graphics_object *rep;
3202 };
3203 
3204 // ---------------------------------------------------------------------
3205 
3206 class OCTINTERP_API root_figure : public base_graphics_object
3207 {
3208 public:
3209  class OCTINTERP_API properties : public base_properties
3210  {
3211  public:
3212  void remove_child (const graphics_handle& h);
3213 
3214  Matrix get_boundingbox (bool internal = false,
3215  const Matrix& parent_pix_size = Matrix ()) const;
3216 
3217  // See the genprops.awk script for an explanation of the
3218  // properties declarations.
3219 
3220  // FIXME: Properties that still dont have callbacks are:
3221  // language, monitorpositions, pointerlocation, pointerwindow.
3222  // Note that these properties are not yet used by Octave, so setting
3223  // them will have no effect.
3224 
3225  // Programming note: Keep property list sorted if new ones are added.
3226 
3227  BEGIN_PROPERTIES (root_figure, root)
3228  handle_property callbackobject Sr , graphics_handle ()
3229  array_property commandwindowsize r , Matrix (1, 2, 0)
3230  handle_property currentfigure S , graphics_handle ()
3231  bool_property diary GS , "off"
3232  string_property diaryfile GS , "diary"
3233  bool_property echo GS , "off"
3234  string_property errormessage Gr , ""
3235  string_property fixedwidthfontname , "Courier"
3236  radio_property format GS , "+|bank|bit|hex|long|longe|longeng|longg|native-bit|native-hex|none|rat|{short}|shorte|shorteng|shortg"
3237  radio_property formatspacing GS , "compact|{loose}"
3238  string_property language , "ascii"
3239  array_property monitorpositions , Matrix (1, 4, 0)
3240  array_property pointerlocation , Matrix (1, 2, 0)
3241  double_property pointerwindow r , 0.0
3242  double_property recursionlimit GS , 256.0
3243  double_property screendepth r , default_screendepth ()
3244  double_property screenpixelsperinch r , default_screenpixelsperinch ()
3245  array_property screensize r , default_screensize ()
3246  bool_property showhiddenhandles , "off"
3247  radio_property units U , "inches|centimeters|normalized|points|{pixels}"
3248  END_PROPERTIES
3249 
3250  private:
3251  std::list<graphics_handle> cbo_stack;
3252 
3253  };
3254 
3255 private:
3256  properties xproperties;
3257 
3258 public:
3259 
3260  root_figure (void)
3261  : xproperties (0, graphics_handle ()), default_properties () { }
3262 
3263  ~root_figure (void) { }
3264 
3265  void mark_modified (void) { }
3266 
3267  void override_defaults (base_graphics_object& obj)
3268  {
3269  // Now override with our defaults. If the default_properties
3270  // list includes the properties for all defaults (line,
3271  // surface, etc.) then we don't have to know the type of OBJ
3272  // here, we just call its set function and let it decide which
3273  // properties from the list to use.
3274  obj.set_from_list (default_properties);
3275  }
3276 
3277  void set (const caseless_str& name, const octave_value& value)
3278  {
3279  if (name.compare ("default", 7))
3280  // strip "default", pass rest to function that will
3281  // parse the remainder and add the element to the
3282  // default_properties map.
3283  default_properties.set (name.substr (7), value);
3284  else
3285  xproperties.set (name, value);
3286  }
3287 
3288  octave_value get (const caseless_str& name) const
3289  {
3290  octave_value retval;
3291 
3292  if (name.compare ("default", 7))
3293  return get_default (name.substr (7));
3294  else if (name.compare ("factory", 7))
3295  return get_factory_default (name.substr (7));
3296  else
3297  retval = xproperties.get (name);
3298 
3299  return retval;
3300  }
3301 
3302  octave_value get_default (const caseless_str& name) const
3303  {
3304  octave_value retval = default_properties.lookup (name);
3305 
3306  if (retval.is_undefined ())
3307  {
3308  // no default property found, use factory default
3309  retval = factory_properties.lookup (name);
3310 
3311  if (retval.is_undefined ())
3312  error ("get: invalid default property '%s'", name.c_str ());
3313  }
3314 
3315  return retval;
3316  }
3317 
3318  octave_value get_factory_default (const caseless_str& name) const
3319  {
3320  octave_value retval = factory_properties.lookup (name);
3321 
3322  if (retval.is_undefined ())
3323  error ("get: invalid factory default property '%s'", name.c_str ());
3324 
3325  return retval;
3326  }
3327 
3328  octave_value get_defaults (void) const
3329  {
3330  return default_properties.as_struct ("default");
3331  }
3332 
3333  property_list get_defaults_list (void) const
3334  {
3335  return default_properties;
3336  }
3337 
3338  octave_value get_factory_defaults (void) const
3339  {
3340  return factory_properties.as_struct ("factory");
3341  }
3342 
3343  property_list get_factory_defaults_list (void) const
3344  {
3345  return factory_properties;
3346  }
3347 
3348  base_properties& get_properties (void) { return xproperties; }
3349 
3350  const base_properties& get_properties (void) const { return xproperties; }
3351 
3352  bool valid_object (void) const { return true; }
3353 
3354  void reset_default_properties (void);
3355 
3356  bool has_readonly_property (const caseless_str& pname) const
3357  {
3358  bool retval = xproperties.has_readonly_property (pname);
3359  if (! retval)
3360  retval = base_properties::has_readonly_property (pname);
3361  return retval;
3362  }
3363 
3364 private:
3365  property_list default_properties;
3366 
3367  static property_list factory_properties;
3368 
3369  static property_list::plist_map_type init_factory_properties (void);
3370 };
3371 
3372 // ---------------------------------------------------------------------
3373 
3374 class OCTINTERP_API figure : public base_graphics_object
3375 {
3376 public:
3377  class OCTINTERP_API properties : public base_properties
3378  {
3379  public:
3380  void init_integerhandle (const octave_value& val)
3381  {
3382  integerhandle = val;
3383  }
3384 
3385  void remove_child (const graphics_handle& h);
3386 
3387  void set_visible (const octave_value& val);
3388 
3389  graphics_toolkit get_toolkit (void) const
3390  {
3391  if (! toolkit)
3392  toolkit = gtk_manager::get_toolkit ();
3393 
3394  return toolkit;
3395  }
3396 
3397  void set_toolkit (const graphics_toolkit& b);
3398 
3399  void set___graphics_toolkit__ (const octave_value& val)
3400  {
3401  if (! error_state)
3402  {
3403  if (val.is_string ())
3404  {
3405  std::string nm = val.string_value ();
3406  graphics_toolkit b = gtk_manager::find_toolkit (nm);
3407  if (b.get_name () != nm)
3408  {
3409  error ("set___graphics_toolkit__: invalid graphics toolkit");
3410  }
3411  else
3412  {
3413  if (nm != get___graphics_toolkit__ ())
3414  {
3415  set_toolkit (b);
3416  mark_modified ();
3417  }
3418  }
3419  }
3420  else
3421  error ("set___graphics_toolkit__ must be a string");
3422  }
3423  }
3424 
3425  void adopt (const graphics_handle& h);
3426 
3427  void set_position (const octave_value& val,
3428  bool do_notify_toolkit = true);
3429 
3430  void set_outerposition (const octave_value& val,
3431  bool do_notify_toolkit = true);
3432 
3433  Matrix get_boundingbox (bool internal = false,
3434  const Matrix& parent_pix_size = Matrix ()) const;
3435 
3436  void set_boundingbox (const Matrix& bb, bool internal = false,
3437  bool do_notify_toolkit = true);
3438 
3439  Matrix map_from_boundingbox (double x, double y) const;
3440 
3441  Matrix map_to_boundingbox (double x, double y) const;
3442 
3443  void update_units (const caseless_str& old_units);
3444 
3445  void update_paperunits (const caseless_str& old_paperunits);
3446 
3447  std::string get_title (void) const;
3448 
3449  // See the genprops.awk script for an explanation of the
3450  // properties declarations.
3451  // Programming note: Keep property list sorted if new ones are added.
3452 
3453  BEGIN_PROPERTIES (figure)
3454  array_property alphamap , Matrix (64, 1, 1)
3455  callback_property buttondownfcn , Matrix ()
3456  callback_property closerequestfcn , "closereq"
3457  color_property color , color_property (color_values (1, 1, 1), radio_values ("none"))
3458  array_property colormap , jet_colormap ()
3459  handle_property currentaxes S , graphics_handle ()
3460  string_property currentcharacter r , ""
3461  handle_property currentobject r , graphics_handle ()
3462  array_property currentpoint r , Matrix (2, 1, 0)
3463  bool_property dockcontrols , "off"
3464  bool_property doublebuffer , "on"
3465  string_property filename , ""
3466  bool_property integerhandle S , "on"
3467  bool_property inverthardcopy , "off"
3468  callback_property keypressfcn , Matrix ()
3469  callback_property keyreleasefcn , Matrix ()
3470  radio_property menubar , "none|{figure}"
3471  double_property mincolormap , 64
3472  string_property name , ""
3473  radio_property nextplot , "new|{add}|replacechildren|replace"
3474  bool_property numbertitle , "on"
3475  array_property outerposition s , Matrix (1, 4, -1.0)
3476  radio_property paperorientation U , "{portrait}|landscape|rotated"
3477  array_property paperposition m , default_figure_paperposition ()
3478  radio_property paperpositionmode au , "auto|{manual}"
3479  array_property papersize U , default_figure_papersize ()
3480  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>"
3481  radio_property paperunits Su , "{inches}|centimeters|normalized|points"
3482  radio_property pointer , "crosshair|fullcrosshair|{arrow}|ibeam|watch|topl|topr|botl|botr|left|top|right|bottom|circle|cross|fleur|custom|hand"
3483  array_property pointershapecdata , Matrix (16, 16, 0)
3484  array_property pointershapehotspot , Matrix (1, 2, 0)
3485  array_property position s , default_figure_position ()
3486  radio_property renderer , "{painters}|zbuffer|opengl|none"
3487  radio_property renderermode , "{auto}|manual"
3488  bool_property resize , "on"
3489  callback_property resizefcn , Matrix ()
3490  radio_property selectiontype , "{normal}|open|alt|extend"
3491  radio_property toolbar , "none|{auto}|figure"
3492  radio_property units Su , "inches|centimeters|normalized|points|{pixels}|characters"
3493  callback_property windowbuttondownfcn , Matrix ()
3494  callback_property windowbuttonmotionfcn , Matrix ()
3495  callback_property windowbuttonupfcn , Matrix ()
3496  callback_property windowkeypressfcn , Matrix ()
3497  callback_property windowkeyreleasefcn , Matrix ()
3498  callback_property windowscrollwheelfcn , Matrix ()
3499  radio_property windowstyle , "{normal}|modal|docked"
3500  string_property wvisual , ""
3501  radio_property wvisualmode , "{auto}|manual"
3502  string_property xdisplay , ""
3503  string_property xvisual , ""
3504  radio_property xvisualmode , "{auto}|manual"
3505  // Octave-specific properties
3506  radio_property __mouse_mode__ hS , "{none}|pan|rotate|select|text|zoom"
3507  any_property __pan_mode__ h , Matrix ()
3508  any_property __rotate_mode__ h , Matrix ()
3509  any_property __zoom_mode__ h , Matrix ()
3510  bool_property __enhanced__ h , "on"
3511  string_property __graphics_toolkit__ hs , gtk_manager::default_toolkit ()
3512  any_property __guidata__ h , Matrix ()
3513  any_property __plot_stream__ h , Matrix ()
3514  END_PROPERTIES
3515 
3516  protected:
3517  void init (void)
3518  {
3519  alphamap.add_constraint (dim_vector (-1, 1));
3520  colormap.add_constraint (dim_vector (-1, 3));
3521  outerposition.add_constraint (dim_vector (1, 4));
3522  paperposition.add_constraint (dim_vector (1, 4));
3523  papersize.add_constraint (dim_vector (1, 2));
3524  pointershapecdata.add_constraint (dim_vector (16, 16));
3525  pointershapehotspot.add_constraint (dim_vector (1, 2));
3526  position.add_constraint (dim_vector (1, 4));
3527  }
3528 
3529  private:
3530  Matrix get_auto_paperposition (void);
3531 
3532  void update_paperpositionmode (void)
3533  {
3534  if (paperpositionmode.is ("auto"))
3535  paperposition.set (get_auto_paperposition ());
3536  }
3537 
3538  mutable graphics_toolkit toolkit;
3539  };
3540 
3541 private:
3542  properties xproperties;
3543 
3544 public:
3545  figure (const graphics_handle& mh, const graphics_handle& p)
3546  : base_graphics_object (), xproperties (mh, p), default_properties ()
3547  { }
3548 
3549  ~figure (void) { }
3550 
3551  void override_defaults (base_graphics_object& obj)
3552  {
3553  // Allow parent (root figure) to override first (properties knows how
3554  // to find the parent object).
3555  xproperties.override_defaults (obj);
3556 
3557  // Now override with our defaults. If the default_properties
3558  // list includes the properties for all defaults (line,
3559  // surface, etc.) then we don't have to know the type of OBJ
3560  // here, we just call its set function and let it decide which
3561  // properties from the list to use.
3562  obj.set_from_list (default_properties);
3563  }
3564 
3565  void set (const caseless_str& name, const octave_value& value)
3566  {
3567  if (name.compare ("default", 7))
3568  // strip "default", pass rest to function that will
3569  // parse the remainder and add the element to the
3570  // default_properties map.
3571  default_properties.set (name.substr (7), value);
3572  else
3573  xproperties.set (name, value);
3574  }
3575 
3576  octave_value get (const caseless_str& name) const
3577  {
3578  octave_value retval;
3579 
3580  if (name.compare ("default", 7))
3581  retval = get_default (name.substr (7));
3582  else
3583  retval = xproperties.get (name);
3584 
3585  return retval;
3586  }
3587 
3588  octave_value get_default (const caseless_str& name) const;
3589 
3590  octave_value get_defaults (void) const
3591  {
3592  return default_properties.as_struct ("default");
3593  }
3594 
3595  property_list get_defaults_list (void) const
3596  {
3597  return default_properties;
3598  }
3599 
3600  base_properties& get_properties (void) { return xproperties; }
3601 
3602  const base_properties& get_properties (void) const { return xproperties; }
3603 
3604  bool valid_object (void) const { return true; }
3605 
3606  void reset_default_properties (void);
3607 
3608  bool has_readonly_property (const caseless_str& pname) const
3609  {
3610  bool retval = xproperties.has_readonly_property (pname);
3611  if (! retval)
3612  retval = base_properties::has_readonly_property (pname);
3613  return retval;
3614  }
3615 
3616 private:
3617  property_list default_properties;
3618 };
3619 
3620 // ---------------------------------------------------------------------
3621 
3622 class OCTINTERP_API graphics_xform
3623 {
3624 public:
3625  graphics_xform (void)
3626  : xform (xform_eye ()), xform_inv (xform_eye ()),
3627  sx ("linear"), sy ("linear"), sz ("linear"), zlim (1, 2, 0.0)
3628  {
3629  zlim(1) = 1.0;
3630  }
3631 
3632  graphics_xform (const Matrix& xm, const Matrix& xim,
3633  const scaler& x, const scaler& y, const scaler& z,
3634  const Matrix& zl)
3635  : xform (xm), xform_inv (xim), sx (x), sy (y), sz (z), zlim (zl) { }
3636 
3637  graphics_xform (const graphics_xform& g)
3638  : xform (g.xform), xform_inv (g.xform_inv), sx (g.sx),
3639  sy (g.sy), sz (g.sz), zlim (g.zlim) { }
3640 
3641  ~graphics_xform (void) { }
3642 
3643  graphics_xform& operator = (const graphics_xform& g)
3644  {
3645  xform = g.xform;
3646  xform_inv = g.xform_inv;
3647  sx = g.sx;
3648  sy = g.sy;
3649  sz = g.sz;
3650  zlim = g.zlim;
3651 
3652  return *this;
3653  }
3654 
3655  static ColumnVector xform_vector (double x, double y, double z);
3656 
3657  static Matrix xform_eye (void);
3658 
3659  ColumnVector transform (double x, double y, double z,
3660  bool use_scale = true) const;
3661 
3662  ColumnVector untransform (double x, double y, double z,
3663  bool use_scale = true) const;
3664 
3665  ColumnVector untransform (double x, double y, bool use_scale = true) const
3666  { return untransform (x, y, (zlim(0)+zlim(1))/2, use_scale); }
3667 
3668  Matrix xscale (const Matrix& m) const { return sx.scale (m); }
3669  Matrix yscale (const Matrix& m) const { return sy.scale (m); }
3670  Matrix zscale (const Matrix& m) const { return sz.scale (m); }
3671 
3672  Matrix scale (const Matrix& m) const
3673  {
3674  bool has_z = (m.columns () > 2);
3675 
3676  if (sx.is_linear () && sy.is_linear ()
3677  && (! has_z || sz.is_linear ()))
3678  return m;
3679 
3680  Matrix retval (m.dims ());
3681 
3682  int r = m.rows ();
3683 
3684  for (int i = 0; i < r; i++)
3685  {
3686  retval(i,0) = sx.scale (m(i,0));
3687  retval(i,1) = sy.scale (m(i,1));
3688  if (has_z)
3689  retval(i,2) = sz.scale (m(i,2));
3690  }
3691 
3692  return retval;
3693  }
3694 
3695 private:
3696  Matrix xform;
3697  Matrix xform_inv;
3698  scaler sx, sy, sz;
3699  Matrix zlim;
3700 };
3701 
3702 enum
3703 {
3704  AXE_ANY_DIR = 0,
3705  AXE_DEPTH_DIR = 1,
3706  AXE_HORZ_DIR = 2,
3707  AXE_VERT_DIR = 3
3708 };
3709 
3710 class OCTINTERP_API axes : public base_graphics_object
3711 {
3712 public:
3713  class OCTINTERP_API properties : public base_properties
3714  {
3715  public:
3716  void set_defaults (base_graphics_object& obj, const std::string& mode);
3717 
3718  void remove_child (const graphics_handle& h);
3719 
3720  const scaler& get_x_scaler (void) const { return sx; }
3721  const scaler& get_y_scaler (void) const { return sy; }
3722  const scaler& get_z_scaler (void) const { return sz; }
3723 
3724  Matrix get_boundingbox (bool internal = false,
3725  const Matrix& parent_pix_size = Matrix ()) const;
3726  Matrix get_extent (bool with_text = false,
3727  bool only_text_height=false) const;
3728 
3729  double get_fontsize_points (double box_pix_height = 0) const;
3730 
3731  void update_boundingbox (void)
3732  {
3733  if (units_is ("normalized"))
3734  {
3735  sync_positions ();
3736  base_properties::update_boundingbox ();
3737  }
3738  }
3739 
3740  void update_camera (void);
3741  void update_axes_layout (void);
3742  void update_aspectratios (void);
3743  void update_transform (void)
3744  {
3745  update_aspectratios ();
3746  update_camera ();
3747  update_axes_layout ();
3748  }
3749 
3750  void sync_positions (void);
3751 
3752  void update_autopos (const std::string& elem_type);
3753  void update_xlabel_position (void);
3754  void update_ylabel_position (void);
3755  void update_zlabel_position (void);
3756  void update_title_position (void);
3757 
3758  graphics_xform get_transform (void) const
3759  { return graphics_xform (x_render, x_render_inv, sx, sy, sz, x_zlim); }
3760 
3761  Matrix get_transform_matrix (void) const { return x_render; }
3762  Matrix get_inverse_transform_matrix (void) const { return x_render_inv; }
3763  Matrix get_opengl_matrix_1 (void) const { return x_gl_mat1; }
3764  Matrix get_opengl_matrix_2 (void) const { return x_gl_mat2; }
3765  Matrix get_transform_zlim (void) const { return x_zlim; }
3766 
3767  int get_xstate (void) const { return xstate; }
3768  int get_ystate (void) const { return ystate; }
3769  int get_zstate (void) const { return zstate; }
3770  double get_xPlane (void) const { return xPlane; }
3771  double get_xPlaneN (void) const { return xPlaneN; }
3772  double get_yPlane (void) const { return yPlane; }
3773  double get_yPlaneN (void) const { return yPlaneN; }
3774  double get_zPlane (void) const { return zPlane; }
3775  double get_zPlaneN (void) const { return zPlaneN; }
3776  double get_xpTick (void) const { return xpTick; }
3777  double get_xpTickN (void) const { return xpTickN; }
3778  double get_ypTick (void) const { return ypTick; }
3779  double get_ypTickN (void) const { return ypTickN; }
3780  double get_zpTick (void) const { return zpTick; }
3781  double get_zpTickN (void) const { return zpTickN; }
3782  double get_x_min (void) const { return std::min (xPlane, xPlaneN); }
3783  double get_x_max (void) const { return std::max (xPlane, xPlaneN); }
3784  double get_y_min (void) const { return std::min (yPlane, yPlaneN); }
3785  double get_y_max (void) const { return std::max (yPlane, yPlaneN); }
3786  double get_z_min (void) const { return std::min (zPlane, zPlaneN); }
3787  double get_z_max (void) const { return std::max (zPlane, zPlaneN); }
3788  double get_fx (void) const { return fx; }
3789  double get_fy (void) const { return fy; }
3790  double get_fz (void) const { return fz; }
3791  double get_xticklen (void) const { return xticklen; }
3792  double get_yticklen (void) const { return yticklen; }
3793  double get_zticklen (void) const { return zticklen; }
3794  double get_xtickoffset (void) const { return xtickoffset; }
3795  double get_ytickoffset (void) const { return ytickoffset; }
3796  double get_ztickoffset (void) const { return ztickoffset; }
3797  bool get_x2Dtop (void) const { return x2Dtop; }
3798  bool get_y2Dright (void) const { return y2Dright; }
3799  bool get_layer2Dtop (void) const { return layer2Dtop; }
3800  bool get_is2D (void) const { return is2D; }
3801  bool get_xySym (void) const { return xySym; }
3802  bool get_xyzSym (void) const { return xyzSym; }
3803  bool get_zSign (void) const { return zSign; }
3804  bool get_nearhoriz (void) const { return nearhoriz; }
3805 
3806  ColumnVector pixel2coord (double px, double py) const
3807  { return get_transform ().untransform (px, py, (x_zlim(0)+x_zlim(1))/2); }
3808 
3809  ColumnVector coord2pixel (double x, double y, double z) const
3810  { return get_transform ().transform (x, y, z); }
3811 
3812  void zoom_about_point (const std::string& mode, double x, double y,
3813  double factor, bool push_to_zoom_stack = true);
3814  void zoom (const std::string& mode, double factor,
3815  bool push_to_zoom_stack = true);
3816  void zoom (const std::string& mode, const Matrix& xl, const Matrix& yl,
3817  bool push_to_zoom_stack = true);
3818 
3819  void translate_view (const std::string& mode,
3820  double x0, double x1, double y0, double y1,
3821  bool push_to_zoom_stack = true);
3822 
3823  void pan (const std::string& mode, double factor,
3824  bool push_to_zoom_stack = true);
3825 
3826  void rotate3d (double x0, double x1, double y0, double y1,
3827  bool push_to_zoom_stack = true);
3828 
3829  void rotate_view (double delta_az, double delta_el,
3830  bool push_to_zoom_stack = true);
3831 
3832  void unzoom (void);
3833  void push_zoom_stack (void);
3834  void clear_zoom_stack (bool do_unzoom = true);
3835 
3836  void update_units (const caseless_str& old_units);
3837 
3838  void update_fontunits (const caseless_str& old_fontunits);
3839 
3840  private:
3841  scaler sx, sy, sz;
3842  Matrix x_render, x_render_inv;
3843  Matrix x_gl_mat1, x_gl_mat2;
3844  Matrix x_zlim;
3845  std::list<octave_value> zoom_stack;
3846 
3847  // Axes layout data
3848  int xstate, ystate, zstate;
3849  double xPlane, xPlaneN, yPlane, yPlaneN, zPlane, zPlaneN;
3850  double xpTick, xpTickN, ypTick, ypTickN, zpTick, zpTickN;
3851  double fx, fy, fz;
3852  double xticklen, yticklen, zticklen;
3853  double xtickoffset, ytickoffset, ztickoffset;
3854  bool x2Dtop, y2Dright, layer2Dtop, is2D;
3855  bool xySym, xyzSym, zSign, nearhoriz;
3856 
3857 #if HAVE_FREETYPE
3858  // FreeType renderer, used for calculation of text (tick labels) size
3859  ft_render text_renderer;
3860 #endif
3861 
3862  void set_text_child (handle_property& h, const std::string& who,
3863  const octave_value& v);
3864 
3865  void delete_text_child (handle_property& h);
3866 
3867  // See the genprops.awk script for an explanation of the
3868  // properties declarations.
3869  // Programming note: Keep property list sorted if new ones are added.
3870 
3871  BEGIN_PROPERTIES (axes)
3872  radio_property activepositionproperty , "{outerposition}|position"
3873  row_vector_property alim m , default_lim ()
3874  radio_property alimmode , "{auto}|manual"
3875  color_property ambientlightcolor , color_values (1, 1, 1)
3876  bool_property box , "on"
3877  array_property cameraposition m , Matrix (1, 3, 0.0)
3878  radio_property camerapositionmode , "{auto}|manual"
3879  array_property cameratarget m , Matrix (1, 3, 0.0)
3880  radio_property cameratargetmode , "{auto}|manual"
3881  array_property cameraupvector m , Matrix (1, 3, 0.0)
3882  radio_property cameraupvectormode , "{auto}|manual"
3883  double_property cameraviewangle m , 10.0
3884  radio_property cameraviewanglemode , "{auto}|manual"
3885  row_vector_property clim m , default_lim ()
3886  radio_property climmode al , "{auto}|manual"
3887  color_property color , color_property (color_values (1, 1, 1), radio_values ("none"))
3888  array_property colororder , default_colororder ()
3889  array_property currentpoint , Matrix (2, 3, 0.0)
3890  array_property dataaspectratio mu , Matrix (1, 3, 1.0)
3891  radio_property dataaspectratiomode u , "{auto}|manual"
3892  radio_property drawmode , "{normal}|fast"
3893  radio_property fontangle u , "{normal}|italic|oblique"
3894  string_property fontname u , OCTAVE_DEFAULT_FONTNAME
3895  double_property fontsize u , 10
3896  radio_property fontunits SU , "{points}|normalized|inches|centimeters|pixels"
3897  radio_property fontweight u , "{normal}|light|demi|bold"
3898  radio_property gridlinestyle , "-|--|{:}|-.|none"
3899  // NOTE: interpreter is not a Matlab axis property, but it makes
3900  // more sense to have it so that axis ticklabels can use it.
3901  radio_property interpreter , "tex|{none}|latex"
3902  radio_property layer u , "{bottom}|top"
3903  // FIXME: should be kind of string array.
3904  any_property linestyleorder S , "-"
3905  double_property linewidth , 0.5
3906  radio_property minorgridlinestyle , "-|--|{:}|-.|none"
3907  double_property mousewheelzoom , 0.5
3908  radio_property nextplot , "add|replacechildren|{replace}"
3909  array_property outerposition u , default_axes_outerposition ()
3910  array_property plotboxaspectratio mu , Matrix (1, 3, 1.0)
3911  radio_property plotboxaspectratiomode u , "{auto}|manual"
3912  array_property position u , default_axes_position ()
3913  radio_property projection , "{orthographic}|perspective"
3914  radio_property tickdir mu , "{in}|out"
3915  radio_property tickdirmode u , "{auto}|manual"
3916  array_property ticklength u , default_axes_ticklength ()
3917  array_property tightinset r , Matrix (1, 4, 0.0)
3918  handle_property title SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
3919  // FIXME: uicontextmenu should be moved here.
3920  radio_property units SU , "{normalized}|inches|centimeters|points|pixels|characters"
3921  array_property view u , default_axes_view ()
3922  radio_property xaxislocation u , "{bottom}|top|zero"
3923  color_property xcolor , color_values (0, 0, 0)
3924  radio_property xdir u , "{normal}|reverse"
3925  bool_property xgrid , "off"
3926  handle_property xlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
3927  row_vector_property xlim mu , default_lim ()
3928  radio_property xlimmode al , "{auto}|manual"
3929  bool_property xminorgrid , "off"
3930  bool_property xminortick , "off"
3931  radio_property xscale alu , "{linear}|log"
3932  row_vector_property xtick mu , default_axes_tick ()
3933  // FIXME: should be kind of string array.
3934  any_property xticklabel S , ""
3935  radio_property xticklabelmode u , "{auto}|manual"
3936  radio_property xtickmode u , "{auto}|manual"
3937  radio_property yaxislocation u , "{left}|right|zero"
3938  color_property ycolor , color_values (0, 0, 0)
3939  radio_property ydir u , "{normal}|reverse"
3940  bool_property ygrid , "off"
3941  handle_property ylabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
3942  row_vector_property ylim mu , default_lim ()
3943  radio_property ylimmode al , "{auto}|manual"
3944  bool_property yminorgrid , "off"
3945  bool_property yminortick , "off"
3946  radio_property yscale alu , "{linear}|log"
3947  row_vector_property ytick mu , default_axes_tick ()
3948  any_property yticklabel S , ""
3949  radio_property yticklabelmode u , "{auto}|manual"
3950  radio_property ytickmode u , "{auto}|manual"
3951  color_property zcolor , color_values (0, 0, 0)
3952  radio_property zdir u , "{normal}|reverse"
3953  bool_property zgrid , "off"
3954  handle_property zlabel SOf , gh_manager::make_graphics_handle ("text", __myhandle__, false, false, false)
3955  row_vector_property zlim mu , default_lim ()
3956  radio_property zlimmode al , "{auto}|manual"
3957  bool_property zminorgrid , "off"
3958  bool_property zminortick , "off"
3959  radio_property zscale alu , "{linear}|log"
3960  row_vector_property ztick mu , default_axes_tick ()
3961  any_property zticklabel S , ""
3962  radio_property zticklabelmode u , "{auto}|manual"
3963  radio_property ztickmode u , "{auto}|manual"
3964  // Octave-specific properties
3965  bool_property __hold_all__ h , "off"
3966  // hidden properties for alignment of subplots
3967  radio_property autopos_tag h , "{none}|subplot"
3968  // hidden properties for inset
3969  array_property looseinset hu , Matrix (1, 4, 0.0)
3970  // hidden properties for transformation computation
3971  array_property x_viewtransform h , Matrix (4, 4, 0.0)
3972  array_property x_projectiontransform h , Matrix (4, 4, 0.0)
3973  array_property x_viewporttransform h , Matrix (4, 4, 0.0)
3974  array_property x_normrendertransform h , Matrix (4, 4, 0.0)
3975  array_property x_rendertransform h , Matrix (4, 4, 0.0)
3976  // hidden properties for minor ticks
3977  row_vector_property xmtick h , Matrix ()
3978  row_vector_property ymtick h , Matrix ()
3979  row_vector_property zmtick h , Matrix ()
3980  // hidden property for text rendering
3981  double_property fontsize_points hgr , 0
3982  END_PROPERTIES
3983 
3984  protected:
3985  void init (void);
3986 
3987  private:
3988 
3989  std::string
3990  get_scale (const std::string& scale, const Matrix& lims)
3991  {
3992  std::string retval = scale;
3993 
3994  if (scale == "log" && lims.numel () > 1 && lims(0) < 0 && lims(1) < 0)
3995  retval = "neglog";
3996 
3997  return retval;
3998  }
3999 
4000  void update_xscale (void)
4001  {
4002  sx = get_scale (get_xscale (), xlim.get ().matrix_value ());
4003  }
4004 
4005  void update_yscale (void)
4006  {
4007  sy = get_scale (get_yscale (), ylim.get ().matrix_value ());
4008  }
4009 
4010  void update_zscale (void)
4011  {
4012  sz = get_scale (get_zscale (), zlim.get ().matrix_value ());
4013  }
4014 
4015  void update_view (void) { sync_positions (); }
4016  void update_dataaspectratio (void) { sync_positions (); }
4017  void update_dataaspectratiomode (void) { sync_positions (); }
4018  void update_plotboxaspectratio (void) { sync_positions (); }
4019  void update_plotboxaspectratiomode (void) { sync_positions (); }
4020 
4021  void update_layer (void) { update_axes_layout (); }
4022  void update_yaxislocation (void)
4023  {
4024  sync_positions ();
4025  update_axes_layout ();
4026  update_ylabel_position ();
4027  }
4028  void update_xaxislocation (void)
4029  {
4030  sync_positions ();
4031  update_axes_layout ();
4032  update_xlabel_position ();
4033  }
4034 
4035  void update_xdir (void) { update_camera (); update_axes_layout (); }
4036  void update_ydir (void) { update_camera (); update_axes_layout (); }
4037  void update_zdir (void) { update_camera (); update_axes_layout (); }
4038 
4039  void update_ticklength (void);
4040  void update_tickdir (void) { update_ticklength (); }
4041  void update_tickdirmode (void) { update_ticklength (); }
4042 
4043  void update_xtick (void)
4044  {
4045  if (xticklabelmode.is ("auto"))
4046  calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
4047  sync_positions ();
4048  }
4049  void update_ytick (void)
4050  {
4051  if (yticklabelmode.is ("auto"))
4052  calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
4053  sync_positions ();
4054  }
4055  void update_ztick (void)
4056  {
4057  if (zticklabelmode.is ("auto"))
4058  calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
4059  sync_positions ();
4060  }
4061 
4062  void update_xtickmode (void)
4063  {
4064  if (xtickmode.is ("auto"))
4065  {
4066  calc_ticks_and_lims (xlim, xtick, xmtick, xlimmode.is ("auto"),
4067  xscale.is ("log"));
4068  update_xtick ();
4069  }
4070  }
4071  void update_ytickmode (void)
4072  {
4073  if (ytickmode.is ("auto"))
4074  {
4075  calc_ticks_and_lims (ylim, ytick, ymtick, ylimmode.is ("auto"),
4076  yscale.is ("log"));
4077  update_ytick ();
4078  }
4079  }
4080  void update_ztickmode (void)
4081  {
4082  if (ztickmode.is ("auto"))
4083  {
4084  calc_ticks_and_lims (zlim, ztick, zmtick, zlimmode.is ("auto"),
4085  zscale.is ("log"));
4086  update_ztick ();
4087  }
4088  }
4089 
4090  void update_xticklabelmode (void)
4091  {
4092  if (xticklabelmode.is ("auto"))
4093  calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
4094  }
4095  void update_yticklabelmode (void)
4096  {
4097  if (yticklabelmode.is ("auto"))
4098  calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
4099  }
4100  void update_zticklabelmode (void)
4101  {
4102  if (zticklabelmode.is ("auto"))
4103  calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
4104  }
4105 
4106  void update_font (void);
4107  void update_fontname (void)
4108  {
4109  update_font ();
4110  sync_positions ();
4111  }
4112  void update_fontsize (void)
4113  {
4114  update_font ();
4115  sync_positions ();
4116  }
4117  void update_fontangle (void)
4118  {
4119  update_font ();
4120  sync_positions ();
4121  }
4122  void update_fontweight (void)
4123  {
4124  update_font ();
4125  sync_positions ();
4126  }
4127 
4128  void update_outerposition (void)
4129  {
4130  set_activepositionproperty ("outerposition");
4131  caseless_str old_units = get_units ();
4132  set_units ("normalized");
4133  Matrix outerbox = outerposition.get ().matrix_value ();
4134  Matrix innerbox = position.get ().matrix_value ();
4135  Matrix linset = looseinset.get ().matrix_value ();
4136  Matrix tinset = tightinset.get ().matrix_value ();
4137  outerbox(2) = outerbox(2) + outerbox(0);
4138  outerbox(3) = outerbox(3) + outerbox(1);
4139  innerbox(0) = outerbox(0) + std::max (linset(0), tinset(0));
4140  innerbox(1) = outerbox(1) + std::max (linset(1), tinset(1));
4141  innerbox(2) = outerbox(2) - std::max (linset(2), tinset(2));
4142  innerbox(3) = outerbox(3) - std::max (linset(3), tinset(3));
4143  innerbox(2) = innerbox(2) - innerbox(0);
4144  innerbox(3) = innerbox(3) - innerbox(1);
4145  position = innerbox;
4146  set_units (old_units);
4147  update_transform ();
4148  }
4149 
4150  void update_position (void)
4151  {
4152  set_activepositionproperty ("position");
4153  caseless_str old_units = get_units ();
4154  set_units ("normalized");
4155  Matrix outerbox = outerposition.get ().matrix_value ();
4156  Matrix innerbox = position.get ().matrix_value ();
4157  Matrix linset = looseinset.get ().matrix_value ();
4158  Matrix tinset = tightinset.get ().matrix_value ();
4159  innerbox(2) = innerbox(2) + innerbox(0);
4160  innerbox(3) = innerbox(3) + innerbox(1);
4161  outerbox(0) = innerbox(0) - std::max (linset(0), tinset(0));
4162  outerbox(1) = innerbox(1) - std::max (linset(1), tinset(1));
4163  outerbox(2) = innerbox(2) + std::max (linset(2), tinset(2));
4164  outerbox(3) = innerbox(3) + std::max (linset(3), tinset(3));
4165  outerbox(2) = outerbox(2) - outerbox(0);
4166  outerbox(3) = outerbox(3) - outerbox(1);
4167  outerposition = outerbox;
4168  set_units (old_units);
4169  update_transform ();
4170  }
4171 
4172  void update_looseinset (void)
4173  {
4174  caseless_str old_units = get_units ();
4175  set_units ("normalized");
4176  Matrix innerbox = position.get ().matrix_value ();
4177  innerbox(2) = innerbox(2) + innerbox(0);
4178  innerbox(3) = innerbox(3) + innerbox(1);
4179  Matrix outerbox = outerposition.get ().matrix_value ();
4180  outerbox(2) = outerbox(2) + outerbox(0);
4181  outerbox(3) = outerbox(3) + outerbox(1);
4182  Matrix linset = looseinset.get ().matrix_value ();
4183  Matrix tinset = tightinset.get ().matrix_value ();
4184  if (activepositionproperty.is ("position"))
4185  {
4186  outerbox(0) = innerbox(0) - std::max (linset(0), tinset(0));
4187  outerbox(1) = innerbox(1) - std::max (linset(1), tinset(1));
4188  outerbox(2) = innerbox(2) + std::max (linset(2), tinset(2));
4189  outerbox(3) = innerbox(3) + std::max (linset(3), tinset(3));
4190  outerbox(2) = outerbox(2) - outerbox(0);
4191  outerbox(3) = outerbox(3) - outerbox(1);
4192  outerposition = outerbox;
4193  }
4194  else
4195  {
4196  innerbox(0) = outerbox(0) + std::max (linset(0), tinset(0));
4197  innerbox(1) = outerbox(1) + std::max (linset(1), tinset(1));
4198  innerbox(2) = outerbox(2) - std::max (linset(2), tinset(2));
4199  innerbox(3) = outerbox(3) - std::max (linset(3), tinset(3));
4200  innerbox(2) = innerbox(2) - innerbox(0);
4201  innerbox(3) = innerbox(3) - innerbox(1);
4202  position = innerbox;
4203  }
4204  set_units (old_units);
4205  update_transform ();
4206  }
4207 
4208  double calc_tick_sep (double minval, double maxval);
4209  void calc_ticks_and_lims (array_property& lims, array_property& ticks,
4210  array_property& mticks,
4211  bool limmode_is_auto, bool is_logscale);
4212  void calc_ticklabels (const array_property& ticks, any_property& labels,
4213  bool is_logscale);
4214  Matrix get_ticklabel_extents (const Matrix& ticks,
4215  const string_vector& ticklabels,
4216  const Matrix& limits);
4217 
4218  void fix_limits (array_property& lims)
4219  {
4220  if (lims.get ().is_empty ())
4221  return;
4222 
4223  Matrix l = lims.get ().matrix_value ();
4224  if (l(0) > l(1))
4225  {
4226  l(0) = 0;
4227  l(1) = 1;
4228  lims = l;
4229  }
4230  else if (l(0) == l(1))
4231  {
4232  l(0) -= 0.5;
4233  l(1) += 0.5;
4234  lims = l;
4235  }
4236  }
4237 
4238  Matrix calc_tightbox (const Matrix& init_pos);
4239 
4240  public:
4241  Matrix get_axis_limits (double xmin, double xmax,
4242  double min_pos, double max_neg,
4243  bool logscale);
4244 
4245  void update_xlim ()
4246  {
4247  if (xtickmode.is ("auto"))
4248  calc_ticks_and_lims (xlim, xtick, xmtick, xlimmode.is ("auto"),
4249  xscale.is ("log"));
4250  if (xticklabelmode.is ("auto"))
4251  calc_ticklabels (xtick, xticklabel, xscale.is ("log"));
4252 
4253  fix_limits (xlim);
4254 
4255  update_xscale ();
4256 
4257  update_axes_layout ();
4258  }
4259 
4260  void update_ylim (void)
4261  {
4262  if (ytickmode.is ("auto"))
4263  calc_ticks_and_lims (ylim, ytick, ymtick, ylimmode.is ("auto"),
4264  yscale.is ("log"));
4265  if (yticklabelmode.is ("auto"))
4266  calc_ticklabels (ytick, yticklabel, yscale.is ("log"));
4267 
4268  fix_limits (ylim);
4269 
4270  update_yscale ();
4271 
4272  update_axes_layout ();
4273  }
4274 
4275  void update_zlim (void)
4276  {
4277  if (ztickmode.is ("auto"))
4278  calc_ticks_and_lims (zlim, ztick, zmtick, zlimmode.is ("auto"),
4279  zscale.is ("log"));
4280  if (zticklabelmode.is ("auto"))
4281  calc_ticklabels (ztick, zticklabel, zscale.is ("log"));
4282 
4283  fix_limits (zlim);
4284 
4285  update_zscale ();
4286 
4287  update_axes_layout ();
4288  }
4289 
4290  };
4291 
4292 private:
4293  properties xproperties;
4294 
4295 public:
4296  axes (const graphics_handle& mh, const graphics_handle& p)
4297  : base_graphics_object (), xproperties (mh, p), default_properties ()
4298  {
4299  xproperties.update_transform ();
4300  }
4301 
4302  ~axes (void) { }
4303 
4304  void override_defaults (base_graphics_object& obj)
4305  {
4306  // Allow parent (figure) to override first (properties knows how
4307  // to find the parent object).
4308  xproperties.override_defaults (obj);
4309 
4310  // Now override with our defaults. If the default_properties
4311  // list includes the properties for all defaults (line,
4312  // surface, etc.) then we don't have to know the type of OBJ
4313  // here, we just call its set function and let it decide which
4314  // properties from the list to use.
4315  obj.set_from_list (default_properties);
4316  }
4317 
4318  void set (const caseless_str& name, const octave_value& value)
4319  {
4320  if (name.compare ("default", 7))
4321  // strip "default", pass rest to function that will
4322  // parse the remainder and add the element to the
4323  // default_properties map.
4324  default_properties.set (name.substr (7), value);
4325  else
4326  xproperties.set (name, value);
4327  }
4328 
4329  void set_defaults (const std::string& mode)
4330  {
4331  xproperties.set_defaults (*this, mode);
4332  }
4333 
4334  octave_value get (const caseless_str& name) const
4335  {
4336  octave_value retval;
4337 
4338  // FIXME: finish this.
4339  if (name.compare ("default", 7))
4340  retval = get_default (name.substr (7));
4341  else
4342  retval = xproperties.get (name);
4343 
4344  return retval;
4345  }
4346 
4347  octave_value get_default (const caseless_str& name) const;
4348 
4349  octave_value get_defaults (void) const
4350  {
4351  return default_properties.as_struct ("default");
4352  }
4353 
4354  property_list get_defaults_list (void) const
4355  {
4356  return default_properties;
4357  }
4358 
4359  base_properties& get_properties (void) { return xproperties; }
4360 
4361  const base_properties& get_properties (void) const { return xproperties; }
4362 
4363  void update_axis_limits (const std::string& axis_type);
4364 
4365  void update_axis_limits (const std::string& axis_type,
4366  const graphics_handle& h);
4367 
4368  bool valid_object (void) const { return true; }
4369 
4370  void reset_default_properties (void);
4371 
4372  bool has_readonly_property (const caseless_str& pname) const
4373  {
4374  bool retval = xproperties.has_readonly_property (pname);
4375  if (! retval)
4376  retval = base_properties::has_readonly_property (pname);
4377  return retval;
4378  }
4379 
4380 protected:
4381  void initialize (const graphics_object& go);
4382 
4383 private:
4384  property_list default_properties;
4385 };
4386 
4387 // ---------------------------------------------------------------------
4388 
4389 class OCTINTERP_API line : public base_graphics_object
4390 {
4391 public:
4392  class OCTINTERP_API properties : public base_properties
4393  {
4394  public:
4395  // See the genprops.awk script for an explanation of the
4396  // properties declarations.
4397  // Programming note: Keep property list sorted if new ones are added.
4398 
4399  BEGIN_PROPERTIES (line)
4400  color_property color , color_values (0, 0, 0)
4401  string_property displayname , ""
4402  radio_property erasemode , "{normal}|none|xor|background"
4403  // FIXME: interpreter is not a property of Matlab line objects.
4404  // Octave uses this for legend() with the string displayname.
4405  radio_property interpreter , "{tex}|none|latex"
4406  radio_property linestyle , "{-}|--|:|-.|none"
4407  double_property linewidth , 0.5
4408  radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram"
4409  color_property markeredgecolor , color_property (radio_values ("{auto}|none"), color_values (0, 0, 0))
4410  color_property markerfacecolor , color_property (radio_values ("auto|{none}"), color_values (0, 0, 0))
4411  double_property markersize , 6
4412  row_vector_property xdata u , default_data ()
4413  string_property xdatasource , ""
4414  row_vector_property ydata u , default_data ()
4415  string_property ydatasource , ""
4416  row_vector_property zdata u , Matrix ()
4417  string_property zdatasource , ""
4418 
4419  // hidden properties for limit computation
4420  row_vector_property xlim hlr , Matrix ()
4421  row_vector_property ylim hlr , Matrix ()
4422  row_vector_property zlim hlr , Matrix ()
4423  bool_property xliminclude hl , "on"
4424  bool_property yliminclude hl , "on"
4425  bool_property zliminclude hl , "off"
4426  END_PROPERTIES
4427 
4428  private:
4429  Matrix compute_xlim (void) const;
4430  Matrix compute_ylim (void) const;
4431 
4432  void update_xdata (void) { set_xlim (compute_xlim ()); }
4433 
4434  void update_ydata (void) { set_ylim (compute_ylim ()); }
4435 
4436  void update_zdata (void)
4437  {
4438  set_zlim (zdata.get_limits ());
4439  set_zliminclude (get_zdata ().numel () > 0);
4440  }
4441  };
4442 
4443 private:
4444  properties xproperties;
4445 
4446 public:
4447  line (const graphics_handle& mh, const graphics_handle& p)
4448  : base_graphics_object (), xproperties (mh, p)
4449  { }
4450 
4451  ~line (void) { }
4452 
4453  base_properties& get_properties (void) { return xproperties; }
4454 
4455  const base_properties& get_properties (void) const { return xproperties; }
4456 
4457  bool valid_object (void) const { return true; }
4458 
4459  bool has_readonly_property (const caseless_str& pname) const
4460  {
4461  bool retval = xproperties.has_readonly_property (pname);
4462  if (! retval)
4463  retval = base_properties::has_readonly_property (pname);
4464  return retval;
4465  }
4466 };
4467 
4468 // ---------------------------------------------------------------------
4469 
4470 class OCTINTERP_API text : public base_graphics_object
4471 {
4472 public:
4473  class OCTINTERP_API properties : public base_properties
4474  {
4475  public:
4476  double get_fontsize_points (double box_pix_height = 0) const;
4477 
4478  void set_position (const octave_value& val)
4479  {
4480  if (! error_state)
4481  {
4482  octave_value new_val (val);
4483 
4484  if (new_val.numel () == 2)
4485  {
4486  dim_vector dv (1, 3);
4487 
4488  new_val = new_val.resize (dv, true);
4489  }
4490 
4491  if (position.set (new_val, false))
4492  {
4493  set_positionmode ("manual");
4494  update_position ();
4495  position.run_listeners (POSTSET);
4496  mark_modified ();
4497  }
4498  else
4499  set_positionmode ("manual");
4500  }
4501  }
4502 
4503  // See the genprops.awk script for an explanation of the
4504  // properties declarations.
4505 
4506  BEGIN_PROPERTIES (text)
4507  color_property backgroundcolor , color_property (radio_values ("{none}"), color_values (1, 1, 1))
4508  color_property color u , color_values (0, 0, 0)
4509  string_property displayname , ""
4510  color_property edgecolor , color_property (radio_values ("{none}"), color_values (0, 0, 0))
4511  bool_property editing , "off"
4512  radio_property erasemode , "{normal}|none|xor|background"
4513  array_property extent rG , Matrix (1, 4, 0.0)
4514  radio_property fontangle u , "{normal}|italic|oblique"
4515  string_property fontname u , OCTAVE_DEFAULT_FONTNAME
4516  double_property fontsize u , 10
4517  radio_property fontunits SU , "inches|centimeters|normalized|{points}|pixels"
4518  radio_property fontweight u , "light|{normal}|demi|bold"
4519  radio_property horizontalalignment mu , "{left}|center|right"
4520  radio_property interpreter u , "{tex}|none|latex"
4521  radio_property linestyle , "{-}|--|:|-.|none"
4522  double_property linewidth , 0.5
4523  double_property margin , 2
4524  array_property position smu , Matrix (1, 3, 0.0)
4525  double_property rotation mu , 0
4526  text_label_property string u , ""
4527  radio_property units u , "{data}|pixels|normalized|inches|centimeters|points"
4528  radio_property verticalalignment mu , "top|cap|{middle}|baseline|bottom"
4529 
4530  // hidden properties for limit computation
4531  row_vector_property xlim hlr , Matrix ()
4532  row_vector_property ylim hlr , Matrix ()
4533  row_vector_property zlim hlr , Matrix ()
4534  bool_property xliminclude hl , "off"
4535  bool_property yliminclude hl , "off"
4536  bool_property zliminclude hl , "off"
4537  // hidden properties for auto-positioning
4538  radio_property positionmode hu , "{auto}|manual"
4539  radio_property rotationmode hu , "{auto}|manual"
4540  radio_property horizontalalignmentmode hu , "{auto}|manual"
4541  radio_property verticalalignmentmode hu , "{auto}|manual"
4542  radio_property autopos_tag h , "{none}|xlabel|ylabel|zlabel|title"
4543  // hidden property for text rendering
4544  double_property fontsize_points hgr , 0
4545  END_PROPERTIES
4546 
4547  Matrix get_data_position (void) const;
4548  Matrix get_extent_matrix (void) const;
4549  const uint8NDArray& get_pixels (void) const { return pixels; }
4550 #if HAVE_FREETYPE
4551  // FreeType renderer, used for calculation of text size
4552  ft_render renderer;
4553 #endif
4554 
4555  protected:
4556  void init (void)
4557  {
4558  position.add_constraint (dim_vector (1, 3));
4559  cached_units = get_units ();
4560  update_font ();
4561  }
4562 
4563  private:
4564  void update_position (void)
4565  {
4566  Matrix pos = get_data_position ();
4567  Matrix lim;
4568 
4569  lim = Matrix (1, 3, pos(0));
4570  lim(2) = (lim(2) <= 0 ? octave_Inf : lim(2));
4571  set_xlim (lim);
4572 
4573  lim = Matrix (1, 3, pos(1));
4574  lim(2) = (lim(2) <= 0 ? octave_Inf : lim(2));
4575  set_ylim (lim);
4576 
4577  if (pos.numel () == 3)
4578  {
4579  lim = Matrix (1, 3, pos(2));
4580  lim(2) = (lim(2) <= 0 ? octave_Inf : lim(2));
4581  set_zliminclude ("on");
4582  set_zlim (lim);
4583  }
4584  else
4585  set_zliminclude ("off");
4586  }
4587 
4588  void update_text_extent (void);
4589 
4590  void request_autopos (void);
4591  void update_positionmode (void) { request_autopos (); }
4592  void update_rotationmode (void) { request_autopos (); }
4593  void update_horizontalalignmentmode (void) { request_autopos (); }
4594  void update_verticalalignmentmode (void) { request_autopos (); }
4595 
4596  void update_font (void);
4597  void update_string (void) { request_autopos (); update_text_extent (); }
4598  void update_rotation (void) { update_text_extent (); }
4599  void update_color (void) { update_font (); update_text_extent (); }
4600  void update_fontname (void) { update_font (); update_text_extent (); }
4601  void update_fontsize (void) { update_font (); update_text_extent (); }
4602  void update_fontangle (void) { update_font (); update_text_extent (); }
4603  void update_fontweight (void) { update_font (); update_text_extent (); }
4604  void update_interpreter (void) { update_text_extent (); }
4605  void update_horizontalalignment (void) { update_text_extent (); }
4606  void update_verticalalignment (void) { update_text_extent (); }
4607 
4608  void update_units (void);
4609  void update_fontunits (const caseless_str& old_fontunits);
4610 
4611  private:
4612  std::string cached_units;
4613  uint8NDArray pixels;
4614  };
4615 
4616 private:
4617  properties xproperties;
4618 
4619 public:
4620  text (const graphics_handle& mh, const graphics_handle& p)
4621  : base_graphics_object (), xproperties (mh, p)
4622  {
4623  xproperties.set_clipping ("off");
4624  }
4625 
4626  ~text (void) { }
4627 
4628  base_properties& get_properties (void) { return xproperties; }
4629 
4630  const base_properties& get_properties (void) const { return xproperties; }
4631 
4632  bool valid_object (void) const { return true; }
4633 
4634  bool has_readonly_property (const caseless_str& pname) const
4635  {
4636  bool retval = xproperties.has_readonly_property (pname);
4637  if (! retval)
4638  retval = base_properties::has_readonly_property (pname);
4639  return retval;
4640  }
4641 };
4642 
4643 // ---------------------------------------------------------------------
4644 
4645 class OCTINTERP_API image : public base_graphics_object
4646 {
4647 public:
4648  class OCTINTERP_API properties : public base_properties
4649  {
4650  public:
4651  bool is_aliminclude (void) const
4652  { return (aliminclude.is_on () && alphadatamapping.is ("scaled")); }
4653  std::string get_aliminclude (void) const
4654  { return aliminclude.current_value (); }
4655 
4656  bool is_climinclude (void) const
4657  { return (climinclude.is_on () && cdatamapping.is ("scaled")); }
4658  std::string get_climinclude (void) const
4659  { return climinclude.current_value (); }
4660 
4661  octave_value get_color_data (void) const;
4662 
4663  void initialize_data (void) { update_cdata (); }
4664 
4665  // See the genprops.awk script for an explanation of the
4666  // properties declarations.
4667  // Programming note: Keep property list sorted if new ones are added.
4668 
4669  BEGIN_PROPERTIES (image)
4670  array_property alphadata u , Matrix (1, 1, 1.0)
4671  radio_property alphadatamapping al , "{none}|direct|scaled"
4672  array_property cdata u , default_image_cdata ()
4673  radio_property cdatamapping al , "scaled|{direct}"
4674  string_property displayname , ""
4675  radio_property erasemode , "{normal}|none|xor|background"
4676  row_vector_property xdata mu , Matrix ()
4677  row_vector_property ydata mu , Matrix ()
4678  // hidden properties for limit computation
4679  row_vector_property alim hlr , Matrix ()
4680  row_vector_property clim hlr , Matrix ()
4681  row_vector_property xlim hlr , Matrix ()
4682  row_vector_property ylim hlr , Matrix ()
4683  bool_property aliminclude hlg , "on"
4684  bool_property climinclude hlg , "on"
4685  bool_property xliminclude hl , "on"
4686  bool_property yliminclude hl , "on"
4687  radio_property xdatamode ha , "{auto}|manual"
4688  radio_property ydatamode ha , "{auto}|manual"
4689  END_PROPERTIES
4690 
4691  protected:
4692  void init (void)
4693  {
4694  xdata.add_constraint (2);
4695  ydata.add_constraint (2);
4696  cdata.add_constraint ("double");
4697  cdata.add_constraint ("single");
4698  cdata.add_constraint ("logical");
4699  cdata.add_constraint ("uint8");
4700  cdata.add_constraint ("uint16");
4701  cdata.add_constraint ("int16");
4702  cdata.add_constraint ("real");
4703  cdata.add_constraint (dim_vector (-1, -1));
4704  cdata.add_constraint (dim_vector (-1, -1, 3));
4705  alphadata.add_constraint (dim_vector (-1, -1));
4706  alphadata.add_constraint ("double");
4707  alphadata.add_constraint ("uint8");
4708  }
4709 
4710  private:
4711  void update_alphadata (void)
4712  {
4713  if (alphadatamapping_is ("scaled"))
4714  set_alim (alphadata.get_limits ());
4715  else
4716  alim = alphadata.get_limits ();
4717  }
4718 
4719  void update_cdata (void)
4720  {
4721  if (cdatamapping_is ("scaled"))
4722  set_clim (cdata.get_limits ());
4723  else
4724  clim = cdata.get_limits ();
4725 
4726  if (xdatamode.is ("auto"))
4727  update_xdata ();
4728 
4729  if (ydatamode.is ("auto"))
4730  update_ydata ();
4731  }
4732 
4733  void update_xdata (void)
4734  {
4735  if (xdata.get ().is_empty ())
4736  set_xdatamode ("auto");
4737 
4738  if (xdatamode.is ("auto"))
4739  {
4740  set_xdata (get_auto_xdata ());
4741  set_xdatamode ("auto");
4742  }
4743 
4744  Matrix limits = xdata.get_limits ();
4745  float dp = pixel_xsize ();
4746 
4747  limits(0) = limits(0) - dp;
4748  limits(1) = limits(1) + dp;
4749  set_xlim (limits);
4750  }
4751 
4752  void update_ydata (void)
4753  {
4754  if (ydata.get ().is_empty ())
4755  set_ydatamode ("auto");
4756 
4757  if (ydatamode.is ("auto"))
4758  {
4759  set_ydata (get_auto_ydata ());
4760  set_ydatamode ("auto");
4761  }
4762 
4763  Matrix limits = ydata.get_limits ();
4764  float dp = pixel_ysize ();
4765 
4766  limits(0) = limits(0) - dp;
4767  limits(1) = limits(1) + dp;
4768  set_ylim (limits);
4769  }
4770 
4771  Matrix get_auto_xdata (void)
4772  {
4773  dim_vector dv = get_cdata ().dims ();
4774  Matrix data;
4775  if (dv(1) > 0.)
4776  {
4777  data = Matrix (1, 2, 1);
4778  data(1) = dv(1);
4779  }
4780  return data;
4781  }
4782 
4783  Matrix get_auto_ydata (void)
4784  {
4785  dim_vector dv = get_cdata ().dims ();
4786  Matrix data;
4787  if (dv(0) > 0.)
4788  {
4789  data = Matrix (1, 2, 1);
4790  data(1) = dv(0);
4791  }
4792  return data;
4793  }
4794 
4795  float pixel_size (octave_idx_type dim, const Matrix limits)
4796  {
4797  octave_idx_type l = dim - 1;
4798  float dp;
4799 
4800  if (l > 0 && limits(0) != limits(1))
4801  dp = (limits(1) - limits(0))/(2*l);
4802  else
4803  {
4804  if (limits(1) == limits(2))
4805  dp = 0.5;
4806  else
4807  dp = (limits(1) - limits(0))/2;
4808  }
4809  return dp;
4810  }
4811 
4812  public:
4813  float pixel_xsize (void)
4814  {
4815  return pixel_size ((get_cdata ().dims ())(1), xdata.get_limits ());
4816  }
4817 
4818  float pixel_ysize (void)
4819  {
4820  return pixel_size ((get_cdata ().dims ())(0), ydata.get_limits ());
4821  }
4822  };
4823 
4824 private:
4825  properties xproperties;
4826 
4827 public:
4828  image (const graphics_handle& mh, const graphics_handle& p)
4829  : base_graphics_object (), xproperties (mh, p)
4830  {
4831  xproperties.initialize_data ();
4832  }
4833 
4834  ~image (void) { }
4835 
4836  base_properties& get_properties (void) { return xproperties; }
4837 
4838  const base_properties& get_properties (void) const { return xproperties; }
4839 
4840  bool valid_object (void) const { return true; }
4841 
4842  bool has_readonly_property (const caseless_str& pname) const
4843  {
4844  bool retval = xproperties.has_readonly_property (pname);
4845  if (! retval)
4846  retval = base_properties::has_readonly_property (pname);
4847  return retval;
4848  }
4849 };
4850 
4851 // ---------------------------------------------------------------------
4852 
4853 class OCTINTERP_API patch : public base_graphics_object
4854 {
4855 public:
4856  class OCTINTERP_API properties : public base_properties
4857  {
4858  public:
4859  octave_value get_color_data (void) const;
4860 
4861  // Matlab allows incoherent data to be stored into patch properties.
4862  // The patch should then be ignored by the renderer.
4863  bool has_bad_data (std::string &msg) const
4864  {
4865  msg = bad_data_msg;
4866  return ! msg.empty ();
4867  }
4868 
4869  bool is_aliminclude (void) const
4870  { return (aliminclude.is_on () && alphadatamapping.is ("scaled")); }
4871  std::string get_aliminclude (void) const
4872  { return aliminclude.current_value (); }
4873 
4874  bool is_climinclude (void) const
4875  { return (climinclude.is_on () && cdatamapping.is ("scaled")); }
4876  std::string get_climinclude (void) const
4877  { return climinclude.current_value (); }
4878 
4879  // See the genprops.awk script for an explanation of the
4880  // properties declarations.
4881  // Programming note: Keep property list sorted if new ones are added.
4882 
4883  BEGIN_PROPERTIES (patch)
4884  radio_property alphadatamapping l , "none|{scaled}|direct"
4885  double_property ambientstrength , 0.3
4886  radio_property backfacelighting , "unlit|lit|{reverselit}"
4887  array_property cdata u , Matrix ()
4888  radio_property cdatamapping l , "{scaled}|direct"
4889  double_property diffusestrength , 0.6
4890  string_property displayname , ""
4891  double_radio_property edgealpha , double_radio_property (1.0, radio_values ("flat|interp"))
4892  color_property edgecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
4893  radio_property edgelighting , "{none}|flat|gouraud|phong"
4894  radio_property erasemode , "{normal}|background|xor|none"
4895  double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp"))
4896  color_property facecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
4897  radio_property facelighting , "{none}|flat|gouraud|phong"
4898  array_property faces u , default_patch_faces ()
4899  array_property facevertexalphadata , Matrix ()
4900  array_property facevertexcdata u , Matrix ()
4901  // FIXME: interpreter is not a property of a Matlab patch.
4902  // Octave uses this for legend() with the string displayname.
4903  radio_property interpreter , "{tex}|none|latex"
4904  radio_property linestyle , "{-}|--|:|-.|none"
4905  double_property linewidth , 0.5
4906  radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram"
4907  color_property markeredgecolor , color_property (radio_values ("none|{auto}|flat"), color_values (0, 0, 0))
4908  color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0))
4909  double_property markersize , 6
4910  radio_property normalmode , "{auto}|manual"
4911  double_property specularcolorreflectance , 1.0
4912  double_property specularexponent , 10.0
4913  double_property specularstrength , 0.9
4914  array_property vertexnormals , Matrix ()
4915  array_property vertices u , default_patch_vertices ()
4916  array_property xdata u , default_patch_xdata ()
4917  array_property ydata u , default_patch_ydata ()
4918  array_property zdata u , Matrix ()
4919 
4920  // hidden properties for limit computation
4921  row_vector_property alim hlr , Matrix ()
4922  row_vector_property clim hlr , Matrix ()
4923  row_vector_property xlim hlr , Matrix ()
4924  row_vector_property ylim hlr , Matrix ()
4925  row_vector_property zlim hlr , Matrix ()
4926  bool_property aliminclude hlg , "on"
4927  bool_property climinclude hlg , "on"
4928  bool_property xliminclude hl , "on"
4929  bool_property yliminclude hl , "on"
4930  bool_property zliminclude hl , "on"
4931  END_PROPERTIES
4932 
4933  protected:
4934  void init (void)
4935  {
4936  xdata.add_constraint (dim_vector (-1, -1));
4937  ydata.add_constraint (dim_vector (-1, -1));
4938  zdata.add_constraint (dim_vector (-1, -1));
4939  faces.add_constraint (dim_vector (-1, -1));
4940  vertices.add_constraint (dim_vector (-1, 2));
4941  vertices.add_constraint (dim_vector (-1, 3));
4942  cdata.add_constraint (dim_vector (-1, -1));
4943  cdata.add_constraint (dim_vector (-1, -1, 3));
4944  facevertexcdata.add_constraint (dim_vector (-1, 1));
4945  facevertexcdata.add_constraint (dim_vector (-1, 3));
4946  facevertexalphadata.add_constraint (dim_vector (-1, 1));
4947  vertexnormals.add_constraint (dim_vector (-1, -1));
4948  }
4949 
4950  private:
4951  std::string bad_data_msg;
4952 
4953  void update_faces (void) { update_data ();}
4954 
4955  void update_vertices (void) { update_data ();}
4956 
4957  void update_facevertexcdata (void) { update_data ();}
4958 
4959  void update_fvc (void);
4960 
4961  void update_xdata (void)
4962  {
4963  if (get_xdata ().is_empty ())
4964  {
4965  // For compatibility with matlab behavior,
4966  // if x/ydata are set empty, silently empty other *data and
4967  // faces properties while vertices remain unchanged.
4968  set_ydata (Matrix ());
4969  set_zdata (Matrix ());
4970  set_cdata (Matrix ());
4971  set_faces (Matrix ());
4972  }
4973  else
4974  update_fvc ();
4975 
4976  set_xlim (xdata.get_limits ());
4977  }
4978 
4979  void update_ydata (void)
4980  {
4981  if (get_ydata ().is_empty ())
4982  {
4983  set_xdata (Matrix ());
4984  set_zdata (Matrix ());
4985  set_cdata (Matrix ());
4986  set_faces (Matrix ());
4987  }
4988  else
4989  update_fvc ();
4990 
4991  set_ylim (ydata.get_limits ());
4992  }
4993 
4994  void update_zdata (void)
4995  {
4996  update_fvc ();
4997  set_zlim (zdata.get_limits ());
4998  }
4999 
5000  void update_cdata (void)
5001  {
5002  update_fvc ();
5003 
5004  if (cdatamapping_is ("scaled"))
5005  set_clim (cdata.get_limits ());
5006  else
5007  clim = cdata.get_limits ();
5008  }
5009 
5010 
5011  void update_data (void);
5012  };
5013 
5014 private:
5015  properties xproperties;
5016 
5017 public:
5018  patch (const graphics_handle& mh, const graphics_handle& p)
5019  : base_graphics_object (), xproperties (mh, p)
5020  { }
5021 
5022  ~patch (void) { }
5023 
5024  base_properties& get_properties (void) { return xproperties; }
5025 
5026  const base_properties& get_properties (void) const { return xproperties; }
5027 
5028  bool valid_object (void) const { return true; }
5029 
5030  bool has_readonly_property (const caseless_str& pname) const
5031  {
5032  bool retval = xproperties.has_readonly_property (pname);
5033  if (! retval)
5034  retval = base_properties::has_readonly_property (pname);
5035  return retval;
5036  }
5037 };
5038 
5039 // ---------------------------------------------------------------------
5040 
5041 class OCTINTERP_API surface : public base_graphics_object
5042 {
5043 public:
5044  class OCTINTERP_API properties : public base_properties
5045  {
5046  public:
5047  octave_value get_color_data (void) const;
5048 
5049  bool is_aliminclude (void) const
5050  { return (aliminclude.is_on () && alphadatamapping.is ("scaled")); }
5051  std::string get_aliminclude (void) const
5052  { return aliminclude.current_value (); }
5053 
5054  bool is_climinclude (void) const
5055  { return (climinclude.is_on () && cdatamapping.is ("scaled")); }
5056  std::string get_climinclude (void) const
5057  { return climinclude.current_value (); }
5058 
5059  // See the genprops.awk script for an explanation of the
5060  // properties declarations.
5061  // Programming note: Keep property list sorted if new ones are added.
5062 
5063  BEGIN_PROPERTIES (surface)
5064  array_property alphadata u , Matrix (1, 1, 1.0)
5065  radio_property alphadatamapping l , "none|direct|{scaled}"
5066  double_property ambientstrength , 0.3
5067  radio_property backfacelighting , "unlit|lit|{reverselit}"
5068  array_property cdata u , default_surface_cdata ()
5069  radio_property cdatamapping al , "{scaled}|direct"
5070  string_property cdatasource , ""
5071  double_property diffusestrength , 0.6
5072  string_property displayname , ""
5073  double_radio_property edgealpha , double_radio_property (1.0, radio_values ("flat|interp"))
5074  color_property edgecolor , color_property (color_values (0, 0, 0), radio_values ("none|flat|interp"))
5075  radio_property edgelighting , "{none}|flat|gouraud|phong"
5076  radio_property erasemode , "{normal}|none|xor|background"
5077  double_radio_property facealpha , double_radio_property (1.0, radio_values ("flat|interp|texturemap"))
5078  color_property facecolor , color_property (radio_values ("none|{flat}|interp|texturemap"), color_values (0, 0, 0))
5079  radio_property facelighting , "{none}|flat|gouraud|phong"
5080  // FIXME: interpreter is not a Matlab surface property
5081  // Octave uses this for legend() with the string displayname.
5082  radio_property interpreter , "{tex}|none|latex"
5083  radio_property linestyle , "{-}|--|:|-.|none"
5084  double_property linewidth , 0.5
5085  radio_property marker , "{none}|+|o|*|.|x|s|square|d|diamond|^|v|>|<|p|pentagram|h|hexagram"
5086  color_property markeredgecolor , color_property (radio_values ("none|{auto}|flat"), color_values (0, 0, 0))
5087  color_property markerfacecolor , color_property (radio_values ("{none}|auto|flat"), color_values (0, 0, 0))
5088  double_property markersize , 6
5089  radio_property meshstyle , "{both}|row|column"
5090  radio_property normalmode u , "{auto}|manual"
5091  double_property specularcolorreflectance , 1
5092  double_property specularexponent , 10
5093  double_property specularstrength , 0.9
5094  array_property vertexnormals u , Matrix ()
5095  array_property xdata u , default_surface_xdata ()
5096  string_property xdatasource , ""
5097  array_property ydata u , default_surface_ydata ()
5098  string_property ydatasource , ""
5099  array_property zdata u , default_surface_zdata ()
5100  string_property zdatasource , ""
5101 
5102  // hidden properties for limit computation
5103  row_vector_property alim hlr , Matrix ()
5104  row_vector_property clim hlr , Matrix ()
5105  row_vector_property xlim hlr , Matrix ()
5106  row_vector_property ylim hlr , Matrix ()
5107  row_vector_property zlim hlr , Matrix ()
5108  bool_property aliminclude hlg , "on"
5109  bool_property climinclude hlg , "on"
5110  bool_property xliminclude hl , "on"
5111  bool_property yliminclude hl , "on"
5112  bool_property zliminclude hl , "on"
5113  END_PROPERTIES
5114 
5115  protected:
5116  void init (void)
5117  {
5118  xdata.add_constraint (dim_vector (-1, -1));
5119  ydata.add_constraint (dim_vector (-1, -1));
5120  zdata.add_constraint (dim_vector (-1, -1));
5121  cdata.add_constraint ("double");
5122  cdata.add_constraint ("single");
5123  cdata.add_constraint (dim_vector (-1, -1));
5124  cdata.add_constraint (dim_vector (-1, -1, 3));
5125  alphadata.add_constraint ("double");
5126  alphadata.add_constraint ("uint8");
5127  alphadata.add_constraint (dim_vector (-1, -1));
5128  vertexnormals.add_constraint (dim_vector (-1, -1, 3));
5129  vertexnormals.add_constraint (dim_vector (0, 0));
5130  }
5131 
5132  private:
5133  void update_alphadata (void)
5134  {
5135  if (alphadatamapping_is ("scaled"))
5136  set_alim (alphadata.get_limits ());
5137  else
5138  alim = alphadata.get_limits ();
5139  }
5140 
5141  void update_cdata (void)
5142  {
5143  if (cdatamapping_is ("scaled"))
5144  set_clim (cdata.get_limits ());
5145  else
5146  clim = cdata.get_limits ();
5147  }
5148 
5149  void update_xdata (void)
5150  {
5151  update_normals ();
5152  set_xlim (xdata.get_limits ());
5153  }
5154 
5155  void update_ydata (void)
5156  {
5157  update_normals ();
5158  set_ylim (ydata.get_limits ());
5159  }
5160 
5161  void update_zdata (void)
5162  {
5163  update_normals ();
5164  set_zlim (zdata.get_limits ());
5165  }
5166 
5167  void update_normals (void);
5168 
5169  void update_normalmode (void)
5170  { update_normals (); }
5171 
5172  void update_vertexnormals (void)
5173  { set_normalmode ("manual"); }
5174  };
5175 
5176 private:
5177  properties xproperties;
5178 
5179 public:
5180  surface (const graphics_handle& mh, const graphics_handle& p)
5181  : base_graphics_object (), xproperties (mh, p)
5182  { }
5183 
5184  ~surface (void) { }
5185 
5186  base_properties& get_properties (void) { return xproperties; }
5187 
5188  const base_properties& get_properties (void) const { return xproperties; }
5189 
5190  bool valid_object (void) const { return true; }
5191 
5192  bool has_readonly_property (const caseless_str& pname) const
5193  {
5194  bool retval = xproperties.has_readonly_property (pname);
5195  if (! retval)
5196  retval = base_properties::has_readonly_property (pname);
5197  return retval;
5198  }
5199 };
5200 
5201 // ---------------------------------------------------------------------
5202 
5203 class OCTINTERP_API hggroup : public base_graphics_object
5204 {
5205 public:
5206  class OCTINTERP_API properties : public base_properties
5207  {
5208  public:
5209  void remove_child (const graphics_handle& h)
5210  {
5211  base_properties::remove_child (h);
5212  update_limits ();
5213  }
5214 
5215  void adopt (const graphics_handle& h)
5216  {
5217 
5218  base_properties::adopt (h);
5219  update_limits (h);
5220  }
5221 
5222  // See the genprops.awk script for an explanation of the
5223  // properties declarations.
5224  // Programming note: Keep property list sorted if new ones are added.
5225 
5226  BEGIN_PROPERTIES (hggroup)
5227  string_property displayname , ""
5228  radio_property erasemode , "{normal}|none|xor|background"
5229 
5230  // hidden properties for limit computation
5231  row_vector_property alim hr , Matrix ()
5232  row_vector_property clim hr , Matrix ()
5233  row_vector_property xlim hr , Matrix ()
5234  row_vector_property ylim hr , Matrix ()
5235  row_vector_property zlim hr , Matrix ()
5236  bool_property aliminclude h , "on"
5237  bool_property climinclude h , "on"
5238  bool_property xliminclude h , "on"
5239  bool_property yliminclude h , "on"
5240  bool_property zliminclude h , "on"
5241  END_PROPERTIES
5242 
5243  private:
5244  void update_limits (void) const;
5245 
5246  void update_limits (const graphics_handle& h) const;
5247 
5248  protected:
5249  void init (void)
5250  { }
5251 
5252  };
5253 
5254 private:
5255  properties xproperties;
5256 
5257 public:
5258  hggroup (const graphics_handle& mh, const graphics_handle& p)
5259  : base_graphics_object (), xproperties (mh, p)
5260  { }
5261 
5262  ~hggroup (void) { }
5263 
5264  base_properties& get_properties (void) { return xproperties; }
5265 
5266  const base_properties& get_properties (void) const { return xproperties; }
5267 
5268  bool valid_object (void) const { return true; }
5269 
5270  void update_axis_limits (const std::string& axis_type);
5271 
5272  void update_axis_limits (const std::string& axis_type,
5273  const graphics_handle& h);
5274 
5275  bool has_readonly_property (const caseless_str& pname) const
5276  {
5277  bool retval = xproperties.has_readonly_property (pname);
5278  if (! retval)
5279  retval = base_properties::has_readonly_property (pname);
5280  return retval;
5281  }
5282 
5283 };
5284 
5285 // ---------------------------------------------------------------------
5286 
5287 class OCTINTERP_API uimenu : public base_graphics_object
5288 {
5289 public:
5290  class OCTINTERP_API properties : public base_properties
5291  {
5292  public:
5293  void remove_child (const graphics_handle& h)
5294  {
5295  base_properties::remove_child (h);
5296  }
5297 
5298  void adopt (const graphics_handle& h)
5299  {
5300  base_properties::adopt (h);
5301  }
5302 
5303  // See the genprops.awk script for an explanation of the
5304  // properties declarations.
5305  // Programming note: Keep property list sorted if new ones are added.
5306 
5307  BEGIN_PROPERTIES (uimenu)
5308  any_property __object__ , Matrix ()
5309  string_property accelerator , ""
5310  callback_property callback , Matrix ()
5311  bool_property checked , "off"
5312  bool_property enable , "on"
5313  color_property foregroundcolor , color_values (0, 0, 0)
5314  string_property label , ""
5315  double_property position , 0
5316  bool_property separator , "off"
5317  // Octave-specific properties
5318  string_property fltk_label h , ""
5319  END_PROPERTIES
5320 
5321  protected:
5322  void init (void)
5323  { }
5324  };
5325 
5326 private:
5327  properties xproperties;
5328 
5329 public:
5330  uimenu (const graphics_handle& mh, const graphics_handle& p)
5331  : base_graphics_object (), xproperties (mh, p)
5332  { }
5333 
5334  ~uimenu (void) { }
5335 
5336  base_properties& get_properties (void) { return xproperties; }
5337 
5338  const base_properties& get_properties (void) const { return xproperties; }
5339 
5340  bool valid_object (void) const { return true; }
5341 
5342  bool has_readonly_property (const caseless_str& pname) const
5343  {
5344  bool retval = xproperties.has_readonly_property (pname);
5345  if (! retval)
5346  retval = base_properties::has_readonly_property (pname);
5347  return retval;
5348  }
5349 
5350 };
5351 
5352 // ---------------------------------------------------------------------
5353 
5354 class OCTINTERP_API uicontextmenu : public base_graphics_object
5355 {
5356 public:
5357  class OCTINTERP_API properties : public base_properties
5358  {
5359  public:
5360 
5361  void add_dependent_obj (graphics_handle gh)
5362  { dependent_obj_list.push_back (gh); }
5363 
5364  // FIXME: the list may contain duplicates.
5365  // Should we return only unique elements?
5366  const std::list<graphics_handle> get_dependent_obj_list (void)
5367  { return dependent_obj_list; }
5368 
5369  // See the genprops.awk script for an explanation of the
5370  // properties declarations.
5371  // Programming note: Keep property list sorted if new ones are added.
5372 
5373  BEGIN_PROPERTIES (uicontextmenu)
5374  any_property __object__ , Matrix ()
5375  callback_property callback , Matrix ()
5376  array_property position , Matrix (1, 2, 0.0)
5377  END_PROPERTIES
5378 
5379  protected:
5380  void init (void)
5381  {
5382  position.add_constraint (dim_vector (1, 2));
5383  position.add_constraint (dim_vector (2, 1));
5384  visible.set (octave_value (false));
5385  }
5386 
5387  private:
5388  // List of objects that might depend on this uicontextmenu object
5389  std::list<graphics_handle> dependent_obj_list;
5390  };
5391 
5392 private:
5393  properties xproperties;
5394 
5395 public:
5396  uicontextmenu (const graphics_handle& mh, const graphics_handle& p)
5397  : base_graphics_object (), xproperties (mh, p)
5398  { }
5399 
5400  ~uicontextmenu (void);
5401 
5402  base_properties& get_properties (void) { return xproperties; }
5403 
5404  const base_properties& get_properties (void) const { return xproperties; }
5405 
5406  bool valid_object (void) const { return true; }
5407 
5408  bool has_readonly_property (const caseless_str& pname) const
5409  {
5410  bool retval = xproperties.has_readonly_property (pname);
5411  if (! retval)
5412  retval = base_properties::has_readonly_property (pname);
5413  return retval;
5414  }
5415 
5416 };
5417 
5418 // ---------------------------------------------------------------------
5419 
5420 class OCTINTERP_API uicontrol : public base_graphics_object
5421 {
5422 public:
5423  class OCTINTERP_API properties : public base_properties
5424  {
5425  public:
5426  Matrix get_boundingbox (bool internal = false,
5427  const Matrix& parent_pix_size = Matrix ()) const;
5428 
5429  double get_fontsize_points (double box_pix_height = 0) const;
5430 
5431  // See the genprops.awk script for an explanation of the
5432  // properties declarations.
5433  // Programming note: Keep property list sorted if new ones are added.
5434 
5435  BEGIN_PROPERTIES (uicontrol)
5436  any_property __object__ , Matrix ()
5437  color_property backgroundcolor , color_values (1, 1, 1)
5438  callback_property callback , Matrix ()
5439  array_property cdata , Matrix ()
5440  bool_property clipping , "on"
5441  radio_property enable , "{on}|inactive|off"
5442  array_property extent rG , Matrix (1, 4, 0.0)
5443  radio_property fontangle u , "{normal}|italic|oblique"
5444  string_property fontname u , OCTAVE_DEFAULT_FONTNAME
5445  double_property fontsize u , 10
5446  radio_property fontunits S , "inches|centimeters|normalized|{points}|pixels"
5447  radio_property fontweight u , "light|{normal}|demi|bold"
5448  color_property foregroundcolor , color_values (0, 0, 0)
5449  radio_property horizontalalignment , "left|{center}|right"
5450  callback_property keypressfcn , Matrix ()
5451  double_property listboxtop , 1
5452  double_property max , 1
5453  double_property min , 0
5454  array_property position , default_control_position ()
5455  array_property sliderstep , default_control_sliderstep ()
5456  string_array_property string u , ""
5457  radio_property style S , "{pushbutton}|togglebutton|radiobutton|checkbox|edit|text|slider|frame|listbox|popupmenu"
5458  string_property tooltipstring , ""
5459  radio_property units u , "normalized|inches|centimeters|points|{pixels}|characters"
5460  row_vector_property value , Matrix (1, 1, 1.0)
5461  radio_property verticalalignment , "top|{middle}|bottom"
5462  END_PROPERTIES
5463 
5464  private:
5465  std::string cached_units;
5466 
5467  protected:
5468  void init (void)
5469  {
5470  cdata.add_constraint ("double");
5471  cdata.add_constraint ("single");
5472  cdata.add_constraint (dim_vector (-1, -1, 3));
5473  position.add_constraint (dim_vector (1, 4));
5474  sliderstep.add_constraint (dim_vector (1, 2));
5475  cached_units = get_units ();
5476  }
5477 
5478  void update_text_extent (void);
5479 
5480  void update_string (void) { update_text_extent (); }
5481  void update_fontname (void) { update_text_extent (); }
5482  void update_fontsize (void) { update_text_extent (); }
5483  void update_fontangle (void) { update_text_extent (); }
5484  void update_fontweight (void) { update_text_extent (); }
5485  void update_fontunits (const caseless_str& old_units);
5486 
5487  void update_units (void);
5488 
5489  };
5490 
5491 private:
5492  properties xproperties;
5493 
5494 public:
5495  uicontrol (const graphics_handle& mh, const graphics_handle& p)
5496  : base_graphics_object (), xproperties (mh, p)
5497  { }
5498 
5499  ~uicontrol (void) { }
5500