On Sun, Nov 03, 2002 at 10:17:40AM +0900, Alan (Ursus Major) wrote:
> 
> This start at a  pulldown list accepts insertions, accepts a callback
> method.
> It does /not/ yet accept parenting or keys during initialization.
> There is a problem with packing with the 'pd = PullDown.new.pack' statement.

That's because @frame doesn't have a parent. So when you create a
PullDown instance, you need to pass it a parent widget, and then create
@frame as a child of that parent.

Also, if you intend for this widget to be reusable, you should try to
make it conform as closely as possible to normal Tk widget behavior.
Concretely, that means two things:

  1) Initialize should return self, not @frame. 

  2) You should override pack(), place(), and grid() like so:

     def pack(*args)
       @frame.pack(*args)
     end

My rule of thumb in creating compound widgets is that the base class
should be the class whose behavior is most useful to expose ... in this
case that's presumably TkListbox, so you've started off all right:

> class PullDown < TkListbox

But this really confuses things:

>   @frame.pack
>  end

In fact, that's not just un-Tk-like, it violates the expectations of
just about every OO programmer on the planet, since it means that 

  PullDown.new

doesn't return an instance of PullDown!

However, in order to properly pack your compound widget, the component
that receives the pack() call has to be the outermost container, which
of course is your @frame . So you need to provide a pack() method (and I
suppose unpack() too) that delegates to @frame.

The other alternative would be to subclass from TkFrame. Then the
logical object structure would match the physical widget hierarchy, and
you would have to mess around with pack(), place(), and grid(). But that
probably isn't what you want, because once you've constructed the
widget, you will most likely never need to invoke any other methods on
the outer frame ... but you will very likely need to invoke some methods
on the listbox itself, so you would end up having to write a ton of
methods to delegate to the listbox.

As for the more general question of the best way to construct a
drop-down list ... well, Tk has somewhat limited capabilities, so there
aren't too many alternatives. The only question I have about your
approach is, when the lower section is displayed, what happens to the
widgets that are already there? Or is the entire root window going to
get resized? Something like that has to happen to give your thingie a
space to appear in. Not pretty.

Of course, there's a better solution than that ... though I wouldn't
call it a good one, and it's certainly not easy: use a Toplevel window
for the dropdown section. Then you have to deal with the window manager
to get screen x & y so you can position your Toplevel correctly. Like I
said, it's not easy. But if you think you want to try it, I may have
some code lying around (probably Python) that I could dig up as a
sample.

If none of the above sounds acceptable, you may just have to work with a
different GUI toolkit. Unless someone else knows some other interesting
tricks.

-- 
Matt Gushee                 When a nation follows the Way,
Englewood, Colorado, USA    Horses bear manure through
mgushee / havenrock.com           its fields;
http://www.havenrock.com/   When a nation ignores the Way,
                            Horses bear soldiers through
                                its streets.
                                
                            --Lao Tzu (Peter Merel, trans.)