Article #446: FLTK Callbacks Recast

  
  FLTK Apps      FLTK Library      Forums      Links     Login 
 Home  |  Articles & FAQs  |  Bugs & Features  |  Documentation  |  Download  |  Screenshots  ]
 

Return to Articles | Show Comments | Submit Comment ]

Article #446: FLTK Callbacks Recast

Created at 10:59 May 17, 2005 by mike_os_x

Objects should have a clean, simple interface with the rest of the program. It's easy to make a mess of this when hooking into a GUI, so this article explores some ways to avoid that.

The approach taken here eliminates some complications, but introduces a few of its own. It has worked well so far on a real project, and I hope you will get something from it.

go to the article Download | Home Page | Listing ]


Comments

Submit Comment ]

From taesoo, 12:58 Aug 21, 2005 (score=4)

I use subclassing for the same purpose. (Simplifying the code) I believe many others are also using subclassing but I cannot find one here. So, I present here how to.

PS. I am not sure which one is better. I see that the suggested method in the article has an advantage that many callback functions can be used. But it uses non-member function for UI handling, and it doesn't support user_data.

// Example source code. 
// Callee is the class which I made.
// Options are the class where the callbacks will be received.
class Options : Window, Callee 
   {
   …
        virtual void onCallback(Widget * sender, int userData);   
   …
   };


void Options::buildUI()
   {
   …
   trigLevel = new IntInput(PAD,PAD,30,LABEL_H,"level");
   connect( trigLevel, 111 ); // whatever number.
   …
   }

void Options::onCallback(Widget* sender, int userData)
{
        if(userData==111)
        {
                // do something.
        }
}

// Base class
class Callee
{
public:
        Callee(){}
        virtual~Callee(){}

        /** Usage: connect(new Button(0,0,80,20,"SomeButton"), 100); 
        void connect(Widget* sender, int userData=-1)
        {
                sender->parent()->user_data((void*)this);
                sender->callback(cbFunc, (void*)userData);
        }

protected:
        /// you can distinguish the caller based on sender, sender->label() or userData.
        virtual void onCallback(Widget * sender, int userData)=0;

private:
        static void cbFunc(Widget * sender, void *data)
        {
                ((Callee*)sender->parent()->user_data())->onCallback(sender, (int)data);
        }
};
Basically this does exactly the same as the method of having two functions with less source code. There is one limitation of this method; every widget in a group should be connected to the same parent because parent's userdata is shared between them. That's why Option is inherited from both Fltk::Window(or Group) and Callee. In this way, connect function can have second argument (int userdata) which is very convenient to use. If you cannot accept this restriction, you can change the code so that each widget uses only its userdata.
Reply ]

From ariock, 06:45 May 23, 2005 (score=3)

Nice article excetp for the dynamic_cast which is not needed in most cases and requires that the RTTI is enabled when you build...

But all in all this is the way I do things too.
Reply ]

 
 

Comments are owned by the poster. All other content is copyright 1998-2015 by Bill Spitzak and others. This project is hosted by Seriss Corporation. Please report site problems to 'erco@seriss.com'.