octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Changeset]: Re: cla() ?


From: John W. Eaton
Subject: Re: [Changeset]: Re: cla() ?
Date: Fri, 10 Oct 2008 16:22:29 -0400

On 10-Oct-2008, Ben Abbott wrote:

| 
| On Friday, October 10, 2008, at 11:34AM, "John W. Eaton" <address@hidden> 
wrote:
| >On 10-Oct-2008, Ben Abbott wrote:
| >
| >| 
| >| On Oct 10, 2008, at 7:44 AM, Michael Goffioul wrote:
| >| 
| >| > On Fri, Oct 10, 2008 at 1:40 PM, Ben Abbott <address@hidden> wrote:
| >| >> It does not appear that __go_delete__ does the job properly either.
| >| >>
| >| >> octave-3.1.51+:1> figure(1)
| >| >> octave-3.1.51+:2> axis
| >| >> ans =
| >| >>  0   1   0   1   0   1
| >| >> octave-3.1.51+:3> gca
| >| >> ans = -1.3284
| >| >> octave-3.1.51+:4> delete(gca)
| >| >> octave-3.1.51+:5> get(gcf,'currentaxes')
| >| >> ans = -1.3284
| >| >
| >| > That's not the problem. __go_delete__ should just make
| >| > sure that get(gcf,'children') does not contain the axes
| >| > handle anymore. In the case above, the figure object should
| >| > catch the child removal and update currentaxes accordingly.
| >| > In practice, figure::properties::remove_child overload is
| >| > missing.
| >| >
| >| > Michael.
| >| 
| >| ok!
| >| 
| >|  From my naive position that looks like a simple change. Might someone  
| >| take care of that?
| >
| >I would, but I don't know precisely what the
| >figure::properties::remove_child function should do.   I assume it
| >would be something like
| >
| >  void
| >  figure::properties::remove_child (const graphics_handle& h)
| >  {
| >    if (h.ok () && h == currentaxes.handle_value ())
| >      xset (0, "currentaxes", ???);
| >
| >    base_properties::remove_child (h);
| >  }
| >
| >but I don't know how to determine which axes should become the new
| >currentaxes.
| >
| >jwe
| 
| Looking at Matlab ...
| 
| figure(1)
| axis;
| figure(2)
| axis;
| delete(gca)
| get(gca,'parent')
| ans = 2
| 
| Which implies that an axis for figure 2 is created when gca is called.
| 
| figure(1)
| subplot(211)
| set(gca,'tag','first')
| subplot(212)
| set(gca,'tag','second')
| delete(gca)
| get(gca,'tag')
| ans = 'first'
| 
| In this instance the deleted axis remains deleted.
| 
| So it appears that if no axis exists for the current figure, gca will create 
an axis and return its handle. If an axis does exist as a child of the current 
figure, then (after some playing) the handle for the newest axis is returned. 
Which corresponds to findobj(gcf,"type","axes")(1).
| 
| So when the "currentaxes" of a figure is deleted, the equivalent of the code 
below is run.
| 
| currentaxes = findobj (hfig, "type", "axes")(1);
| if (isempty (currentaxes))
|   currentaxes = axes;
| endif 
| 
| Ben


I thought the following function would work

  void
  figure::properties::remove_child (const graphics_handle& h)
  {
    bool update_currentaxes = false;

    if (! is_beingdeleted ())
      {
        if (h.ok ())
          {
            graphics_object go = gh_manager::get_object (h);

            update_currentaxes = go.valid_object () && go.isa ("axes");
          }
      }

    base_properties::remove_child (h);

    if (update_currentaxes)
      {
        for (octave_idx_type i = 0; i < children.numel (); i++)
          {
            double child = children(i);

            graphics_handle gh = gh_manager::lookup (child);

            if (gh.ok ())
              {
                graphics_object go = gh_manager::get_object (gh);

                if (go.valid_object () && go.isa ("axes"))
                  {
                    currentaxes = gh;
                    return;
                  }
              }
          }

        currentaxes = gh_manager::make_graphics_handle ("axes", __myhandle__);
      }
  }

Unfortunately, this fails because by the time it is called, the handle
H that is passed no longer points to an axes object.  Instead, it is
just a base_graphics_object.  Looking at F__go_delete__, I see

                  // 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;
                    }

I think the problem is that gh_manager::free is called before the
remove_child function is called, and gh_manager::free erases the
handle/object pair from the handle_map.  If the NOTE is correct, then
we can't simply move the call to gh_manager::free to after the call to
remove_child.

I guess this gets back to the issue that Michael has brought up about
having gh_manager::free also remove the child from its parent.
However, my attempts to make that change did not work.  I think I'm
missing some protection from infinite recursion on gh_manager::free.

I'm having some trouble understanding how callbacks, delete,
gh_manager::free, removing children, etc. should work, so I
could use some help here.

Thanks,

jwe


reply via email to

[Prev in Thread] Current Thread [Next in Thread]