// DO NOT EDIT!  Generated automatically by genprops.awk.

/*

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 "gripes.h"
#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 (! contains (val))
      {
	error ("invalid value = %s", val.c_str ());
	retval = false;
      }

    return retval;
  }
  
  bool contains (const std::string& val)
  {
    return (possible_vals.find (val) != possible_vals.end ());
  }

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

	for (octave_idx_type i = 0; i < 64; i++)
	  {
	    // This is the jet colormap.  It would be nice to be able
	    // to feval the jet function but since there is a static
	    // property object that includes a colormap_property
	    // object, we need to initialize this before main is even
	    // called, so calling an interpreted function is not
	    // possible.

	    double x = i / 63.0;

	    if (x >= 3.0/8.0 && x < 5.0/8.0)
	      cmap(i,0) = 4.0 * x - 3.0/2.0;
	    else if (x >= 5.0/8.0 && x < 7.0/8.0)
	      cmap(i,0) = 1.0;
	    else if (x >= 7.0/8.0)
	      cmap(i,0) = -4.0 * x + 9.0/2.0;

	    if (x >= 1.0/8.0 && x < 3.0/8.0)
	      cmap(i,1) = 4.0 * x - 1.0/2.0;
	    else if (x >= 3.0/8.0 && x < 5.0/8.0)
	      cmap(i,1) = 1.0;
	    else if (x >= 5.0/8.0 && x < 7.0/8.0)
	      cmap(i,1) = -4.0 * x + 7.0/2.0;

	    if (x < 1/8)
	      cmap(i,2) = 4.0 * x + 1.0/2.0;
	    else if (x >= 1.0/8.0 && x < 3.0/8.0)
	      cmap(i,2) = 1.0;
	    else if (x >= 3.0/8.0 && x < 5.0/8.0)
	      cmap(i,2) = -4.0 * x + 5.0/2.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.

private:

  graphics_handle currentfigure;
  octave_value visible;

public:

  graphics_handle get_currentfigure (void) const { return currentfigure; }
  octave_value get_visible (void) const { return visible; }

  void set_currentfigure (const graphics_handle& val);
  void set_currentfigure (const octave_value& val) { set_currentfigure (graphics_handle (val)); }

  void set_visible (const octave_value& val)
  {
    if (! error_state)
      {
        visible = val;
        mark_modified ();
      }
  }


private:

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

  void defaults (void) const
  {
    gripe_not_implemented ("root_figure::defaults");
  }

  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.

private:

  octave_value __plot_stream__;
  octave_value nextplot;
  octave_value closerequestfcn;
  graphics_handle currentaxes;
  colormap_property colormap;
  octave_value visible;
  octave_value paperorientation;

public:

  octave_value get___plot_stream__ (void) const { return __plot_stream__; }
  octave_value get_nextplot (void) const { return nextplot; }
  octave_value get_closerequestfcn (void) const { return closerequestfcn; }
  graphics_handle get_currentaxes (void) const { return currentaxes; }
  colormap_property get_colormap (void) const { return colormap; }
  octave_value get_visible (void) const { return visible; }
  octave_value get_paperorientation (void) const { return paperorientation; }

  void set___plot_stream__ (const octave_value& val)
  {
    if (! error_state)
      {
        __plot_stream__ = val;
        mark_modified ();
      }
  }

  void set_nextplot (const octave_value& val)
  {
    if (! error_state)
      {
        nextplot = val;
        mark_modified ();
      }
  }

  void set_closerequestfcn (const octave_value& val)
  {
    if (! error_state)
      {
        closerequestfcn = val;
        mark_modified ();
      }
  }

  void set_currentaxes (const graphics_handle& val);
  void set_currentaxes (const octave_value& val) { set_currentaxes (graphics_handle (val)); }

  void set_colormap (const colormap_property& val)
  {
    if (! error_state)
      {
        colormap = val;
        mark_modified ();
      }
  }

  void set_colormap (const octave_value& val) { set_colormap (colormap_property (val)); }

  void set_visible (const octave_value& val);
  void set_paperorientation (const octave_value& val)
  {
    if (! error_state)
      {
        paperorientation = val;
        mark_modified ();
      }
  }


private:

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

  void defaults (void) const { gripe_not_implemented ("figure::defaults"); }

  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.

private:

  octave_value position;
  mutable graphics_handle title;
  octave_value box;
  octave_value key;
  octave_value keybox;
  octave_value keypos;
  octave_value dataaspectratio;
  octave_value dataaspectratiomode;
  octave_value xlim;
  octave_value ylim;
  octave_value zlim;
  octave_value clim;
  octave_value xlimmode;
  octave_value ylimmode;
  octave_value zlimmode;
  octave_value climmode;
  mutable graphics_handle xlabel;
  mutable graphics_handle ylabel;
  mutable graphics_handle zlabel;
  octave_value xgrid;
  octave_value ygrid;
  octave_value zgrid;
  octave_value xminorgrid;
  octave_value yminorgrid;
  octave_value zminorgrid;
  octave_value xtick;
  octave_value ytick;
  octave_value ztick;
  octave_value xtickmode;
  octave_value ytickmode;
  octave_value ztickmode;
  octave_value xticklabel;
  octave_value yticklabel;
  octave_value zticklabel;
  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;

public:

  octave_value get_position (void) const { return position; }
  graphics_handle get_title (void) const;
  octave_value get_box (void) const { return box; }
  octave_value get_key (void) const { return key; }
  octave_value get_keybox (void) const { return keybox; }
  octave_value get_keypos (void) const { return keypos; }
  octave_value get_dataaspectratio (void) const { return dataaspectratio; }
  octave_value get_dataaspectratiomode (void) const { return dataaspectratiomode; }
  octave_value get_xlim (void) const { return xlim; }
  octave_value get_ylim (void) const { return ylim; }
  octave_value get_zlim (void) const { return zlim; }
  octave_value get_clim (void) const { return clim; }
  octave_value get_xlimmode (void) const { return xlimmode; }
  octave_value get_ylimmode (void) const { return ylimmode; }
  octave_value get_zlimmode (void) const { return zlimmode; }
  octave_value get_climmode (void) const { return climmode; }
  graphics_handle get_xlabel (void) const;
  graphics_handle get_ylabel (void) const;
  graphics_handle get_zlabel (void) const;
  octave_value get_xgrid (void) const { return xgrid; }
  octave_value get_ygrid (void) const { return ygrid; }
  octave_value get_zgrid (void) const { return zgrid; }
  octave_value get_xminorgrid (void) const { return xminorgrid; }
  octave_value get_yminorgrid (void) const { return yminorgrid; }
  octave_value get_zminorgrid (void) const { return zminorgrid; }
  octave_value get_xtick (void) const { return xtick; }
  octave_value get_ytick (void) const { return ytick; }
  octave_value get_ztick (void) const { return ztick; }
  octave_value get_xtickmode (void) const { return xtickmode; }
  octave_value get_ytickmode (void) const { return ytickmode; }
  octave_value get_ztickmode (void) const { return ztickmode; }
  octave_value get_xticklabel (void) const { return xticklabel; }
  octave_value get_yticklabel (void) const { return yticklabel; }
  octave_value get_zticklabel (void) const { return zticklabel; }
  octave_value get_xticklabelmode (void) const { return xticklabelmode; }
  octave_value get_yticklabelmode (void) const { return yticklabelmode; }
  octave_value get_zticklabelmode (void) const { return zticklabelmode; }
  octave_value get_xscale (void) const { return xscale; }
  octave_value get_yscale (void) const { return yscale; }
  octave_value get_zscale (void) const { return zscale; }
  octave_value get_xdir (void) const { return xdir; }
  octave_value get_ydir (void) const { return ydir; }
  octave_value get_zdir (void) const { return zdir; }
  octave_value get_xaxislocation (void) const { return xaxislocation; }
  octave_value get_yaxislocation (void) const { return yaxislocation; }
  octave_value get_view (void) const { return view; }
  octave_value get_visible (void) const { return visible; }
  octave_value get_nextplot (void) const { return nextplot; }
  octave_value get_outerposition (void) const { return outerposition; }

  void set_position (const octave_value& val)
  {
    if (! error_state)
      {
        position = val;
        mark_modified ();
      }
  }

  void set_title (const graphics_handle& val);
  void set_title (const octave_value& val);
  void set_box (const octave_value& val)
  {
    if (! error_state)
      {
        box = val;
        mark_modified ();
      }
  }

  void set_key (const octave_value& val)
  {
    if (! error_state)
      {
        key = val;
        mark_modified ();
      }
  }

  void set_keybox (const octave_value& val)
  {
    if (! error_state)
      {
        keybox = val;
        mark_modified ();
      }
  }

  void set_keypos (const octave_value& val)
  {
    if (! error_state)
      {
        keypos = val;
        mark_modified ();
      }
  }

  void set_dataaspectratio (const octave_value& val)
  {
    if (! error_state)
      {
        dataaspectratio = val;
        set_dataaspectratiomode ("manual");
        mark_modified ();
      }
  }

  void set_dataaspectratiomode (const octave_value& val)
  {
    if (! error_state)
      {
        dataaspectratiomode = val;
        mark_modified ();
      }
  }

  void set_xlim (const octave_value& val)
  {
    if (! error_state)
      {
        xlim = val;
        set_xlimmode ("manual");
        mark_modified ();
      }
  }

  void set_ylim (const octave_value& val)
  {
    if (! error_state)
      {
        ylim = val;
        set_ylimmode ("manual");
        mark_modified ();
      }
  }

  void set_zlim (const octave_value& val)
  {
    if (! error_state)
      {
        zlim = val;
        set_zlimmode ("manual");
        mark_modified ();
      }
  }

  void set_clim (const octave_value& val)
  {
    if (! error_state)
      {
        clim = val;
        set_climmode ("manual");
        mark_modified ();
      }
  }

  void set_xlimmode (const octave_value& val)
  {
    if (! error_state)
      {
        xlimmode = val;
        mark_modified ();
      }
  }

  void set_ylimmode (const octave_value& val)
  {
    if (! error_state)
      {
        ylimmode = val;
        mark_modified ();
      }
  }

  void set_zlimmode (const octave_value& val)
  {
    if (! error_state)
      {
        zlimmode = val;
        mark_modified ();
      }
  }

  void set_climmode (const octave_value& val)
  {
    if (! error_state)
      {
        climmode = val;
        mark_modified ();
      }
  }

  void set_xlabel (const graphics_handle& val);
  void set_xlabel (const octave_value& val);
  void set_ylabel (const graphics_handle& val);
  void set_ylabel (const octave_value& val);
  void set_zlabel (const graphics_handle& val);
  void set_zlabel (const octave_value& val);
  void set_xgrid (const octave_value& val)
  {
    if (! error_state)
      {
        xgrid = val;
        mark_modified ();
      }
  }

  void set_ygrid (const octave_value& val)
  {
    if (! error_state)
      {
        ygrid = val;
        mark_modified ();
      }
  }

  void set_zgrid (const octave_value& val)
  {
    if (! error_state)
      {
        zgrid = val;
        mark_modified ();
      }
  }

  void set_xminorgrid (const octave_value& val)
  {
    if (! error_state)
      {
        xminorgrid = val;
        mark_modified ();
      }
  }

  void set_yminorgrid (const octave_value& val)
  {
    if (! error_state)
      {
        yminorgrid = val;
        mark_modified ();
      }
  }

  void set_zminorgrid (const octave_value& val)
  {
    if (! error_state)
      {
        zminorgrid = val;
        mark_modified ();
      }
  }

  void set_xtick (const octave_value& val)
  {
    if (! error_state)
      {
        xtick = val;
        set_xtickmode ("manual");
        mark_modified ();
      }
  }

  void set_ytick (const octave_value& val)
  {
    if (! error_state)
      {
        ytick = val;
        set_ytickmode ("manual");
        mark_modified ();
      }
  }

  void set_ztick (const octave_value& val)
  {
    if (! error_state)
      {
        ztick = val;
        set_ztickmode ("manual");
        mark_modified ();
      }
  }

  void set_xtickmode (const octave_value& val)
  {
    if (! error_state)
      {
        xtickmode = val;
        mark_modified ();
      }
  }

  void set_ytickmode (const octave_value& val)
  {
    if (! error_state)
      {
        ytickmode = val;
        mark_modified ();
      }
  }

  void set_ztickmode (const octave_value& val)
  {
    if (! error_state)
      {
        ztickmode = val;
        mark_modified ();
      }
  }

  void set_xticklabel (const octave_value& val)
  {
    if (! error_state)
      {
        xticklabel = val;
        set_xticklabelmode ("manual");
        mark_modified ();
      }
  }

  void set_yticklabel (const octave_value& val)
  {
    if (! error_state)
      {
        yticklabel = val;
        set_yticklabelmode ("manual");
        mark_modified ();
      }
  }

  void set_zticklabel (const octave_value& val)
  {
    if (! error_state)
      {
        zticklabel = val;
        set_zticklabelmode ("manual");
        mark_modified ();
      }
  }

  void set_xticklabelmode (const octave_value& val)
  {
    if (! error_state)
      {
        xticklabelmode = val;
        mark_modified ();
      }
  }

  void set_yticklabelmode (const octave_value& val)
  {
    if (! error_state)
      {
        yticklabelmode = val;
        mark_modified ();
      }
  }

  void set_zticklabelmode (const octave_value& val)
  {
    if (! error_state)
      {
        zticklabelmode = val;
        mark_modified ();
      }
  }

  void set_xscale (const octave_value& val)
  {
    if (! error_state)
      {
        xscale = val;
        mark_modified ();
      }
  }

  void set_yscale (const octave_value& val)
  {
    if (! error_state)
      {
        yscale = val;
        mark_modified ();
      }
  }

  void set_zscale (const octave_value& val)
  {
    if (! error_state)
      {
        zscale = val;
        mark_modified ();
      }
  }

  void set_xdir (const octave_value& val)
  {
    if (! error_state)
      {
        xdir = val;
        mark_modified ();
      }
  }

  void set_ydir (const octave_value& val)
  {
    if (! error_state)
      {
        ydir = val;
        mark_modified ();
      }
  }

  void set_zdir (const octave_value& val)
  {
    if (! error_state)
      {
        zdir = val;
        mark_modified ();
      }
  }

  void set_xaxislocation (const octave_value& val)
  {
    if (! error_state)
      {
        xaxislocation = val;
        mark_modified ();
      }
  }

  void set_yaxislocation (const octave_value& val)
  {
    if (! error_state)
      {
        yaxislocation = val;
        mark_modified ();
      }
  }

  void set_view (const octave_value& val)
  {
    if (! error_state)
      {
        view = val;
        mark_modified ();
      }
  }

  void set_visible (const octave_value& val)
  {
    if (! error_state)
      {
        visible = val;
        mark_modified ();
      }
  }

  void set_nextplot (const octave_value& val)
  {
    if (! error_state)
      {
        nextplot = val;
        mark_modified ();
      }
  }

  void set_outerposition (const octave_value& val)
  {
    if (! error_state)
      {
        outerposition = val;
        mark_modified ();
      }
  }


private:

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

  void defaults (void) const { gripe_not_implemented ("axes::defaults"); }

  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.

private:

  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;

public:

  octave_value get_xdata (void) const { return xdata; }
  octave_value get_ydata (void) const { return ydata; }
  octave_value get_zdata (void) const { return zdata; }
  octave_value get_ldata (void) const { return ldata; }
  octave_value get_udata (void) const { return udata; }
  octave_value get_xldata (void) const { return xldata; }
  octave_value get_xudata (void) const { return xudata; }
  color_property get_color (void) const { return color; }
  octave_value get_linestyle (void) const { return linestyle; }
  octave_value get_linewidth (void) const { return linewidth; }
  octave_value get_marker (void) const { return marker; }
  octave_value get_markeredgecolor (void) const { return markeredgecolor; }
  octave_value get_markerfacecolor (void) const { return markerfacecolor; }
  octave_value get_markersize (void) const { return markersize; }
  octave_value get_keylabel (void) const { return keylabel; }

  void set_xdata (const octave_value& val)
  {
    if (! error_state)
      {
        xdata = val;
        mark_modified ();
      }
  }

  void set_ydata (const octave_value& val)
  {
    if (! error_state)
      {
        ydata = val;
        mark_modified ();
      }
  }

  void set_zdata (const octave_value& val)
  {
    if (! error_state)
      {
        zdata = val;
        mark_modified ();
      }
  }

  void set_ldata (const octave_value& val)
  {
    if (! error_state)
      {
        ldata = val;
        mark_modified ();
      }
  }

  void set_udata (const octave_value& val)
  {
    if (! error_state)
      {
        udata = val;
        mark_modified ();
      }
  }

  void set_xldata (const octave_value& val)
  {
    if (! error_state)
      {
        xldata = val;
        mark_modified ();
      }
  }

  void set_xudata (const octave_value& val)
  {
    if (! error_state)
      {
        xudata = val;
        mark_modified ();
      }
  }

  void set_color (const color_property& val)
  {
    if (! error_state)
      {
        color = val;
        mark_modified ();
      }
  }

  void set_color (const octave_value& val) { set_color (color_property (val)); }

  void set_linestyle (const octave_value& val)
  {
    if (! error_state)
      {
        linestyle = val;
        mark_modified ();
      }
  }

  void set_linewidth (const octave_value& val)
  {
    if (! error_state)
      {
        linewidth = val;
        mark_modified ();
      }
  }

  void set_marker (const octave_value& val)
  {
    if (! error_state)
      {
        marker = val;
        mark_modified ();
      }
  }

  void set_markeredgecolor (const octave_value& val)
  {
    if (! error_state)
      {
        markeredgecolor = val;
        mark_modified ();
      }
  }

  void set_markerfacecolor (const octave_value& val)
  {
    if (! error_state)
      {
        markerfacecolor = val;
        mark_modified ();
      }
  }

  void set_markersize (const octave_value& val)
  {
    if (! error_state)
      {
        markersize = val;
        mark_modified ();
      }
  }

  void set_keylabel (const octave_value& val)
  {
    if (! error_state)
      {
        keylabel = val;
        mark_modified ();
      }
  }


private:

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

  void defaults (void) const { gripe_not_implemented ("line::defaults"); }

  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.

private:

  octave_value string;
  octave_value units;
  octave_value position;
  octave_value rotation;
  octave_value horizontalalignment;
  color_property color;

public:

  octave_value get_string (void) const { return string; }
  octave_value get_units (void) const { return units; }
  octave_value get_position (void) const { return position; }
  octave_value get_rotation (void) const { return rotation; }
  octave_value get_horizontalalignment (void) const { return horizontalalignment; }
  color_property get_color (void) const { return color; }

  void set_string (const octave_value& val)
  {
    if (! error_state)
      {
        string = val;
        mark_modified ();
      }
  }

  void set_units (const octave_value& val)
  {
    if (! error_state)
      {
        units = val;
        mark_modified ();
      }
  }

  void set_position (const octave_value& val)
  {
    if (! error_state)
      {
        position = val;
        mark_modified ();
      }
  }

  void set_rotation (const octave_value& val)
  {
    if (! error_state)
      {
        rotation = val;
        mark_modified ();
      }
  }

  void set_horizontalalignment (const octave_value& val)
  {
    if (! error_state)
      {
        horizontalalignment = val;
        mark_modified ();
      }
  }

  void set_color (const color_property& val)
  {
    if (! error_state)
      {
        color = val;
        mark_modified ();
      }
  }

  void set_color (const octave_value& val) { set_color (color_property (val)); }


private:

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

  void defaults (void) const { gripe_not_implemented ("text::defaults"); }

  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.

private:

  octave_value cdata;
  octave_value xdata;
  octave_value ydata;

public:

  octave_value get_cdata (void) const { return cdata; }
  octave_value get_xdata (void) const { return xdata; }
  octave_value get_ydata (void) const { return ydata; }

  void set_cdata (const octave_value& val)
  {
    if (! error_state)
      {
        cdata = val;
        mark_modified ();
      }
  }

  void set_xdata (const octave_value& val)
  {
    if (! error_state)
      {
        xdata = val;
        mark_modified ();
      }
  }

  void set_ydata (const octave_value& val)
  {
    if (! error_state)
      {
        ydata = val;
        mark_modified ();
      }
  }


private:

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

  void defaults (void) const { gripe_not_implemented ("image::defaults"); }

  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.

private:

  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;

public:

  octave_value get_cdata (void) const { return cdata; }
  octave_value get_xdata (void) const { return xdata; }
  octave_value get_ydata (void) const { return ydata; }
  octave_value get_zdata (void) const { return zdata; }
  color_property get_facecolor (void) const { return facecolor; }
  octave_value get_facealpha (void) const { return facealpha; }
  color_property get_edgecolor (void) const { return edgecolor; }
  octave_value get_linestyle (void) const { return linestyle; }
  octave_value get_linewidth (void) const { return linewidth; }
  octave_value get_marker (void) const { return marker; }
  octave_value get_markeredgecolor (void) const { return markeredgecolor; }
  octave_value get_markerfacecolor (void) const { return markerfacecolor; }
  octave_value get_markersize (void) const { return markersize; }

  void set_cdata (const octave_value& val)
  {
    if (! error_state)
      {
        cdata = val;
        mark_modified ();
      }
  }

  void set_xdata (const octave_value& val)
  {
    if (! error_state)
      {
        xdata = val;
        mark_modified ();
      }
  }

  void set_ydata (const octave_value& val)
  {
    if (! error_state)
      {
        ydata = val;
        mark_modified ();
      }
  }

  void set_zdata (const octave_value& val)
  {
    if (! error_state)
      {
        zdata = val;
        mark_modified ();
      }
  }

  void set_facecolor (const color_property& val)
  {
    if (! error_state)
      {
        facecolor = val;
        mark_modified ();
      }
  }

  void set_facecolor (const octave_value& val) { set_facecolor (color_property (val)); }

  void set_facealpha (const octave_value& val)
  {
    if (! error_state)
      {
        facealpha = val;
        mark_modified ();
      }
  }

  void set_edgecolor (const color_property& val)
  {
    if (! error_state)
      {
        edgecolor = val;
        mark_modified ();
      }
  }

  void set_edgecolor (const octave_value& val) { set_edgecolor (color_property (val)); }

  void set_linestyle (const octave_value& val)
  {
    if (! error_state)
      {
        linestyle = val;
        mark_modified ();
      }
  }

  void set_linewidth (const octave_value& val)
  {
    if (! error_state)
      {
        linewidth = val;
        mark_modified ();
      }
  }

  void set_marker (const octave_value& val)
  {
    if (! error_state)
      {
        marker = val;
        mark_modified ();
      }
  }

  void set_markeredgecolor (const octave_value& val)
  {
    if (! error_state)
      {
        markeredgecolor = val;
        mark_modified ();
      }
  }

  void set_markerfacecolor (const octave_value& val)
  {
    if (! error_state)
      {
        markerfacecolor = val;
        mark_modified ();
      }
  }

  void set_markersize (const octave_value& val)
  {
    if (! error_state)
      {
        markersize = val;
        mark_modified ();
      }
  }


private:

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

  void defaults (void) const { gripe_not_implemented ("patch::defaults"); }

  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.

private:

  octave_value xdata;
  octave_value ydata;
  octave_value zdata;
  octave_value keylabel;

public:

  octave_value get_xdata (void) const { return xdata; }
  octave_value get_ydata (void) const { return ydata; }
  octave_value get_zdata (void) const { return zdata; }
  octave_value get_keylabel (void) const { return keylabel; }

  void set_xdata (const octave_value& val)
  {
    if (! error_state)
      {
        xdata = val;
        mark_modified ();
      }
  }

  void set_ydata (const octave_value& val)
  {
    if (! error_state)
      {
        ydata = val;
        mark_modified ();
      }
  }

  void set_zdata (const octave_value& val)
  {
    if (! error_state)
      {
        zdata = val;
        mark_modified ();
      }
  }

  void set_keylabel (const octave_value& val)
  {
    if (! error_state)
      {
        keylabel = val;
        mark_modified ();
      }
  }


private:

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

  void defaults (void) const { gripe_not_implemented ("surface::defaults"); }

  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: ***
*/
