Mercurial > octave-nkf
comparison 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 |
comparison
equal
deleted
inserted
replaced
14013:1734ebe27134 | 14014:907d03def9d5 |
---|---|
2321 | 2321 |
2322 return val.is_empty () ? octave_NaN : val.double_value (); | 2322 return val.is_empty () ? octave_NaN : val.double_value (); |
2323 } | 2323 } |
2324 | 2324 |
2325 static void | 2325 static void |
2326 delete_graphics_object (const graphics_handle& h) | |
2327 { | |
2328 if (h.ok ()) | |
2329 { | |
2330 graphics_object obj = gh_manager::get_object (h); | |
2331 | |
2332 // Don't do recursive deleting, due to callbacks | |
2333 if (! obj.get_properties ().is_beingdeleted ()) | |
2334 { | |
2335 graphics_handle parent_h = obj.get_parent (); | |
2336 | |
2337 graphics_object parent_obj = | |
2338 gh_manager::get_object (parent_h); | |
2339 | |
2340 // NOTE: free the handle before removing it from its | |
2341 // parent's children, such that the object's | |
2342 // state is correct when the deletefcn callback | |
2343 // is executed | |
2344 | |
2345 gh_manager::free (h); | |
2346 | |
2347 // A callback function might have already deleted | |
2348 // the parent | |
2349 if (parent_obj.valid_object ()) | |
2350 parent_obj.remove_child (h); | |
2351 | |
2352 Vdrawnow_requested = true; | |
2353 } | |
2354 } | |
2355 } | |
2356 | |
2357 static void | |
2358 delete_graphics_object (double val) | |
2359 { | |
2360 delete_graphics_object (gh_manager::lookup (val)); | |
2361 } | |
2362 | |
2363 static void | |
2364 delete_graphics_objects (const NDArray vals) | |
2365 { | |
2366 for (octave_idx_type i = 0; i < vals.numel (); i++) | |
2367 delete_graphics_object (vals.elem (i)); | |
2368 } | |
2369 | |
2370 static void | |
2371 close_figure (const graphics_handle& handle) | |
2372 { | |
2373 octave_value closerequestfcn = xget (handle, "closerequestfcn"); | |
2374 | |
2375 OCTAVE_SAFE_CALL (gh_manager::execute_callback, (handle, closerequestfcn)); | |
2376 } | |
2377 | |
2378 static void | |
2379 force_close_figure (const graphics_handle& handle) | |
2380 { | |
2381 // Remove the deletefcn and closerequestfcn callbacks and delete the | |
2382 // object directly. | |
2383 | |
2384 xset (handle, "deletefcn", Matrix ()); | |
2385 xset (handle, "closerequestfcn", Matrix ()); | |
2386 | |
2387 delete_graphics_object (handle); | |
2388 } | |
2389 | |
2390 void | |
2391 gh_manager::do_close_all_figures (void) | |
2392 { | |
2393 // FIXME -- should we process or discard pending events? | |
2394 | |
2395 event_queue.clear (); | |
2396 | |
2397 // Don't use figure_list_iterator because we'll be removing elements | |
2398 // from the list elsewhere. | |
2399 | |
2400 Matrix hlist = do_figure_handle_list (true); | |
2401 | |
2402 for (octave_idx_type i = 0; i < hlist.numel (); i++) | |
2403 { | |
2404 graphics_handle h = gh_manager::lookup (hlist(i)); | |
2405 | |
2406 if (h.ok ()) | |
2407 close_figure (h); | |
2408 } | |
2409 | |
2410 // They should all be closed now. If not, force them to close. | |
2411 | |
2412 hlist = do_figure_handle_list (true); | |
2413 | |
2414 for (octave_idx_type i = 0; i < hlist.numel (); i++) | |
2415 { | |
2416 graphics_handle h = gh_manager::lookup (hlist(i)); | |
2417 | |
2418 if (h.ok ()) | |
2419 force_close_figure (h); | |
2420 } | |
2421 | |
2422 // None left now, right? | |
2423 | |
2424 hlist = do_figure_handle_list (true); | |
2425 | |
2426 assert (hlist.numel () == 0); | |
2427 | |
2428 // Clear all callback objects from our list. | |
2429 | |
2430 callback_objects.clear (); | |
2431 } | |
2432 | |
2433 static void | |
2326 adopt (const graphics_handle& p, const graphics_handle& h) | 2434 adopt (const graphics_handle& p, const graphics_handle& h) |
2327 { | 2435 { |
2328 graphics_object parent_obj = gh_manager::get_object (p); | 2436 graphics_object parent_obj = gh_manager::get_object (p); |
2329 parent_obj.adopt (h); | 2437 parent_obj.adopt (h); |
2330 } | 2438 } |
2415 { | 2523 { |
2416 graphics_object go = gh_manager::get_object (h); | 2524 graphics_object go = gh_manager::get_object (h); |
2417 | 2525 |
2418 finalize (go); | 2526 finalize (go); |
2419 } | 2527 } |
2528 | |
2420 // --------------------------------------------------------------------- | 2529 // --------------------------------------------------------------------- |
2421 | 2530 |
2422 void | 2531 void |
2423 base_properties::set_from_list (base_graphics_object& obj, | 2532 base_properties::set_from_list (base_graphics_object& obj, |
2424 property_list& defaults) | 2533 property_list& defaults) |
2734 { return 72.0; } | 2843 { return 72.0; } |
2735 | 2844 |
2736 Matrix get_screen_size (void) const | 2845 Matrix get_screen_size (void) const |
2737 { return Matrix (1, 2, 0.0); } | 2846 { return Matrix (1, 2, 0.0); } |
2738 | 2847 |
2848 void close (void) { } | |
2849 | |
2739 private: | 2850 private: |
2740 void send_quit (const octave_value& pstream) const | 2851 void send_quit (const octave_value& pstream) const |
2741 { | 2852 { |
2742 if (! pstream.is_empty ()) | 2853 if (! pstream.is_empty ()) |
2743 { | 2854 { |
2775 { | 2886 { |
2776 if (available_toolkits.size () == 0) | 2887 if (available_toolkits.size () == 0) |
2777 register_toolkit (new gnuplot_toolkit ()); | 2888 register_toolkit (new gnuplot_toolkit ()); |
2778 | 2889 |
2779 return available_toolkits["gnuplot"]; | 2890 return available_toolkits["gnuplot"]; |
2891 } | |
2892 | |
2893 void | |
2894 graphics_toolkit::close_all_toolkits (void) | |
2895 { | |
2896 while (! available_toolkits.empty ()) | |
2897 { | |
2898 available_toolkits_iterator p = available_toolkits.begin (); | |
2899 | |
2900 p->second.close (); | |
2901 | |
2902 available_toolkits.erase (p); | |
2903 } | |
2780 } | 2904 } |
2781 | 2905 |
2782 std::map<std::string, graphics_toolkit> graphics_toolkit::available_toolkits; | 2906 std::map<std::string, graphics_toolkit> graphics_toolkit::available_toolkits; |
2783 | 2907 |
2784 // --------------------------------------------------------------------- | 2908 // --------------------------------------------------------------------- |
2935 | 3059 |
2936 if (xisnan (val.value ()) || is_handle (val)) | 3060 if (xisnan (val.value ()) || is_handle (val)) |
2937 { | 3061 { |
2938 currentfigure = val; | 3062 currentfigure = val; |
2939 | 3063 |
2940 gh_manager::push_figure (val); | 3064 if (val.ok ()) |
3065 gh_manager::push_figure (val); | |
2941 } | 3066 } |
2942 else | 3067 else |
2943 gripe_set_invalid ("currentfigure"); | 3068 gripe_set_invalid ("currentfigure"); |
2944 } | 3069 } |
2945 | 3070 |
7399 void | 7524 void |
7400 gh_manager::create_instance (void) | 7525 gh_manager::create_instance (void) |
7401 { | 7526 { |
7402 instance = new gh_manager (); | 7527 instance = new gh_manager (); |
7403 | 7528 |
7404 #if 0 | 7529 if (instance) |
7405 singleton_cleanup_list::add (cleanup_instance); | 7530 singleton_cleanup_list::add (cleanup_instance); |
7406 #endif | |
7407 } | 7531 } |
7408 | 7532 |
7409 graphics_handle | 7533 graphics_handle |
7410 gh_manager::do_make_graphics_handle (const std::string& go_name, | 7534 gh_manager::do_make_graphics_handle (const std::string& go_name, |
7411 const graphics_handle& p, | 7535 const graphics_handle& p, |
8781 break; | 8905 break; |
8782 } | 8906 } |
8783 } | 8907 } |
8784 | 8908 |
8785 if (! error_state) | 8909 if (! error_state) |
8786 { | 8910 delete_graphics_objects (vals); |
8787 for (octave_idx_type i = 0; i < vals.numel (); i++) | |
8788 { | |
8789 h = gh_manager::lookup (vals.elem (i)); | |
8790 | |
8791 if (h.ok ()) | |
8792 { | |
8793 graphics_object obj = gh_manager::get_object (h); | |
8794 | |
8795 // Don't do recursive deleting, due to callbacks | |
8796 if (! obj.get_properties ().is_beingdeleted ()) | |
8797 { | |
8798 graphics_handle parent_h = obj.get_parent (); | |
8799 | |
8800 graphics_object parent_obj = | |
8801 gh_manager::get_object (parent_h); | |
8802 | |
8803 // NOTE: free the handle before removing it from its | |
8804 // parent's children, such that the object's | |
8805 // state is correct when the deletefcn callback | |
8806 // is executed | |
8807 | |
8808 gh_manager::free (h); | |
8809 | |
8810 // A callback function might have already deleted | |
8811 // the parent | |
8812 if (parent_obj.valid_object ()) | |
8813 parent_obj.remove_child (h); | |
8814 | |
8815 Vdrawnow_requested = true; | |
8816 } | |
8817 } | |
8818 } | |
8819 } | |
8820 } | 8911 } |
8821 else | 8912 else |
8822 error ("delete: invalid graphics object"); | 8913 error ("delete: invalid graphics object"); |
8823 } | 8914 } |
8824 else | 8915 else |
9021 The third calling form of @code{drawnow} is for debugging and is\n\ | 9112 The third calling form of @code{drawnow} is for debugging and is\n\ |
9022 undocumented.\n\ | 9113 undocumented.\n\ |
9023 @end deftypefn") | 9114 @end deftypefn") |
9024 { | 9115 { |
9025 static int drawnow_executing = 0; | 9116 static int drawnow_executing = 0; |
9026 static bool __go_close_all_registered__ = false; | |
9027 | 9117 |
9028 octave_value retval; | 9118 octave_value retval; |
9029 | 9119 |
9030 gh_manager::lock (); | 9120 gh_manager::lock (); |
9031 | 9121 |
9034 | 9124 |
9035 frame.protect_var (drawnow_executing); | 9125 frame.protect_var (drawnow_executing); |
9036 | 9126 |
9037 if (++drawnow_executing <= 1) | 9127 if (++drawnow_executing <= 1) |
9038 { | 9128 { |
9039 if (! __go_close_all_registered__) | |
9040 { | |
9041 octave_add_atexit_function ("__go_close_all__"); | |
9042 | |
9043 __go_close_all_registered__ = true; | |
9044 } | |
9045 | |
9046 if (args.length () == 0 || args.length () == 1) | 9129 if (args.length () == 0 || args.length () == 1) |
9047 { | 9130 { |
9048 Matrix hlist = gh_manager::figure_handle_list (true); | 9131 Matrix hlist = gh_manager::figure_handle_list (true); |
9049 | 9132 |
9050 for (int i = 0; ! error_state && i < hlist.length (); i++) | 9133 for (int i = 0; ! error_state && i < hlist.length (); i++) |