If you have comments or questions concerning this source file, discuss them in the forum.
/*
Copyright (c) 2002 Nicolai Haehnle

See the license.txt for details. If that file was not included in the
source distributions, please email <prefect@rtts.org>
*/
// gui_panel.h -- the GUI base class

#ifndef GUI_PANEL_H
#define GUI_PANEL_H

class GPanel;
class GGrid;

typedef std::list<GPanel*>::iterator GPanel_lit;
typedef std::list<GPanel*>::reverse_iterator GPanel_rlit;

class GPanel : public LObject {
    friend class GGrid;

private:
    GPanel  *m_pFocus;      // follows m_logical
    bool    m_bFocussed;    // are we in the line of focus?
    GPanel  *m_pMouseIn;    // follows m_draw
    bool    m_bGrabbedMouse;    // this panel grabbed the mouse
    bool    m_bHasMouse;    // mouse is currently in this panel

    bool    m_bModal;       // inside Run()
    int     m_iEndModal;

    bool    m_bDormant;     // don't call Think() for self and children
    bool    m_bOblivious;   // self and children ignore all events
    bool    m_bCanFocus;    // the panel can receive the input focus
    bool    m_bVisible;     // draw self and children
    bool    m_bTopLevel;    // screen coordinates don't go over parents; always true when !m_pParent

    bool    m_bActive;      // special activity (such as button being pressed)

public:
    GPanel              *m_pParent;
    std::list<GPanel*>  m_Children; // front() is topmost

protected:
    LRect   m_rc;           // position and size relative to parent

    byte    m_color[4];     // the normal drawing color

public:
    GPanel(GPanel *pParent, int x, int y, int w, int h, bool bTopLevel = false);
    virtual ~GPanel();

    int Run();
    void EndModal(int iCode);

    bool IsVisible();
    void SetVisible(bool bVisible) { m_bVisible = bVisible; }

    void SetTopLevel(bool toplevel);
    inline bool GetTopLevel() { return m_bTopLevel; }

    bool IsDormant() { return m_bDormant; }
    void SetDormant(bool bDormant) { m_bDormant = bDormant; }
    bool IsOblivious() { return m_bOblivious; }
    void SetOblivious(bool bOblivious);
    void SetCanFocus(bool bCanFocus);
    bool CanFocus() { return m_bCanFocus && !m_bOblivious; }

    bool IsFocussed() { return m_bFocussed; }
    void SetFocus(GPanel *pPanel);
    bool FocusNext();
    bool FocusLast();

    void PanelToScreen(int *x, int *y);
    void ScreenToPanel(int *x, int *y);

    void GrabMouse(bool bGrab);
    bool GrabbedMouse() { return m_bGrabbedMouse; }
    bool IsMouseOver() { return m_bHasMouse; }

public: // Overridable functions
    virtual const char *MouseCursor();

    virtual void Begin();
    virtual void End();

    virtual void Draw();
    virtual void Logic();

    virtual bool OkayToQuit();
    virtual void GainFocus(bool bGain);
    virtual bool Key(int code, char c, bool down);
    virtual void MouseEnter(bool bEnter);
    virtual bool MouseButton(int btn, int x, int y, bool down);
    virtual void MouseMove(int x, int y);

public:
    inline void SetColor(int r, int g, int b, int a = 255) {
        m_color[0] = r; m_color[1] = g; m_color[2] = b; m_color[3] = a;
    }

    inline void SetPos(int x, int y) { m_rc.pos[0] = x; m_rc.pos[1] = y; }
    inline void SetSize(int w, int h) { m_rc.size[0] = w; m_rc.size[1] = h; }

    inline void GetPos(int *x, int *y) { *x = m_rc.pos[0]; *y = m_rc.pos[1]; }
    inline void GetSize(int *w, int *h) { *w = m_rc.size[0]; *h = m_rc.size[1]; }
    inline int GetWidth() { return m_rc.size[0]; }
    inline int GetHeight() { return m_rc.size[1]; }

private:
    void intAddChild(GPanel *pChild);
    void intRemoveChild(GPanel *pChild);

    void intDrawMouse();

    void intDraw();
    void intLogic();

    GPanel *intTrackMouse(int x, int y);

    bool intOkayToQuit();
    void intGainFocus(bool bGain);
    bool intKey(int code, char c, bool down);
    void intMouseEnter(bool bEnter);
    bool intMouseButton(int btn, int x, int y, bool down);
    void intMouseMove(int x, int y);

private:
    static GPanel               *s_pModal; // pointer to the current modal panel
    static GPanel               *s_pGrabMouse;  // the top-level panel in the grab line
    static std::list<GPanel*>   s_TopLevel; // list of top-level panels (front() is top-most)

    static void cbKey(int code, char c, bool down);
    static GPanel *cbTrackMouse(int scrx, int scry);
    static void cbMouseButton(int btn, int x, int y, bool down);
    static void cbMouseMove(int x, int y);
    static void cbQuitRequest();
};

#endif // GUI_PANEL_H