Mike wrote: > You say you like the recent "simple" API, I was looking at the 2.0.x API and > it has four callback setup m/fs and I was suggesting replacing them with one. > Isn't that even simpler? Is there an even newer API?
It is essentially the same system as 1.1, the callback is overloaded just to pass user_data with different syntax. > > void callback( void (*)(Widget*, void*), void* ); > > is a very old C-style pattern. It is nothing wrong with this "very old C" style ... if it is flexible enought. You can use user_data for your callaback object, have a single wrapper function to call it and build an API to automatically assign this wrapper and create the callback object - see Functor below > The description in the tutorial of how to connect an object into this using a > static member function The reason is that only ordinary "c" function can be a callback here; class static function is completely the same animal (just inside a namespace) > I think the point I am trying to make is that FLTK is a C++ API and as > such can avoid the need for type casting, one way being the method I I agree that typesafety and flexibility is the goal, but I think it does not need to be a part of Fl_Widget class. Having callback structure "outside" the widget has a few advantages, like callback lifetime management. Suppose widget A calls some object B method. Who should be responsible for removal of calback (in other words to whom it should belong), A or B? Preferably both and callback should be removed by the first who dies, ie if it is B it must inform A not to call it amymore. Also attaching callbacks to non-widget objects, making callback chain or tree propagation is easier. > suggested. From this perspective Fl_Signal is just a fix to this C-Style > part of the, what should be a C++, API. and > idealistic than practical i.e. what would the perfect FLTK C++ API look > like wrt setting up callbacks? I was looking to various callback systems: libsigc++, boost::singal, QT signal/slot stuff and was not too much happy with any of them... I see that good system should: 1) Be typesafe 2) Accept multiple callbacks so you do not need to define a list and write a wrapper which would call this list. This also allows possibility to make a call for many object - ie some single setting controls appearance of many objects. 3) Accept any form of function, method (or operator) as callback. You do not want to write any wrappers or subclass stock widgets just to add the accepted syntax for the functionality what is already there by the means of other functions or to define ugly signals and slots (hello, QT). This means that making subcalls should be also available with possibility of the use of return values as parameters to other functions 4)Should be flexible how to define the arguments to the function: - by value - by pointer to a variable - by a return value of some other function/method by making a subcall 5) Have good lifetime management and means to control when the callback is removed Essentially you should be able to do single-line callback assign what you would write normaly in single-line C code, so if you want to do within the callback object1->method(var1, 6.3, object2->method2(function2(), var2)); would translate to callback assignment syntax callback(object, &Object1::method, &var1, 6.3, call(object2, &Object2::method2, call(function2))); and this exactly what Fl_Signal does. But instead of assigning callback like widget->callback(object, &Object1::method, &var1, ...) it places the "widget" as the first parameter within the callback constructor: Fl_Call(widget, object, &Object::method, &var1, ...) I think it achieves all goals but 5) only partially: widget can not automatically control the callback lifespan and you need to delete it explicitly. And that is why I was asking for this "destructed callback" functionality > > You bring up a problem of users needing to destroy the user_data when the > widget goes. With the method I propose there is no "user data", the > widget simply has a reference to a functor and what you bring up is sort > of a separate issue. Now if user data was required it would be in the > functor or an object referenced by the functor. But you are right, a You can already do that: place your "real" data in your functor and use user_data() for your functor pointer, like: class Functor{ ... //some_internal void operator (){ call_from_internal_data();} template <typename T, ...> Functor(T t, ..){ ... /* build internal data*/} ... // more constructors with more parameters } void functor_wrapper(Fl_Widget * w, void * data){ (Functor *)data)->(); } template <typename T, ...> Functor * callback(Fl_Widget * w, T callback_function, ...){ Functor * f = new Functor(callback_function, ...) w->callback(&functor_wrapper, f, ...)); return f; } void destroy_functor(Fl_Widget * w){ if(w->callback() == &functor_wrapper){// only destroying true functors delete (Functor *)(w->data()); w->callback(0,0); } } and then type-safely write callback(widget, function, ...); and later destroy_callback(widget); > > void callback(shared_ptr<Receiver> r); > I do not think we want to use std template library too much because then you need to link to libstdc++ : I always compile c++ code with "gcc" and not "g++" to avoid linking to that beast (but this my be only my personal detaste with stdc++ - rather writing my own templates) One more thing: you said that templates are supported well with recent compilers. This is only partially true: When I was witting it (a few ears ago), I was trying to use not very advanced template functionality bud still had to go around many bugs in their implementations. And I was testing it only with gcc and MS visual studio! So I think we should avoid the use of templates in fltk core at any cost. R. _______________________________________________ fltk-dev mailing list fltk-dev@easysw.com http://lists.easysw.com/mailman/listinfo/fltk-dev