From baac659433417ee555e3e04a28ea6c06fa23d588 Mon Sep 17 00:00:00 2001 From: pixel Date: Mon, 12 Jul 2004 15:08:14 +0000 Subject: Widget slowly working... --- include/glwidgets.h | 32 +++--- include/widgets.h | 96 +++++++++++++--- lib/engine.cc | 4 +- lib/glbase.cc | 4 + lib/glwidgets.cc | 16 +-- lib/widgets.cc | 308 ++++++++++++++++++++++++++++++++++++++++++++++++++-- src/test.cc | 12 +- 7 files changed, 424 insertions(+), 48 deletions(-) diff --git a/include/glwidgets.h b/include/glwidgets.h index b606a14..241dd55 100644 --- a/include/glwidgets.h +++ b/include/glwidgets.h @@ -1,15 +1,17 @@ -#ifndef __GLWIDGETS_H__ -#define __GLWIDGETS_H__ - -#include - -namespace mogltk { - class glRoot : public Root { - public: - glRoot(shape *); - protected: - virtual void draw(); - }; -}; - -#endif +#ifndef __GLWIDGETS_H__ +#define __GLWIDGETS_H__ + +#include + +namespace mogltk { + namespace widgets { + class glRoot : public Root { + public: + glRoot(shape *); + protected: + virtual void draw(); + }; + }; +}; + +#endif diff --git a/include/widgets.h b/include/widgets.h index bef2682..116eef5 100644 --- a/include/widgets.h +++ b/include/widgets.h @@ -5,6 +5,18 @@ #include namespace mogltk { + enum event_t { + 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_DOWN, + E_MOUSE_UP, + E_MOUSE_CLICK, + E_MOUSE_DBL_CLICK, + }; class widget : public Base { public: virtual ~widget(); @@ -18,34 +30,92 @@ namespace mogltk { int GetAY(); int GetAX2(); int GetAY2(); + widget * Father(); + widget * Child(); + widget * Next(); + widget * Prev(); void fulldraw(); shape * Shaper(); + void mainloop(); + void m_event(int x, int y, event_t event); + bool inside(int x, int y); protected: widget(widget * father, int x, int y, int sx, int sy, int type, String name, shape *); - virtual void draw() = 0; + virtual void draw(); + String caption; + virtual bool process_event(int x, int y, event_t event); + void set_exclusive(widget *); + void unset_exclusive(widget *); private: void computeabs(); int x, y, sx, sy, ax, ay, ax2, ay2; widget * father, * next, * prev, * child, * root; static widget * focused; int type; - String name, caption; + String name; shape * sh; + widget * exclusive; void idraw(); + bool ievent(int x, int y, event_t event); + void icomputeabs(); }; - class drawer : public Base { - public: - virtual void draw(widget *) = 0; - }; + namespace widgets { + class drawer : public Base { + public: + virtual void draw(widget *) = 0; + }; - class Root : public widget { - public: - Root(shape *, drawer * = 0); - void setdrawer(drawer *); - protected: - virtual void draw(); - drawer * dr; + class action : public Base { + public: + virtual void do_action(widget *) = 0; + }; + + class Root : public widget { + public: + Root(shape *, drawer * = 0); + void setdrawer(drawer *); + protected: + virtual void draw(); + drawer * dr; + }; + + class Button : public widget { + public: + Button(action *, shape *, widget * father, int x, int y, int w, int h, const String & caption); + protected: + virtual void draw(); + virtual bool process_event(int, int, event_t); + bool bevel; + private: + bool dragging; + action * a; + }; + + class Label : public widget { + public: + Label(shape *, widget * father, int x, int y, int w, int h, const String & caption, const ColorP & color = BLACK); + protected: + virtual void draw(); + private: + ColorP color; + }; + + class SmartBox : public widget { + public: + SmartBox(shape *, widget * father, int x, int y, int w, int h, const String & caption); + protected: + virtual void draw(); + virtual bool process_event(int, int, event_t); + private: + int ox, oy, oax, oay; + }; + + class MsgBox : public SmartBox { + public: + MsgBox(shape *, widget * father, const String & caption, const String & text); + virtual ~MsgBox(); + }; }; }; diff --git a/lib/engine.cc b/lib/engine.cc index 34317b1..a52aa1b 100644 --- a/lib/engine.cc +++ b/lib/engine.cc @@ -66,8 +66,8 @@ class keyhandler_t : public mogltk::engine::keyevent { mogltk::engine::mouseevent::mouseevent() { new_handler = 0; - old_handler = getmouseevent(); - old_handler->new_handler = this; + if ((old_handler = getmouseevent())) + old_handler->new_handler = this; setmouseevent(this); } diff --git a/lib/glbase.cc b/lib/glbase.cc index 9c33c54..22cbe3f 100644 --- a/lib/glbase.cc +++ b/lib/glbase.cc @@ -165,6 +165,7 @@ void mogltk::glbase::glVertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w) { } void mogltk::glbase::changeviewport(int x, int y, unsigned int w, unsigned int h) { +#if 0 if ((w == 0) && (h == 0)) { w = GetWidth() - x; h = GetHeight() - y; @@ -174,6 +175,9 @@ void mogltk::glbase::changeviewport(int x, int y, unsigned int w, unsigned int h glViewport(x, y, w, h); if (!engine::base_o->is2D()) gluPerspective(fovy, ratio, 1.0, 1024.0); +#endif + glScissor(x, GetHeight() - y - h - 1, w + 1, h + 1); + glEnable(GL_SCISSOR_TEST); } void mogltk::glbase::changefovy(GLdouble nfoyv) { diff --git a/lib/glwidgets.cc b/lib/glwidgets.cc index 511cdc4..3119831 100644 --- a/lib/glwidgets.cc +++ b/lib/glwidgets.cc @@ -1,8 +1,8 @@ -#include -#include -#include "mcolor.h" -#include "glwidgets.h" - -void mogltk::glRoot::draw() { - Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2()); -} +#include +#include +#include "mcolor.h" +#include "glwidgets.h" + +void mogltk::widgets::glRoot::draw() { + Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2()); +} diff --git a/lib/widgets.cc b/lib/widgets.cc index 91e5904..5676721 100644 --- a/lib/widgets.cc +++ b/lib/widgets.cc @@ -1,8 +1,8 @@ -#include + #include #include #include "font.h" -#include "widgets.h" #include "engine.h" +#include "widgets.h" #ifdef HAVE_CONFIG_H #include "config.h" @@ -10,10 +10,104 @@ #include "gettext.h" +mogltk::widget * dragged_widget = 0; + +class widget_mouse_event : public mogltk::engine::mouseevent { + public: + widget_mouse_event(mogltk::widget *); + virtual void move(SDL_MouseMotionEvent); + virtual void action(SDL_MouseButtonEvent); + private: + mogltk::widget * root; + int mouse_x_down, mouse_y_down; + bool mouse_down, mouse_drag; + Uint32 old_click; +}; + +widget_mouse_event::widget_mouse_event(mogltk::widget * _root) : root(_root), mouse_down(false), mouse_drag(false) { +} + +void widget_mouse_event::move(SDL_MouseMotionEvent m) { + bool out_threshold; + + if (mouse_down) { + int dx, dy; + + dx = ABS(mouse_x_down - mogltk::engine::mouseX()); + dy = ABS(mouse_y_down - mogltk::engine::mouseY()); + + out_threshold = (dx <= 1) && (dy <= 1); + } + + if (mouse_down && (out_threshold || mouse_drag)) { + if (!mouse_drag) { + printm(M_INFO, "mouse_start_drag\n"); + // generate a mouse_start_drag event + root->m_event(mouse_x_down, mouse_y_down, mogltk::E_MOUSE_START_DRAG); + } + if (dragged_widget) { + printm(M_INFO, "mouse_drag_over"); + // generate a mouse_drag_over event + dragged_widget->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_DRAG_OVER); + } + + printm(M_INFO, "mouse_drag\n"); + // generate a mouse_drag event + root->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_DRAG); + mouse_drag = true; + } else { + printm(M_INFO, "mouse_move\n"); + root->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_MOVE); + // generate a mouse_move event + } +} + +void widget_mouse_event::action(SDL_MouseButtonEvent b) { + if (b.button == 1) { + if (b.state) { + mouse_x_down = mogltk::engine::mouseX(); + mouse_y_down = mogltk::engine::mouseY(); + mouse_down = true; + printm(M_INFO, "mouse_down\n"); + root->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_DOWN); + // generate a mouse_down event; + } else { + mouse_down = false; + if (mouse_drag) { + mouse_drag = false; + printm(M_INFO, "mouse_end_drag\n"); + root->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_END_DRAG); + // generate a mouse_end_drag event + if (dragged_widget) { + printm(M_INFO, "mouse_end_drag_over"); + dragged_widget->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_END_DRAG_OVER); + // generate a mouse_end_drag_over event + dragged_widget = 0; + } + } else { + printm(M_INFO, "mouse_click\n"); + root->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_CLICK); + // generate a mouse_click event + + if ((SDL_GetTicks() - old_click) < 500) { + printm(M_INFO, "mouse_dbl_click\n"); + root->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_DBL_CLICK); + // generate a mouse_dbl_click event + } + + old_click = SDL_GetTicks(); + } + printm(M_INFO, "mouse_up\n"); + root->m_event(mogltk::engine::mouseX(), mogltk::engine::mouseY(), mogltk::E_MOUSE_UP); + // generate a mouse_up event. + } + } +} + 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) { + x(_x), y(_y), sx(_sx), sy(_sy), father(_father), type(_type), name(_name), sh(_sh), exclusive(0) { if (!father) { root = this; @@ -66,6 +160,9 @@ void mogltk::widget::move(int nx, int ny) { y = ny; computeabs(); + + if (child) + child->icomputeabs(); } void mogltk::widget::resize(int nsx, int nsy) { @@ -85,11 +182,11 @@ int mogltk::widget::GetY() { } int mogltk::widget::GetH() { - return sx; + return sy; } int mogltk::widget::GetW() { - return sy; + return sx; } int mogltk::widget::GetAX() { @@ -108,6 +205,22 @@ int mogltk::widget::GetAY2() { return ay2; } +mogltk::widget * mogltk::widget::Father() { + return father; +} + +mogltk::widget * mogltk::widget::Child() { + return child; +} + +mogltk::widget * mogltk::widget::Next() { + return next; +} + +mogltk::widget * mogltk::widget::Prev() { + return prev; +} + mogltk::shape * mogltk::widget::Shaper() { return sh; } @@ -150,25 +263,204 @@ void mogltk::widget::idraw() { child->idraw(); } +bool mogltk::widget::inside(int xe, int ye) { + return !((xe < ax) || (xe > ax2) || (ye < ay) || (ye > ay2)); +} + +void mogltk::widget::m_event(int x, int y, mogltk::event_t event) { + switch (event) { + case E_MOUSE_DRAG_OVER: + case E_MOUSE_END_DRAG_OVER: + process_event(x, y, event); + break; + default: + ievent(x, y, event); + } +} + +bool mogltk::widget::ievent(int xe, int ye, mogltk::event_t event) { + if (next) + if (next->ievent(xe, ye, event)) + return true; + + if (!inside(xe, ye)) + return false; + + if (exclusive) + return exclusive->ievent(xe, ye, event); + + if (child) + if (child->ievent(xe, ye, event)) + return true; + + return process_event(xe, ye, event); +} + +void mogltk::widget::draw() { +} + +bool mogltk::widget::process_event(int, int, mogltk::event_t) { + return false; +} + +void mogltk::widget::icomputeabs() { + computeabs(); + + if (next) + next->computeabs(); + + if (child) + child->computeabs(); +} + +void mogltk::widget::set_exclusive(mogltk::widget * w) { + w->exclusive = this; +} + +void mogltk::widget::unset_exclusive(mogltk::widget * w) { + w->exclusive = 0; +} + /* * Predefined widgets. */ /* Here is Root */ -mogltk::Root::Root(mogltk::shape * sh, mogltk::drawer * _dr) : widget(0, 0, 0, 0, 0, 0, "Root", sh), dr(_dr) { +mogltk::widgets::Root::Root(mogltk::shape * sh, mogltk::widgets::drawer * _dr) : widget(0, 0, 0, 0, 0, 0, "Root", sh), dr(_dr) { if (engine::root) delete engine::root; engine::root = this; } -void mogltk::Root::draw() { +void mogltk::widgets::Root::draw() { if (dr) dr->draw(this); else Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2()); } -void mogltk::Root::setdrawer(drawer * _dr) { +void mogltk::widgets::Root::setdrawer(drawer * _dr) { dr = _dr; } + +mogltk::widgets::Button::Button(action * _a, shape * sh, widget * father, int x, int y, int w, int h, const String & _caption) : widget(father, x, y, w, h, 0, "Button", sh), bevel(false), dragging(false), a(_a) { + caption = _caption; +} + +void mogltk::widgets::Button::draw() { + Shaper()->button(GetAX() + 1, GetAY() + 1, GetAX2() - 1, GetAY2() - 1, caption, bevel); +} + +bool mogltk::widgets::Button::process_event(int xe, int ye, mogltk::event_t event) { + switch (event) { + case E_MOUSE_DOWN: + bevel = true; + return true; + case E_MOUSE_CLICK: + bevel = false; + // action here. + if (a) + a->do_action(this); + return true; + case E_MOUSE_START_DRAG: + dragged_widget = this; + dragging = true; + return true; + case E_MOUSE_DRAG_OVER: + bevel = inside(xe, ye); + return true; + case E_MOUSE_END_DRAG_OVER: + dragging = false; + if (bevel); + // action here. + if (a) + a->do_action(this); + bevel = false; + return true; + } + return false; +} + +mogltk::widgets::SmartBox::SmartBox(shape * sh, mogltk::widget * father, int x, int y, int w, int h, const String & _caption) : widget(father, x, y, w, h, 0, "SmartBox", sh) { + caption = _caption; +} + +void mogltk::widgets::SmartBox::draw() { + Shaper()->window(GetAX(), GetAY(), GetAX2(), GetAY2(), caption); +} + +bool mogltk::widgets::SmartBox::process_event(int x, int y, mogltk::event_t event) { + switch (event) { + case E_MOUSE_START_DRAG: + if ((GetAY() + 20) > y) { + dragged_widget = this; + ox = x; + oy = y; + oax = GetX(); + oay = GetY(); + return true; + } + break; + case E_MOUSE_DRAG_OVER: + move(x - ox + oax, y - oy + oay); + return true; + } + return false; +} + +class MessageBoxAction : public mogltk::widgets::action { + public: + MessageBoxAction(mogltk::widget * _parent) : parent(_parent) { } + virtual void do_action(mogltk::widget *) { + delete parent; + delete this; + } + private: + mogltk::widget * parent; +}; + +mogltk::widgets::MsgBox::MsgBox(shape * sh, mogltk::widget * father, const String & caption, const String & text) : SmartBox(sh, father, 0, 0, 0, 0, caption) { + rect size = SystemFont->size(text); + rect lsize = size; + + size.w += 12; + size.h += 60; + + size.x = (father->GetW() - size.w) / 2; + size.y = (father->GetH() - size.h) / 2; + resize(size.w, size.h); + move(size.x, size.y); + + new Button(new MessageBoxAction(this), sh, this, size.w / 2 - 25, size.h - 30, 50, 24, "Ok"); + new Label(sh, this, 6, 24, lsize.w, lsize.h, text, BLACK); + + set_exclusive(father); +} + +mogltk::widgets::MsgBox::~MsgBox() { + unset_exclusive(Father()); +} + +mogltk::widgets::Label::Label(shape * sh, mogltk::widget * father, int x, int y, int w, int h, const String & _caption, const ColorP & _color) : widget(father, x, y, w, h, 0, "Label", sh), color(_color) { + caption = _caption; +} + +void mogltk::widgets::Label::draw() { + Shaper()->text(GetAX(), GetAY(), caption, color); +} + + + +void mogltk::widget::mainloop() { + bool end_event_loop = false; + widget_mouse_event * mouse = new widget_mouse_event(this); + + while (!end_event_loop && !engine::quitrequested()) { + root->fulldraw(); + Shaper()->pixel(engine::mouseX(), engine::mouseY(), BLACK); + engine::base_o->Flip(); + } + + delete mouse; +} diff --git a/src/test.cc b/src/test.cc index d19b5d8..66a2af4 100644 --- a/src/test.cc +++ b/src/test.cc @@ -569,7 +569,7 @@ virtual int startup() throw (GeneralException) { mogltk::texture * sshot = 0, * plastex = new mogltk::texture(1024, 512); int x, y, sx1, sx2, sy1, sy2, lastframe, curframe, px, py, lasttick = 0, curtick = 0, oldblend, seconds = 0, newseconds = 0; double t = 0; - verbosity = M_ERROR; + verbosity = M_INFO; String str; bool got_transit = false; Uint8 * plasma = (Uint8 *) malloc(640 * 480), * pplasma; @@ -642,8 +642,8 @@ virtual int startup() throw (GeneralException) { mogltk::glSprite * eG1 = new mogltk::glSprite(&Input("elkyaG1.raw"), 53, 100); mogltk::glSprite * eM1 = new mogltk::glSprite(&Input("elkyaM1.raw"), 53, 100); // mogltk::glSprite * spr = new mogltk::glSprite(&Input("test.raw"), 200, 200); - mogltk::widget * w = new mogltk::Root(sh); #endif + mogltk::widget * w = new mogltk::widgets::Root(sh); #else mogltk::base * gl = new mogltk::base(); mogltk::shape * sh = new mogltk::shape(); @@ -686,6 +686,14 @@ virtual int startup() throw (GeneralException) { px = 200; py = 350; #endif +#if 0 + new mogltk::widgets::Button(0, sh, + new mogltk::widgets::SmartBox(sh, w, 120, 50, 100, 100, "Test"), + 12, 30, 50, 20, "Toto"); +#endif + new mogltk::widgets::MsgBox(sh, w, "Test", "Blablabla\nCeci est un test de la\nclasse MsgBox."); + + w->mainloop(); while (!mogltk::engine::quitrequested()) { #if 0 -- cgit v1.2.3