[ vilyu @ 20.02.2005. 12:46 ] @
Zdravo,

Imam sledeci problem: prema dokumentaciji sa www.fltk.net preporucuje se da cast-ovanje radim u static void callback funkciji, a da zatim obradu podataka izvedem u inline funkciji. Ali, ako na taj nacin radim, trosim oba argumenta callback funkcije na pokazivace ka prozoru i dugmetu, i ne ostaje mi "prostora" za jedan int kroz userdata, koji bi identifikovao koje je dugme pritisnuto. Da li zbog toga da izvedem novu klasu dugmeta, sa ugradjenim intom, ili je neko drugo resenje bolje? Hvala unapred. Evo moje klase:

Code:
class MyWindow : public Window {
  Button MyBtn;
  bool alternacija;
  
  inline void MyBtn_CB_i(Button* but) {
    alternacija = !alternacija;
    if(alternacija)
      but->image(gifImage::get("images/vert.gif"));
    else
      but->image(gifImage::get("images/horiz.gif"));
  }
  static void MyBtn_CB(Widget* w, void* v) {
    ((MyWindow*)v)->MyBtn_CB_i((Button*)w);
  }
  
public:

  MyWindow(const char* label=0) :
    Window(USEDEFAULT, USEDEFAULT, 320, 90, label, true),
    MyBtn(10,10,40,40)
  {
    MyBtn.callback(MyBtn_CB,this);
    MyBtn.image(gifImage::get("images/vert.gif"));
    alternacija = true;
    end();
    show();
  }
  
  ~MyWindow() {}
  
};
[ leka @ 20.02.2005. 15:12 ] @
vilyu, pogledaj fltk::Widget::user_data() metode, tu ti lezi pomoc.
[ vilyu @ 21.02.2005. 18:47 ] @
Leko, pregledao sam dokumentaciju, i trazio po net-u, ali nisam uspeo da
nadjem to na sta si ti mislio. Jedino sam naleteo na slanje drugog
argumenta kao long, sto mi ne znaci mnogo.

Da li callback mogu da definisem kao
Code:
button.callback(MyFunc, void* 
user_data, this)


Ili da probam da prosledim neku klasu kao user_data?

Hvala
[ igac @ 21.02.2005. 21:54 ] @
i ja imam isti problem...
leka jel moze npr
Code:

Button *b = new Button(...);
int x = 5;
b->user_data(&x);
b->callback(fja,this);
...
void fja(Widget *w, void *d) {
    Button *b = (Button *)w;
    int m = (int *) (b->user_data());
 ...
}
...


jel moze nekako tako da se proslijedi int 5 u fju callback ? ja sam probao ali nesto mi ne uspijeva...
[ vilyu @ 21.02.2005. 22:44 ] @
Izgleda da sam konacno nasao kako to moze da se odradi. U klasu sam
dodao (nadam se da e-mail nece ostetiti kod):
Code:
  int br_polja;

   void* a_i_b(void* prozor, int br_polja) {
     this->br_polja = br_polja;
     return prozor;
   }


A callback sam napisao kao:
Code:
MyBtn.callback(MyBtn_CB,a_i_b(this,20));


Da li postoji elegantnije resenje?
[ igac @ 22.02.2005. 19:54 ] @
ja sam rijesio tako sto sam kao data poslao struct sa tim intom sto mi je trebao i this-om :)
[ Dejan Lozanovic @ 23.02.2005. 08:33 ] @
http://www.fltk.org/articles.php?L379+I30+T+P1+Q

Citat:

Because of the way C++ and FLTK work, you can only use static methods for callbacks, at least directly.

To get the this pointer for the class you can pass the pointer as the user_data argument for your callback. Typically this is then used to call a non-static method:
Code:

class MyClass {
  static static_callback(Fl_Widget* w, void* data) {
    ((MyClass*)data)->real_callback(w);
  }
  void real_callback(Fl_Widget* w) {
    ... this is the real callback ...
  }
public:
  MyClass() {
    ...
    // building the gui now:
    button = new Fl_Button(...);
    button->callback(static_callback, this);
  }
};

If you need the user_data pointer for something else, you can also set the user_data pointer in the top-most group/window in your class, and then use the Fl_Widget pointer that is passed to your callback to find the class pointer (this is the method used by FLUID):
Code:

class MyClass {
  static static_callback(Fl_Widget *w, void *data) {
    Fl_Widget *p = w->parent();
    while (p->parent()) p = p->parent();
    ((MyClass*)p->user_data())->real_callback(w, data);
  }
  void real_callback(Fl_Widget *w, void *data) {
    ... this is the real callback ...
  }
public:
  MyClass() {
    ...
    // building the gui now:
    window = new Fl_Window(...);
    window->user_data(this);
    button = new Fl_Button(...);
    button->callback(static_callback, ...);
  }
};


[ leka @ 24.02.2005. 01:14 ] @
callback() je overloadovan metod i postoje varijante koje uzimaju dva argumenta:
Code:

void     callback (Callback1 *c, long p=0)
void     callback (Callback0 *c)
void     callback (Callback *c)
void     callback (Callback *c, void *p)

Nas interesuje, zbog resavanja gore spomenutog problema, poslednja varijanta.
Uz pomoc nje kolbek funkciji se moze proslediti pokazivac na bilo kakav objekat:
Code:

.
.
.
void OkButtonCB(fltk::ReturnButton *w, void *nesto)
{
  fltk::Widget* o = (fltk::Widget*)nesto;
  o->label(w->label); // postavlja labele i tastera i labela na istu vrednost
}

int main() 
{
.
.
.
fltk::Widget neki_label...
fltk::ReturnButton tastercic...
.
.
.
tastercic.callback((fltk::Callback*)OkButtonCB, &neki_label);
/*
moglo je i:
Socket moja_veza("http://www.gov.yu", &neki_bafer);
tastercic.callback((fltk::Callback*)MrezniCB, &moja_veza);
*/
.
.
.


Dakle, u ovom primeru prosledjujemo pokazivac na kompleksan objekat - fltk::Widget, na isti nacin smo mogli da prosledimo pokazivac na neki broj recimo i slicno... Jako jednostavno.