Mercurial > hg > octave-nkf
diff src/graphics.cc @ 14014:907d03def9d5
explicitly close figures in clean_up_and_exit instead of using an atexit function
* graphics.cc (Fdrawnow): Don't register __go_close_all__ as an atexit
function.
* __go_close_all__.m: Delete.
* plot/module.mk (plot_FCN_FILES): Remove __go_close_all__.m from the
list.
* graphics.cc (gh_manager::create_instance): Do register cleanup
function.
* graphics.cc (delete_graphics_objects, delete_graphics_object,
close_figure, force_close_figure): New functions.
(F__go_delete__): Call delete_graphics_objects to do the work.
* graphics.h, graphics.cc (gh_manager::close_all_figures,
gh_manager::do_close_all_figures): New functions.
* graphics.h.in, graphics.cc (close_all_figures): New function.
* toplev.cc (clean_up_and_exit): Call close_all_figures.
* graphics.h.in (uitoggletool::~uitoggletool, uipushtool::~uipushtool,
uitoolbar::~uitoolbar, uipanel::~uipanel, uicontrol::~uicontrol,
uicontextmenu::~uicontextmenu, uimenu::~uimenu, hggroup::~hggroup,
surface::~surface, image::~image, text::~text, line::~line,
axes::~axes, figure::~figure, root_figure::~root_figure):
Don't delete children.
* toplev.cc (SAFE_CALL, IGNORE_INTERRUPT): Rename to OCTAVE_SAFE_CALL
and OCTAVE_IGNORE_INTERRUPT and move to toplev.h. Temporarily set
Vdebug_on_error and Vdebug_on_warning. Reset error_state to zero.
Change all callers.
* graphics.h.in (base_graphics_toolkit::close): New virtual function.
(graphics_toolkit::close, graphics_toolkit::close_all_toolkits):
New functions.
* graphics.cc (gnuplot_toolkit::close): New function.
):
* __init_fltk__.cc (F__init_fltk__): Don't register __remove_fltk__ as
an atexit function.
(F__remove_fltk__): Move to fltk_toolkit::close.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 08 Dec 2011 06:28:18 -0500 |
parents | 54f76558c41a |
children | 8feb25ecddaf |
line wrap: on
line diff
--- a/src/graphics.cc +++ b/src/graphics.cc @@ -2323,6 +2323,114 @@ } static void +delete_graphics_object (const graphics_handle& h) +{ + if (h.ok ()) + { + graphics_object obj = gh_manager::get_object (h); + + // Don't do recursive deleting, due to callbacks + if (! obj.get_properties ().is_beingdeleted ()) + { + graphics_handle parent_h = obj.get_parent (); + + graphics_object parent_obj = + gh_manager::get_object (parent_h); + + // NOTE: free the handle before removing it from its + // parent's children, such that the object's + // state is correct when the deletefcn callback + // is executed + + gh_manager::free (h); + + // A callback function might have already deleted + // the parent + if (parent_obj.valid_object ()) + parent_obj.remove_child (h); + + Vdrawnow_requested = true; + } + } +} + +static void +delete_graphics_object (double val) +{ + delete_graphics_object (gh_manager::lookup (val)); +} + +static void +delete_graphics_objects (const NDArray vals) +{ + for (octave_idx_type i = 0; i < vals.numel (); i++) + delete_graphics_object (vals.elem (i)); +} + +static void +close_figure (const graphics_handle& handle) +{ + octave_value closerequestfcn = xget (handle, "closerequestfcn"); + + OCTAVE_SAFE_CALL (gh_manager::execute_callback, (handle, closerequestfcn)); +} + +static void +force_close_figure (const graphics_handle& handle) +{ + // Remove the deletefcn and closerequestfcn callbacks and delete the + // object directly. + + xset (handle, "deletefcn", Matrix ()); + xset (handle, "closerequestfcn", Matrix ()); + + delete_graphics_object (handle); +} + +void +gh_manager::do_close_all_figures (void) +{ + // FIXME -- should we process or discard pending events? + + event_queue.clear (); + + // Don't use figure_list_iterator because we'll be removing elements + // from the list elsewhere. + + Matrix hlist = do_figure_handle_list (true); + + for (octave_idx_type i = 0; i < hlist.numel (); i++) + { + graphics_handle h = gh_manager::lookup (hlist(i)); + + if (h.ok ()) + close_figure (h); + } + + // They should all be closed now. If not, force them to close. + + hlist = do_figure_handle_list (true); + + for (octave_idx_type i = 0; i < hlist.numel (); i++) + { + graphics_handle h = gh_manager::lookup (hlist(i)); + + if (h.ok ()) + force_close_figure (h); + } + + // None left now, right? + + hlist = do_figure_handle_list (true); + + assert (hlist.numel () == 0); + + // Clear all callback objects from our list. + + callback_objects.clear (); +} + +static void adopt (const graphics_handle& p, const graphics_handle& h) { graphics_object parent_obj = gh_manager::get_object (p); @@ -2417,6 +2525,7 @@ finalize (go); } + // --------------------------------------------------------------------- void @@ -2736,6 +2845,8 @@ Matrix get_screen_size (void) const { return Matrix (1, 2, 0.0); } + void close (void) { } + private: void send_quit (const octave_value& pstream) const { @@ -2779,6 +2890,19 @@ return available_toolkits["gnuplot"]; } +void +graphics_toolkit::close_all_toolkits (void) +{ + while (! available_toolkits.empty ()) + { + available_toolkits_iterator p = available_toolkits.begin (); + + p->second.close (); + + available_toolkits.erase (p); + } +} + std::map<std::string, graphics_toolkit> graphics_toolkit::available_toolkits; // --------------------------------------------------------------------- @@ -2937,7 +3061,8 @@ { currentfigure = val; - gh_manager::push_figure (val); + if (val.ok ()) + gh_manager::push_figure (val); } else gripe_set_invalid ("currentfigure"); @@ -7401,9 +7526,8 @@ { instance = new gh_manager (); -#if 0 - singleton_cleanup_list::add (cleanup_instance); -#endif + if (instance) + singleton_cleanup_list::add (cleanup_instance); } graphics_handle @@ -8783,40 +8907,7 @@ } if (! error_state) - { - for (octave_idx_type i = 0; i < vals.numel (); i++) - { - h = gh_manager::lookup (vals.elem (i)); - - if (h.ok ()) - { - graphics_object obj = gh_manager::get_object (h); - - // Don't do recursive deleting, due to callbacks - if (! obj.get_properties ().is_beingdeleted ()) - { - graphics_handle parent_h = obj.get_parent (); - - graphics_object parent_obj = - gh_manager::get_object (parent_h); - - // NOTE: free the handle before removing it from its - // parent's children, such that the object's - // state is correct when the deletefcn callback - // is executed - - gh_manager::free (h); - - // A callback function might have already deleted - // the parent - if (parent_obj.valid_object ()) - parent_obj.remove_child (h); - - Vdrawnow_requested = true; - } - } - } - } + delete_graphics_objects (vals); } else error ("delete: invalid graphics object"); @@ -9023,7 +9114,6 @@ @end deftypefn") { static int drawnow_executing = 0; - static bool __go_close_all_registered__ = false; octave_value retval; @@ -9036,13 +9126,6 @@ if (++drawnow_executing <= 1) { - if (! __go_close_all_registered__) - { - octave_add_atexit_function ("__go_close_all__"); - - __go_close_all_registered__ = true; - } - if (args.length () == 0 || args.length () == 1) { Matrix hlist = gh_manager::figure_handle_list (true);