Index: src/graphics.h.in =================================================================== RCS file: /cvs/octave/src/graphics.h.in,v retrieving revision 1.47 diff -c -p -r1.47 graphics.h.in *** src/graphics.h.in 19 Jan 2008 07:39:17 -0000 1.47 --- src/graphics.h.in 22 Jan 2008 13:57:27 -0000 *************** public: *** 1052,1058 **** octave_value get_uicontextmenu (void) const { return uicontextmenu.get (); } octave_value get_userdata (void) const { return userdata.get (); } ! std::string get_visible (void) const { return visible.current_value (); } bool is_beingdeleted (void) const { return beingdeleted.is_on (); } --- 1052,1059 ---- octave_value get_uicontextmenu (void) const { return uicontextmenu.get (); } octave_value get_userdata (void) const { return userdata.get (); } ! ! bool is_visible (void) const { return visible.is_on (); } std::string get_visible (void) const { return visible.current_value (); } bool is_beingdeleted (void) const { return beingdeleted.is_on (); } *************** public: *** 1071,1076 **** --- 1072,1079 ---- void set_parent (const octave_value& val); + void set_modified (const octave_value& val) { __modified__ = val; } + void set_busyaction (const octave_value& val) { if (! error_state) *************** private: *** 1632,1637 **** --- 1635,1755 ---- // --------------------------------------------------------------------- + class graphics_backend; + + class base_graphics_backend + { + public: + friend class graphics_backend; + + public: + base_graphics_backend (const std::string& nm) + : name (nm), count (0) { } + + virtual ~base_graphics_backend (void) { } + + std::string get_name (void) const { return name; } + + virtual bool is_valid (void) const { return false; } + + virtual void close_figure (const octave_value&) const + { error ("close_figure: invalid graphics backend"); } + + virtual void redraw_figure (const graphics_handle&) const + { error ("redraw_figure: invalid graphics backend"); } + + virtual void print_figure (const graphics_handle&, const std::string&, + const std::string&, bool, + const std::string& = "") const + { error ("print_figure: invalid graphics backend"); } + + virtual Matrix get_canvas_size (const graphics_handle&) const + { + error ("get_canvas_size: invalid graphics backend"); + return Matrix (1, 2, 0.0); + } + + private: + std::string name; + int count; + }; + + class graphics_backend + { + public: + graphics_backend (void) + : rep (new base_graphics_backend ("unknown")) + { + rep->count++; + } + + graphics_backend (base_graphics_backend* b) + : rep (b) + { + rep->count++; + } + + graphics_backend (const graphics_backend& b) + : rep (b.rep) + { + rep->count++; + } + + ~graphics_backend (void) + { + if (--rep->count == 0) + delete rep; + } + + graphics_backend& operator = (const graphics_backend& b) + { + if (rep != b.rep) + { + if (--rep->count == 0) + delete rep; + + rep = b.rep; + rep->count++; + } + + return *this; + } + + operator bool (void) const { return rep->is_valid (); } + + 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 print_figure (const graphics_handle& fh, 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); } + + Matrix get_canvas_size (const graphics_handle& fh) const + { return rep->get_canvas_size (fh); } + + OCTINTERP_API static graphics_backend default_backend (void); + + static void register_backend (const graphics_backend& b) + { available_backends[b.get_name ()] = b; } + + static void unregister_backend (const std::string& name) + { available_backends.erase (name); } + + private: + base_graphics_backend *rep; + + private: + static std::map available_backends; + }; + + // --------------------------------------------------------------------- + class OCTINTERP_API root_figure : public base_graphics_object { public: *************** public: *** 1744,1752 **** class properties : public base_properties { public: ! void close (void); void set_visible (const octave_value& val); // See the genprops.awk script for an explanation of the // properties declarations. --- 1862,1881 ---- class properties : public base_properties { public: ! void close (bool pop = true); ! void set_visible (const octave_value& val); + graphics_backend get_backend (void) const + { + if (! backend) + backend = graphics_backend::default_backend (); + + return backend; + } + + void set_backend (const graphics_backend& b) { backend = b; } + // See the genprops.awk script for an explanation of the // properties declarations. *************** public: *** 1813,1818 **** --- 1942,1950 ---- pointershapehotspot.add_constraint (dim_vector (1, 2)); position.add_constraint (dim_vector (1, 4)); } + + private: + mutable graphics_backend backend; }; private: *************** public: *** 1881,1886 **** --- 2013,2024 ---- bool valid_object (void) const { return true; } + graphics_backend get_backend (void) const + { return xproperties.get_backend (); } + + void set_backend (const graphics_backend& b) + { xproperties.set_backend (b); } + private: property_list default_properties; }; Index: src/graphics.cc =================================================================== RCS file: /cvs/octave/src/graphics.cc,v retrieving revision 1.76 diff -c -p -r1.76 graphics.cc *** src/graphics.cc 19 Jan 2008 06:08:03 -0000 1.76 --- src/graphics.cc 22 Jan 2008 13:57:27 -0000 *************** along with Octave; see the file COPYING. *** 43,48 **** --- 43,50 ---- #include "ov-fcn-handle.h" #include "parse.h" #include "unwind-prot.h" + #include "file-ops.h" + #include "file-stat.h" static void gripe_set_invalid (const std::string& pname) *************** base_properties::delete_children (void) *** 1146,1151 **** --- 1148,1216 ---- // --------------------------------------------------------------------- + class gnuplot_backend : public base_graphics_backend + { + public: + gnuplot_backend (void) + : base_graphics_backend ("gnuplot") { } + + ~gnuplot_backend (void) { } + + bool is_valid (void) const { return true; } + + void close_figure (const octave_value& pstream) const + { + if (! pstream.is_empty()) + { + octave_value_list args; + args(1) = "\nquit;\n"; + args(0) = pstream; + feval ("fputs", args); + args.resize (1); + feval ("fflush", args); + feval ("pclose", args); + } + } + + 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; + args.resize (4); + args(0) = fh.as_octave_value (); + args(1) = term; + args(2) = file; + args(3) = mono; + if (! debug_file.empty ()) + args(4) = debug_file; + feval ("gnuplot_drawnow", args); + } + + Matrix get_canvas_size (const graphics_handle& fh) const + { return Matrix (1, 2, 0.0); } + }; + + graphics_backend + graphics_backend::default_backend (void) + { + if (available_backends.size () == 0) + register_backend (new gnuplot_backend ()); + + return available_backends["gnuplot"]; + } + + std::map graphics_backend::available_backends; + + // --------------------------------------------------------------------- + #include "graphics-props.cc" // --------------------------------------------------------------------- *************** figure::properties::set_visible (const o *** 1202,1225 **** } void ! figure::properties::close (void) { ! if (! get___plot_stream__ ().is_empty ()) ! { ! octave_value_list args; ! args(1) = "\nquit;\n"; ! args(0) = get___plot_stream__ (); ! feval ("fputs", args); ! args.resize (1); ! feval ("fflush", args); ! feval ("pclose", args); ! } ! gh_manager::pop_figure (__myhandle__); ! graphics_handle cf = gh_manager::current_figure (); ! xset (0, "currentfigure", cf.value ()); } octave_value --- 1267,1285 ---- } 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 ()); ! } } octave_value *************** Undocumented internal function.\n\ *** 2305,2310 **** --- 2365,2494 ---- return octave_value (gh_manager::figure_handle_list ()); } + DEFUN (drawnow, args, , + "-*- texinfo -*-\n\ + @deftypefn {Built-in Function} {} __go_drawnow__ ()\n\ + @deftypefnx {Built-in Function} {} __go_drawnow__ (@var{term}, @var{file}, @var{mono}, @var{debug_file})\n\ + Undocumented internal function.\n\ + @end deftypefn") + { + static int drawnow_executing = 0; + static bool __go_close_all_registered__ = false; + + octave_value retval; + + if (drawnow_executing >= 1) + return retval; + + if (! __go_close_all_registered__) + { + // FIXME: is there a C++ way to do this? + int parse_status; + eval_string ("atexit (\"__go_close_all__\")", true, parse_status); + __go_close_all_registered__ = true; + } + + ++drawnow_executing; + + if (args.length () == 0) + { + Matrix hlist = gh_manager::figure_handle_list (); + + for (int i = 0; ! error_state && i < hlist.length (); i++) + { + graphics_handle h = gh_manager::lookup (hlist(i)); + + if (h.ok () && h != 0) + { + graphics_object go = gh_manager::get_object (h); + figure::properties& fprops = dynamic_cast (go.get_properties ()); + + if (fprops.is_modified ()) + { + if (fprops.is_visible ()) + fprops.get_backend ().redraw_figure (h); + else if (! fprops.get___plot_stream__ ().is_empty ()) + { + fprops.close (false); + fprops.set___plot_stream__ (Matrix ()); + fprops.set___enhanced__ (false); + } + fprops.set_modified (false); + } + } + } + } + else if (args.length () >= 2 && args.length () <= 4) + { + std::string term, file, debug_file; + bool mono; + + term = args(0).string_value (); + + if (! error_state) + { + file = args(1).string_value (); + + if (! error_state) + { + int pos = file.find_last_of (file_ops::dir_sep_chars); + + if (pos != NPOS) + { + file_stat fs (file.substr (0, pos)); + + if (! (fs && fs.is_dir ())) + error ("drawnow: nonexistent directory `%s'", + file.substr (0, pos).c_str ()); + } + + mono = (args.length () >= 3 ? args(2).bool_value () : false); + + if (! error_state) + { + debug_file = (args.length () > 3 ? args(3).string_value () + : ""); + + if (! error_state) + { + graphics_handle h = gcf (); + + if (h.ok ()) + { + graphics_object go = gh_manager::get_object (h); + figure::properties& fprops = dynamic_cast (go.get_properties ()); + + fprops.get_backend () + .print_figure (h, term, file, mono, debug_file); + } + else + error ("drawnow: nothing to draw"); + } + else + error ("drawnow: invalid debug_file, expected a string value"); + } + else + error ("drawnow: invalid colormode, expected a boolean value"); + } + else + error ("drawnow: invalid file, expected a string value"); + } + else + error ("drawnow: invalid terminal, expected a string value"); + } + else + print_usage (); + + // FIXME: is there a C++ way to do this? + octave_value_list fargs; + fargs(0) = false; + feval ("__request_drawnow__", fargs); + + --drawnow_executing; + + return retval; + } + octave_value get_property_from_handle (double handle, const std::string &property, const std::string &func) Index: scripts/plot/Makefile.in =================================================================== RCS file: /cvs/octave/scripts/plot/Makefile.in,v retrieving revision 1.66 diff -c -p -r1.66 Makefile.in *** scripts/plot/Makefile.in 12 Jan 2008 08:00:38 -0000 1.66 --- scripts/plot/Makefile.in 22 Jan 2008 13:57:27 -0000 *************** SOURCES = \ *** 85,91 **** contourc.m \ contourf.m \ cylinder.m \ ! drawnow.m \ ellipsoid.m \ errorbar.m \ ezcontourf.m \ --- 85,91 ---- contourc.m \ contourf.m \ cylinder.m \ ! gnuplot_drawnow.m \ ellipsoid.m \ errorbar.m \ ezcontourf.m \