Re: New 'GObject' as base for GtkObject?




Karl Nelson <kenelson@ece.ucdavis.edu> writes:

> > > > (Interfaces, on the other hand, don't require making the casts
> > > > non-equivalent.)
> > > 
> > > Interfaces that can't contain data mean that you can't make
> > > virtual interfaces.
> > 
> > What is a virtual interface? (Isn't there some other
> > term than 'virtual' that people could use occasionally?) 
> 
> I mean define some sub part of the object that can be
> recovered to the whole.  If a sub piece doesn't at
> least have a pointer to the base, where is this info
> stored?

OK, that makes more sense, though the name virtual interface
for this seems odd. (In a way, I'd call this a non-virtual
interface). But I'd rather see interfaces used when
there is a 1-1 relationship between the piece and the whole,
which removes the need to pass around both, and use
actual "objects" when I mean aggregation.

> > These presupposes that interfaces transparently look like
> > objects in C, which is certainly not necessarily the case.
> > The design that we've played around with (I always forget
> > the details, so Tim will have to jump in and correct me
> > is that an interface is just an extra vtable attached
> > to the object.).
> 
> This means passing around only the most basic object
> defeating the cast checking system.  

As Tim and Havoc have pointed out, you probably want to
make a GtkRadio opaque type which is just an alias
for GtkObject so that the interfaces contain the correct
type. But you are still effectively passing around
the pointer to the base object. 
 
> (separate idea) How do you export
> specific pieces of the interface?  For example, a frame
> has 2 container interfaces.  I want to pass one of them
> to something that is going to add a dialog in.  How would
> I code that?  How would that reference so that it could
> call signals? 

I don't see this as inheritance - the classic dictum
is that inheritance models is_a relationships, not
has_a relationships. gos couldn't handle this situation
since it has only one copy of each base object, and
trying to handle it with the C++ MI model would be,
at best, a horrible kludge. The right way to do this
is with aggregation or helper objects (more below)

> > > This means either interfaces must hvae virtual functions to
> > > look up the reference, or the interface must be able to cast
> > > to the location of the real reference.  
> > > 
> > > You can try to kludge around this by having lots of cases in
> > > the functions that deal with referencing, etc.  But this
> > > is incredibly bad OO.
> > 
> > You seem to see multiple interfaces in terms of aggregation of
> > distinct objects, which is I think, a really kludgy wayof implementing
> > things.
> 
> Kind of.  I am thinking of interfaces as being mini objects.  
> An object be made up of composites of those mini objects or
> it may export a mini-object as a part of it self.  Thus if
> I have 
> 
>   void place_tic_tack_toe(GtkContainerIntf* w);  
>    /* builds a tree interface in w */  
> 
> It can work with w if w is the window, a frame, or one side of
> a paned.  Clearly, this is powerful abstraction as I don't
> need special functions to export
>   
>   place_tic_tack_toe(paned.side1);

I've been working some with Python recently, and in
a language like Python that has first class function objects,
the way to do this is obvious:

 def place_tic_tack_toe (self, func):
    func(self.thing_to_place)

 place_tic_tack_toe(paned.add1)

That just works right now. Almost like cheating, isn't it? I'd do the
same thing in Scheme, and maybe even Perl, thoughj neither is as
compact. Unfortunately, function pointers in C or C++ aren't as
powerful, or as convenient, but you could pass in a function / closure
data pair, or you could use helper objects. Helper objects is probably
the way I'd do things in C++ or Java ... something like:

Interfaces:

class GtkSlot {
public:
    virtual void add (GtkWidget *child);
    virtual void remove(GtkWidget *child);
}

class GtkPaned {
    [...]
    GtkSlot get_slot (int side);
}

Implemenation:

class GtkPanedSlot : GtkSlot {
public:
  GtkPanedSlot (GtkPaned *paned, int side) {
    mPaned = paned;
    side = side;
  }

  void add (GtkWidget *child) {
     if (mSide == 1)
        mPaned.add1 (child);
     else 
        mPaned.add2 (child);
  }

private:
  GtkPaned_var mPaned;
  int mSide;
}

GtkSlot GtkPaned::get_slot (int side) 
{  
   return GtkPanedSlot (this, side);
}

[ Taking the liberty to make up an imaginary C++ binding
  with CORBA style smart pointers ]

In C, you could also use helper objects, or it might be easier just to
require containers to number their slots (in some internal fashion),
so you could have:

 int gtk_paned_get_slot_number (int side);
 gtk_container_add_numbered (GtkContainer *container, int slot);

This could easily be wrapped into a slot object for C++.

> > Of course multiple interfaces are a powerful tool for enabling
> > aggregates while maintaining implementation independence (E.g, the
> > GtkRadioGroup / GtkRadioMenuItem aggregate mentioned akbove) but I
> > don't see such natural aggregates inducing hacks of the type you
> > mention.
> 
> Well, I have other suggestions on radio groups.  It
> would be better to make a group of toggles then build
> a special radio for all these things.
 
Well, the GtkRadio interface could probably be called
GtkToggle just as well. But appearance should be different
for radio buttons so a separate class is necessary.
  
> > > I could scrap the data moving an make a pure java
> > > model where only the class is built in my system.  (I
> > > have both the class and object constructed without 
> > > inheritance.)  
> > 
> > A model that separates out interfaces from objects
> > instead of trying to make them appear the same makes
> > it pretty easy to make a much simpler implementation
> > that actually is compatible with existing GTK+
> > code since you don't have to solve the arbitrary
> > "cast object of type A to object of type B allowing
> > for multiple inheritance" problem.
> 
> I intend to solve that by introducing proxies.  They
> are an addition to the gos type system were if it can't
> find something it goes to the base object to get it.  Thus
> exporting interfaces is as easy as deriving from a ProxyObject
> instead of a real one.
   
Can you give an example?
  
> > > But this is far less flexible as interfaces
> > > would then need to use set_data to add their extra stuff.
> > 
> > What extra stuff? Each class implementing an interface
> > is responsible for storing the data associated with
> > the implementation. The only functions that can be
> > generic to all implementations of the interface should
> > just be wrappers around the functions in the interface.
> 
> I was just saying that if there was data associated with
> an interface (for example, some drag interface may need 
> to store scratch info).  Otherwise, this means that 
> every thing that uses the interface may have to code
> the method.  I was hoping that we can make the interface
> then some implementations that use it (perhaps in abstract)
> so that we don't need to do all this copy/paste/modify stuff.

Well, in the rare case where a) you need to store data
and b) the data is too private to add accessors to the
interfaces for the purposes of stroing it, I don't
see using object data as harmful. Most likely better
than adding multiple inheritance of implementation to
cover this rare case.

> gtk+ has too much of this already.  It would be simpler if
> we borrowed the good ideas from other kits like FLtk.  For
> example, if I make a toggle interface I can just define
> a Group that works on Toggle interfaces.  Then there need
> be no concept of "radio" buttons.  
> I just place radio style
> toggle buttons together with a "Group" object.  It is more
> flexible and the code for the toggle is the same for every
> thing that acts like a radio group.  I have been fighting
> for days now because RadioMenuItems and RadioButtons work
> differently!  (Boy, won't that simplify the Packer demo a
> bit as the toggles could all be grouped.)

The natural way to do this is to have a RadioGroup object
that interracts with Radio interfaces (ok, Toggle interfaces).
Which is exactly the example Tim and I have been using.
But the point I would make is that the state lives in
the GtkRadioGroup  object, not in the GtkRadio interfaces.

Regards,
                                        Owen
 




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