# HG changeset patch # User pantxo # Date 1395396328 -3600 # Node ID a30e1d20fd3cd9bccbee05a746091e47fee83b62 # Parent d4b69559a0f7a477157b99328f5deb791541d3c1 Freset: properly reset graphics objects (bug #35511) * graphics.in.h (base_graphics_object, graphics_object, root): add new method "get_factory_defaults_list" to retrieve factory defaults as property_list * graphics.in.h (base_graphics_object::reset_default_properties (void)): move definition to graphics.cc * graphics.cc (xreset_default_properties): new function to set a list of prop/val * graphics.cc (base_graphics_object::reset_default_properties): use xreset_default_properties, override with parents' defaults * graphics.cc (root_figure::reset_default_properties, figure::reset_default_properties, uitoolbar::reset_default_properties): same as above but first empty local defaults * graphics.cc (axes_figure::reset_default_properties): same as above but use "propeties.set_defaults" to reset properties to their factory value. * graphics.cc (axes_figure::properties::set_defaults): new "reset" mode, that does the same as "replace" but x/y/zlabels and title are reset instead of being deleting/recreating. * graphics.cc: add %!tests for Freset diff -r d4b69559a0f7 -r a30e1d20fd3c libinterp/corefcn/graphics.cc --- a/libinterp/corefcn/graphics.cc Mon Jul 28 09:28:57 2014 +0200 +++ b/libinterp/corefcn/graphics.cc Fri Mar 21 11:05:28 2014 +0100 @@ -2755,6 +2755,39 @@ finalize (go); } +static void +xreset_default_properties (graphics_handle gh, + property_list::pval_map_type factory_pval) +{ + graphics_object obj = gh_manager::get_object (gh); + + property_list::pval_map_type pval; + + for (property_list::pval_map_const_iterator it = factory_pval.begin (); + it != factory_pval.end (); it++) + { + std::string pname = it->first; + + // Don't reset internal properties and handle_properties + if (! obj.has_readonly_property (pname) && + pname.find ("__") != 0 && pname.find ("current") != 0 && + pname != "uicontextmenu" && pname != "parent") + { + // Store *mode prop/val in order to set them last + if (pname.find ("mode") == (pname.length () - 4)) + pval.insert (std::pair + (pname, it->second)); + else + obj.set (pname, it->second); + } + } + + // set *mode properties + for (property_list::pval_map_const_iterator it = pval.begin (); + it != pval.end (); it++) + obj.set (it->first, it->second); +} + // --------------------------------------------------------------------- void @@ -2774,7 +2807,7 @@ q++) { std::string pname = q->first; - + obj.set (pname, q->second); if (error_state) @@ -3086,6 +3119,21 @@ } } +void +base_graphics_object::reset_default_properties (void) + { + if (valid_object ()) + { + property_list::pval_map_type factory_pval = + gh_manager::get_object (0).get_factory_defaults_list () + .find (type ())->second; + + xreset_default_properties (get_handle (), factory_pval); + + override_defaults (*this); + } + } + std::string base_graphics_object::values_as_string (void) { @@ -3570,39 +3618,14 @@ property_list root_figure::factory_properties = root_figure::init_factory_properties (); -static void -reset_default_properties (property_list& default_properties) -{ - property_list new_defaults; - - for (property_list::plist_map_const_iterator p = default_properties.begin (); - p != default_properties.end (); p++) - { - const property_list::pval_map_type pval_map = p->second; - std::string prefix = p->first; - - for (property_list::pval_map_const_iterator q = pval_map.begin (); - q != pval_map.end (); - q++) - { - std::string s = q->first; - - if (prefix == "axes" && (s == "position" || s == "units")) - new_defaults.set (prefix + s, q->second); - else if (prefix == "figure" && (s == "position" || s == "units" - || s == "windowstyle" - || s == "paperunits")) - new_defaults.set (prefix + s, q->second); - } - } - - default_properties = new_defaults; -} - void root_figure::reset_default_properties (void) { - ::reset_default_properties (default_properties); + // empty list of local defaults + default_properties = property_list (); + + xreset_default_properties (get_handle (), + xproperties.factory_defaults ()); } // --------------------------------------------------------------------- @@ -4462,7 +4485,23 @@ void figure::reset_default_properties (void) { - ::reset_default_properties (default_properties); + // empty list of local defaults + default_properties = property_list (); + + property_list::pval_map_type plist = xproperties.factory_defaults (); + plist.erase ("units"); + plist.erase ("position"); + plist.erase ("paperunits"); + plist.erase ("paperposition"); + plist.erase ("windowstyle"); + xreset_default_properties (get_handle (), plist); + + // FIXME: the following short sleep is needed in order + // to avoid a crash when using qt toolkit + Fsleep (octave_value (0.001)); + + // override with parents' defaults + override_defaults (*this); } // --------------------------------------------------------------------- @@ -4883,27 +4922,42 @@ visible = "on"; - // Replace preserves Position and Units properties - if (mode != "replace") + // Replace/Reset preserves Position and Units properties + if (mode != "replace" && mode != "reset") { outerposition = default_axes_outerposition (); position = default_axes_position (); activepositionproperty = "outerposition"; } - - delete_children (true); - - xlabel = gh_manager::make_graphics_handle ("text", __myhandle__, - false, false); - - ylabel = gh_manager::make_graphics_handle ("text", __myhandle__, - false, false); - - zlabel = gh_manager::make_graphics_handle ("text", __myhandle__, - false, false); - - title = gh_manager::make_graphics_handle ("text", __myhandle__, - false, false); + + if (mode != "reset") + { + delete_children (true); + + xlabel = gh_manager::make_graphics_handle ("text", __myhandle__, + false, false); + ylabel = gh_manager::make_graphics_handle ("text", __myhandle__, + false, false); + zlabel = gh_manager::make_graphics_handle ("text", __myhandle__, + false, false); + title = gh_manager::make_graphics_handle ("text", __myhandle__, + false, false); + adopt (xlabel.handle_value ()); + adopt (ylabel.handle_value ()); + adopt (zlabel.handle_value ()); + adopt (title.handle_value ()); + } + else + { + graphics_object go = gh_manager::get_object (xlabel.handle_value ()); + go.reset_default_properties (); + go = gh_manager::get_object (ylabel.handle_value ()); + go.reset_default_properties (); + go = gh_manager::get_object (zlabel.handle_value ()); + go.reset_default_properties (); + go = gh_manager::get_object (title.handle_value ()); + go.reset_default_properties (); + } xset (xlabel.handle_value (), "handlevisibility", "off"); xset (ylabel.handle_value (), "handlevisibility", "off"); @@ -4941,11 +4995,6 @@ xset (zlabel.handle_value (), "autopos_tag", "zlabel"); xset (title.handle_value (), "autopos_tag", "title"); - adopt (xlabel.handle_value ()); - adopt (ylabel.handle_value ()); - adopt (zlabel.handle_value ()); - adopt (title.handle_value ()); - update_transform (); sync_positions (); override_defaults (obj); @@ -7649,7 +7698,11 @@ void axes::reset_default_properties (void) { - ::reset_default_properties (default_properties); + // empty list of local defaults + default_properties = property_list (); + + // reset factory defaults + set_defaults ("reset"); } void @@ -8694,7 +8747,14 @@ void uitoolbar::reset_default_properties (void) { - ::reset_default_properties (default_properties); + // empty list of local defaults + default_properties = property_list (); + + xreset_default_properties (get_handle (), + xproperties.factory_defaults ()); + + // override with parents' defaults + override_defaults (*this); } // --------------------------------------------------------------------- @@ -9320,12 +9380,13 @@ DEFUN (reset, args, , "-*- texinfo -*-\n\ -@deftypefn {Built-in Function} {} reset (@var{h}, @var{property})\n\ -Remove any defaults set for the handle @var{h}. The default figure\n\ -properties of @qcode{\"position\"}, @qcode{\"units\"},\n\ -@qcode{\"windowstyle\"} and @qcode{\"paperunits\"} and the default axes\n\ -properties of @qcode{\"position\"} and @qcode{\"units\"} are not reset.\n\ -@seealso{cla, clf}\n\ +@deftypefn {Built-in Function} {} reset (@var{h})\n\ +Resets the properites of object(s) @var{h} to their default values.\n\ +For figures, the properties @qcode{\"position\"}, @qcode{\"units\"},\n\ +@qcode{\"windowstyle\"}, and @qcode{\"paperunits\"} are not affected.\n\ +For axes, the properties @qcode{\"position\"} and @qcode{\"units\"} are\n\ +not affected.\n\ +@seealso{cla, clf, newplot}\n\ @end deftypefn") { int nargin = args.length (); @@ -9342,12 +9403,137 @@ // loop over graphics objects for (octave_idx_type n = 0; n < hcv.length (); n++) gh_manager::get_object (hcv(n)).reset_default_properties (); + + if (! error_state) + Fdrawnow (); } } return octave_value (); } +/* + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! hax = axes ("defaultlinelinewidth", 3); +%! +%! hli = line (1:10, 1:10, 1:10, "marker", "o", +%! "markerfacecolor", "b", "linestyle", ":"); +%! +%! reset (hli); +%! assert (get (hli, "marker"), get (0, "defaultlinemarker")) +%! assert (get (hli, "markerfacecolor"), ... +%! get (0, "defaultlinemarkerfacecolor")) +%! assert (get (hli, "linestyle"), ... +%! get (0, "defaultlinelinestyle")) +%! assert (get (hli, "linewidth"), 3, tol) # parent axes defaults +%! +%! unwind_protect_cleanup +%! close (hf) +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! t1 = (1/16:1/8:1)' * 2*pi; +%! t2 = ((1/16:1/16:1)' + 1/32) * 2*pi; +%! x1 = sin (t1) - 0.8; +%! y1 = cos (t1); +%! x2 = sin (t2) + 0.8; +%! y2 = cos (t2); +%! vert = [x1, y1; x2, y2]; +%! fac = [1:8,NaN(1,8);9:24]; +%! hpa = patch ('Faces',fac, 'Vertices',vert, 'FaceColor','r'); +%! +%! reset (hpa); +%! assert (get (hpa, "faces"), get (0, "defaultpatchfaces"), tol) +%! assert (get (hpa, "vertices"), get (0, "defaultpatchvertices"), tol) +%! assert (get (hpa, "facevertexcdata"), ... +%! get (0, "defaultpatchfacevertexcdata"), tol) +%! unwind_protect_cleanup +%! close (hf) +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! hsu = surface (peaks, "edgecolor", "none"); +%! +%! reset (hsu); +%! assert (get (hsu, "xdata"), get (0, "defaultsurfacexdata"), tol) +%! assert (get (hsu, "ydata"), get (0, "defaultsurfaceydata"), tol) +%! assert (get (hsu, "zdata"), get (0, "defaultsurfacezdata"), tol) +%! assert (get (hsu, "edgecolor"), ... +%! get (0, "defaultsurfaceedgecolor"), tol) +%! unwind_protect_cleanup +%! close (hf) +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! him =image (rand (10,10), "cdatamapping", "scaled"); +%! +%! reset (him); +%! assert (get (him, "cdata"), get (0, "defaultimagecdata"), tol) +%! assert (get (him, "cdatamapping"), ... +%! get (0, "defaultimagecdatamapping"), tol) +%! unwind_protect_cleanup +%! close (hf) +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! hte = text (5, 5, "Hi!", "fontsize", 20 ,"color", "r"); +%! +%! reset (hte); +%! assert (get (hte, "position"), get (0, "defaulttextposition"), tol) +%! assert (get (hte, "fontsize"), get (0, "defaulttextfontsize"), tol) +%! assert (get (hte, "color"), get (0, "defaulttextcolor"), tol) +%! unwind_protect_cleanup +%! close (hf) +%! end_unwind_protect + +%!test +%! hf = figure ("visible", "off"); +%! unwind_protect +%! tol = 20 * eps; +%! pos = get (0, "defaultaxesposition") * .5; +%! hax = axes ("linewidth", 2, "position", pos); +%! title ("Reset me, please!") +%! +%! reset (hax); +%! assert (get (hax, "linewidth"), get (0, "defaultaxeslinewidth"), tol) +%! assert (get (hax, "position"), pos, tol) # axes position is unchanged +%! assert (get (hax, "default"), struct ()) # no more axes' defaults +%! assert (get (get (hax, "title"), "string"), "") +%! unwind_protect_cleanup +%! close (hf) +%! end_unwind_protect + +%!test +%! set (0, "defaultfigurevisible", "off") +%! hf = figure ("visible", "off", "paperunits", "centimeters", ... +%! "papertype", "a4"); +%! unwind_protect +%! reset (hf) +%! assert (get (hf, "papertype"), get (0, "defaultfigurepapertype")) +%! assert (get (hf, "paperunits"), "centimeters") # paperunits is unchanged +%! assert (get (hf, "visible"), get (0, "defaultfigurevisible")) +%! unwind_protect_cleanup +%! close (hf) +%! set (0, "defaultfigurevisible", "remove") +%! end_unwind_protect +*/ + DEFUN (set, args, nargout, "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} set (@var{h}, @var{property}, @var{value}, @dots{})\n\ diff -r d4b69559a0f7 -r a30e1d20fd3c libinterp/corefcn/graphics.in.h --- a/libinterp/corefcn/graphics.in.h Mon Jul 28 09:28:57 2014 +0200 +++ b/libinterp/corefcn/graphics.in.h Fri Mar 21 11:05:28 2014 +0100 @@ -2698,6 +2698,12 @@ return octave_value (); } + virtual property_list get_factory_defaults_list (void) const + { + error ("base_graphics_object::get_factory_defaults_list: invalid graphics object"); + return property_list (); + } + virtual bool has_readonly_property (const caseless_str& pname) const { return base_properties::has_readonly_property (pname); @@ -2829,16 +2835,7 @@ virtual void remove_all_listeners (void); - virtual void reset_default_properties (void) - { - if (valid_object ()) - { - std::string msg = (type () + "::reset_default_properties"); - gripe_not_implemented (msg.c_str ()); - } - else - error ("base_graphics_object::default: invalid graphics object"); - } + virtual void reset_default_properties (void); protected: virtual void initialize (const graphics_object& go) @@ -2976,6 +2973,11 @@ return rep->get_factory_defaults (); } + property_list get_factory_defaults_list (void) const + { + return rep->get_factory_defaults_list (); + } + bool has_readonly_property (const caseless_str& pname) const { return rep->has_readonly_property (pname); @@ -3225,6 +3227,11 @@ return factory_properties.as_struct ("factory"); } + property_list get_factory_defaults_list (void) const + { + return factory_properties; + } + base_properties& get_properties (void) { return xproperties; } const base_properties& get_properties (void) const { return xproperties; }