#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Menu_Window.H>

#define GRID_WIDTH 10
#define GRID_SIZE 100
#define GRID_NUMBER 5
#define GRID_MAX    11

const char* Label[]=
{"2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048", "4096",
                "8192", "16384"};
const unsigned int Number[]=
{2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384};


class My_Fl_Box: public Fl_Box
{
    friend class My_Fl_Window;
public:
    My_Fl_Box(int index) :
        Fl_Box((index % GRID_NUMBER) * (GRID_SIZE + GRID_WIDTH),
               (index / GRID_NUMBER) * (GRID_SIZE + GRID_WIDTH),
               GRID_SIZE,
               GRID_SIZE,
               Label[index % GRID_MAX]),
        m_nIndex(index),
        m_nRow(index / GRID_NUMBER),
        m_nCol(index % GRID_NUMBER),
        m_nText(index % GRID_MAX)

    {
        box(FL_EMBOSSED_BOX);
        color(FL_GREEN);
        labelfont(FL_BOLD + FL_ITALIC);
        labelcolor(FL_RED);
        labelsize(GRID_SIZE / 4);
        labeltype(FL_SHADOW_LABEL);
        hide();
    }

protected:
    int m_nIndex;
    int m_nRow;
    int m_nCol;
    unsigned int m_nText;

    virtual void draw()
    {
        label(Label[m_nText]);
        Fl_Box::draw();
    }

};

class My_Fl_Window: public Fl_Window
{
public:
    My_Fl_Window(int argc,
                 char**argv) :
                    Fl_Window(GRID_NUMBER * (GRID_SIZE + GRID_WIDTH),
                              (GRID_WIDTH + GRID_SIZE) * GRID_NUMBER)
    {
        for (size_t r=0; r < GRID_NUMBER; r++)
        {
            for (size_t c=0; c < GRID_NUMBER; c++)
            {
                box[r * GRID_NUMBER + c]=
                                new Fl_Box(r * (GRID_SIZE + GRID_WIDTH),
                                           c * (GRID_WIDTH + GRID_SIZE),
                                           GRID_SIZE,
                                           GRID_SIZE,
                                           "");
                box[r * GRID_NUMBER + c]->box(FL_UP_BOX);


            }
        }
        for (size_t r=0; r < GRID_NUMBER; r++)
        {
            for (size_t c=0; c < GRID_NUMBER; c++)
            {
                tile[r * GRID_NUMBER + c]=new My_Fl_Box(r * GRID_NUMBER + c);
            }
        }
        //Fl_Window::end();
        Fl_Window::show(argc, argv);
        Fl::run();
    }
protected:
    void calculate(int e)
    {
        const char* ptr="no";
        switch (m_key)
        {
           case FL_Left:
               ptr="left";
               for (int r=0; r< GRID_NUMBER; r++)
               {
                   tile[r*GRID_NUMBER]->m_nText = r;
                   tile[r*GRID_NUMBER]->hide();
               }
               break;
           case FL_Up:
               ptr="up";
               break;
           case FL_Right:
               ptr="right";
               for (int r=0; r< GRID_NUMBER; r++)
               {
                   tile[r*GRID_NUMBER]->m_nText = r;
                   tile[r*GRID_NUMBER]->show();
               }
               break;
           case FL_Down:
               ptr="down";
               break;

        }
        printf("keypress: %s\n", ptr);
    }
    virtual void draw()
    {
        calculate(m_key);
        Fl_Window::draw();


//        for (size_t r=0; r < GRID_NUMBER; r++)
//        {
//            for (size_t c=0; c < GRID_NUMBER; c++)
//            {
//                //tile[r * GRID_NUMBER + c]->label(ptr);
//                tile[r * GRID_NUMBER + c]->show();
//            }
//        }
    }
    virtual int
    handle(int e)
    {
        int ret=Fl_Window::handle(e);

        switch (e)
        {
            case FL_PUSH:
            case FL_RELEASE:
            case FL_KEYUP:
            case FL_KEYDOWN:
            case FL_DRAG:
            {
                if (Fl::event_key() == FL_Left || Fl::event_key() == FL_Up
                                || Fl::event_key() == FL_Right
                                || Fl::event_key() == FL_Down)
                {
                    m_key=Fl::event_key();
                    redraw();
                }
            }
                break;
        }
        return (ret);
    }
    int m_key;
    Fl_Box* box[GRID_NUMBER * GRID_NUMBER];
    My_Fl_Box* tile[GRID_NUMBER * GRID_NUMBER];
};

int
main(int argc,
     char **argv)
{

    My_Fl_Window window(argc, argv);
    return 0;
}
