changeset 8059:75c99d3f97d7

Octave to backend notification scheme
author John W. Eaton <jwe@octave.org>
date Tue, 26 Aug 2008 13:24:15 -0400
parents ca39c21fa4b8
children 09f32aac8fbc
files src/ChangeLog src/DLD-FUNCTIONS/fltk_backend.cc src/genprops.awk src/graphics.cc src/graphics.h.in
diffstat 5 files changed, 328 insertions(+), 109 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Tue Aug 26 13:23:27 2008 -0400
+++ b/src/ChangeLog	Tue Aug 26 13:24:15 2008 -0400
@@ -1,3 +1,57 @@
+2008-08-26  Michael Goffioul  <michael.goffioul@gmail.com>
+
+	* DLD_FUNCTIONS/fltk_backend.cc (fltk_backend::close_figure): Remove.
+	(fltk_backend::object_destroyed, fltk_backend::property_changed): New
+	methods.
+	* genprops.awk (emit_declarations): Generate "enum" property fields.
+	(emit_sources): Emit set_id calls.
+	* graphics.h.in (base_property::id): New field.
+	(base_property::base_property): Initialize it.
+	(base_property::get_id, base_property::set_id): Add accessors.
+	(property::get_id, property::set_id): Likewise.
+	(base_graphics_backend::close_figure, graphics_backend::close_figure):
+	Remove methods.
+	(base_graphics_backend::redraw_figure,
+	base_graphics_backend::print_figure, graphics_backend::redraw_figure,
+	graphics_backend::print_figure): Change graphics_handle argument into
+	graphics_object.
+	(base_graphics_backend::property_changed,
+	base_graphics_backend::object_created,
+	base_graphics_backend::object_destroyed,
+	graphics_backend::property_changed, graphics_backend::object_created,
+	graphics_backend::object_destroyed): New signature with
+	graphics_object argument.
+	(base_properties::base_properties): Add set_id calls.
+	(class base_properties): Add "enum" property fields.
+	(root_figure::properties::remove_child): Add overloaded method.
+	(figure::properties::close): Remove.
+	(figure::properties::set_backend): Call object_destroyed instead of
+	close.
+	(figure::~figure): Remove close call.
+	(figure::properties::get_title): New method.
+	* graphics.cc (base_property::set): Call property_changed only for
+	valid id (>=0); Use graphics_object argument.
+	(gh_manager::do_free): Call object_destroyed with graphics_object
+	argument.
+	(base_graphics_backend::property_changed,
+	base_graphics_backend::object_created,
+	base_graphics_object::object_destroyed): Implement wrappers for
+	graphics_handle argument case.
+	(gnuplot_backend::close_figure): Remove.
+	(gnuplot_backend::object_destroyed,
+	gnuplot_backend::property_changed): New methods.
+	(gnuplot_backend::redraw_figure, gnuplot_backend::print_figure):
+	Change graphics_handle argument to graphics_object.
+	(root_figure::properties::remove_child): Add.
+	(figure::properties::close): Remove.
+	(figure::properties::set_position): Do not call set_figure_position.
+	(figure::properties::get_title): New method.
+	(gh_manager::do_make_graphics_handle): Call object_created with
+	a graphics_object argument.
+	(gh_manager::do_make_figure_handle): Likewise.
+	(Fdrawnow): Call redraw_figure and print_figure with a graphics_object
+	argument.
+
 2008-08-26  Maciek Gajewski <maciej.gajewski0@gmail.com>
 
 	* graphics.h.in (base_property::set): Remove inline implementation.
--- a/src/DLD-FUNCTIONS/fltk_backend.cc	Tue Aug 26 13:23:27 2008 -0400
+++ b/src/DLD-FUNCTIONS/fltk_backend.cc	Tue Aug 26 13:24:15 2008 -0400
@@ -696,10 +696,31 @@
 
   bool is_valid (void) const { return true; }
 
-  void close_figure (const octave_value& ov) const
+  void object_destroyed (const graphics_object& go)
+  {
+    if (go.isa ("figure"))
+      {
+	octave_value ov = go.get (caseless_str ("__plot_stream__"));
+	figure_manager::Instance ().delete_window (ov.string_value ());
+      }
+  }
+
+  void property_changed (const graphics_object& go, int id)
   {
-    if (ov.is_string ())
-      figure_manager::Instance ().delete_window (ov.string_value ());
+    if (go.isa ("figure"))
+      {
+	octave_value ov = go.get (caseless_str ("__plot_stream__"));
+	
+	if (! ov.is_empty ())
+	  {
+	    switch (id)
+	      {
+	      case base_properties::VISIBLE:
+		// FIXME: something to do here
+		break;
+	      }
+	  }
+      }
   }
 
   void redraw_figure (const graphics_handle& fh) const
--- a/src/genprops.awk	Tue Aug 26 13:23:27 2008 -0400
+++ b/src/genprops.awk	Tue Aug 26 13:24:15 2008 -0400
@@ -260,6 +260,18 @@
 
   if (idx > 0)
     print "\npublic:\n";
+  
+  if (idx > 0)
+  {
+    printf ("  enum\n  {");
+    for (i = 1; i <= idx; i++)
+    {
+      printf ("%s\n    %s = %d", (i == 1 ? "" : ","), toupper(name[i]), pcount);
+      pcount++;
+    }
+    printf ("\n  };\n\n");
+    pcount = (int(pcount/1000)+1)*1000;
+  }
 
   for (i = 1; i <= idx; i++)
   {
@@ -325,7 +337,8 @@
           printf ("        set_%smode (\"manual\");\n", name[i]);
 	if (has_builtin_listeners)
 	  printf ("        %s.run_listeners (POSTSET);\n", name[i]);
-        printf ("        mark_modified ();\n      }\n  }\n\n");
+        printf ("        mark_modified ();\n");
+        printf ("      }\n  }\n\n");
       }
       else
         printf (";\n\n");
@@ -380,6 +393,7 @@
     for (i = 1; i <= idx; i++)
     {
 ##    printf ("  insert_static_property (\"%s\", %s);\n", name[i], name[i]) >> filename;
+      printf ("  %s.set_id (%s);\n", name[i], toupper(name[i])) >> filename;
       if (hidden[i])
         printf ("  %s.set_hidden (true);\n", name[i]) >> filename;
     }
@@ -492,6 +506,7 @@
   filename = "graphics-props.cc";
   printf ("// DO NOT EDIT!  Generated automatically by genprops.awk.\n\n");
   printf ("// DO NOT EDIT!  Generated automatically by genprops.awk.\n\n") > filename;
+  pcount = 1000;
 }
 
 /BEGIN_PROPERTIES\(.*\)/ {
--- a/src/graphics.cc	Tue Aug 26 13:23:27 2008 -0400
+++ b/src/graphics.cc	Tue Aug 26 13:24:15 2008 -0400
@@ -33,6 +33,7 @@
 #include <map>
 #include <set>
 #include <string>
+#include <sstream>
 
 #include "file-ops.h"
 #include "file-stat.h"
@@ -464,12 +465,15 @@
   do_set (v);
 
   // notify backend
-  graphics_object go = gh_manager::get_object (parent);
-  if (go)
+  if (id >= 0)
     {
-      graphics_backend backend = go.get_backend();
-      if (backend)
-        backend.property_changed (parent, name);
+      graphics_object go = gh_manager::get_object (parent);
+      if (go)
+	{
+	  graphics_backend backend = go.get_backend();
+	  if (backend)
+	    backend.property_changed (go, id);
+	}
     }
   
   // run listeners
@@ -1189,13 +1193,16 @@
 
 	  if (p != handle_map.end ())
 	    {
+	      // FIXME: should we explicitely free all children first?
+	      //        => call delete_children () ?
+
 	      p->second.get_properties ().set_beingdeleted (true);
 	      p->second.get_properties ().execute_deletefcn ();
 
 	      // notify backend
 	      graphics_backend backend = p->second.get_backend ();
 	      if (backend)
-                backend.object_destroyed (h);
+                backend.object_destroyed (p->second);
                  // note - this will be valid only for first explicitly deleted object.
                  // All his children will have unknown backend then.
                  
@@ -1342,6 +1349,31 @@
 
 // ---------------------------------------------------------------------
 
+void
+base_graphics_backend::property_changed (const graphics_handle& h, int id)
+{
+  graphics_object go = gh_manager::get_object (h);
+
+  property_changed (go, id);
+}
+
+void
+base_graphics_backend::object_created (const graphics_handle& h)
+{
+  graphics_object go = gh_manager::get_object (h);
+
+  object_created (go);
+}
+
+void
+base_graphics_backend::object_destroyed (const graphics_handle& h)
+{
+  graphics_object go = gh_manager::get_object (h);
+
+  object_destroyed (go);
+}
+// ---------------------------------------------------------------------
+
 static int
 compare (const void *a_arg, const void *b_arg)
 {
@@ -1763,8 +1795,76 @@
   ~gnuplot_backend (void) { }
 
   bool is_valid (void) const { return true; }
- 
-  void close_figure (const octave_value& pstream) const
+
+  void object_destroyed (const graphics_object& go)
+    {
+      if (go.isa ("figure"))
+	{
+	  const figure::properties& props =
+	      dynamic_cast<const figure::properties&> (go.get_properties ());
+
+	  send_quit (props.get___plot_stream__ ());
+	}
+    }
+
+  void property_changed (const graphics_object& go, int id)
+    {
+      if (go.isa ("figure"))
+	{
+	  graphics_object obj (go);
+
+	  figure::properties& props =
+	      dynamic_cast<figure::properties&> (obj.get_properties ());
+
+	  switch (id)
+	    {
+	    case base_properties::VISIBLE:
+	      if (! props.is_visible ())
+		{
+		  send_quit (props.get___plot_stream__ ());
+		  props.set___plot_stream__ (Matrix ());
+		  props.set___enhanced__ (false);
+		}
+	      break;
+	    }
+	}
+    }
+
+  void redraw_figure (const graphics_object& go) const
+    {
+      octave_value_list args;
+      args(0) = go.get_handle ().as_octave_value ();
+      feval ("gnuplot_drawnow", args);
+    }
+
+  void print_figure (const graphics_object& go, const std::string& term,
+		     const std::string& file, bool mono,
+		     const std::string& debug_file) const
+    {
+      octave_value_list args;
+      if (! debug_file.empty ())
+	args(4) = debug_file;
+      args(3) = mono;
+      args(2) = file;
+      args(1) = term;
+      args(0) = go.get_handle ().as_octave_value ();
+      feval ("gnuplot_drawnow", args);
+    }
+
+  Matrix get_canvas_size (const graphics_handle&) const
+    {
+      Matrix sz (1, 2, 0.0);
+      return sz;
+    }
+
+  double get_screen_resolution (void) const
+    { return 72.0; }
+
+  Matrix get_screen_size (void) const
+    { return Matrix (1, 2, 0.0); }
+
+private:
+  void send_quit (const octave_value& pstream) const
     {
       if (! pstream.is_empty())
 	{
@@ -1787,39 +1887,6 @@
 	    }
 	}
     }
-
-  void redraw_figure (const graphics_handle& fh) const
-    {
-      octave_value_list args;
-      args(0) = fh.as_octave_value ();
-      feval ("gnuplot_drawnow", args);
-    }
-
-  void print_figure (const graphics_handle& fh, const std::string& term,
-		     const std::string& file, bool mono,
-		     const std::string& debug_file) const
-    {
-      octave_value_list args;
-      if (! debug_file.empty ())
-	args(4) = debug_file;
-      args(3) = mono;
-      args(2) = file;
-      args(1) = term;
-      args(0) = fh.as_octave_value ();
-      feval ("gnuplot_drawnow", args);
-    }
-
-  Matrix get_canvas_size (const graphics_handle&) const
-    {
-      Matrix sz (1, 2, 0.0);
-      return sz;
-    }
-
-  double get_screen_resolution (void) const
-    { return 72.0; }
-
-  Matrix get_screen_size (void) const
-    { return Matrix (1, 2, 0.0); }
 };
 
 graphics_backend
@@ -1903,6 +1970,18 @@
     gripe_set_invalid ("callbackobject");
 }
 
+void
+root_figure::properties::remove_child (const graphics_handle& gh)
+{
+  gh_manager::pop_figure (gh);
+
+  graphics_handle cf = gh_manager::current_figure ();
+
+  xset (0, "currentfigure", cf.value ());
+  
+  base_properties::remove_child (gh);
+}
+
 property_list
 root_figure::factory_properties = root_figure::init_factory_properties ();
 
@@ -1936,22 +2015,6 @@
     }
 }
 
-void
-figure::properties::close (bool pop)
-{
-  if (backend)
-    backend.close_figure (get___plot_stream__ ());
-
-  if (pop)
-    {
-      gh_manager::pop_figure (__myhandle__);
-
-      graphics_handle cf = gh_manager::current_figure ();
-
-      xset (0, "currentfigure", cf.value ());
-    }
-}
-
 Matrix
 figure::properties::get_boundingbox (bool) const
 {
@@ -1999,9 +2062,6 @@
 
       if (old_bb != new_bb)
 	{
-	  // FIXME: maybe this should be converted into a more generic
-	  //        call like "update_gui (this)"
-	  get_backend ().set_figure_position (__myhandle__, new_bb);
 	  if (old_bb(2) != new_bb(2) || old_bb(3) != new_bb(3))
 	    {
 	      execute_resizefcn ();
@@ -2013,6 +2073,24 @@
     }
 }
 
+std::string
+figure::properties::get_title (void) const
+{
+  if (is_numbertitle ())
+    {
+      std::ostringstream os;
+      std::string name = get_name ();
+
+      os << "Figure " << __myhandle__.value ();
+      if (! name.empty ())
+	os << ": " << get_name ();
+
+      return os.str ();
+    }
+  else
+    return get_name ();
+}
+
 octave_value
 figure::get_default (const caseless_str& name) const
 {
@@ -3548,14 +3626,16 @@
   
   if (go)
     {
-      handle_map[h] = graphics_object (go);
+      graphics_object obj (go);
+
+      handle_map[h] = obj;
       if (do_createfcn)
         go->get_properties ().execute_createfcn ();
 
       // notify backend
       graphics_backend backend = go->get_backend ();
       if (backend)
-        backend.object_created (h);
+        backend.object_created (obj);
     }
   else
     error ("gh_manager::do_make_graphics_handle: invalid object type `%s'",
@@ -3570,12 +3650,14 @@
   graphics_handle h = val;
 
   base_graphics_object* go = new figure (h, 0);
-  handle_map[h] = graphics_object (go);
+  graphics_object obj (go);
+
+  handle_map[h] = obj;
 
   // notify backend
   graphics_backend backend = go->get_backend ();
   if (backend)
-    backend.object_created (h);
+    backend.object_created (obj);
   
   return h;
 }
@@ -4563,16 +4645,11 @@
 			{
 			  gh_manager::unlock ();
 
-			  fprops.get_backend ().redraw_figure (h);
+			  fprops.get_backend ().redraw_figure (go);
 
 			  gh_manager::lock ();
 			}
-		      else if (! fprops.get___plot_stream__ ().is_empty ())
-			{
-			  fprops.close (false);
-			  fprops.set___plot_stream__ (Matrix ());
-			  fprops.set___enhanced__ (false);
-			}
+
 		      fprops.set_modified (false);
 		    }
 		}
@@ -4641,7 +4718,7 @@
 			      gh_manager::unlock ();
 
 			      go.get_backend ()
-				.print_figure (h, term, file, mono, debug_file);
+				.print_figure (go, term, file, mono, debug_file);
 
 			      gh_manager::lock ();
 			    }
--- a/src/graphics.h.in	Tue Aug 26 13:23:27 2008 -0400
+++ b/src/graphics.h.in	Tue Aug 26 13:24:15 2008 -0400
@@ -348,13 +348,13 @@
   friend class property;
 
 public:
-  base_property (void) : count (1) { }
+  base_property (void) : id (-1), count (1) { }
 
   base_property (const std::string& s, const graphics_handle& h)
-    : count (1), name (s), parent (h), hidden (false) { }
+    : id (-1), count (1), name (s), parent (h), hidden (false) { }
 
   base_property (const base_property& p)
-    : count (1), name (p.name), parent (p.parent), hidden (p.hidden) { }
+    : id (-1), count (1), name (p.name), parent (p.parent), hidden (p.hidden) { }
 
   virtual ~base_property (void) { }
 
@@ -372,6 +372,10 @@
 
   void set_hidden (bool flag) { hidden = flag; }
 
+  int get_id (void) const { return id; }
+
+  void set_id (int d) { id = d; }
+
   // Sets property value, notifies backend.
   // If do_run is true, runs associated listeners.
   void set (const octave_value& v, bool do_run = true);
@@ -409,6 +413,7 @@
   typedef std::map<listener_mode, octave_value_list>::const_iterator listener_map_const_iterator;
 
 private:
+  int id;
   int count;
   std::string name;
   graphics_handle parent;
@@ -1190,6 +1195,12 @@
   void set_hidden (bool flag)
     { rep->set_hidden (flag); }
 
+  int get_id (void) const
+    { return rep->get_id (); }
+
+  void set_id (int d)
+    { rep->set_id (d); }
+
   octave_value get (void) const
     { return rep->get (); }
 
@@ -1299,6 +1310,7 @@
 // ---------------------------------------------------------------------
 
 class graphics_backend;
+class graphics_object;
 
 class base_graphics_backend
 {
@@ -1315,13 +1327,10 @@
 
   virtual bool is_valid (void) const { return false; }
 
-  virtual void close_figure (const octave_value& /*pstream*/) const
-    { gripe_invalid ("close_figure"); }
-
-  virtual void redraw_figure (const graphics_handle&) const
+  virtual void redraw_figure (const graphics_object&) const
     { gripe_invalid ("redraw_figure"); }
 
-  virtual void print_figure (const graphics_handle&, const std::string&,
+  virtual void print_figure (const graphics_object&, const std::string&,
 			     const std::string&, bool,
 			     const std::string& = "") const
     { gripe_invalid ("print_figure"); }
@@ -1344,21 +1353,24 @@
       return Matrix (1, 2, 0.0);
     }
 
-  virtual void set_figure_position (const graphics_handle&, const Matrix&) const
-    { gripe_invalid ("set_figure_position"); }
-
   // Called when graphics object using this backend changes it's property.
-  virtual void property_changed (const graphics_handle&, const std::string&)
+  virtual void property_changed (const graphics_object&, int)
     { gripe_invalid ("property_changed"); }
+
+  void property_changed (const graphics_handle&, int);
   
   // Called when new object using this backend is created.
-  virtual void object_created (const graphics_handle&)
+  virtual void object_created (const graphics_object&)
     { gripe_invalid ("object_created"); }
 
+  void object_created (const graphics_handle&);
+
   // Called when object using this backend is destroyed.
-  virtual void object_destroyed (const graphics_handle&)
+  virtual void object_destroyed (const graphics_object&)
     { gripe_invalid ("object_destroyed"); }
 
+  void object_destroyed (const graphics_handle&);
+
 private:
   std::string name;
   int count;
@@ -1416,16 +1428,13 @@
 
   std::string get_name (void) const { return rep->get_name (); }
 
-  void close_figure (const octave_value& pstream) const
-    { rep->close_figure (pstream); }
-
-  void redraw_figure (const graphics_handle& fh) const
-    { rep->redraw_figure (fh); }
+  void redraw_figure (const graphics_object& go) const
+    { rep->redraw_figure (go); }
   
-  void print_figure (const graphics_handle& fh, const std::string& term,
+  void print_figure (const graphics_object& go, const std::string& term,
 		     const std::string& file, bool mono,
 		     const std::string& debug_file = "") const
-    { rep->print_figure (fh, term, file, mono, debug_file); }
+    { rep->print_figure (go, term, file, mono, debug_file); }
 
   Matrix get_canvas_size (const graphics_handle& fh) const
     { return rep->get_canvas_size (fh); }
@@ -1436,20 +1445,26 @@
   Matrix get_screen_size (void) const
     { return rep->get_screen_size (); }
 
-  void set_figure_position (const graphics_handle& h, const Matrix& pos) const
-    { rep->set_figure_position (h, pos); }
+  // Notifies backend that object't property has changed.
+  void property_changed (const graphics_object& go, int id)
+    { rep->property_changed (go, id); }
   
-  // Notifies backend that object't property has changed.
-  void property_changed (const graphics_handle& h, const std::string& prop)
-    { rep->property_changed (h, prop); }
+  void property_changed (const graphics_handle& h, int id)
+    { rep->property_changed (h, id); }
 
   // Notifies backend that new object was created.
+  void object_created (const graphics_object& go)
+    { rep->object_created (go); }
+  
   void object_created (const graphics_handle& h)
     { rep->object_created (h); }
   
   // Notifies backend that object was destroyed.
   // This is called only for explicitly deleted object. Children are
   // deleted implicitly and backend isn't notified.
+  void object_destroyed (const graphics_object& go)
+    { rep->object_destroyed (go); }
+  
   void object_destroyed (const graphics_handle& h)
     { rep->object_destroyed (h); }
   
@@ -1482,7 +1497,6 @@
 
     return m;
   }
-	
 
 private:
   base_graphics_backend *rep;
@@ -1523,7 +1537,23 @@
       __modified__ ("__modified__", mh, true),
       __myhandle__ (mh),
       uicontextmenu ("uicontextmenu", mh, graphics_handle ())
-    { }
+    {
+      beingdeleted.set_id (BEINGDELETED);
+      busyaction.set_id (BUSYACTION);
+      buttondownfcn.set_id (BUTTONDOWNFCN);
+      clipping.set_id (CLIPPING);
+      createfcn.set_id (CREATEFCN);
+      deletefcn.set_id (DELETEFCN);
+      handlevisibility.set_id (HANDLEVISIBILITY);
+      hittest.set_id (HITTEST);
+      interruptible.set_id (INTERRUPTIBLE);
+      parent.set_id (PARENT);
+      selected.set_id (SELECTED);
+      selectionhighlight.set_id (SELECTIONHIGHLIGHT);
+      tag.set_id (TAG);
+      userdata.set_id (USERDATA);
+      visible.set_id (VISIBLE);
+    }
 
   virtual ~base_properties (void) { }
 
@@ -1787,7 +1817,27 @@
   virtual bool is_zliminclude (void) const { return false; }
   virtual bool is_climinclude (void) const { return false; }
   virtual bool is_aliminclude (void) const { return false; }
-  
+ 
+  enum
+    {
+      BEINGDELETED = 0,
+      BUSYACTION,
+      BUTTONDOWNFCN,
+      // CHILDREN,
+      CLIPPING,
+      CREATEFCN,
+      DELETEFCN,
+      HANDLEVISIBILITY,
+      HITTEST,
+      INTERRUPTIBLE,
+      PARENT,
+      SELECTED,
+      SELECTIONHIGHLIGHT,
+      TAG,
+      USERDATA,
+      VISIBLE
+    };
+
 protected:
   // properties common to all objects
   bool_property beingdeleted;
@@ -2195,6 +2245,8 @@
   class OCTINTERP_API properties : public base_properties
   {
   public:
+    void remove_child (const graphics_handle& h);
+    
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
@@ -2311,8 +2363,6 @@
   class OCTINTERP_API properties : public base_properties
   {
   public:
-    void close (bool pop = true);
-
     void set_visible (const octave_value& val);
 
     graphics_backend get_backend (void) const
@@ -2325,7 +2375,8 @@
 
     void set_backend (const graphics_backend& b) 
     { 
-      close (false);
+      if (backend)
+	backend.object_destroyed (__myhandle__);
       backend = b; 
       __backend__ = b.get_name ();
       __plot_stream__ = Matrix ();
@@ -2359,6 +2410,8 @@
 
     void set_boundingbox (const Matrix& bb);
 
+    std::string get_title (void) const;
+
     // See the genprops.awk script for an explanation of the
     // properties declarations.
 
@@ -2444,7 +2497,6 @@
   ~figure (void)
   {
     xproperties.delete_children (); 
-    xproperties.close ();
   }
 
   void override_defaults (base_graphics_object& obj)