/* * mogltk * Copyright (C) 1999-2004 Nicolas "Pixel" Noble * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* $Id: widgets.h,v 1.17 2006-10-28 16:50:46 pixel Exp $ */ #ifndef __WIDGETS_H__ #define __WIDGETS_H__ #include #include #include #include namespace mogltk { enum event_t { E_TIMER, E_MOUSE_START_DRAG, E_MOUSE_DRAG, E_MOUSE_DRAG_OVER, E_MOUSE_END_DRAG, E_MOUSE_END_DRAG_OVER, E_MOUSE_MOVE, E_MOUSE_OUT, E_MOUSE_DOWN, E_MOUSE_RIGHT_DOWN, E_MOUSE_MIDDLE_DOWN, E_MOUSE_UP, E_MOUSE_RIGHT_UP, E_MOUSE_MIDDLE_UP, E_MOUSE_CLICK, E_MOUSE_OUT_CLICK, E_MOUSE_DBL_CLICK, }; class Widget : public Base { public: virtual ~Widget() throw (GeneralException); virtual void move(int x, int y); virtual void resize(int sx, int sy); int GetX(); int GetY(); int GetH(); int GetW(); int GetAX(); int GetAY(); int GetAX2(); int GetAY2(); virtual mogltk::rect GetDrawRect(); Widget * Father(); Widget * Child(); Widget * Next(); Widget * Prev(); Widget * InnerPanel(); virtual Widget * find_widget(int x, int y); void fulldraw(); Shape * Shaper(); void mainloop() throw (GeneralException); void m_event(int x, int y, event_t event); bool inside(int x, int y); bool GetVisible(); virtual void SetVisible(bool); bool GetEnabled(); virtual void SetEnabled(bool); void MoveOnTop(); static void check_timed_events(); void center(bool cx = true, bool cy = true); void set_viewport(); void delete_me(); protected: Widget(Widget * father, int x, int y, int sx, int sy, int type, String name, Shape *); virtual void draw(); virtual bool process_event(int x, int y, event_t event); virtual void resize_notify(); virtual Widget * create_panel(); void set_exclusive(Widget *); void unset_exclusive(Widget *); void add_out_move(); void remove_out_move(); void add_out_click(); void remove_out_click(); void set_timed_event(Uint32); void set_absolute_timed_event(Uint32); String caption; private: int x, y, sx, sy, ax, ay, ax2, ay2; Widget * father, * next, * prev, * child, * last, * root, * panel; static Widget * focused; int type; String name; Shape * sh; Widget * exclusive; bool visible; bool enabled; class timed_event { public: timed_event(Widget * _w, Uint32 _t) : w(_w), t(_t) { } Widget * w; Uint32 t; }; static std::vector timed_events; static std::vector add_list; static std::vector del_list; static bool in_delete_loop; void computeabs(); void idraw(); bool ievent(int x, int y, event_t event); void icomputeabs(); void iresize_notify(); void linkme(); }; namespace Widgets { /*! The drawer is mostly used inside the Root Widget, to implement the function to draw the background. */ class drawer : public Base { public: virtual void draw(Widget *) = 0; }; /*! The action class defines "what happens" when you activate a Widget, mostly used in buttons and co. */ class action : public Base { public: virtual void do_action(Widget *) = 0; }; /*! The Root Widget is the father of all the Widgets. It'll define the background, as well as the whole tree of the visible Widgets onscreen. */ class Root : public Widget { public: Root(Shape *, drawer * = 0, drawer * = 0); void setdrawer(drawer *); void setbgdrawer(drawer *); virtual void drawbg(); protected: virtual void draw(); private: drawer * dr; drawer * bg; }; /*! The Panel Widget is not visible. Its only usage is to hold several other Widgets at a relative position. */ class Panel : public Widget { public: Panel(Shape *, Widget * father, int x, int y, int w, int h); }; /*! The Button Widget will draw a very simple button onscreen, and react to all the necessary mouse events. */ class Button : public Widget { public: Button(action *, Shape *, Widget * father, int x, int y, int w, int h, const String & caption); virtual ~Button() throw (GeneralException); void simulate_press(); action * cascade_action(); protected: virtual void draw(); virtual bool process_event(int, int, event_t); bool bevel; private: bool dragging; action * a, * cascade; }; /*! The Label Widget is only a pure inactive chunk of text. */ class Label : public Widget { public: Label(Shape *, Widget * father, int x, int y, int w, int h, const String & caption, const ColorP & color = BLACK, mogltk::Font * = mogltk::SystemFont); virtual ~Label() throw (GeneralException) {} protected: virtual void draw(); private: ColorP color; mogltk::Font * label_font; }; /*! The SmartBox is a simple window with a title line. */ class SmartBox : public Widget { public: SmartBox(Shape *, Widget * father, int x, int y, int w, int h, const String & caption); virtual rect GetDrawRect(); protected: virtual void draw(); virtual bool process_event(int, int, event_t); private: int ox, oy, oax, oay; }; /*! The SmartBoxClose is a SmartBox with a close button at upper-left. */ class SmartBoxClose : public SmartBox { public: SmartBoxClose(Shape *, Widget * father, int x, int y, int w, int h, const String & caption); }; /*! The MsgBox is a SmartBoxClose which holds a text, as well as a 'Ok' button. */ class MsgBox : public SmartBox { public: MsgBox(action *, Shape *, Widget * father, const String & caption, const String & text, mogltk::Font * = mogltk::SystemFont); virtual ~MsgBox() throw (GeneralException); private: mogltk::Font * msgbox_font; }; /*! The Frame Widget will act as a visible panel. It'll hold Widgets within a visible frame or fence. */ class Frame : public Widget { public: Frame(Shape *, Widget * father, int x, int y, int w, int h); virtual rect GetDrawRect(); protected: virtual void draw(); }; /*! The ContextMenu is a quite heavy Widget which will display a kind of popup menu, holding several buttons or submenus in nodes. */ class ContextMenu : public Widget { public: ContextMenu(Shape *, Widget * father, int x, int y); virtual ~ContextMenu() throw (GeneralException); void addnode(const String &, action *); void addline(); void addsub(const String &, ContextMenu *); ContextMenu * createsub(const String &); virtual void move(int x, int y); virtual void resize(int w, int h); virtual void SetVisible(bool); virtual void SetEnabled(int i, bool); void StickyDisplay(); protected: virtual void draw(); virtual bool process_event(int x, int y, event_t event); class node : public Base { public: node(const String &, int x, int y, int w, int h, action * = 0, ContextMenu * sub = 0, ContextMenu * father = 0, bool = false); String GetCaption(); action * GetAction(); ContextMenu * GetSub(); ContextMenu * GetFather(); bool GetLine(); bool GetEnabled(); void SetEnabled(bool); int GetX(); int GetY(); int GetW(); int GetH(); private: String caption; int x, y, w, h; action * a; ContextMenu * sub, * father; bool line, enabled; }; std::vector nodes; int selected; ContextMenu * subselected; private: bool in_click, sticky; bool iin_click(); }; /*! The Menu Widget will be display ontop of the father Widget, and its submenus are simply sont ContextMenus. */ class Menu : public Widget { public: Menu(Shape *, Widget * father); virtual ~Menu() throw (GeneralException) {} void addnode(const String &, action *); void addsub(const String &, ContextMenu * sub); ContextMenu * createsub(const String &); virtual void SetEnabled(int i, bool); void SetCaption(int i, const String &); protected: virtual void resize_notify(); virtual void draw(); virtual bool process_event(int, int, event_t); class node : public Base { public: node(const String & caption, ContextMenu * sub, action * a, int x); String GetCaption(); void SetCaption(const String &); ContextMenu * GetSub(); action * GetAction(); int GetX(); bool GetEnabled(); void SetEnabled(bool); private: String caption; ContextMenu * sub; action * a; int x; bool enabled; }; private: std::vector nodes; int cur_x; int selected; ContextMenu * subselected; }; /*! The InputText Widget is used to do a simple input box on the screen. */ class InputText : public Widget { public: InputText(action *, Shape *, Widget * father, int x, int y); virtual ~InputText() throw (GeneralException); virtual void draw(); const String & GetText() const; void SetText(const String &); void activate(); void SetCursorPos(int); virtual bool process_event(int, int, event_t); private: class inputtext_keyevent : public mogltk::engine::keyevent { public: inputtext_keyevent(InputText *); virtual void down(SDL_keysym k); virtual void up(SDL_keysym k); private: InputText * father; } * it_keyevent; String text; action * a; bool cursor_visible; int cursor_pos; }; /*! The InputDialog is a kind of MsgBox which holds an InputText as well as a 'Ok' button. It also contains an action so that the text can be readed from where the dialog is created. */ class InputDialog : public SmartBox { public: InputDialog(action *, Shape *, Widget * father, const String & caption, const String & text, mogltk::Font * = mogltk::SystemFont); virtual ~InputDialog() throw (GeneralException); String GetText(); private: InputText * it; mogltk::Font * InputDialog_font; }; /*! The ActionAndDelete provides a mechanism for a Widget to run an action then self-destruct. Used for example by the MsgBox and InputDialog. */ class ActionAndDelete : public mogltk::Widgets::action { public: ActionAndDelete(mogltk::Widget * _parent, mogltk::Widgets::action * _a) : parent(_parent), a(_a) { } virtual void do_action(mogltk::Widget *) { if (a) a->do_action(parent); parent->delete_me(); delete this; } private: mogltk::Widget * parent; mogltk::Widgets::action * a; }; }; }; #endif