# HG changeset patch # User Pantxo Diribarne # Date 1428765935 -7200 # Node ID 69f92e0affd2bf81601782548b89a73f23df0ad8 # Parent a00d545c95dfe21c6f91244674c2a3f5a1da917c Handle uicontextmenu deletion/reset (bug #44801) *graphics.in.h (base_graphics_opbject::properties): add updater for uicontextmenu property *graphics.in.h (uicontextmenu::properties::dependent_obj_list): new private attribute to store the list of objects that may depend on this uicontextmenu. *graphics.in.h (uicontextmenu::properties::get_dependent_obj_list (), uicontextmenu::properties::add_dependent_obj ()): new methods * graphics.cc (base_graphics_opbject::properties::update_uicontextmenu): new method to mark this graphics object as dependent on an uicontextmenu object. * graphics.cc (uicontextmenu::~uicontextmenu): reset the "uicontextmenu" property of objects that have this uicontextmenu as current. * graphics.cc (handle_property::do_set): let users reset a handle property using empty matrix. * graphics.cc: add BIST for bug #44801 * genpropdoc.m: document "uicontextmenu" property diff -r a00d545c95df -r 69f92e0affd2 doc/interpreter/genpropdoc.m --- a/doc/interpreter/genpropdoc.m Tue Apr 14 14:27:22 2015 -0400 +++ b/doc/interpreter/genpropdoc.m Sat Apr 11 17:25:35 2015 +0200 @@ -166,6 +166,10 @@ s.printdefault = false; case "uicontextmenu" + s.doc = "Graphics handle of the uicontextmenu object that is \ +currently associated to this __objname__ object."; + s.valid = valid_handle; + case "userdata" s.doc = "User-defined data to associate with the graphics object."; s.valid = "Any Octave data"; diff -r a00d545c95df -r 69f92e0affd2 libinterp/corefcn/graphics.cc --- a/libinterp/corefcn/graphics.cc Tue Apr 14 14:27:22 2015 -0400 +++ b/libinterp/corefcn/graphics.cc Sat Apr 11 17:25:35 2015 +0200 @@ -1473,6 +1473,18 @@ bool handle_property::do_set (const octave_value& v) { + // Users may want to use empty matrix to reset a handle property + if (v.is_empty ()) + { + if (! get ().is_empty ()) + { + current_val = graphics_handle (); + return true; + } + else + return false; + } + double dv = v.double_value (); if (! error_state) @@ -3085,6 +3097,21 @@ obj.update_axis_limits (axis_type, h); } +void +base_properties::update_uicontextmenu (void) const +{ + if (uicontextmenu.get ().is_empty ()) + return; + + graphics_object obj = gh_manager::get_object (uicontextmenu.get ()); + if (obj && obj.isa ("uicontextmenu")) + { + uicontextmenu::properties& props = + reinterpret_cast (obj.get_properties ()); + props.add_dependent_obj (__myhandle__); + } +} + bool base_properties::is_handle_visible (void) const { @@ -8813,6 +8840,51 @@ // --------------------------------------------------------------------- +uicontextmenu::~uicontextmenu (void) +{ + std::list lst = xproperties.get_dependent_obj_list (); + std::list::const_iterator it; + + for (it = lst.begin (); it != lst.end (); it++) + { + graphics_object go = gh_manager::get_object (*it); + + if (go.valid_object () && + go.get ("uicontextmenu") == xproperties.get___myhandle__ ()) + go.set ("uicontextmenu", Matrix ()); + } +} + + +/* +## Test deletion/reset of uicontextmenu +%!test +%! hf = figure ("visible", "off"); +%! hax = axes ("parent", hf); +%! unwind_protect +%! hctx1 = uicontextmenu ("parent", hf); +%! hctx2 = uicontextmenu ("parent", hf); +%! set (hf, "uicontextmenu", hctx2); +%! set (hax, "uicontextmenu", hctx2); +%! assert (get (hf, "uicontextmenu"), hctx2); +%! assert (get (hax, "uicontextmenu"), hctx2); +%! assert (get (hf, "children"), [hctx2; hctx1; hax]); +%! delete (hctx2); +%! assert (get (hf, "uicontextmenu"), []); +%! assert (get (hax, "uicontextmenu"), []); +%! assert (get (hf, "children"), [hctx1; hax]); +%! set (hf, "uicontextmenu", hctx1); +%! assert (get (hf, "uicontextmenu"), hctx1); +%! set (hf, "uicontextmenu", []); +%! assert (get (hf, "uicontextmenu"), []); +%! assert (get (hf, "children"), [hctx1; hax]); +%! unwind_protect_cleanup +%! close (hf); +%! end_unwind_protect; + */ + +// --------------------------------------------------------------------- + octave_value uicontrol::properties::get_extent (void) const { diff -r a00d545c95df -r 69f92e0affd2 libinterp/corefcn/graphics.in.h --- a/libinterp/corefcn/graphics.in.h Tue Apr 14 14:27:22 2015 -0400 +++ b/libinterp/corefcn/graphics.in.h Sat Apr 11 17:25:35 2015 +0200 @@ -2595,6 +2595,8 @@ virtual void update_axis_limits (const std::string& axis_type, const graphics_handle& h) const; + virtual void update_uicontextmenu (void) const; + virtual void delete_children (bool clear = false) { children.delete_children (clear); @@ -2663,7 +2665,7 @@ bool_property selectionhighlight , "on" string_property tag s , "" string_property type frs , ty - handle_property uicontextmenu , graphics_handle () + handle_property uicontextmenu u , graphics_handle () any_property userdata , Matrix () bool_property visible , "on" // additional (Octave-specific) properties @@ -5355,6 +5357,15 @@ class OCTINTERP_API properties : public base_properties { public: + + void add_dependent_obj (graphics_handle gh) + { dependent_obj_list.push_back (gh); } + + // FIXME: the list may contain duplicates. + // Should we return only unique elements? + const std::list get_dependent_obj_list (void) + { return dependent_obj_list; } + // See the genprops.awk script for an explanation of the // properties declarations. // Programming note: Keep property list sorted if new ones are added. @@ -5372,6 +5383,10 @@ position.add_constraint (dim_vector (2, 1)); visible.set (octave_value (true)); } + + private: + // List of objects that might depend on this uicontextmenu object + std::list dependent_obj_list; }; private: @@ -5382,7 +5397,7 @@ : base_graphics_object (), xproperties (mh, p) { } - ~uicontextmenu (void) { } + ~uicontextmenu (void); base_properties& get_properties (void) { return xproperties; }