diff options
-rw-r--r-- | include/widgets.h | 44 | ||||
-rw-r--r-- | lib/widgets.cc | 201 | ||||
-rw-r--r-- | src/test.cc | 60 |
3 files changed, 284 insertions, 21 deletions
diff --git a/include/widgets.h b/include/widgets.h index 88ba2d9..2eec009 100644 --- a/include/widgets.h +++ b/include/widgets.h @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: widgets.h,v 1.4 2004-07-15 14:21:30 pixel Exp $ */ +/* $Id: widgets.h,v 1.5 2004-07-16 15:04:52 pixel Exp $ */ #ifndef __WIDGETS_H__ #define __WIDGETS_H__ @@ -28,6 +28,7 @@ namespace mogltk { enum event_t { + E_TIMER, E_MOUSE_START_DRAG, E_MOUSE_DRAG, E_MOUSE_DRAG_OVER, @@ -68,6 +69,8 @@ namespace mogltk { virtual void SetVisible(bool); bool GetEnabled(); virtual void SetEnabled(bool); + void MoveOnTop(); + static void check_timed_events(); protected: widget(widget * father, int x, int y, int sx, int sy, int type, String name, shape *); virtual void draw(); @@ -79,10 +82,12 @@ namespace mogltk { 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, * root; + widget * father, * next, * prev, * child, * last, * root; static widget * focused; int type; String name; @@ -90,6 +95,13 @@ namespace mogltk { 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_event> timed_events; void computeabs(); void idraw(); @@ -176,6 +188,7 @@ namespace mogltk { 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); @@ -205,7 +218,7 @@ namespace mogltk { int selected; ContextMenu * subselected; private: - bool in_click; + bool in_click, sticky; bool iin_click(); }; @@ -213,11 +226,34 @@ namespace mogltk { class Menu : public widget { public: Menu(shape *, widget * father); - virtual void resize_notify(); + void addnode(const String &, action *); + void addsub(const String &, ContextMenu * sub); + ContextMenu * createsub(const String &); + virtual void SetEnabled(int i, bool); 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(); + 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<node> nodes; + int cur_x; + int selected; }; }; }; diff --git a/lib/widgets.cc b/lib/widgets.cc index c0e09db..3298385 100644 --- a/lib/widgets.cc +++ b/lib/widgets.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* $Id: widgets.cc,v 1.6 2004-07-15 14:21:31 pixel Exp $ */ +/* $Id: widgets.cc,v 1.7 2004-07-16 15:04:53 pixel Exp $ */ #include <SDL.h> #include <vector> @@ -36,6 +36,8 @@ mogltk::widget * dragged_widget = 0; std::vector<mogltk::widget *> out_move, out_click; +std::vector<mogltk::widget::timed_event> mogltk::widget::timed_events; + class widget_mouse_event : public mogltk::engine::mouseevent { public: @@ -122,6 +124,19 @@ void widget_mouse_event::action(SDL_MouseButtonEvent b) { printm(M_INFO, "mouse_down\n"); root->m_event(mx, my, mogltk::E_MOUSE_DOWN); // generate a mouse_down event; + for (i = out_click.begin(); i != out_click.end(); i++) { + out_click_stack.push_back(*i); + } + + for (i = out_click_stack.begin(); i != out_click_stack.end(); i++) { + if (!(*i)->inside(mx, my)) { + (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT_CLICK); + // generate a mouse_out_click event + } + } + + out_click_stack.empty(); + } else { mouse_down = false; if (mouse_drag) { @@ -171,7 +186,7 @@ void widget_mouse_event::action(SDL_MouseButtonEvent b) { mogltk::widget * mogltk::widget::focused = 0; mogltk::widget::widget(widget * _father, int _x, int _y, int _sx, int _sy, int _type, String _name, mogltk::shape * _sh) : - x(_x), y(_y), sx(_sx), sy(_sy), father(_father), type(_type), name(_name), sh(_sh), exclusive(0), visible(true), enabled(true) { + x(_x), y(_y), sx(_sx), sy(_sy), father(_father), prev(0), child(0), last(0), type(_type), name(_name), sh(_sh), exclusive(0), visible(true), enabled(true) { if (!father) { root = this; father = this; @@ -184,11 +199,11 @@ mogltk::widget::widget(widget * _father, int _x, int _y, int _sx, int _sy, int _ next = father->child; if (next) next->prev = this; + if (!father->last) + father->last = this; father->child = this; root = father->root; } - prev = 0; - child = 0; computeabs(); } @@ -204,6 +219,8 @@ mogltk::widget::~widget() { if (next) next->prev = prev; + else + father->last = prev; } void mogltk::widget::computeabs() { @@ -361,8 +378,8 @@ void mogltk::widget::m_event(int x, int y, mogltk::event_t event) { } bool mogltk::widget::ievent(int xe, int ye, mogltk::event_t event) { - if (next) - if (next->ievent(xe, ye, event)) + if (prev) + if (prev->ievent(xe, ye, event)) return true; if (!inside(xe, ye)) @@ -371,8 +388,8 @@ bool mogltk::widget::ievent(int xe, int ye, mogltk::event_t event) { if (exclusive) return exclusive->ievent(xe, ye, event); - if (child) - if (child->ievent(xe, ye, event)) + if (last) + if (last->ievent(xe, ye, event)) return true; if (!enabled || !visible) @@ -430,6 +447,40 @@ void mogltk::widget::SetEnabled(bool _enabled) { enabled = _enabled; } +void mogltk::widget::MoveOnTop() { + if (!prev) + return; + + if (!next) { + father->last = prev; + } else { + next->prev = prev; + } + prev->next = next; + prev = 0; + next = father->child; + + next->prev = this; + father->child = this; +} + +void mogltk::widget::check_timed_events() { + std::vector<timed_event>::iterator i; + Uint32 t = SDL_GetTicks(); + widget * w; + + for (i = timed_events.begin(); i != timed_events.end(); i++) { + if (i->t <= t) { + w = i->w; + timed_events.erase(i); + w->process_event(engine::mouseX(), engine::mouseY(), E_TIMER); + i = timed_events.begin(); + if (i == timed_events.end()) + return ; + } + } +} + void mogltk::widget::add_out_move() { std::vector<widget *>::iterator i; @@ -474,6 +525,15 @@ void mogltk::widget::remove_out_click() { } } +void mogltk::widget::set_timed_event(Uint32 t) { + timed_events.push_back(timed_event(this, SDL_GetTicks() + t)); +} + +void mogltk::widget::set_absolute_timed_event(Uint32 t) { + timed_events.push_back(timed_event(this, t)); +} + + /* * Predefined widgets. */ @@ -569,6 +629,7 @@ bool mogltk::widgets::SmartBox::process_event(int x, int y, mogltk::event_t even break; case E_MOUSE_DRAG_OVER: move(x - ox + oax, y - oy + oay); + MoveOnTop(); return true; } return false; @@ -711,7 +772,7 @@ int mogltk::widgets::ContextMenu::node::GetH() { return h; } -mogltk::widgets::ContextMenu::ContextMenu(shape * sh, mogltk::widget * father, int x, int y) : widget(father, x, y, 8, 4, 1, "ContextMenu", sh), selected(-1), subselected(0), in_click(false) { +mogltk::widgets::ContextMenu::ContextMenu(shape * sh, mogltk::widget * father, int x, int y) : widget(father, x, y, 8, 4, 1, "ContextMenu", sh), selected(-1), subselected(0), in_click(false), sticky(false) { } mogltk::widgets::ContextMenu::~ContextMenu() { @@ -792,6 +853,8 @@ void mogltk::widgets::ContextMenu::resize(int w, int h) { } void mogltk::widgets::ContextMenu::SetVisible(bool visible) { + if (!visible && sticky) + return; widget::SetVisible(visible); if (!visible && subselected) { subselected->SetVisible(false); @@ -799,6 +862,7 @@ void mogltk::widgets::ContextMenu::SetVisible(bool visible) { if (visible) { add_out_click(); + MoveOnTop(); } } @@ -806,6 +870,11 @@ void mogltk::widgets::ContextMenu::SetEnabled(int i, bool e) { nodes[i].SetEnabled(e); } +void mogltk::widgets::ContextMenu::StickyDisplay() { + sticky = true; + SetVisible(true); +} + void mogltk::widgets::ContextMenu::draw() { std::vector<node>::iterator i; int n; @@ -835,6 +904,7 @@ bool mogltk::widgets::ContextMenu::process_event(int xe, int ye, mogltk::event_t switch (event) { case E_MOUSE_MOVE: + sticky = false; for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { if (!i->GetLine()) { int ax, ax2, ay, ay2; @@ -873,6 +943,9 @@ bool mogltk::widgets::ContextMenu::process_event(int xe, int ye, mogltk::event_t } in_click = true; break; + case E_MOUSE_DOWN: + in_click = true; + break; case E_MOUSE_OUT: selected = -1; remove_out_move(); @@ -905,7 +978,34 @@ bool mogltk::widgets::ContextMenu::iin_click() { * The Menu topframe * ********************/ -mogltk::widgets::Menu::Menu(shape * sh, mogltk::widget * father) : widget(father, 0, 0, 0, 0, 0, "Menu", sh) { +mogltk::widgets::Menu::node::node(const String & _caption, mogltk::widgets::ContextMenu * _sub, mogltk::widgets::action * _a, int _x) : caption(_caption), sub(_sub), a(_a), x(_x) { +} + +String mogltk::widgets::Menu::node::GetCaption() { + return caption; +} + +mogltk::widgets::ContextMenu * mogltk::widgets::Menu::node::GetSub() { + return sub; +} + +mogltk::widgets::action * mogltk::widgets::Menu::node::GetAction() { + return a; +} + +int mogltk::widgets::Menu::node::GetX() { + return x; +} + +bool mogltk::widgets::Menu::node::GetEnabled() { + return enabled; +} + +void mogltk::widgets::Menu::node::SetEnabled(bool _enabled) { + enabled = _enabled; +} + +mogltk::widgets::Menu::Menu(shape * sh, mogltk::widget * father) : widget(father, 0, 0, 0, 0, 0, "Menu", sh), cur_x(0), selected(-1) { rect r = father->GetDrawRect(); move(r.x, r.y); resize(r.w, 16); @@ -916,11 +1016,89 @@ void mogltk::widgets::Menu::resize_notify() { resize(r.w, 16); } +void mogltk::widgets::Menu::addnode(const String & caption, mogltk::widgets::action * a) { + nodes.push_back(node(caption, 0, a, cur_x)); + cur_x += SystemFont->singletextsize(caption) + 6; +} + +void mogltk::widgets::Menu::addsub(const String & caption, mogltk::widgets::ContextMenu * sub) { + nodes.push_back(node(caption, sub, 0, cur_x)); + cur_x += SystemFont->singletextsize(caption) + 6; +} + +mogltk::widgets::ContextMenu * mogltk::widgets::Menu::createsub(const String & caption) { + ContextMenu * r = new ContextMenu(Shaper(), Father(), GetX() + cur_x, GetY() + 16); + addsub(caption, r); + r->SetVisible(false); + return r; +} + +void mogltk::widgets::Menu::SetEnabled(int i, bool e) { + nodes[i].SetEnabled(e); +} + void mogltk::widgets::Menu::draw(void) { - Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2(), BLUE); + std::vector<node>::iterator i; + int n; + + Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2(), DOS_WHITE); + + for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { + if (selected == n) { + if ((i + 1) == nodes.end()) { + Shaper()->box(GetAX() + i->GetX(), GetAY(), cur_x, GetAY2(), DOS_MAGENTA); + } else { + Shaper()->box(GetAX() + i->GetX(), GetAY(), GetAX() + i[1].GetX(), GetAY2(), DOS_MAGENTA); + } + } + Shaper()->text(GetAX() + i->GetX() + 3, GetAY(), i->GetCaption(), BLACK); + } } bool mogltk::widgets::Menu::process_event(int mx, int my, mogltk::event_t event) { + std::vector<node>::iterator i; + action * a; + ContextMenu * sub; + int n; + + switch (event) { + case E_MOUSE_MOVE: + selected = -1; + for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) { + int ax, ax2, ay, ay2; + + ax = GetAX() + i->GetX(); + ay = GetAY(); + if ((i + 1) != nodes.end()) { + ax2 = GetAX() + i[1].GetX(); + } else { + ax2 = GetAX() + cur_x; + } + ay2 = GetAY2(); + + if (!((mx < ax) || (mx > ax2) || (my < ay) || (my > ay2))) { + selected = n; + } + } + add_out_move(); + return true; + case E_MOUSE_CLICK: + a = 0; + if (selected != -1) { + if ((a = nodes[selected].GetAction()) && nodes[selected].GetEnabled()) { + a->do_action(this); + return true; + } else if ((sub = nodes[selected].GetSub()) && nodes[selected].GetEnabled()) { + sub->StickyDisplay(); + return true; + } + } + break; + case E_MOUSE_OUT: + selected = -1; + remove_out_move(); + return true; + } return false; } @@ -943,6 +1121,7 @@ void mogltk::widget::mainloop() { mogltk::ColorP::Max.A = 255; Sprite::Cursor->draw(mx - 8, my - 6); engine::base_o->Flip(); + widget::check_timed_events(); } delete mouse; diff --git a/src/test.cc b/src/test.cc index 45d758c..3219004 100644 --- a/src/test.cc +++ b/src/test.cc @@ -698,14 +698,48 @@ virtual int startup() throw (GeneralException) { new mogltk::widgets::Frame(sh, w, 10, 10, 600, 400); //new mogltk::widgets::MsgBox(sh, w, "Test", "Blablabla\nCeci est un test de la\nclasse MsgBox."); - mogltk::widgets::ContextMenu * c = new mogltk::widgets::ContextMenu(sh, w, 20, 20), * c2; - mogltk::widget * sm; - mogltk::rect r; + class tLabel : public mogltk::widgets::Label { + public: + tLabel(mogltk::shape * sh, mogltk::widget * father) : Label(sh, father, 250, 200, 16, 16, "I"), tick(0) { set_timed_event(500); } + virtual bool process_event(int mx, int my, mogltk::event_t event) { + if (Label::process_event(mx, my, event)) + return true; + + if (event == mogltk::E_TIMER) { + set_timed_event(500); + tick = (tick + 1) % 4; + switch (tick) { + case 0: + caption = "I"; + break; + case 1: + caption = "/"; + break; + case 2: + caption = "-"; + break; + case 3: + caption = "\\"; + break; + } + } + } + private: + int tick; + }; - sm = new mogltk::widgets::SmartBox(sh, w, 250, 300, 100, 70, "SmartBox"); - r = sm->GetDrawRect(); - new mogltk::widgets::Menu(sh, w); + mogltk::widgets::ContextMenu * c, * c2; + //c = new mogltk::widgets::ContextMenu(sh, w, 20, 20); + mogltk::widgets::Menu * sm; + new mogltk::widgets::SmartBox(sh, w, 250, 300, 100, 70, "SmartBox"); + sm = new mogltk::widgets::Menu(sh, w); + + sm->addnode("Toto", 0); + sm->addnode("Titi", 0); + sm->addnode("Tutu", 0); + +#if 0 c->addnode("Test", 0); c->addnode("Test2", 0); c->addline(); @@ -716,6 +750,20 @@ virtual int startup() throw (GeneralException) { c2->addnode("A sub", 0); c2->createsub("subsub")->addnode("Toto", 0); c2->SetEnabled(0, false); +#endif + + c = sm->createsub("Sub Menu"); + c->addnode("Blah1", 0); + c->addnode("Blah2", 0); + c->addnode("Blah3", 0); + c->addline(); + c2 = c->createsub("SubBlah"); + c2->addnode("SubBlah1", 0); + c2->addnode("SubBlah2", 0); + + sm->MoveOnTop(); + + new tLabel(sh, w); w->mainloop(); |