Oop

Object Oriented FLTK Programming

#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl.H>
#include <stdio.h> //for spintf

using namespace std;

class Grid : public Fl_Window{
    public:
        Grid(int x, int y, int w, int h, const char* l); //vars optional
        Fl_Button* buts[4][4]; //array instead of vector
        Fl_Input* inp;
    private:
        static void but_cb(Fl_Widget* o, void* v);
        void but_cbi(Fl_Button* wid);
};

Grid::Grid(int x, int y, int w, int h,const char* l=0):Fl_Window(x,y,w,h,l){
    //call base class ctor
    begin();
    for (int r=0; r<4; r++)
    {
        for (int c=0; c<4; c++)
        {
           buts[r][c]=new Fl_Button(c*40, r*40, 40, 40);
           buts[r][c]->callback(but_cb, this); 
           //notice we send the "this" pointer as user_data arg (this = instance of Grid class)
        }
    }
    inp=new Fl_Input(0,160,100,40);
    end();
    resizable(this);
    show();
}

void Grid::but_cb(Fl_Widget* o, void* v){
    //static functions don't have "this" pointer. But we sent it through with v
    Grid* win = (Grid*)v;
    Fl_Button* b = (Fl_Button*)o;
    win->but_cbi(b);
}

void Grid::but_cbi(Fl_Button* wid){
    //now "this" pointer exists implicitly as the function belongs to every instance of the class
    //so we can access every widget in the instance of the class like python
    //find index
    char s[64];
    for (int r=0; r<4; r++)
        for (int c=0; c<4; c++)
        {
            if (buts[r][c] == wid)
            {
                sprintf(s, "%d", r*4+c);
                wid->copy_label(s); //must use copy_label as char s does not exist after foo
                strcat(s, inp->value());
                inp->value(s);
            }
        }
    wid->color(FL_RED);
}

int main(){
    Grid g(50,50,200,200);
    Fl::run();
}

A better way. Create an Fl_Button subclass that also has integer data.

#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Input.H>
#include <FL/Fl.H>
#include <stdio.h> //for spintf

using namespace std;

class MyButton : public Fl_Button{
    public:
        MyButton(int x, int y, int w, int h, const char* l=0):Fl_Button(x,y,w,h,l){}
        int num;
};

class Grid : public Fl_Window{
    public:
        Grid(int x, int y, int w, int h, const char* l); //vars optional
        MyButton* buts[4][4]; //array instead of vector
        Fl_Input* inp;
    private:
        static void but_cb(Fl_Widget* o, void* v);
        inline void but_cbi(MyButton* wid);
};

Grid::Grid(int x, int y, int w, int h,const char* l=0):Fl_Window(x,y,w,h,l){ 
    //call base class ctor
    begin();
    int i=0;
    for (int r=0; r<4; r++)
    {
        for (int c=0; c<4; c++)
        {
           buts[r][c]=new MyButton(c*40, r*40, 40, 40);
           buts[r][c]->callback(but_cb, this); 
           //notice we send the "this" pointer as user_data arg (this = instance of Grid class)
           buts[r][c]->num = i++;
        }
    }
    inp=new Fl_Input(0,160,100,40);
    end();
    resizable(this);
    show();
}

void Grid::but_cb(Fl_Widget* o, void* v){
    //static functions don't have "this" pointer. But we sent it through with v
    Grid* win = (Grid*)v;
    MyButton* b = (MyButton*)o;
    win->but_cbi(b);
}

void Grid::but_cbi(MyButton* wid){
    //now "this" pointer exists implicitly as the function belongs to every instance of the class
    //so we can access every widget in the instance of the class like python
    char s[8];
    sprintf(s, "%d", wid->num);
    wid->copy_label(s); //must use copy_label as char s does not exist after foo
    strcat(s, inp->value());
    inp->value(s);
    wid->color(FL_RED);
}

int main(){
    Grid g(50,50,200,200);
    Fl::run();
}