# HG changeset patch # User John W. Eaton # Date 1323447170 18000 # Node ID e3bed294b11776b0ba6f6b670af35b841955c7c9 # Parent caf69ec5b94c716af820a1272ab74878d2610d23 refactor graphics_toolkit class (bug #31583) * graphics_toolkit.m: Call loaded_graphics_toolkits to check whether the given toolkit was correctly loaded. * graphics.cc (gnuplot_toolkit): Move to separate file. * __init_gnuplot__.cc: New file, split from graphics.cc. * DLD-FUNCTIONS/module-files: Include __init_gnuplot__.cc in the list. * graphics.h.in, graphics.cc (gtk_manager): New class, extracted from graphics_toolkit, to manage the available and loaded graphics_toolkits. Change all uses of moved functions. * __init_fltk__.cc: Add PKG_ADD line to register toolkit. (toolkit_loaded): Rename from toolkit_registered. * graphics.cc (Fregister_graphics_toolkit, Floaded_graphics_toolkits): New functions. diff -r caf69ec5b94c -r e3bed294b117 scripts/plot/graphics_toolkit.m --- a/scripts/plot/graphics_toolkit.m Fri Dec 09 08:53:44 2011 -0500 +++ b/scripts/plot/graphics_toolkit.m Fri Dec 09 11:12:50 2011 -0500 @@ -52,10 +52,10 @@ endif endif - if (! any (strcmp (available_graphics_toolkits (), name))) + if (! any (strcmp (loaded_graphics_toolkits (), name))) feval (["__init_", name, "__"]); - if (! any (strcmp (available_graphics_toolkits (), name))) - error ("graphics_toolkit: %s toolkit was not correctly registered", name); + if (! any (strcmp (loaded_graphics_toolkits (), name))) + error ("graphics_toolkit: %s toolkit was not correctly loaded", name); endif endif diff -r caf69ec5b94c -r e3bed294b117 src/DLD-FUNCTIONS/__init_fltk__.cc --- a/src/DLD-FUNCTIONS/__init_fltk__.cc Fri Dec 09 08:53:44 2011 -0500 +++ b/src/DLD-FUNCTIONS/__init_fltk__.cc Fri Dec 09 11:12:50 2011 -0500 @@ -29,6 +29,8 @@ */ +// PKG_ADD: register_graphics_toolkit ("fltk"); + #ifdef HAVE_CONFIG_H #include #endif @@ -1769,12 +1771,12 @@ std::string figure_manager::fltk_idx_header="fltk index="; int figure_manager::curr_index = 1; -static bool toolkit_registered = false; +static bool toolkit_loaded = false; static int __fltk_redraw__ (void) { - if (toolkit_registered) + if (toolkit_loaded) { // We scan all figures and add those which use FLTK. graphics_object obj = gh_manager::get_object (0); @@ -1941,13 +1943,13 @@ void close (void) { - if (toolkit_registered) + if (toolkit_loaded) { munlock ("__init_fltk__"); figure_manager::close_all (); - graphics_toolkit::unregister_toolkit (FLTK_GRAPHICS_TOOLKIT_NAME); - toolkit_registered = false; + gtk_manager::unload_toolkit (FLTK_GRAPHICS_TOOLKIT_NAME); + toolkit_loaded = false; octave_value_list args; args(0) = "__fltk_redraw__"; @@ -1963,12 +1965,13 @@ DEFUN_DLD (__init_fltk__, , , "") { - if (! toolkit_registered) + if (! toolkit_loaded) { mlock (); - graphics_toolkit::register_toolkit (new fltk_graphics_toolkit); - toolkit_registered = true; + graphics_toolkit tk (new fltk_graphics_toolkit ()); + gtk_manager::load_toolkit (tk); + toolkit_loaded = true; octave_value_list args; args(0) = "__fltk_redraw__"; diff -r caf69ec5b94c -r e3bed294b117 src/DLD-FUNCTIONS/__init_gnuplot__.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/DLD-FUNCTIONS/__init_gnuplot__.cc Fri Dec 09 11:12:50 2011 -0500 @@ -0,0 +1,193 @@ +/* + +Copyright (C) 2007-2011 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 3 of the License, 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, see +. + +*/ + +/* + +To initialize: + + graphics_toolkit ("gnuplot"); + plot (randn (1e3, 1)); + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "defun-dld.h" +#include "error.h" +#include "graphics.h" +#include "parse.h" +#include "variables.h" + +// PKG_ADD: register_graphics_toolkit ("gnuplot"); + +static bool toolkit_loaded = false; + +class gnuplot_graphics_toolkit : public base_graphics_toolkit +{ +public: + gnuplot_graphics_toolkit (void) + : base_graphics_toolkit ("gnuplot") { } + + ~gnuplot_graphics_toolkit (void) { } + + bool is_valid (void) const { return true; } + + bool initialize (const graphics_object& go) + { + return go.isa ("figure"); + } + + void finalize (const graphics_object& go) + { + if (go.isa ("figure")) + { + const figure::properties& props = + dynamic_cast (go.get_properties ()); + + send_quit (props.get___plot_stream__ ()); + } + } + + void update (const graphics_object& go, int id) + { + if (go.isa ("figure")) + { + graphics_object obj (go); + + figure::properties& props = + dynamic_cast (obj.get_properties ()); + + switch (id) + { + case base_properties::ID_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); } + + void close (void) + { + if (toolkit_loaded) + { + munlock ("__init_gnuplot__"); + + gtk_manager::unload_toolkit ("gnuplot"); + + toolkit_loaded = false; + } + } + +private: + + void send_quit (const octave_value& pstream) const + { + if (! pstream.is_empty ()) + { + octave_value_list args; + Matrix fids = pstream.matrix_value (); + + if (! error_state) + { + args(1) = "\nquit;\n"; + args(0) = fids(0); + feval ("fputs", args); + + args.resize (1); + feval ("fflush", args); + feval ("pclose", args); + + if (fids.numel () > 1) + { + args(0) = fids(1); + feval ("pclose", args); + + if (fids.numel () > 2) + { + args(0) = fids(2); + feval ("waitpid", args); + } + } + } + } + } +}; + +// Initialize the fltk graphics toolkit. + +DEFUN_DLD (__init_gnuplot__, , , "") +{ + octave_value retval; + + if (! toolkit_loaded) + { + mlock (); + + graphics_toolkit tk (new gnuplot_graphics_toolkit ()); + gtk_manager::load_toolkit (tk); + + toolkit_loaded = true; + } + + return retval; +} + diff -r caf69ec5b94c -r e3bed294b117 src/DLD-FUNCTIONS/module-files --- a/src/DLD-FUNCTIONS/module-files Fri Dec 09 08:53:44 2011 -0500 +++ b/src/DLD-FUNCTIONS/module-files Fri Dec 09 11:12:50 2011 -0500 @@ -6,6 +6,7 @@ __fltk_uigetfile__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS) __glpk__.cc|$(GLPK_CPPFLAGS)|$(GLPK_LDFLAGS)|$(GLPK_LIBS) __init_fltk__.cc|$(GRAPHICS_CFLAGS) $(FT2_CPPFLAGS)|$(GRAPHICS_LDFLAGS) $(FT2_LDFLAGS)|$(GRAPHICS_LIBS) $(FT2_LIBS) +__init_gnuplot__.cc __lin_interpn__.cc __magick_read__.cc|$(MAGICK_CPPFLAGS)|$(MAGICK_LDFLAGS)|$(MAGICK_LIBS) __pchip_deriv__.cc diff -r caf69ec5b94c -r e3bed294b117 src/graphics.cc --- a/src/graphics.cc Fri Dec 09 08:53:44 2011 -0500 +++ b/src/graphics.cc Fri Dec 09 11:12:50 2011 -0500 @@ -2763,137 +2763,6 @@ // --------------------------------------------------------------------- -class gnuplot_toolkit : public base_graphics_toolkit -{ -public: - gnuplot_toolkit (void) - : base_graphics_toolkit ("gnuplot") { } - - ~gnuplot_toolkit (void) { } - - bool is_valid (void) const { return true; } - - bool initialize (const graphics_object& go) - { - return go.isa ("figure"); - } - - void finalize (const graphics_object& go) - { - if (go.isa ("figure")) - { - const figure::properties& props = - dynamic_cast (go.get_properties ()); - - send_quit (props.get___plot_stream__ ()); - } - } - - void update (const graphics_object& go, int id) - { - if (go.isa ("figure")) - { - graphics_object obj (go); - - figure::properties& props = - dynamic_cast (obj.get_properties ()); - - switch (id) - { - case base_properties::ID_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); } - - void close (void) { } - -private: - void send_quit (const octave_value& pstream) const - { - if (! pstream.is_empty ()) - { - octave_value_list args; - Matrix fids = pstream.matrix_value (); - - if (! error_state) - { - args(1) = "\nquit;\n"; - args(0) = fids(0); - feval ("fputs", args); - - args.resize (1); - feval ("fflush", args); - feval ("pclose", args); - - if (fids.numel () > 1) - { - args(0) = fids(1); - feval ("pclose", args); - - if (fids.numel () > 2) - { - args(0) = fids(2); - feval ("waitpid", args); - } - } - } - } - } -}; - -graphics_toolkit -graphics_toolkit::default_toolkit (void) -{ - if (available_toolkits.size () == 0) - register_toolkit (new gnuplot_toolkit ()); - - return available_toolkits["gnuplot"]; -} - -std::map graphics_toolkit::available_toolkits; - -// --------------------------------------------------------------------- - void base_graphics_object::update_axis_limits (const std::string& axis_type) { @@ -7505,7 +7374,7 @@ handle_map[0] = graphics_object (new root_figure ()); // Make sure the default graphics toolkit is registered. - graphics_toolkit::default_toolkit (); + gtk_manager::default_toolkit (); } void @@ -9076,6 +8945,52 @@ return retval; } +gtk_manager *gtk_manager::instance = 0; + +void +gtk_manager::create_instance (void) +{ + instance = new gtk_manager (); + + if (instance) + singleton_cleanup_list::add (cleanup_instance); +} + +graphics_toolkit +gtk_manager::do_get_toolkit (void) const +{ + graphics_toolkit retval; + + const_loaded_toolkits_iterator pl = loaded_toolkits.find (dtk); + + if (pl == loaded_toolkits.end ()) + { + const_available_toolkits_iterator pa = available_toolkits.find (dtk); + + if (pa != available_toolkits.end ()) + { + octave_value_list args; + args(0) = dtk; + feval ("graphics_toolkit", args); + + if (! error_state) + pl = loaded_toolkits.find (dtk); + + if (error_state || pl == loaded_toolkits.end ()) + error ("failed to load %s graphics toolkit", dtk.c_str ()); + else + retval = pl->second; + } + else + error ("default graphics toolkit `%s' is not available!", + dtk.c_str ()); + } + else + retval = pl->second; + + return retval; +} + DEFUN (available_graphics_toolkits, , , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} available_graphics_toolkits ()\n\ @@ -9084,7 +8999,43 @@ { gh_manager::auto_lock guard; - return octave_value (graphics_toolkit::available_toolkits_list ()); + return octave_value (gtk_manager::available_toolkits_list ()); +} + +DEFUN (register_graphics_toolkit, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} register_graphics_toolkit (@var{toolkit})\n\ +List @var{toolkit} as an available graphics toolkit.\n\ +@end deftypefn") +{ + octave_value retval; + + gh_manager::auto_lock guard; + + if (args.length () == 1) + { + std::string name = args(0).string_value (); + + if (! error_state) + gtk_manager::register_toolkit (name); + else + error ("register_graphics_toolkit: expecting character string"); + } + else + print_usage (); + + return retval; +} + +DEFUN (loaded_graphics_toolkits, , , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} loaded_graphics_toolkits ()\n\ +Return a cell array of the currently loaded graphics toolkits.\n\ +@end deftypefn") +{ + gh_manager::auto_lock guard; + + return octave_value (gtk_manager::loaded_toolkits_list ()); } DEFUN (drawnow, args, , diff -r caf69ec5b94c -r e3bed294b117 src/graphics.h.in --- a/src/graphics.h.in Fri Dec 09 08:53:44 2011 -0500 +++ b/src/graphics.h.in Fri Dec 09 11:12:50 2011 -0500 @@ -2236,65 +2236,197 @@ // Close the graphics toolkit. void close (void) { rep->close (); } - OCTINTERP_API static graphics_toolkit default_toolkit (void); - - static void register_toolkit (const graphics_toolkit& b) - { available_toolkits[b.get_name ()] = b; } +private: + + base_graphics_toolkit *rep; +}; + +class gtk_manager +{ +public: + + static graphics_toolkit get_toolkit (void) + { + return instance_ok () ? instance->do_get_toolkit () : graphics_toolkit (); + } + + static void register_toolkit (const std::string& name) + { + if (instance_ok ()) + instance->do_register_toolkit (name); + } static void unregister_toolkit (const std::string& name) - { available_toolkits.erase (name); } + { + if (instance_ok ()) + instance->do_unregister_toolkit (name); + } + + static void load_toolkit (const graphics_toolkit& tk) + { + if (instance_ok ()) + instance->do_load_toolkit (tk); + } + + static void unload_toolkit (const std::string& name) + { + if (instance_ok ()) + instance->do_unload_toolkit (name); + } static graphics_toolkit find_toolkit (const std::string& name) { - const_available_toolkits_iterator p = available_toolkits.find (name); - - if (p != available_toolkits.end ()) - return p->second; - else - return default_toolkit (); + return instance_ok () + ? instance->do_find_toolkit (name) : graphics_toolkit (); } static Cell available_toolkits_list (void) { + return instance_ok () ? instance->do_available_toolkits_list () : Cell (); + } + + static Cell loaded_toolkits_list (void) + { + return instance_ok () ? instance->do_loaded_toolkits_list () : Cell (); + } + + static void unload_all_toolkits (void) + { + if (instance_ok ()) + instance->do_unload_all_toolkits (); + } + + static std::string default_toolkit (void) + { + return instance_ok () ? instance->do_default_toolkit () : std::string (); + } + +private: + + // FIXME -- default toolkit should be configurable. + + gtk_manager (void) + : dtk ("gnuplot"), available_toolkits (), loaded_toolkits () { } + + ~gtk_manager (void) { } + + static void create_instance (void); + + static bool instance_ok (void) + { + bool retval = true; + + if (! instance) + create_instance (); + + if (! instance) + { + ::error ("unable to create gh_manager!"); + + retval = false; + } + + return retval; + } + + static void cleanup_instance (void) { delete instance; instance = 0; } + + static gtk_manager *instance; + + // The name of the default toolkit. + std::string dtk; + + // The list of toolkits that we know about. + std::set available_toolkits; + + // The list of toolkits we have actually loaded. + std::map loaded_toolkits; + + typedef std::set::iterator available_toolkits_iterator; + + typedef std::set::const_iterator + const_available_toolkits_iterator; + + typedef std::map::iterator + loaded_toolkits_iterator; + + typedef std::map::const_iterator + const_loaded_toolkits_iterator; + + graphics_toolkit do_get_toolkit (void) const; + + void do_register_toolkit (const std::string& name) + { + available_toolkits.insert (name); + } + + void do_unregister_toolkit (const std::string& name) + { + available_toolkits.erase (name); + } + + void do_load_toolkit (const graphics_toolkit& tk) + { + loaded_toolkits[tk.get_name ()] = tk; + } + + void do_unload_toolkit (const std::string& name) + { + loaded_toolkits.erase (name); + } + + graphics_toolkit do_find_toolkit (const std::string& name) const + { + const_loaded_toolkits_iterator p = loaded_toolkits.find (name); + + if (p != loaded_toolkits.end ()) + return p->second; + else + return graphics_toolkit (); + } + + Cell do_available_toolkits_list (void) const + { Cell m (1 , available_toolkits.size ()); - const_available_toolkits_iterator p; - int i; - - for (i = 0, p = available_toolkits.begin (); - p != available_toolkits.end (); p++, i++) - m(i) = p->first; + + octave_idx_type i = 0; + for (const_available_toolkits_iterator p = available_toolkits.begin (); + p != available_toolkits.end (); p++) + m(i++) = *p; return m; } - static void close_all_toolkits (void) - { - while (! available_toolkits.empty ()) + Cell do_loaded_toolkits_list (void) const + { + Cell m (1 , loaded_toolkits.size ()); + + octave_idx_type i = 0; + for (const_loaded_toolkits_iterator p = loaded_toolkits.begin (); + p != loaded_toolkits.end (); p++) + m(i++) = p->first; + + return m; + } + + void do_unload_all_toolkits (void) + { + while (! loaded_toolkits.empty ()) { - available_toolkits_iterator p = available_toolkits.begin (); + loaded_toolkits_iterator p = loaded_toolkits.begin (); std::string name = p->first; p->second.close (); - // The toolkit may have unregistered itself. If not, we'll do + // The toolkit may have unloaded itself. If not, we'll do // it here. - if (available_toolkits.find (name) != available_toolkits.end ()) - unregister_toolkit (name); + if (loaded_toolkits.find (name) != loaded_toolkits.end ()) + unload_toolkit (name); } } -private: - base_graphics_toolkit *rep; - - static OCTINTERP_API std::map - available_toolkits; - - typedef std::map::iterator - available_toolkits_iterator; - - typedef std::map::const_iterator - const_available_toolkits_iterator; + std::string do_default_toolkit (void) { return dtk; } }; // --------------------------------------------------------------------- @@ -3146,7 +3278,7 @@ graphics_toolkit get_toolkit (void) const { if (! toolkit) - toolkit = graphics_toolkit::default_toolkit (); + toolkit = gtk_manager::get_toolkit (); return toolkit; } @@ -3160,7 +3292,7 @@ if (val.is_string ()) { std::string nm = val.string_value (); - graphics_toolkit b = graphics_toolkit::find_toolkit (nm); + graphics_toolkit b = gtk_manager::find_toolkit (nm); if (b.get_name () != nm) { error ("set___graphics_toolkit__: invalid graphics toolkit"); diff -r caf69ec5b94c -r e3bed294b117 src/toplev.cc --- a/src/toplev.cc Fri Dec 09 08:53:44 2011 -0500 +++ b/src/toplev.cc Fri Dec 09 11:12:50 2011 -0500 @@ -671,7 +671,7 @@ OCTAVE_SAFE_CALL (gh_manager::close_all_figures, ()); - OCTAVE_SAFE_CALL (graphics_toolkit::close_all_toolkits, ()); + OCTAVE_SAFE_CALL (gtk_manager::unload_all_toolkits, ()); OCTAVE_SAFE_CALL (symbol_table::cleanup, ());