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++)