diff src/graphics.h.in @ 6874:94bda6abc224

[project @ 2007-09-06 21:34:24 by jwe]
author jwe
date Thu, 06 Sep 2007 21:34:24 +0000
parents
children b2b7526a5772
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/graphics.h.in
@@ -0,0 +1,1897 @@
+/*
+
+Copyright (C) 2007 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, write to the Free
+Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.
+
+*/
+
+#if !defined (graphics_h)
+#define graphics_h 1
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <cctype>
+
+#include <algorithm>
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+
+#include "oct-map.h"
+#include "ov.h"
+
+class
+radio_values
+{
+public:
+  radio_values (const std::string& opt_string = std::string ());
+  radio_values (const radio_values& a)
+    : default_val (a.default_val), possible_vals (a.possible_vals) { }
+
+  radio_values& operator = (const radio_values& a)
+  {
+    if (&a != this)
+      {
+	default_val = a.default_val;
+	possible_vals = a.possible_vals;
+      }
+
+    return *this;
+  }
+
+  std::string default_value (void) const { return default_val; }
+
+  std::set<std::string> possible_values (void) const { return possible_vals; }
+
+  bool validate (const std::string& val)
+  {
+    bool retval = true;
+
+    if (possible_vals.find (val) == possible_vals.end ())
+      {
+	error ("invalid value = %s", val.c_str ());
+	retval = false;
+      }
+
+    return retval;
+  }
+
+private:
+  // Might also want to cache
+  std::string default_val;
+  std::set<std::string> possible_vals;
+};
+
+class
+radio_property
+{
+public:
+  radio_property (const radio_values& v)
+    : vals (v), current_val (v.default_value ()) { }
+
+  radio_property (const radio_values& v, const std::string& initial_value)
+    : vals (v), current_val (initial_value) { }
+
+  radio_property (const radio_property& a)
+    : vals (a.vals), current_val (a.current_val) { }
+
+  radio_property& operator = (const radio_property& a)
+  {
+    if (&a != this)
+      {
+	vals = a.vals;
+	current_val = a.current_val;
+      }
+
+    return *this;
+  }
+
+  radio_property& operator = (const std::string& newval)
+  {
+    if (vals.validate (newval))
+      current_val = newval;
+
+    return *this;
+  }
+
+  const std::string& current_value (void) const { return current_val; }
+
+private:
+  radio_values vals;
+  std::string current_val;
+};
+
+class
+color_values
+{
+public:
+  color_values (double r = 0, double g = 0, double b = 1)
+  {
+    xrgb[0] = r;
+    xrgb[1] = g;
+    xrgb[2] = b;
+
+    validate ();
+  }
+
+  color_values (std::string str)
+  {
+    if (! str2rgb (str))
+      error ("invalid color specification");
+  }
+
+  color_values (const color_values& c)
+  {
+    xrgb[0] = c.xrgb[0];
+    xrgb[1] = c.xrgb[1];
+    xrgb[2] = c.xrgb[2];
+  }
+
+  color_values& operator = (const color_values& c)
+  {
+    if (&c != this)
+      {
+	xrgb[0] = c.xrgb[0];
+	xrgb[1] = c.xrgb[1];
+	xrgb[2] = c.xrgb[2];
+
+      }
+
+    return *this;
+  }
+
+  const double* rgb (void) const { return xrgb; }
+
+  void validate (void) const
+  {
+    for (int i = 0; i < 3; i++)
+      {
+	if (xrgb[i] < 0 ||  xrgb[i] > 1)
+	  {
+	    error ("invalid RGB color specification");
+	    break;
+	  }
+      }
+  }
+
+private:
+  double xrgb[3];
+
+  bool str2rgb (std::string str);
+};
+
+
+class 
+color_property
+{
+public:
+  color_property (const color_values& c = color_values (),
+		  const radio_values& v = radio_values ())
+    : current_type (color_t), color_val (c), radio_val (v),
+      current_val (v.default_value ())
+  { }
+
+  color_property (const radio_values& v)
+    : current_type (radio_t), color_val (color_values ()), radio_val (v),
+      current_val (v.default_value ())
+  { }
+
+  color_property (const radio_values& v, const std::string& initial_value)
+    : current_type (radio_t), color_val (color_values ()), radio_val (v),
+      current_val (initial_value)
+  { }
+
+  color_property (const octave_value& val);
+
+  operator octave_value (void) const
+  {
+    if (current_type == color_t)
+      {
+	Matrix retval (1, 3);
+	const double *xrgb = color_val.rgb ();
+
+	for (int i = 0; i < 3 ; i++)
+	  retval(i) = xrgb[i];
+
+	return retval;
+      }
+
+    return current_val;
+  }
+
+  color_property& operator = (const color_property& a)
+  {
+    if (&a != this)
+      {
+	current_type = a.current_type;
+	color_val = a.color_val;
+	radio_val = a.radio_val;
+	current_val = a.current_val;
+      }
+
+    return *this;
+  }
+
+  color_property& operator = (const std::string& newval)
+  {
+    if (radio_val.validate (newval))
+      {
+	current_val = newval;
+	current_type = radio_t;
+      }
+
+    return *this;
+  }
+
+  color_property& operator = (const color_values& newval)
+  {
+    color_val = newval;
+    current_type = color_t;
+
+    return *this;
+  }
+
+  color_property& operator = (const octave_value& newval);
+
+  bool is_rgb (void) const { return (current_type == color_t); }
+
+  bool is_radio (void) const { return (current_type == radio_t); }
+
+  const double* rgb (void) const
+  {
+    if (current_type != color_t)
+      error ("color has no rgb value");
+
+    return color_val.rgb ();
+  }
+
+  const std::string& current_value (void) const
+  {
+    if (current_type != radio_t)
+      error ("color has no radio value");
+
+    return current_val;
+  }
+
+private:
+  enum current_enum { color_t, radio_t } current_type;
+  color_values color_val;
+  radio_values radio_val;
+  std::string current_val;
+};
+
+class 
+colormap_property
+{
+public:
+  colormap_property (const Matrix& m = Matrix ())
+    : cmap (m)
+  {
+    if (cmap.is_empty ())
+      {
+	cmap = Matrix (64, 3);
+
+	for (octave_idx_type i = 0; i < 64; i++)
+	  cmap(i,0) = cmap(i,1) = cmap(i,2) = i / 64.0;
+      }
+
+    validate ();
+  }
+
+  colormap_property (const octave_value& val)
+  {
+    cmap = val.matrix_value ();
+
+    validate ();
+  }
+
+  void validate (void) const
+  {
+    if (error_state || cmap.columns () != 3)
+      error ("invalid colormap specification");
+  }
+
+  operator octave_value (void) const { return cmap; }
+
+private:
+  Matrix cmap;
+};
+
+// ---------------------------------------------------------------------
+
+class property_name : public std::string
+{
+public:
+  typedef std::string::iterator iterator;
+  typedef std::string::const_iterator const_iterator;
+
+  property_name (void) : std::string () { }
+  property_name (const std::string& s) : std::string (s) { }
+  property_name (const char *s) : std::string (s) { }
+
+  property_name (const property_name& name) : std::string (name) { }
+
+  property_name& operator = (const property_name& pname)
+  {
+    std::string::operator = (pname);
+    return *this;
+  }
+
+  operator std::string (void) const { return *this; }
+
+  // Case-insensitive comparison.
+  bool compare (const std::string& s, size_t limit = NPOS) const
+  {
+    const_iterator p1 = begin ();
+    const_iterator p2 = s.begin ();
+
+    size_t k = 0;
+
+    while (p1 != end () && p2 != s.end () && k++ < limit)
+      {
+	if (std::tolower (*p1) != std::tolower (*p2))
+	  return false;
+
+	*p1++;
+	*p2++;
+      }
+
+    return (limit == NPOS) ? size () == s.size () : k == limit;
+  }
+};
+
+// ---------------------------------------------------------------------
+
+class property_list
+{
+public:
+  typedef std::map<std::string, octave_value> pval_map_type;
+  typedef std::map<std::string, pval_map_type> plist_map_type;
+  
+  typedef pval_map_type::iterator pval_map_iterator;
+  typedef pval_map_type::const_iterator pval_map_const_iterator;
+
+  typedef plist_map_type::iterator plist_map_iterator;
+  typedef plist_map_type::const_iterator plist_map_const_iterator;
+
+  property_list (const plist_map_type& m = plist_map_type ())
+    : plist_map (m) { }
+
+  ~property_list (void) { }
+
+  void set (const property_name& name, const octave_value& val);
+
+  octave_value lookup (const property_name& name) const;
+
+  plist_map_iterator begin (void) { return plist_map.begin (); }
+  plist_map_const_iterator begin (void) const { return plist_map.begin (); }
+
+  plist_map_iterator end (void) { return plist_map.end (); }
+  plist_map_const_iterator end (void) const { return plist_map.end (); }
+
+  plist_map_iterator find (const std::string& go_name)
+  {
+    return plist_map.find (go_name);
+  }
+
+  plist_map_const_iterator find (const std::string& go_name) const
+  {
+    return plist_map.find (go_name);
+  }
+
+  Octave_map as_struct (const std::string& prefix_arg) const;
+
+private:
+  plist_map_type plist_map;
+};
+
+// ---------------------------------------------------------------------
+
+class graphics_handle
+{
+public:
+  graphics_handle (void) : val (octave_NaN) { }
+
+  graphics_handle (const octave_value& a);
+
+  graphics_handle (int a) : val (a) { }
+
+  graphics_handle (double a) : val (a) { }
+
+  graphics_handle (const graphics_handle& a) : val (a.val) { }
+
+  graphics_handle& operator = (const graphics_handle& a)
+  {
+    if (&a != this)
+      val = a.val;
+
+    return *this;
+  }
+
+  ~graphics_handle (void) { }
+
+  operator double (void) const { return val; }
+
+  double value (void) const { return val; }
+
+  octave_value as_octave_value (void) const
+  {
+    return ok () ? octave_value (val) : octave_value (Matrix ());
+  }
+
+  graphics_handle operator ++ (void)
+  {
+    ++val;
+    return *this;
+  }
+
+  graphics_handle operator ++ (int)
+  {
+    graphics_handle h = *this;
+    ++val;
+    return h;
+  }
+
+  graphics_handle operator -- (void)
+  {
+    --val;
+    return *this;
+  }
+
+  graphics_handle operator -- (int)
+  {
+    graphics_handle h = *this;
+    --val;
+    return h;
+  }
+
+  bool ok (void) const { return ! xisnan (val); }
+
+  operator bool () const { return ok (); }
+
+private:
+  double val;
+};
+
+inline bool
+operator == (const graphics_handle& a, const graphics_handle& b)
+{
+  return a.value () == b.value ();
+}
+
+inline bool
+operator != (const graphics_handle& a, const graphics_handle& b)
+{
+  return a.value () != b.value ();
+}
+
+inline bool
+operator < (const graphics_handle& a, const graphics_handle& b)
+{
+  return a.value () < b.value ();
+}
+
+inline bool
+operator <= (const graphics_handle& a, const graphics_handle& b)
+{
+  return a.value () <= b.value ();
+}
+
+inline bool
+operator >= (const graphics_handle& a, const graphics_handle& b)
+{
+  return a.value () >= b.value ();
+}
+
+inline bool
+operator > (const graphics_handle& a, const graphics_handle& b)
+{
+  return a.value () > b.value ();
+}
+
+// ---------------------------------------------------------------------
+
+class base_graphics_object;
+
+class base_properties
+{
+public:
+  base_properties (const std::string& t = "unknown",
+		   const graphics_handle& mh = graphics_handle (),
+		   const graphics_handle& p = graphics_handle ())
+    : type (t), __modified__ (true), __myhandle__ (mh), parent (p),
+      children () { }
+
+  virtual ~base_properties (void) { }
+
+  virtual std::string graphics_object_name (void) const { return "unknonwn"; }
+
+  void mark_modified (void);
+
+  void override_defaults (base_graphics_object& obj);
+
+  // Look through DEFAULTS for properties with given CLASS_NAME, and
+  // apply them to the current object with set (virtual method).
+
+  void set_from_list (base_graphics_object& obj, property_list& defaults);
+
+  virtual void set (const property_name&, const octave_value&) { }
+
+  graphics_handle get_parent (void) const { return parent; }
+
+  void remove_child (const graphics_handle& h);
+
+  void adopt (const graphics_handle& h)
+  {
+    octave_idx_type n = children.numel ();
+    children.resize (1, n+1);
+    children(n) = h;
+  }
+
+  void set_parent (const octave_value& val);
+
+  void reparent (const graphics_handle& new_parent) { parent = new_parent; }
+
+  virtual void delete_children (void);
+
+protected:
+  std::string type;
+  bool __modified__;
+  graphics_handle __myhandle__;
+  graphics_handle parent;
+  Matrix children;
+};
+
+class base_graphics_object
+{
+public:
+  friend class graphics_object;
+
+  base_graphics_object (void) : count (1) { }
+
+  base_graphics_object (const base_graphics_object&) { }
+
+  virtual ~base_graphics_object (void) { }
+
+  virtual void mark_modified (void)
+  {
+    error ("base_graphics_object::mark_modified: invalid graphics object");
+  }
+
+  virtual void override_defaults (base_graphics_object&)
+  {
+    error ("base_graphics_object::override_defaults: invalid graphics object");
+  }
+
+  virtual void set_from_list (property_list&)
+  {
+    error ("base_graphics_object::set_from_list: invalid graphics object");
+  }
+
+  virtual void set (const property_name&, const octave_value&)
+  {
+    error ("base_graphics_object::set: invalid graphics object");
+  }
+
+  virtual void set_defaults (const std::string&)
+  {
+    error ("base_graphics_object::set_defaults: invalid graphics object");
+  }
+
+  virtual octave_value get (void) const
+  {
+    error ("base_graphics_object::get: invalid graphics object");
+    return octave_value ();
+  }
+
+  virtual octave_value get (const property_name&) const
+  {
+    error ("base_graphics_object::get: invalid graphics object");
+    return octave_value ();
+  }
+
+  virtual octave_value get_default (const property_name&) const;
+
+  virtual octave_value get_factory_default (const property_name&) const;
+
+  virtual octave_value get_defaults (void) const
+  {
+    error ("base_graphics_object::get_defaults: invalid graphics object");
+    return octave_value ();
+  }
+
+  virtual octave_value get_factory_defaults (void) const
+  {
+    error ("base_graphics_object::get_factory_defaults: invalid graphics object");
+    return octave_value ();
+  }
+
+  virtual graphics_handle get_parent (void) const
+  {
+    error ("base_graphics_object::get_parent: invalid graphics object");
+    return graphics_handle ();
+  }
+
+  virtual void remove_child (const graphics_handle&)
+  {
+    error ("base_graphics_object::remove_child: invalid graphics object");
+  }
+
+  virtual void adopt (const graphics_handle&)
+  {
+    error ("base_graphics_object::adopt: invalid graphics object");
+  }
+
+  virtual void reparent (const graphics_handle&)
+  {
+    error ("base_graphics_object::reparent: invalid graphics object");
+  }
+
+  virtual void defaults (void) const
+  {
+    error ("base_graphics_object::default: invalid graphics object");
+  }
+
+  virtual base_properties& get_properties (void)
+  {
+    static base_properties properties;
+    error ("base_graphics_object::get_properties: invalid graphics object");
+    return properties;
+  }
+
+  virtual bool valid_object (void) const { return false; }
+
+  virtual std::string type (void) const { return "unknown"; }
+
+  bool isa (const std::string& go_name) const
+  {
+    return type () == go_name;
+  }
+
+protected:
+  // A reference count.
+  int count;
+};
+
+class graphics_object
+{
+public:
+  graphics_object (void) : rep (new base_graphics_object ()) { }
+
+  graphics_object (base_graphics_object *new_rep)
+    : rep (new_rep) { }
+
+  graphics_object (const graphics_object& obj)
+  {
+    rep = obj.rep;
+    rep->count++;
+  }
+
+  graphics_object& operator = (const graphics_object& obj)
+  {
+    if (rep != obj.rep)
+      {
+	if (--rep->count == 0)
+	  delete rep;
+
+	rep = obj.rep;
+	rep->count++;
+      }
+
+    return *this;
+  }
+
+  ~graphics_object (void)
+  {
+    if (--rep->count == 0)
+      delete rep;
+  }
+
+  void mark_modified (void) { rep->mark_modified (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    rep->override_defaults (obj);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    rep->set_from_list (plist);
+  }
+
+  void set (const property_name& name, const octave_value& val)
+  {
+    rep->set (name, val);
+  }
+
+  void set (const octave_value_list& args);
+
+  void set_defaults (const std::string& mode)
+  {
+    rep->set_defaults (mode);
+  }
+
+  octave_value get (void) const
+  {
+    return rep->get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    return name.compare ("default")
+      ? get_defaults ()
+      : (name.compare ("factory")
+	 ? get_factory_defaults () : rep->get (name));
+  }
+
+  octave_value get_default (const property_name& name) const
+  {
+    return rep->get_default (name);
+  }
+
+  octave_value get_factory_default (const property_name& name) const
+  {
+    return rep->get_factory_default (name);
+  }
+
+  octave_value get_defaults (void) const { return rep->get_defaults (); }
+
+  octave_value get_factory_defaults (void) const
+  {
+    return rep->get_factory_defaults ();
+  }
+
+  graphics_handle get_parent (void) const { return rep->get_parent (); }
+
+  void remove_child (const graphics_handle& h) { return rep->remove_child (h); }
+
+  void adopt (const graphics_handle& h) { return rep->adopt (h); }
+
+  void reparent (const graphics_handle& h) { return rep->reparent (h); }
+
+  void defaults (void) const { rep->defaults (); }
+
+  bool isa (const std::string& go_name) const { return rep->isa (go_name); }
+
+  base_properties& get_properties (void) { return rep->get_properties (); }
+
+  bool valid_object (void) const { return rep->valid_object (); }
+
+  operator bool (void) const { return rep->valid_object (); }
+
+private:
+  base_graphics_object *rep;
+};
+
+// ---------------------------------------------------------------------
+
+class root_figure : public base_graphics_object
+{
+public:
+  class properties : public base_properties
+  {
+  public:
+    properties (void)
+      : base_properties ("root figure", 0, graphics_handle ()),
+	currentfigure (),
+	visible ("on")
+    { }
+
+    ~properties (void) { }
+
+    void set (const property_name& name, const octave_value& val);
+
+    octave_value get (void) const;
+
+    octave_value get (const property_name& name) const;
+
+    std::string graphics_object_name (void) const { return go_name; }
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES
+      graphics_handle currentfigure S
+      octave_value visible
+    END_PROPERTIES
+
+    static std::string go_name;
+  };
+
+private:
+  properties xproperties;
+
+public:
+
+  root_figure (void) : xproperties (), default_properties () { }
+
+  ~root_figure (void) { xproperties.delete_children (); }
+
+  std::string type (void) const { return xproperties.graphics_object_name (); }
+
+  void mark_modified (void) { }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Now override with our defaults.  If the default_properties
+    // list includes the properties for all defaults (line,
+    // surface, etc.) then we don't have to know the type of OBJ
+    // here, we just call its set function and let it decide which
+    // properties from the list to use.
+    obj.set_from_list (default_properties);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    xproperties.set_from_list (*this, plist);
+  }
+
+  void set (const property_name& name, const octave_value& value)
+  {
+    if (name.compare ("default", 7))
+      // strip "default", pass rest to function that will
+      // parse the remainder and add the element to the
+      // default_properties map.
+      default_properties.set (name.substr (7), value);
+    else
+      xproperties.set (name, value);
+  }
+
+  octave_value get (void) const
+  {
+    return xproperties.get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    octave_value retval;
+
+    if (name.compare ("default", 7))
+      return get_default (name.substr (7));
+    else if (name.compare ("factory", 7))
+      return get_factory_default (name.substr (7));
+    else
+      retval = xproperties.get (name);
+
+    return retval;
+  }
+
+  octave_value get_default (const property_name& name) const
+  {
+    octave_value retval = default_properties.lookup (name);
+
+    if (retval.is_undefined ())
+      error ("get: invalid default property `%s'", name.c_str ());
+
+    return retval;
+  }
+
+  octave_value get_factory_default (const property_name& name) const
+  {
+    octave_value retval = factory_properties.lookup (name);
+
+    if (retval.is_undefined ())
+      error ("get: invalid factory default property `%s'", name.c_str ());
+
+    return retval;
+  }
+
+  octave_value get_defaults (void) const
+  {
+    return default_properties.as_struct ("default");
+  }
+
+  octave_value get_factory_defaults (void) const
+  {
+    return factory_properties.as_struct ("factory");
+  }
+
+  graphics_handle get_parent (void) const { return xproperties.get_parent (); }
+
+  void remove_child (const graphics_handle& h) { xproperties.remove_child (h); }
+
+  void adopt (const graphics_handle& h) { xproperties.adopt (h); }
+
+  void reparent (const graphics_handle& np) { xproperties.reparent (np); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+
+private:
+  property_list default_properties;
+
+  static property_list factory_properties;
+
+  static property_list::plist_map_type init_factory_properties (void);
+};
+
+// ---------------------------------------------------------------------
+
+class figure : public base_graphics_object
+{
+public:
+  class properties : public base_properties
+  {
+  public:
+    properties (const graphics_handle& mh, const graphics_handle& p);
+
+    ~properties (void) { }
+
+    void set (const property_name& name, const octave_value& val);
+
+    octave_value get (void) const;
+
+    octave_value get (const property_name& name) const;
+
+    void close (void);
+
+    std::string graphics_object_name (void) const { return go_name; }
+
+    static property_list::pval_map_type factory_defaults (void);
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES
+      octave_value __plot_stream__
+      octave_value nextplot
+      octave_value closerequestfcn
+      graphics_handle currentaxes S
+      colormap_property colormap
+      octave_value visible S
+      octave_value paperorientation
+    END_PROPERTIES
+
+    static std::string go_name;
+  };
+
+private:
+  properties xproperties;
+
+public:
+  figure (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p), default_properties ()
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~figure (void)
+  {
+    xproperties.delete_children ();
+    xproperties.close ();
+  }
+
+  std::string type (void) const { return xproperties.graphics_object_name (); }
+
+  void mark_modified (void) { xproperties.mark_modified (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Allow parent (root figure) to override first (properties knows how
+    // to find the parent object).
+    xproperties.override_defaults (obj);
+
+    // Now override with our defaults.  If the default_properties
+    // list includes the properties for all defaults (line,
+    // surface, etc.) then we don't have to know the type of OBJ
+    // here, we just call its set function and let it decide which
+    // properties from the list to use.
+    obj.set_from_list (default_properties);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    xproperties.set_from_list (*this, plist);
+  }
+
+  void set (const property_name& name, const octave_value& value)
+  {
+    if (name.compare ("default", 7))
+      // strip "default", pass rest to function that will
+      // parse the remainder and add the element to the
+      // default_properties map.
+      default_properties.set (name.substr (7), value);
+    else
+      xproperties.set (name, value);
+  }
+
+  octave_value get (void) const
+  {
+    return xproperties.get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    octave_value retval;
+
+    if (name.compare ("default", 7))
+      retval = get_default (name.substr (7));
+    else
+      retval = xproperties.get (name);
+
+    return retval;
+  }
+
+  octave_value get_default (const property_name& name) const;
+
+  octave_value get_defaults (void) const
+  {
+    return default_properties.as_struct ("default");
+  }
+
+  graphics_handle get_parent (void) const { return xproperties.get_parent (); }
+
+  void remove_child (const graphics_handle& h) { xproperties.remove_child (h); }
+
+  void adopt (const graphics_handle& h) { xproperties.adopt (h); }
+
+  void reparent (const graphics_handle& np) { xproperties.reparent (np); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+
+private:
+  property_list default_properties;
+};
+
+// ---------------------------------------------------------------------
+
+class axes : public base_graphics_object
+{
+public:
+  class properties : public base_properties
+  {
+  public:
+    properties (const graphics_handle& mh, const graphics_handle& p);
+
+    ~properties (void) { }
+
+    void set (const property_name& name, const octave_value& val);
+
+    void set_defaults (base_graphics_object& obj, const std::string& mode);
+
+    octave_value get (void) const;
+
+    octave_value get (const property_name& name) const;
+
+    void remove_child (const graphics_handle& h);
+
+    void delete_children (void);
+
+    std::string graphics_object_name (void) const { return go_name; }
+
+    static property_list::pval_map_type factory_defaults (void);
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES
+      octave_value position
+      mutable graphics_handle title GSO
+      octave_value box
+      octave_value key
+      octave_value keybox
+      octave_value keypos
+      octave_value dataaspectratio m
+      octave_value dataaspectratiomode
+      octave_value xlim m
+      octave_value ylim m
+      octave_value zlim m
+      octave_value clim m
+      octave_value xlimmode
+      octave_value ylimmode
+      octave_value zlimmode
+      octave_value climmode
+      mutable graphics_handle xlabel GSO
+      mutable graphics_handle ylabel GSO
+      mutable graphics_handle zlabel GSO
+      octave_value xgrid
+      octave_value ygrid
+      octave_value zgrid
+      octave_value xminorgrid
+      octave_value yminorgrid
+      octave_value zminorgrid
+      octave_value xtick m
+      octave_value ytick m
+      octave_value ztick m
+      octave_value xtickmode
+      octave_value ytickmode
+      octave_value ztickmode
+      octave_value xticklabel m
+      octave_value yticklabel m
+      octave_value zticklabel m
+      octave_value xticklabelmode
+      octave_value yticklabelmode
+      octave_value zticklabelmode
+      octave_value xscale
+      octave_value yscale
+      octave_value zscale
+      octave_value xdir
+      octave_value ydir
+      octave_value zdir
+      octave_value xaxislocation
+      octave_value yaxislocation
+      octave_value view
+      octave_value visible
+      octave_value nextplot
+      octave_value outerposition
+    END_PROPERTIES
+
+    static std::string go_name;
+  };
+
+private:
+  properties xproperties;
+
+public:
+  axes (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p), default_properties ()
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~axes (void) { xproperties.delete_children (); }
+
+  std::string type (void) const { return xproperties.graphics_object_name (); }
+
+  void mark_modified (void) { xproperties.mark_modified (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Allow parent (figure) to override first (properties knows how
+    // to find the parent object).
+    xproperties.override_defaults (obj);
+
+    // Now override with our defaults.  If the default_properties
+    // list includes the properties for all defaults (line,
+    // surface, etc.) then we don't have to know the type of OBJ
+    // here, we just call its set function and let it decide which
+    // properties from the list to use.
+    obj.set_from_list (default_properties);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    xproperties.set_from_list (*this, plist);
+  }
+
+  void set (const property_name& name, const octave_value& value)
+  {
+    if (name.compare ("default", 7))
+      // strip "default", pass rest to function that will
+      // parse the remainder and add the element to the
+      // default_properties map.
+      default_properties.set (name.substr (7), value);
+    else
+      xproperties.set (name, value);
+  }
+
+  void set_defaults (const std::string& mode)
+  {
+    xproperties.set_defaults (*this, mode);
+  }
+
+  octave_value get (void) const
+  {
+    return xproperties.get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    octave_value retval;
+
+    // FIXME -- finish this.
+    if (name.compare ("default", 7))
+      retval = get_default (name.substr (7));
+    else
+      retval = xproperties.get (name);
+
+    return retval;
+  }
+
+  octave_value get_default (const property_name& name) const;
+
+  octave_value get_defaults (void) const
+  {
+    return default_properties.as_struct ("default");
+  }
+
+  graphics_handle get_parent (void) const { return xproperties.get_parent (); }
+
+  void remove_child (const graphics_handle& h) { xproperties.remove_child (h); }
+
+  void adopt (const graphics_handle& h) { xproperties.adopt (h); }
+
+  void reparent (const graphics_handle& np) { xproperties.reparent (np); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+
+private:
+  property_list default_properties;
+};
+
+// ---------------------------------------------------------------------
+
+class line : public base_graphics_object
+{
+public:
+  class properties : public base_properties
+  {
+  public:
+    properties (const graphics_handle& mh, const graphics_handle& p);
+
+    ~properties (void) { }
+
+    void set (const property_name& name, const octave_value& val);
+
+    octave_value get (void) const;
+
+    octave_value get (const property_name& name) const;
+
+    std::string graphics_object_name (void) const { return go_name; }
+
+    static property_list::pval_map_type factory_defaults (void);
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES
+      octave_value xdata
+      octave_value ydata
+      octave_value zdata
+      octave_value ldata
+      octave_value udata
+      octave_value xldata
+      octave_value xudata
+      color_property color
+      octave_value linestyle
+      octave_value linewidth
+      octave_value marker
+      octave_value markeredgecolor
+      octave_value markerfacecolor
+      octave_value markersize
+      octave_value keylabel
+    END_PROPERTIES
+
+    static std::string go_name;
+  };
+
+private:
+  properties xproperties;
+
+public:
+  line (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~line (void) { xproperties.delete_children (); }
+
+  std::string type (void) const { return xproperties.graphics_object_name (); }
+
+  void mark_modified (void) { xproperties.mark_modified (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Allow parent (figure) to override first (properties knows how
+    // to find the parent object).
+    xproperties.override_defaults (obj);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    xproperties.set_from_list (*this, plist);
+  }
+
+  void set (const property_name& name, const octave_value& val)
+  {
+    xproperties.set (name, val);
+  }
+
+  octave_value get (void) const
+  {
+    return xproperties.get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    return xproperties.get (name);
+  }
+
+  graphics_handle get_parent (void) const { return xproperties.get_parent (); }
+
+  void remove_child (const graphics_handle& h) { xproperties.remove_child (h); }
+
+  void adopt (const graphics_handle& h) { xproperties.adopt (h); }
+
+  void reparent (const graphics_handle& h) { xproperties.reparent (h); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+};
+
+// ---------------------------------------------------------------------
+
+class text : public base_graphics_object
+{
+public:
+  class properties : public base_properties
+  {
+  public:
+    properties (const graphics_handle& mh, const graphics_handle& p);
+
+    ~properties (void) { }
+
+    void set (const property_name& name, const octave_value& val);
+
+    octave_value get (void) const;
+
+    octave_value get (const property_name& name) const;
+
+    std::string graphics_object_name (void) const { return go_name; }
+
+    static property_list::pval_map_type factory_defaults (void);
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES
+      octave_value string
+      octave_value units
+      octave_value position
+      octave_value rotation
+      octave_value horizontalalignment
+      octave_value color
+    END_PROPERTIES
+
+    static std::string go_name;
+  };
+
+private:
+  properties xproperties;
+
+public:
+  text (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~text (void) { xproperties.delete_children (); }
+
+  std::string type (void) const { return xproperties.graphics_object_name (); }
+
+  void mark_modified (void) { xproperties.mark_modified (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Allow parent (figure) to override first (properties knows how
+    // to find the parent object).
+    xproperties.override_defaults (obj);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    xproperties.set_from_list (*this, plist);
+  }
+
+  void set (const property_name& name, const octave_value& val)
+  {
+    xproperties.set (name, val);
+  }
+
+  octave_value get (void) const
+  {
+    return xproperties.get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    return xproperties.get (name);
+  }
+
+  graphics_handle get_parent (void) const { return xproperties.get_parent (); }
+
+  void remove_child (const graphics_handle& h) { xproperties.remove_child (h); }
+
+  void adopt (const graphics_handle& h) { xproperties.adopt (h); }
+
+  void reparent (const graphics_handle& h) { xproperties.reparent (h); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+};
+
+// ---------------------------------------------------------------------
+
+class image : public base_graphics_object
+{
+public:
+  class properties : public base_properties
+  {
+  public:
+    properties (const graphics_handle& mh, const graphics_handle& p);
+
+    ~properties (void) { }
+
+    void set (const property_name& name, const octave_value& val);
+
+    octave_value get (void) const;
+
+    octave_value get (const property_name& name) const;
+
+    std::string graphics_object_name (void) const { return go_name; }
+
+    static property_list::pval_map_type factory_defaults (void);
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES
+      octave_value cdata
+      octave_value xdata
+      octave_value ydata
+    END_PROPERTIES
+
+    static std::string go_name;
+  };
+
+private:
+  properties xproperties;
+
+public:
+  image (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~image (void) { xproperties.delete_children (); }
+
+  std::string type (void) const { return xproperties.graphics_object_name (); }
+
+  void mark_modified (void) { xproperties.mark_modified (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Allow parent (figure) to override first (properties knows how
+    // to find the parent object).
+    xproperties.override_defaults (obj);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    xproperties.set_from_list (*this, plist);
+  }
+
+  void set (const property_name& name, const octave_value& val)
+  {
+    xproperties.set (name, val);
+  }
+
+  octave_value get (void) const
+  {
+    return xproperties.get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    return xproperties.get (name);
+  }
+
+  graphics_handle get_parent (void) const { return xproperties.get_parent (); }
+
+  void remove_child (const graphics_handle& h) { xproperties.remove_child (h); }
+
+  void adopt (const graphics_handle& h) { xproperties.adopt (h); }
+
+  void reparent (const graphics_handle& h) { xproperties.reparent (h); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+};
+
+// ---------------------------------------------------------------------
+
+class patch : public base_graphics_object
+{
+public:
+  class properties : public base_properties
+  {
+  public:
+    properties (const graphics_handle& mh, const graphics_handle& p);
+
+    ~properties (void) { }
+
+    void set (const property_name& name, const octave_value& val);
+
+    octave_value get (void) const;
+
+    octave_value get (const property_name& name) const;
+
+    std::string graphics_object_name (void) const { return go_name; }
+
+    static property_list::pval_map_type factory_defaults (void);
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES
+      octave_value cdata
+      octave_value xdata
+      octave_value ydata
+      octave_value zdata
+      color_property facecolor
+      octave_value facealpha
+      color_property edgecolor
+      octave_value linestyle
+      octave_value linewidth
+      octave_value marker
+      octave_value markeredgecolor
+      octave_value markerfacecolor
+      octave_value markersize
+    END_PROPERTIES
+
+    static std::string go_name;
+  };
+
+private:
+  properties xproperties;
+
+public:
+  patch (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~patch (void) { xproperties.delete_children (); }
+
+  std::string type (void) const { return xproperties.graphics_object_name (); }
+
+  void mark_modified (void) { xproperties.mark_modified (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Allow parent (figure) to override first (properties knows how
+    // to find the parent object).
+    xproperties.override_defaults (obj);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    xproperties.set_from_list (*this, plist);
+  }
+
+  void set (const property_name& name, const octave_value& val)
+  {
+    xproperties.set (name, val);
+  }
+
+  octave_value get (void) const
+  {
+    return xproperties.get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    return xproperties.get (name);
+  }
+
+  graphics_handle get_parent (void) const { return xproperties.get_parent (); }
+
+  void remove_child (const graphics_handle& h) { xproperties.remove_child (h); }
+
+  void adopt (const graphics_handle& h) { xproperties.adopt (h); }
+
+  void reparent (const graphics_handle& h) { xproperties.reparent (h); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+};
+
+// ---------------------------------------------------------------------
+
+class surface : public base_graphics_object
+{
+public:
+  class properties : public base_properties
+  {
+  public:
+    properties (const graphics_handle& mh, const graphics_handle& p);
+
+    ~properties (void) { }
+
+    void set (const property_name& name, const octave_value& val);
+
+    octave_value get (void) const;
+
+    octave_value get (const property_name& name) const;
+
+    std::string graphics_object_name (void) const { return go_name; }
+
+    static property_list::pval_map_type factory_defaults (void);
+
+    // See the genprops.awk script for an explanation of the
+    // properties declarations.
+
+    BEGIN_PROPERTIES
+      octave_value xdata
+      octave_value ydata
+      octave_value zdata
+      octave_value keylabel
+    END_PROPERTIES
+
+    static std::string go_name;
+  };
+
+private:
+  properties xproperties;
+
+public:
+  surface (const graphics_handle& mh, const graphics_handle& p)
+    : base_graphics_object (), xproperties (mh, p)
+  {
+    xproperties.override_defaults (*this);
+  }
+
+  ~surface (void) { xproperties.delete_children (); }
+
+  std::string type (void) const { return xproperties.graphics_object_name (); }
+
+  void mark_modified (void) { xproperties.mark_modified (); }
+
+  void override_defaults (base_graphics_object& obj)
+  {
+    // Allow parent (figure) to override first (properties knows how
+    // to find the parent object).
+    xproperties.override_defaults (obj);
+  }
+
+  void set_from_list (property_list& plist)
+  {
+    xproperties.set_from_list (*this, plist);
+  }
+
+  void set (const property_name& name, const octave_value& val)
+  {
+    xproperties.set (name, val);
+  }
+
+  octave_value get (void) const
+  {
+    return xproperties.get ();
+  }
+
+  octave_value get (const property_name& name) const
+  {
+    return xproperties.get (name);
+  }
+
+  graphics_handle get_parent (void) const { return xproperties.get_parent (); }
+
+  void remove_child (const graphics_handle& h) { xproperties.remove_child (h); }
+
+  void adopt (const graphics_handle& h) { xproperties.adopt (h); }
+
+  void reparent (const graphics_handle& h) { xproperties.reparent (h); }
+
+  base_properties& get_properties (void) { return xproperties; }
+
+  bool valid_object (void) const { return true; }
+};
+
+octave_value
+get_property_from_handle (double handle, const std::string &property,
+			  const std::string &func);
+bool
+set_property_in_handle (double handle, const std::string &property,
+			const octave_value &arg, const std::string &func);
+
+// ---------------------------------------------------------------------
+
+class gh_manager
+{
+protected:
+
+  gh_manager (void);
+
+public:
+
+  static bool instance_ok (void)
+  {
+    bool retval = true;
+
+    if (! instance)
+      instance = new gh_manager ();
+
+    if (! instance)
+      {
+	::error ("unable to create gh_manager!");
+
+	retval = false;
+      }
+
+    return retval;
+  }
+
+  static void free (const graphics_handle& h)
+  {
+    if (instance_ok ())
+      instance->do_free (h);
+  }
+
+  static graphics_handle lookup (double val)
+  {
+    return instance_ok () ? instance->do_lookup (val) : graphics_handle ();
+  }
+
+  static graphics_object get_object (const graphics_handle& h)
+  {
+    return instance_ok () ? instance->do_get_object (h) : graphics_object ();
+  }
+
+  static graphics_handle
+  make_graphics_handle (const std::string& go_name,
+			const graphics_handle& parent)
+  {
+    return instance_ok ()
+      ? instance->do_make_graphics_handle (go_name, parent)
+      : graphics_handle ();
+  }
+
+  static graphics_handle make_figure_handle (double val)
+  {
+    return instance_ok ()
+      ? instance->do_make_figure_handle (val) : graphics_handle ();
+  }
+
+  static void push_figure (const graphics_handle& h)
+  {
+    if (instance_ok ())
+      instance->do_push_figure (h);
+  }
+
+  static void pop_figure (const graphics_handle& h)
+  {
+    if (instance_ok ())
+      instance->do_pop_figure (h);
+  }
+
+  static graphics_handle current_figure (void)
+  {
+    return instance_ok ()
+      ? instance->do_current_figure () : graphics_handle ();
+  }
+
+  static Matrix handle_list (void)
+  {
+    return instance_ok () ? instance->do_handle_list () : Matrix ();
+  }
+
+  static Matrix figure_handle_list (void)
+  {
+    return instance_ok () ? instance->do_figure_handle_list () : Matrix ();
+  }
+
+private:
+
+  static gh_manager *instance;
+
+  typedef std::map<graphics_handle, graphics_object>::iterator iterator;
+  typedef std::map<graphics_handle, graphics_object>::const_iterator const_iterator;
+
+  typedef std::set<graphics_handle>::iterator free_list_iterator;
+  typedef std::set<graphics_handle>::const_iterator const_free_list_iterator;
+
+  typedef std::list<graphics_handle>::iterator figure_list_iterator;
+  typedef std::list<graphics_handle>::const_iterator const_figure_list_iterator;
+
+  // A map of handles to graphics objects.
+  std::map<graphics_handle, graphics_object> handle_map;
+
+  // The available graphics handles.
+  std::set<graphics_handle> handle_free_list;
+
+  // The next handle available if handle_free_list is empty.
+  graphics_handle next_handle;
+
+  // The allocated figure handles.  Top of the stack is most recently
+  // created.
+  std::list<graphics_handle> figure_list;
+
+  graphics_handle get_handle (const std::string& go_name);
+
+  void do_free (const graphics_handle& h);
+
+  graphics_handle do_lookup (double val)
+  {
+    iterator p = handle_map.find (val);
+
+    return (p != handle_map.end ()) ? p->first : graphics_handle ();
+  }
+
+  graphics_object do_get_object (const graphics_handle& h)
+  {
+    iterator p = handle_map.find (h);
+
+    return (p != handle_map.end ()) ? p->second : graphics_object ();
+  }
+
+  graphics_handle do_make_graphics_handle (const std::string& go_name,
+					   const graphics_handle& p);
+
+  graphics_handle do_make_figure_handle (double val);
+
+  Matrix do_handle_list (void)
+  {
+    Matrix retval (1, handle_map.size ());
+    octave_idx_type i = 0;
+    for (const_iterator p = handle_map.begin (); p != handle_map.end (); p++)
+      retval(i++) = p->first;
+    return retval;
+  }
+
+  Matrix do_figure_handle_list (void)
+  {
+    Matrix retval (1, figure_list.size ());
+    octave_idx_type i = 0;
+    for (const_figure_list_iterator p = figure_list.begin ();
+	 p != figure_list.end ();
+	 p++)
+      retval(i++) = *p;
+    return retval;
+  }
+
+  void do_push_figure (const graphics_handle& h);
+
+  void do_pop_figure (const graphics_handle& h);
+
+  graphics_handle do_current_figure (void) const
+  {
+    return figure_list.empty () ? graphics_handle () : figure_list.front ();
+  }
+};
+
+
+// This function is NOT equivalent to the scripting language function gcf.
+graphics_handle gcf (void);
+
+// This function is NOT equivalent to the scripting language function gca.
+graphics_handle gca (void);
+
+#endif
+
+/*
+;;; Local Variables: ***
+;;; mode: C++ ***
+;;; End: ***
+*/