summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpixel <pixel>2004-10-19 01:27:29 +0000
committerpixel <pixel>2004-10-19 01:27:29 +0000
commit70b1a3c1c6b7f33b3af777bedaa784e34ef81719 (patch)
treeb18db6e184e985b5d35c8b41f5ce6bafb8b4e374
parentd2109565408c6be469642b5aafc2f2efe71a632f (diff)
Blah... too much diffs to follow
-rw-r--r--include/widgets.h534
-rw-r--r--lib/glbase.cc534
-rw-r--r--lib/widgets.cc2317
3 files changed, 1720 insertions, 1665 deletions
diff --git a/include/widgets.h b/include/widgets.h
index 7a919f4..600bcec 100644
--- a/include/widgets.h
+++ b/include/widgets.h
@@ -1,263 +1,271 @@
-/*
- * 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.6 2004-07-17 10:08:16 pixel Exp $ */
-
-#ifndef __WIDGETS_H__
-#define __WIDGETS_H__
-
-#include <Exceptions.h>
-#include <shape.h>
-#include <base.h>
-
-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_UP,
- E_MOUSE_CLICK,
- E_MOUSE_OUT_CLICK,
- E_MOUSE_DBL_CLICK,
- };
- class widget : public Base {
- public:
- virtual ~widget();
- 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();
- void fulldraw();
- shape * Shaper();
- void mainloop();
- 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();
- 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();
- 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;
- 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_event> timed_events;
-
- void computeabs();
- void idraw();
- bool ievent(int x, int y, event_t event);
- void icomputeabs();
- void iresize_notify();
- };
-
- namespace widgets {
- class drawer : public Base {
- public:
- virtual void draw(widget *) = 0;
- };
-
- 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);
- virtual rect GetDrawRect();
- 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();
- };
-
- class Frame : public widget {
- public:
- Frame(shape *, widget * father, int x, int y, int w, int h);
- virtual rect GetDrawRect();
- protected:
- virtual void draw();
- };
-
- class ContextMenu : public widget {
- public:
- ContextMenu(shape *, widget * father, int x, int y);
- virtual ~ContextMenu();
- 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<node> nodes;
- int selected;
- ContextMenu * subselected;
- private:
- bool in_click, sticky;
-
- bool iin_click();
- };
-
- class Menu : public widget {
- public:
- Menu(shape *, widget * father);
- 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<node> nodes;
- int cur_x;
- int selected;
- };
- };
-};
-
-#endif
+/*
+ * 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.7 2004-10-19 01:27:29 pixel Exp $ */
+
+#ifndef __WIDGETS_H__
+#define __WIDGETS_H__
+
+#include <Exceptions.h>
+#include <shape.h>
+#include <base.h>
+
+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_UP,
+ E_MOUSE_CLICK,
+ E_MOUSE_OUT_CLICK,
+ E_MOUSE_DBL_CLICK,
+ };
+ class widget : public Base {
+ public:
+ virtual ~widget();
+ 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();
+ 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();
+ 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_event> timed_events;
+
+ void computeabs();
+ void idraw();
+ bool ievent(int x, int y, event_t event);
+ void icomputeabs();
+ void iresize_notify();
+ };
+
+ namespace widgets {
+ class drawer : public Base {
+ public:
+ virtual void draw(widget *) = 0;
+ };
+
+ 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 Panel : public widget {
+ public:
+ Panel(shape *, widget * father, int x, int y, int w, int h);
+ };
+
+ 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);
+ virtual rect GetDrawRect();
+ 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();
+ };
+
+ class Frame : public widget {
+ public:
+ Frame(shape *, widget * father, int x, int y, int w, int h);
+ virtual rect GetDrawRect();
+ protected:
+ virtual void draw();
+ };
+
+ class ContextMenu : public widget {
+ public:
+ ContextMenu(shape *, widget * father, int x, int y);
+ virtual ~ContextMenu();
+ 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<node> nodes;
+ int selected;
+ ContextMenu * subselected;
+ private:
+ bool in_click, sticky;
+
+ bool iin_click();
+ };
+
+ class Menu : public widget {
+ public:
+ Menu(shape *, widget * father);
+ 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<node> nodes;
+ int cur_x;
+ int selected;
+ };
+ };
+};
+
+#endif
diff --git a/lib/glbase.cc b/lib/glbase.cc
index cbb1927..abd3f1e 100644
--- a/lib/glbase.cc
+++ b/lib/glbase.cc
@@ -1,267 +1,267 @@
-/*
- * 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: glbase.cc,v 1.20 2004-07-17 10:08:16 pixel Exp $ */
-
-#include <stdio.h>
-#include <SDL.h>
-#include <SDL_opengl.h>
-#include <Output.h>
-#include <Handle.h>
-#include "glbase.h"
-#include "engine.h"
-#include "generic.h"
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-mogltk::glbase::glbase(int w, int h, int flags) throw (GeneralException) : mogltk::base(w, h, flags, 0), twoD(0), fovy(60.0) {
- SDL_Surface * surface;
- GLint bits;
-
- mogltk::engine::setup();
- if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
- throw GeneralException(String("Couldn't initialise Video SubSystem: ") + SDL_GetError());
- }
-
-#if 1
- SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
-// SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
- SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8);
- SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8);
-#endif
- if (!(surface = SDL_SetVideoMode(w, h, 0, flags | SDL_OPENGL | SDL_HWSURFACE))) {
- throw GeneralException(String("Couldn't set GL mode: ") + SDL_GetError());
- }
-
- mogltk::engine::glbase_o = this;
- mogltk::engine::base_o = this;
-
- ratio = (GLdouble) surface->w / surface->h;
-
- glGetIntegerv(GL_STENCIL_BITS, &bits);
-
- printm(M_INFO, "Video resolution: %dx%dx%d (ratio = %3.2f)\n", surface->w, surface->h, surface->format->BitsPerPixel, ratio);
- printm(M_INFO, "\n");
- printm(M_INFO, "OpenGL infos\n");
- printm(M_INFO, "------------\n");
- printm(M_INFO, String("Vendor : ") + (char *) glGetString(GL_VENDOR) + "\n");
- printm(M_INFO, String("Renderer : ") + (char *) glGetString(GL_RENDERER) + "\n");
- printm(M_INFO, String("Version : ") + (char *) glGetString(GL_VERSION) + "\n");
- printm(M_INFO, String("Extensions: ") + (char *) glGetString(GL_EXTENSIONS) + "\n");
-
- glViewport(0, 0, surface->w, surface->h);
-
- glCullFace(GL_BACK);
- glFrontFace(GL_CCW);
- glEnable(GL_CULL_FACE);
-
- glClearColor(0, 0, 0, 0);
- glShadeModel(GL_SMOOTH);
-
- glEnable(GL_DEPTH_TEST);
- glDepthFunc(GL_LEQUAL);
- glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(fovy, ratio, 1.0, 1024.0);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- SDL_GL_SwapBuffers();
- SDL_ShowCursor(SDL_DISABLE);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- setsurface(surface);
- mogltk::engine::postsetup();
-}
-
-mogltk::glbase::~glbase() {
-}
-
-void mogltk::glbase::Enter2DMode(void) {
- if (twoD)
- return;
-
- glPushAttrib(GL_ENABLE_BIT);
- glDisable(GL_DEPTH_TEST);
- glDisable(GL_CULL_FACE);
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- glOrtho(0.0, GetWidth(), GetHeight(), 0.0, 0.0, 1.0);
-
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
-
- twoD = 1;
-}
-
-void mogltk::glbase::Leave2DMode(void) {
- if (!twoD)
- return;
-
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
-
- glPopAttrib();
-
- twoD = 0;
-}
-
-void mogltk::glbase::Flip(bool clear) {
- mogltk::engine::pollevents();
- SDL_GL_SwapBuffers();
- if (clear)
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-bool mogltk::glbase::is2D() {
- return twoD;
-}
-
-void mogltk::glbase::glVertex(GLshort x, GLshort y, GLshort z, GLshort w) {
-#ifdef DEBUG
- printm(M_INFO, "Calling glVertex(%i, %i, %i, %i) (shorts)\n", x, y, z, w);
-#endif
- glVertex4i(x, y, z, w);
-}
-
-void mogltk::glbase::glVertex(GLint x, GLint y, GLint z, GLint w) {
-#ifdef DEBUG
- printm(M_INFO, "Calling glVertex(%i, %i, %i, %i) (ints)\n", x, y, z, w);
-#endif
- glVertex4i(x, y, z, w);
-}
-
-void mogltk::glbase::glVertex(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
-#ifdef DEBUG
- printm(M_INFO, "Calling glVertex(%f, %f, %f, %f) (floats)\n", x, y, z, w);
-#endif
- glVertex4f(x, y, z, w);
-}
-
-void mogltk::glbase::glVertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w) {
-#ifdef DEBUG
- printm(M_INFO, "Calling glVertex(%f, %f, %f, %f) (doubles)\n", x, y, z, w);
-#endif
- glVertex4d(x, y, z, 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;
- }
-
- ratio = (GLdouble) w / 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) {
- fovy = nfoyv;
- if (!engine::base_o->is2D())
- gluPerspective(fovy, ratio, 1.0, 1024.0);
-}
-
-inline static unsigned int nextpower(unsigned int n) {
- unsigned int i;
-
- if (!n)
- return n;
-
- if (ISPOT(n))
- return n;
-
- for (i = 31; i >= 0; i--) {
- if ((n >> i) & 1) {
- return 1 << (i + 1);
- }
- }
-}
-
-mogltk::texture * mogltk::glbase::GrabTexture() {
- int w = nextpower(GetWidth());
- int h = nextpower(GetHeight());
- texture * r = new texture(w, h);
- SDL_Surface * t;
-
- t = GrabSurface();
- SDL_BlitSurface(t, NULL, r->GetSurface(), NULL);
- SDL_FreeSurface(t);
-
- return r;
-}
-
-SDL_Surface * mogltk::glbase::GrabSurface() {
- int i;
- SDL_Surface * r;
- Uint8 * pixels = (Uint8 *) malloc(GetWidth() * GetHeight() * 3);
- Uint8 * s, * d;
-
- glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, pixels);
-
- r = SDL_CreateRGBSurface(SDL_SWSURFACE, GetWidth(), GetHeight(), 24,
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- 0xff000000,
- 0x00ff0000,
- 0x0000ff00,
- 0x00000000
-#else
- 0x000000ff,
- 0x0000ff00,
- 0x00ff0000,
- 0x00000000
-#endif
- );
-
- for (i = 0; i < GetHeight(); i++) {
- s = pixels + i * GetWidth() * 3;
- d = ((Uint8 *) r->pixels) + (GetHeight() - i - 1) * GetWidth() * 3;
- memcpy(d, s, GetWidth() * 3);
- }
-
- free(pixels);
-
- return r;
-}
+/*
+ * 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: glbase.cc,v 1.21 2004-10-19 01:27:30 pixel Exp $ */
+
+#include <stdio.h>
+#include <SDL.h>
+#include <SDL_opengl.h>
+#include <Output.h>
+#include <Handle.h>
+#include "glbase.h"
+#include "engine.h"
+#include "generic.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+mogltk::glbase::glbase(int w, int h, int flags) throw (GeneralException) : mogltk::base(w, h, flags, 0), twoD(0), fovy(60.0) {
+ SDL_Surface * surface;
+ GLint bits;
+
+ mogltk::engine::setup();
+ if (SDL_InitSubSystem(SDL_INIT_VIDEO) < 0) {
+ throw GeneralException(String("Couldn't initialise Video SubSystem: ") + SDL_GetError());
+ }
+
+#if 1
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+// SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 8);
+#endif
+ if (!(surface = SDL_SetVideoMode(w, h, 0, flags | SDL_OPENGL | SDL_HWSURFACE))) {
+ throw GeneralException(String("Couldn't set GL mode: ") + SDL_GetError());
+ }
+
+ mogltk::engine::glbase_o = this;
+ mogltk::engine::base_o = this;
+
+ ratio = (GLdouble) surface->w / surface->h;
+
+ glGetIntegerv(GL_STENCIL_BITS, &bits);
+
+ printm(M_INFO, "Video resolution: %dx%dx%d (ratio = %3.2f)\n", surface->w, surface->h, surface->format->BitsPerPixel, ratio);
+ printm(M_INFO, "\n");
+ printm(M_INFO, "OpenGL infos\n");
+ printm(M_INFO, "------------\n");
+ printm(M_INFO, String("Vendor : ") + (char *) glGetString(GL_VENDOR) + "\n");
+ printm(M_INFO, String("Renderer : ") + (char *) glGetString(GL_RENDERER) + "\n");
+ printm(M_INFO, String("Version : ") + (char *) glGetString(GL_VERSION) + "\n");
+ printm(M_INFO, String("Extensions: ") + (char *) glGetString(GL_EXTENSIONS) + "\n");
+
+ glViewport(0, 0, surface->w, surface->h);
+
+ glCullFace(GL_BACK);
+ glFrontFace(GL_CCW);
+ glEnable(GL_CULL_FACE);
+
+ glClearColor(0, 0, 0, 0);
+ glShadeModel(GL_SMOOTH);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ gluPerspective(fovy, ratio, 1.0, 1024.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ SDL_GL_SwapBuffers();
+ SDL_ShowCursor(SDL_DISABLE);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ setsurface(surface);
+ mogltk::engine::postsetup();
+}
+
+mogltk::glbase::~glbase() {
+}
+
+void mogltk::glbase::Enter2DMode(void) {
+ if (twoD)
+ return;
+
+ glPushAttrib(GL_ENABLE_BIT);
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
+ glOrtho(0.0, GetWidth(), GetHeight(), 0.0, 0.0, 1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadIdentity();
+
+ twoD = 1;
+}
+
+void mogltk::glbase::Leave2DMode(void) {
+ if (!twoD)
+ return;
+
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+
+ glPopAttrib();
+
+ twoD = 0;
+}
+
+void mogltk::glbase::Flip(bool clear) {
+ mogltk::engine::pollevents();
+ SDL_GL_SwapBuffers();
+ if (clear)
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+bool mogltk::glbase::is2D() {
+ return twoD;
+}
+
+void mogltk::glbase::glVertex(GLshort x, GLshort y, GLshort z, GLshort w) {
+#ifdef DEBUG
+ printm(M_INFO, "Calling glVertex(%i, %i, %i, %i) (shorts)\n", x, y, z, w);
+#endif
+ glVertex4i(x, y, z, w);
+}
+
+void mogltk::glbase::glVertex(GLint x, GLint y, GLint z, GLint w) {
+#ifdef DEBUG
+ printm(M_INFO, "Calling glVertex(%i, %i, %i, %i) (ints)\n", x, y, z, w);
+#endif
+ glVertex4i(x, y, z, w);
+}
+
+void mogltk::glbase::glVertex(GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
+#ifdef DEBUG
+ printm(M_INFO, "Calling glVertex(%f, %f, %f, %f) (floats)\n", x, y, z, w);
+#endif
+ glVertex4f(x, y, z, w);
+}
+
+void mogltk::glbase::glVertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w) {
+#ifdef DEBUG
+ printm(M_INFO, "Calling glVertex(%f, %f, %f, %f) (doubles)\n", x, y, z, w);
+#endif
+ glVertex4d(x, y, z, 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;
+ }
+
+ ratio = (GLdouble) w / 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) {
+ fovy = nfoyv;
+ if (!engine::base_o->is2D())
+ gluPerspective(fovy, ratio, 1.0, 1024.0);
+}
+
+inline static unsigned int nextpower(unsigned int n) {
+ unsigned int i;
+
+ if (!n)
+ return n;
+
+ if (ISPOT(n))
+ return n;
+
+ for (i = 31; i >= 0; i--) {
+ if ((n >> i) & 1) {
+ return 1 << (i + 1);
+ }
+ }
+}
+
+mogltk::texture * mogltk::glbase::GrabTexture() {
+ int w = nextpower(GetWidth());
+ int h = nextpower(GetHeight());
+ texture * r = new texture(w, h);
+ SDL_Surface * t;
+
+ t = GrabSurface();
+ SDL_BlitSurface(t, NULL, r->GetSurface(), NULL);
+ SDL_FreeSurface(t);
+
+ return r;
+}
+
+SDL_Surface * mogltk::glbase::GrabSurface() {
+ int i;
+ SDL_Surface * r;
+ Uint8 * pixels = (Uint8 *) malloc(GetWidth() * GetHeight() * 3);
+ Uint8 * s, * d;
+
+ glReadPixels(0, 0, GetWidth(), GetHeight(), GL_RGB, GL_UNSIGNED_BYTE, pixels);
+
+ r = SDL_CreateRGBSurface(SDL_SWSURFACE, GetWidth(), GetHeight(), 24,
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ 0xff000000,
+ 0x00ff0000,
+ 0x0000ff00,
+ 0x00000000
+#else
+ 0x000000ff,
+ 0x0000ff00,
+ 0x00ff0000,
+ 0x00000000
+#endif
+ );
+
+ for (i = 0; i < GetHeight(); i++) {
+ s = pixels + i * GetWidth() * 3;
+ d = ((Uint8 *) r->pixels) + (GetHeight() - i - 1) * GetWidth() * 3;
+ memcpy(d, s, GetWidth() * 3);
+ }
+
+ free(pixels);
+
+ return r;
+}
diff --git a/lib/widgets.cc b/lib/widgets.cc
index 9d62bd9..c70ad95 100644
--- a/lib/widgets.cc
+++ b/lib/widgets.cc
@@ -1,1135 +1,1182 @@
-/*
- * 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.cc,v 1.8 2004-07-17 10:08:16 pixel Exp $ */
-
-#include <SDL.h>
-#include <vector>
-#include <Input.h>
-#include "font.h"
-#include "engine.h"
-#include "widgets.h"
-#include "sprite.h"
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gettext.h"
-
-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:
- 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) {
- int mx, my;
- bool out_threshold;
- std::vector<mogltk::widget *>::iterator i;
- std::vector<mogltk::widget *> out_move_stack;
-
- mx = mogltk::engine::mouseX();
- my = mogltk::engine::mouseY();
-
- if (mouse_down) {
- int dx, dy;
-
- dx = ABS(mouse_x_down - mx);
- dy = ABS(mouse_y_down - my);
-
- 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(mx, my, mogltk::E_MOUSE_DRAG_OVER);
- }
-
- printm(M_INFO, "mouse_drag\n");
- // generate a mouse_drag event
- root->m_event(mx, my, mogltk::E_MOUSE_DRAG);
- mouse_drag = true;
- } else {
- printm(M_INFO, "mouse_move\n");
- root->m_event(mx, my, mogltk::E_MOUSE_MOVE);
- // generate a mouse_move event
- }
-
- for (i = out_move.begin(); i != out_move.end(); i++) {
- out_move_stack.push_back(*i);
- }
-
- for (i = out_move_stack.begin(); i != out_move_stack.end(); i++) {
- if (!(*i)->inside(mx, my)) {
- (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT);
- // generate a mouse_out event
- }
- }
-
- out_move_stack.empty();
-}
-
-void widget_mouse_event::action(SDL_MouseButtonEvent b) {
- int mx, my;
- std::vector<mogltk::widget *>::iterator i;
- std::vector<mogltk::widget *> out_click_stack;
-
- mx = mogltk::engine::mouseX();
- my = mogltk::engine::mouseY();
-
- if (b.button == 1) {
- if (b.state) {
- mouse_x_down = mx;
- mouse_y_down = my;
- mouse_down = true;
- 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) {
- mouse_drag = false;
- printm(M_INFO, "mouse_end_drag\n");
- root->m_event(mx, my, 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(mx, my, 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(mx, my, mogltk::E_MOUSE_CLICK);
- // generate a mouse_click 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();
-
- if ((SDL_GetTicks() - old_click) < 500) {
- printm(M_INFO, "mouse_dbl_click\n");
- root->m_event(mx, my, mogltk::E_MOUSE_DBL_CLICK);
- // generate a mouse_dbl_click event
- }
-
- old_click = SDL_GetTicks();
- }
- printm(M_INFO, "mouse_up\n");
- root->m_event(mx, my, 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), prev(0), child(0), last(0), type(_type), name(_name), sh(_sh), exclusive(0), visible(true), enabled(true) {
- if (!father) {
- root = this;
- father = this;
- next = 0;
- x = 0;
- y = 0;
- sx = engine::base_o->GetWidth();
- sy = engine::base_o->GetHeight();
- } else {
- next = father->child;
- if (next)
- next->prev = this;
- if (!father->last)
- father->last = this;
- father->child = this;
- root = father->root;
- }
-
- computeabs();
-}
-
-mogltk::widget::~widget() {
- while(child)
- delete child;
-
- if (prev)
- prev->next = next;
- else
- father->child = next;
-
- if (next)
- next->prev = prev;
- else
- father->last = prev;
-}
-
-void mogltk::widget::computeabs() {
- if (father != this) {
- ax = father->ax + x;
- ay = father->ay + y;
- } else {
- ax = x;
- ay = y;
- }
- ax2 = ax + sx;
- ay2 = ay + sy;
-}
-
-void mogltk::widget::move(int nx, int ny) {
- x = nx;
- y = ny;
-
- computeabs();
-
- if (child)
- child->icomputeabs();
-}
-
-void mogltk::widget::resize(int nsx, int nsy) {
- sx = nsx;
- sy = nsy;
-
- ax2 = ax + sx;
- ay2 = ay + sy;
-
- iresize_notify();
-}
-
-int mogltk::widget::GetX() {
- return x;
-}
-
-int mogltk::widget::GetY() {
- return y;
-}
-
-int mogltk::widget::GetH() {
- return sy;
-}
-
-int mogltk::widget::GetW() {
- return sx;
-}
-
-int mogltk::widget::GetAX() {
- return ax;
-}
-
-int mogltk::widget::GetAY() {
- return ay;
-}
-
-int mogltk::widget::GetAX2() {
- return ax2;
-}
-
-int mogltk::widget::GetAY2() {
- return ay2;
-}
-
-mogltk::rect mogltk::widget::GetDrawRect() {
- rect r;
- r.x = 0;
- r.y = 0;
- r.w = GetW();
- r.h = GetH();
-
- return r;
-}
-
-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;
-}
-
-void mogltk::widget::fulldraw() {
- bool was2D = true;
-
- if (mogltk::engine::glbase_o)
- if (!(was2D = mogltk::engine::glbase_o->is2D()))
- mogltk::engine::glbase_o->Enter2DMode();
-
- texture::Unbind();
- mogltk::ColorP::Max = WHITE;
- mogltk::ColorP::Min = BLACK;
- mogltk::ColorP::Min.A = 0;
-
- root->idraw();
-
- if (!was2D)
- mogltk::engine::glbase_o->Leave2DMode();
-}
-
-void mogltk::widget::idraw() {
- int x1, y1, x2, y2;
-
- if (next)
- next->idraw();
-
- if (!visible)
- return;
-
- x1 = MAX(GetAX(), father->GetAX());
- y1 = MAX(GetAY(), father->GetAY());
-
- x2 = MIN(GetAX2(), father->GetAX2());
- y2 = MIN(GetAY2(), father->GetAY2());
-
- engine::base_o->changeviewport(x1, y1, x2 - x1, y2 - y1);
-
- draw();
-
- if (child)
- child->idraw();
-}
-
-bool mogltk::widget::inside(int xe, int ye) {
- if (!visible)
- return false;
- 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:
- case E_MOUSE_OUT:
- case E_MOUSE_OUT_CLICK:
- process_event(x, y, event);
- break;
- default:
- ievent(x, y, event);
- }
-}
-
-bool mogltk::widget::ievent(int xe, int ye, mogltk::event_t event) {
- if (prev)
- if (prev->ievent(xe, ye, event))
- return true;
-
- if (!inside(xe, ye))
- return false;
-
- if (exclusive)
- return exclusive->ievent(xe, ye, event);
-
- if (last)
- if (last->ievent(xe, ye, event))
- return true;
-
- if (!enabled || !visible)
- return false;
-
- 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::resize_notify() {
-}
-
-void mogltk::widget::icomputeabs() {
- computeabs();
-
- if (next)
- next->computeabs();
-
- if (child)
- child->computeabs();
-}
-
-void mogltk::widget::iresize_notify() {
- if (child)
- child->iresize_notify();
-}
-
-void mogltk::widget::set_exclusive(mogltk::widget * w) {
- w->exclusive = this;
-}
-
-void mogltk::widget::unset_exclusive(mogltk::widget * w) {
- w->exclusive = 0;
-}
-
-bool mogltk::widget::GetVisible() {
- return visible;
-}
-
-void mogltk::widget::SetVisible(bool _visible) {
- visible = _visible;
-}
-
-bool mogltk::widget::GetEnabled() {
- return enabled;
-}
-
-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;
-
- for (i = out_move.begin(); i != out_move.end(); i++) {
- if (*i == this)
- return;
- }
-
- out_move.push_back(this);
-}
-
-void mogltk::widget::remove_out_move() {
- std::vector<widget *>::iterator i;
-
- for (i = out_move.begin(); i != out_move.end(); i++) {
- if (*i == this) {
- out_move.erase(i);
- return;
- }
- }
-}
-
-void mogltk::widget::add_out_click() {
- std::vector<widget *>::iterator i;
-
- for (i = out_click.begin(); i != out_click.end(); i++) {
- if (*i == this)
- return;
- }
-
- out_click.push_back(this);
-}
-
-void mogltk::widget::remove_out_click() {
- std::vector<widget *>::iterator i;
-
- for (i = out_click.begin(); i != out_click.end(); i++) {
- if (*i == this) {
- out_click.erase(i);
- return;
- }
- }
-}
-
-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.
- */
-
-/***************
-* Here is Root *
-***************/
-
-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::widgets::Root::draw() {
- if (dr)
- dr->draw(this);
- else
- Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2());
-}
-
-void mogltk::widgets::Root::setdrawer(drawer * _dr) {
- dr = _dr;
-}
-
-
-/***********************
-* The classical Button *
-***********************/
-
-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;
-}
-
-
-/**********************
-* The SmartBox window *
-**********************/
-
-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);
- MoveOnTop();
- return true;
- }
- return false;
-}
-
-mogltk::rect mogltk::widgets::SmartBox::GetDrawRect() {
- rect r;
-
- r.x = 2;
- r.y = 21;
- r.w = GetW() - 4;
- r.h = GetH() - 23;
-
- return r;
-}
-
-
-/***********************
-* The MessageBox child *
-***********************/
-
-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());
-}
-
-
-/*****************
-* A simple Label *
-*****************/
-
-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);
-}
-
-
-/*************************
-* The classical 3D Frame *
-*************************/
-
-mogltk::widgets::Frame::Frame(shape * sh, widget * father, int x, int y, int w, int h) : widget(father, x, y, w, h, 0, "Frame", sh) {
-}
-
-void mogltk::widgets::Frame::draw() {
- Shaper()->obox3d(GetAX(), GetAY(), GetAX2(), GetAY2());
-}
-
-mogltk::rect mogltk::widgets::Frame::GetDrawRect() {
- rect r;
-
- r.x = 4;
- r.y = 4;
- r.w = GetW() - 8;
- r.h = GetH() - 8;
-
- return r;
-}
-
-
-/***********************************
-* The huge and bloated ContextMenu *
-***********************************/
-
-mogltk::widgets::ContextMenu::node::node(const String & _caption, int _x, int _y, int _w, int _h, mogltk::widgets::action * _a, mogltk::widgets::ContextMenu * _sub, mogltk::widgets::ContextMenu * _father, bool _line) : caption(_caption), x(_x), y(_y), w(_w), h(_h), a(_a), sub(_sub), father(_father), line(_line), enabled(true) {
-}
-
-String mogltk::widgets::ContextMenu::node::GetCaption() {
- return caption;
-}
-
-mogltk::widgets::action * mogltk::widgets::ContextMenu::node::GetAction() {
- return a;
-}
-
-mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::node::GetFather() {
- return father;
-}
-
-mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::node::GetSub() {
- return sub;
-}
-
-bool mogltk::widgets::ContextMenu::node::GetLine() {
- return line;
-}
-
-bool mogltk::widgets::ContextMenu::node::GetEnabled() {
- return enabled;
-}
-
-void mogltk::widgets::ContextMenu::node::SetEnabled(bool _enabled) {
- enabled = _enabled;
-}
-
-int mogltk::widgets::ContextMenu::node::GetX() {
- return x;
-}
-
-int mogltk::widgets::ContextMenu::node::GetY() {
- return y;
-}
-
-int mogltk::widgets::ContextMenu::node::GetW() {
- return w;
-}
-
-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), sticky(false) {
-}
-
-mogltk::widgets::ContextMenu::~ContextMenu() {
- std::vector<node>::iterator i;
- ContextMenu * sub;
-
- for (i = nodes.begin(); i != nodes.end(); i++) {
- if ((sub = i->GetSub()))
- delete sub;
- }
-}
-
-void mogltk::widgets::ContextMenu::addnode(const String & caption, mogltk::widgets::action * a) {
- rect size;
-
- size = SystemFont->size(caption);
- nodes.push_back(node(caption, 4, GetH() - 2, size.w, size.h, a, 0, this, false));
- size.w += 8;
- if (GetW() > size.w)
- size.w = GetW();
- resize(size.w, GetH() + size.h);
-}
-
-void mogltk::widgets::ContextMenu::addsub(const String & caption, mogltk::widgets::ContextMenu * sub) {
- rect size;
-
- size = SystemFont->size(caption + " >");
- nodes.push_back(node(caption + " >", 4, GetH() - 2, size.w, size.h, 0, sub, this, false));
- size.w += 8;
- if (GetW() > size.w)
- size.w = GetW();
- resize(size.w, GetH() + size.h);
-}
-
-void mogltk::widgets::ContextMenu::addline() {
- nodes.push_back(node("", 2, GetH() - 1, 0, 0, 0, 0, this, true));
- resize(GetW(), GetH() + 4);
-}
-
-mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::createsub(const String & caption) {
- ContextMenu * r;
-
- r = new ContextMenu(Shaper(), Father(), GetX() + GetW(), GetY() + GetH());
- r->SetVisible(false);
-
- addsub(caption, r);
-
- return r;
-}
-
-void mogltk::widgets::ContextMenu::move(int x, int y) {
- int dx, dy;
- std::vector<node>::iterator i;
- ContextMenu * sub;
-
- dx = x - GetX();
- dy = y - GetY();
- widget::move(x, y);
-
- for (i = nodes.begin(); i != nodes.end(); i++) {
- if ((sub = i->GetSub()))
- sub->move(sub->GetX() + dx, sub->GetY() + dy);
- }
-}
-
-void mogltk::widgets::ContextMenu::resize(int w, int h) {
- int dw;
- std::vector<node>::iterator i;
- ContextMenu * sub;
-
- dw = w - GetW();
- widget::resize(w, h);
-
- for (i = nodes.begin(); i != nodes.end(); i++) {
- if ((sub = i->GetSub()))
- sub->move(sub->GetX() + dw, sub->GetY());
- }
-}
-
-void mogltk::widgets::ContextMenu::SetVisible(bool visible) {
- if (!visible && sticky)
- return;
- widget::SetVisible(visible);
- if (!visible && subselected) {
- subselected->SetVisible(false);
- }
-
- if (visible) {
- add_out_click();
- MoveOnTop();
- }
-}
-
-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;
- rect size;
-
- Shaper()->box3d(GetAX(), GetAY(), GetAX2(), GetAY2());
-
- for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) {
- size = SystemFont->size(i->GetCaption());
- if (i->GetLine()) {
- Shaper()->hline3d(GetAX() + i->GetX(), GetAX() + i->GetX() + GetW() - 4, GetAY() + i->GetY());
- } else {
- if (n == selected) {
- Shaper()->box(GetAX() + 2, GetAY() + i->GetY(), GetAX() + GetW() - 2, GetAY() + i->GetY() + i->GetH(), DOS_MAGENTA);
- }
- Shaper()->text(GetAX() + i->GetX(), GetAY() + i->GetY(), i->GetCaption(), i->GetEnabled() ? BLACK : DOS_GRAY);
- }
- }
-}
-
-bool mogltk::widgets::ContextMenu::process_event(int xe, int ye, mogltk::event_t event) {
- std::vector<node>::iterator i;
- action * a;
- int n;
-
- switch (event) {
- case E_MOUSE_MOVE:
- sticky = false;
- selected = -1;
- for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) {
- if (!i->GetLine()) {
- int ax, ax2, ay, ay2;
-
- ax = GetAX() + 2;
- ay = GetAY() + i->GetY();
- ax2 = GetAX() + GetW() - 2;
- ay2 = GetAY() + i->GetY() + i->GetH();
-
- if (!((xe < ax) || (xe > ax2) || (ye < ay) || (ye > ay2))) {
- selected = n;
- if (subselected) {
- subselected->SetVisible(false);
- subselected->selected = -1;
- subselected->subselected = 0;
- }
- if ((subselected = i->GetSub())) {
- subselected->SetVisible(true);
- subselected->selected = -1;
- subselected->subselected = 0;
- }
- }
- }
- }
- 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);
- in_click = false;
- SetVisible(false);
- return true;
- }
- }
- in_click = true;
- break;
- case E_MOUSE_DOWN:
- in_click = true;
- break;
- case E_MOUSE_OUT:
- selected = -1;
- remove_out_move();
- in_click = false;
- return true;
- case E_MOUSE_OUT_CLICK:
- if (iin_click())
- return true;
- selected = -1;
- subselected = 0;
- SetVisible(false);
- return true;
- }
-
- return false;
-}
-
-bool mogltk::widgets::ContextMenu::iin_click() {
- if (in_click)
- return true;
-
- if (subselected)
- return subselected->iin_click();
-
- return false;
-}
-
-
-/********************
-* The Menu topframe *
-********************/
-
-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;
-}
-
-void mogltk::widgets::Menu::node::SetCaption(const String & s) {
- caption = s;
-}
-
-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);
-}
-
-void mogltk::widgets::Menu::resize_notify() {
- rect r = Father()->GetDrawRect();
- 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::SetCaption(int i, const String & s) {
- nodes[i].SetCaption(s);
-}
-
-void mogltk::widgets::Menu::draw(void) {
- 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;
-}
-
-
-/*
- * The mainloop widget thing.
- */
-
-void mogltk::widget::mainloop() {
- bool end_event_loop = false;
- widget_mouse_event * mouse = new widget_mouse_event(this);
- int mx, my;
-
- while (!end_event_loop && !engine::quitrequested()) {
- root->fulldraw();
- mx = mogltk::engine::mouseX();
- my = mogltk::engine::mouseY();
- mogltk::ColorP::Max.A = 50;
- Sprite::Cursor->draw(mx - 6, my - 3, BLACK);
- mogltk::ColorP::Max.A = 255;
- Sprite::Cursor->draw(mx - 8, my - 6);
- engine::base_o->Flip();
- widget::check_timed_events();
- }
-
- delete mouse;
-}
+/*
+ * 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.cc,v 1.9 2004-10-19 01:27:30 pixel Exp $ */
+
+#include <SDL.h>
+#include <vector>
+#include <Input.h>
+#include "font.h"
+#include "engine.h"
+#include "widgets.h"
+#include "sprite.h"
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gettext.h"
+
+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:
+ 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) {
+ int mx, my;
+ bool out_threshold;
+ std::vector<mogltk::widget *>::iterator i;
+ std::vector<mogltk::widget *> out_move_stack;
+
+ mx = mogltk::engine::mouseX();
+ my = mogltk::engine::mouseY();
+
+ if (mouse_down) {
+ int dx, dy;
+
+ dx = ABS(mouse_x_down - mx);
+ dy = ABS(mouse_y_down - my);
+
+ 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(mx, my, mogltk::E_MOUSE_DRAG_OVER);
+ }
+
+ printm(M_INFO, "mouse_drag\n");
+ // generate a mouse_drag event
+ root->m_event(mx, my, mogltk::E_MOUSE_DRAG);
+ mouse_drag = true;
+ } else {
+ printm(M_INFO, "mouse_move\n");
+ root->m_event(mx, my, mogltk::E_MOUSE_MOVE);
+ // generate a mouse_move event
+ }
+
+ for (i = out_move.begin(); i != out_move.end(); i++) {
+ out_move_stack.push_back(*i);
+ }
+
+ for (i = out_move_stack.begin(); i != out_move_stack.end(); i++) {
+ if (!(*i)->inside(mx, my)) {
+ (*i)->m_event(mx, my, mogltk::E_MOUSE_OUT);
+ // generate a mouse_out event
+ }
+ }
+
+ out_move_stack.empty();
+}
+
+void widget_mouse_event::action(SDL_MouseButtonEvent b) {
+ int mx, my;
+ std::vector<mogltk::widget *>::iterator i;
+ std::vector<mogltk::widget *> out_click_stack;
+
+ mx = mogltk::engine::mouseX();
+ my = mogltk::engine::mouseY();
+
+ if (b.button == 1) {
+ if (b.state) {
+ mouse_x_down = mx;
+ mouse_y_down = my;
+ mouse_down = true;
+ 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) {
+ mouse_drag = false;
+ printm(M_INFO, "mouse_end_drag\n");
+ root->m_event(mx, my, 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(mx, my, 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(mx, my, mogltk::E_MOUSE_CLICK);
+ // generate a mouse_click 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();
+
+ if ((SDL_GetTicks() - old_click) < 500) {
+ printm(M_INFO, "mouse_dbl_click\n");
+ root->m_event(mx, my, mogltk::E_MOUSE_DBL_CLICK);
+ // generate a mouse_dbl_click event
+ }
+
+ old_click = SDL_GetTicks();
+ }
+ printm(M_INFO, "mouse_up\n");
+ root->m_event(mx, my, 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), prev(0), child(0), last(0), panel(0), type(_type), name(_name), sh(_sh), exclusive(0), visible(true), enabled(true) {
+ if (!father) {
+ root = this;
+ father = this;
+ next = 0;
+ x = 0;
+ y = 0;
+ sx = engine::base_o->GetWidth();
+ sy = engine::base_o->GetHeight();
+ } else {
+ next = father->child;
+ if (next)
+ next->prev = this;
+ if (!father->last)
+ father->last = this;
+ father->child = this;
+ root = father->root;
+ }
+
+ computeabs();
+}
+
+mogltk::widget::~widget() {
+ while(child)
+ delete child;
+
+ if (prev)
+ prev->next = next;
+ else
+ father->child = next;
+
+ if (next)
+ next->prev = prev;
+ else
+ father->last = prev;
+}
+
+void mogltk::widget::computeabs() {
+ if (father != this) {
+ ax = father->ax + x;
+ ay = father->ay + y;
+ } else {
+ ax = x;
+ ay = y;
+ }
+ ax2 = ax + sx;
+ ay2 = ay + sy;
+}
+
+void mogltk::widget::move(int nx, int ny) {
+ x = nx;
+ y = ny;
+
+ computeabs();
+
+ if (child)
+ child->icomputeabs();
+}
+
+void mogltk::widget::resize(int nsx, int nsy) {
+ sx = nsx;
+ sy = nsy;
+
+ ax2 = ax + sx;
+ ay2 = ay + sy;
+
+ if (child)
+ child->iresize_notify();
+}
+
+int mogltk::widget::GetX() {
+ return x;
+}
+
+int mogltk::widget::GetY() {
+ return y;
+}
+
+int mogltk::widget::GetH() {
+ return sy;
+}
+
+int mogltk::widget::GetW() {
+ return sx;
+}
+
+int mogltk::widget::GetAX() {
+ return ax;
+}
+
+int mogltk::widget::GetAY() {
+ return ay;
+}
+
+int mogltk::widget::GetAX2() {
+ return ax2;
+}
+
+int mogltk::widget::GetAY2() {
+ return ay2;
+}
+
+mogltk::rect mogltk::widget::GetDrawRect() {
+ rect r;
+ r.x = 0;
+ r.y = 0;
+ r.w = GetW();
+ r.h = GetH();
+
+ return r;
+}
+
+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::widget * mogltk::widget::InnerPanel() {
+ if (!panel)
+ panel = create_panel();
+ return panel;
+}
+
+mogltk::widget * mogltk::widget::find_widget(int _x, int _y) {
+ widget * r = 0;
+
+ if (visible && enabled && (_x >= ax) && (_y >= ay) && (_x <= ax2) && (_y <= ay2)) {
+ if (child)
+ r = child->find_widget(_x, _y);
+ if (!r)
+ r = this;
+ }
+
+ if (!r && next) {
+ r = next->find_widget(_x, _y);
+ }
+
+ return r;
+}
+
+mogltk::shape * mogltk::widget::Shaper() {
+ return sh;
+}
+
+void mogltk::widget::fulldraw() {
+ bool was2D = true;
+
+ if (mogltk::engine::glbase_o)
+ if (!(was2D = mogltk::engine::glbase_o->is2D()))
+ mogltk::engine::glbase_o->Enter2DMode();
+
+ texture::Unbind();
+ mogltk::ColorP::Max = WHITE;
+ mogltk::ColorP::Min = BLACK;
+ mogltk::ColorP::Min.A = 0;
+
+ root->idraw();
+
+ if (!was2D)
+ mogltk::engine::glbase_o->Leave2DMode();
+}
+
+void mogltk::widget::idraw() {
+ int x1, y1, x2, y2;
+
+ if (next)
+ next->idraw();
+
+ if (!visible)
+ return;
+
+ x1 = MAX(GetAX(), father->GetAX());
+ y1 = MAX(GetAY(), father->GetAY());
+
+ x2 = MIN(GetAX2(), father->GetAX2());
+ y2 = MIN(GetAY2(), father->GetAY2());
+
+ engine::base_o->changeviewport(x1, y1, x2 - x1, y2 - y1);
+
+ draw();
+
+ if (child)
+ child->idraw();
+}
+
+bool mogltk::widget::inside(int xe, int ye) {
+ if (!visible)
+ return false;
+ 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:
+ case E_MOUSE_OUT:
+ case E_MOUSE_OUT_CLICK:
+ process_event(x, y, event);
+ break;
+ default:
+ ievent(x, y, event);
+ }
+}
+
+bool mogltk::widget::ievent(int xe, int ye, mogltk::event_t event) {
+ if (prev)
+ if (prev->ievent(xe, ye, event))
+ return true;
+
+ if (!inside(xe, ye))
+ return false;
+
+ if (exclusive)
+ return exclusive->ievent(xe, ye, event);
+
+ if (last)
+ if (last->ievent(xe, ye, event))
+ return true;
+
+ if (!enabled || !visible)
+ return false;
+
+ 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::resize_notify() {
+}
+
+mogltk::widget * mogltk::widget::create_panel() {
+ mogltk::rect r = GetDrawRect();
+ return new widgets::Panel(Shaper(), this, r.x, r.y, r.w, r.h);
+}
+
+void mogltk::widget::icomputeabs() {
+ computeabs();
+
+ if (next)
+ next->computeabs();
+
+ if (child)
+ child->computeabs();
+}
+
+void mogltk::widget::iresize_notify() {
+ if (next)
+ next->iresize_notify();
+ if (child)
+ child->iresize_notify();
+ resize_notify();
+}
+
+void mogltk::widget::set_exclusive(mogltk::widget * w) {
+ w->exclusive = this;
+}
+
+void mogltk::widget::unset_exclusive(mogltk::widget * w) {
+ w->exclusive = 0;
+}
+
+bool mogltk::widget::GetVisible() {
+ return visible;
+}
+
+void mogltk::widget::SetVisible(bool _visible) {
+ visible = _visible;
+}
+
+bool mogltk::widget::GetEnabled() {
+ return enabled;
+}
+
+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;
+
+ for (i = out_move.begin(); i != out_move.end(); i++) {
+ if (*i == this)
+ return;
+ }
+
+ out_move.push_back(this);
+}
+
+void mogltk::widget::remove_out_move() {
+ std::vector<widget *>::iterator i;
+
+ for (i = out_move.begin(); i != out_move.end(); i++) {
+ if (*i == this) {
+ out_move.erase(i);
+ return;
+ }
+ }
+}
+
+void mogltk::widget::add_out_click() {
+ std::vector<widget *>::iterator i;
+
+ for (i = out_click.begin(); i != out_click.end(); i++) {
+ if (*i == this)
+ return;
+ }
+
+ out_click.push_back(this);
+}
+
+void mogltk::widget::remove_out_click() {
+ std::vector<widget *>::iterator i;
+
+ for (i = out_click.begin(); i != out_click.end(); i++) {
+ if (*i == this) {
+ out_click.erase(i);
+ return;
+ }
+ }
+}
+
+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.
+ */
+
+/***************
+* Here is Root *
+***************/
+
+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::widgets::Root::draw() {
+ if (dr)
+ dr->draw(this);
+ else
+ Shaper()->box(GetAX(), GetAY(), GetAX2(), GetAY2());
+}
+
+void mogltk::widgets::Root::setdrawer(drawer * _dr) {
+ dr = _dr;
+}
+
+
+/**************************
+* A simple clipping Panel *
+**************************/
+
+mogltk::widgets::Panel::Panel(shape * sh, widget * father, int x, int y, int w, int h) : widget(father, x, y, w, h, 0, "Panel", sh) {
+}
+
+
+/***********************
+* The classical Button *
+***********************/
+
+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;
+}
+
+
+/**********************
+* The SmartBox window *
+**********************/
+
+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);
+ MoveOnTop();
+ return true;
+ }
+ return false;
+}
+
+mogltk::rect mogltk::widgets::SmartBox::GetDrawRect() {
+ rect r;
+
+ r.x = 2;
+ r.y = 21;
+ r.w = GetW() - 4;
+ r.h = GetH() - 23;
+
+ return r;
+}
+
+
+/***********************
+* The MessageBox child *
+***********************/
+
+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());
+}
+
+
+/*****************
+* A simple Label *
+*****************/
+
+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);
+}
+
+
+/*************************
+* The classical 3D Frame *
+*************************/
+
+mogltk::widgets::Frame::Frame(shape * sh, widget * father, int x, int y, int w, int h) : widget(father, x, y, w, h, 0, "Frame", sh) {
+}
+
+void mogltk::widgets::Frame::draw() {
+ Shaper()->obox3d(GetAX(), GetAY(), GetAX2(), GetAY2());
+}
+
+mogltk::rect mogltk::widgets::Frame::GetDrawRect() {
+ rect r;
+
+ r.x = 4;
+ r.y = 4;
+ r.w = GetW() - 8;
+ r.h = GetH() - 8;
+
+ return r;
+}
+
+
+/***********************************
+* The huge and bloated ContextMenu *
+***********************************/
+
+mogltk::widgets::ContextMenu::node::node(const String & _caption, int _x, int _y, int _w, int _h, mogltk::widgets::action * _a, mogltk::widgets::ContextMenu * _sub, mogltk::widgets::ContextMenu * _father, bool _line) : caption(_caption), x(_x), y(_y), w(_w), h(_h), a(_a), sub(_sub), father(_father), line(_line), enabled(true) {
+}
+
+String mogltk::widgets::ContextMenu::node::GetCaption() {
+ return caption;
+}
+
+mogltk::widgets::action * mogltk::widgets::ContextMenu::node::GetAction() {
+ return a;
+}
+
+mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::node::GetFather() {
+ return father;
+}
+
+mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::node::GetSub() {
+ return sub;
+}
+
+bool mogltk::widgets::ContextMenu::node::GetLine() {
+ return line;
+}
+
+bool mogltk::widgets::ContextMenu::node::GetEnabled() {
+ return enabled;
+}
+
+void mogltk::widgets::ContextMenu::node::SetEnabled(bool _enabled) {
+ enabled = _enabled;
+}
+
+int mogltk::widgets::ContextMenu::node::GetX() {
+ return x;
+}
+
+int mogltk::widgets::ContextMenu::node::GetY() {
+ return y;
+}
+
+int mogltk::widgets::ContextMenu::node::GetW() {
+ return w;
+}
+
+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), sticky(false) {
+}
+
+mogltk::widgets::ContextMenu::~ContextMenu() {
+ std::vector<node>::iterator i;
+ ContextMenu * sub;
+
+ for (i = nodes.begin(); i != nodes.end(); i++) {
+ if ((sub = i->GetSub()))
+ delete sub;
+ }
+}
+
+void mogltk::widgets::ContextMenu::addnode(const String & caption, mogltk::widgets::action * a) {
+ rect size;
+
+ size = SystemFont->size(caption);
+ nodes.push_back(node(caption, 4, GetH() - 2, size.w, size.h, a, 0, this, false));
+ size.w += 8;
+ if (GetW() > size.w)
+ size.w = GetW();
+ resize(size.w, GetH() + size.h);
+}
+
+void mogltk::widgets::ContextMenu::addsub(const String & caption, mogltk::widgets::ContextMenu * sub) {
+ rect size;
+
+ size = SystemFont->size(caption + " >");
+ nodes.push_back(node(caption + " >", 4, GetH() - 2, size.w, size.h, 0, sub, this, false));
+ size.w += 8;
+ if (GetW() > size.w)
+ size.w = GetW();
+ resize(size.w, GetH() + size.h);
+}
+
+void mogltk::widgets::ContextMenu::addline() {
+ nodes.push_back(node("", 2, GetH() - 1, 0, 0, 0, 0, this, true));
+ resize(GetW(), GetH() + 4);
+}
+
+mogltk::widgets::ContextMenu * mogltk::widgets::ContextMenu::createsub(const String & caption) {
+ ContextMenu * r;
+
+ r = new ContextMenu(Shaper(), Father(), GetX() + GetW(), GetY() + GetH());
+ r->SetVisible(false);
+
+ addsub(caption, r);
+
+ return r;
+}
+
+void mogltk::widgets::ContextMenu::move(int x, int y) {
+ int dx, dy;
+ std::vector<node>::iterator i;
+ ContextMenu * sub;
+
+ dx = x - GetX();
+ dy = y - GetY();
+ widget::move(x, y);
+
+ for (i = nodes.begin(); i != nodes.end(); i++) {
+ if ((sub = i->GetSub()))
+ sub->move(sub->GetX() + dx, sub->GetY() + dy);
+ }
+}
+
+void mogltk::widgets::ContextMenu::resize(int w, int h) {
+ int dw;
+ std::vector<node>::iterator i;
+ ContextMenu * sub;
+
+ dw = w - GetW();
+ widget::resize(w, h);
+
+ for (i = nodes.begin(); i != nodes.end(); i++) {
+ if ((sub = i->GetSub()))
+ sub->move(sub->GetX() + dw, sub->GetY());
+ }
+}
+
+void mogltk::widgets::ContextMenu::SetVisible(bool visible) {
+ if (!visible && sticky)
+ return;
+ widget::SetVisible(visible);
+ if (!visible && subselected) {
+ subselected->SetVisible(false);
+ }
+
+ if (visible) {
+ add_out_click();
+ MoveOnTop();
+ }
+}
+
+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;
+ rect size;
+
+ Shaper()->box3d(GetAX(), GetAY(), GetAX2(), GetAY2());
+
+ for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) {
+ size = SystemFont->size(i->GetCaption());
+ if (i->GetLine()) {
+ Shaper()->hline3d(GetAX() + i->GetX(), GetAX() + i->GetX() + GetW() - 4, GetAY() + i->GetY());
+ } else {
+ if (n == selected) {
+ Shaper()->box(GetAX() + 2, GetAY() + i->GetY(), GetAX() + GetW() - 2, GetAY() + i->GetY() + i->GetH(), DOS_MAGENTA);
+ }
+ Shaper()->text(GetAX() + i->GetX(), GetAY() + i->GetY(), i->GetCaption(), i->GetEnabled() ? BLACK : DOS_GRAY);
+ }
+ }
+}
+
+bool mogltk::widgets::ContextMenu::process_event(int xe, int ye, mogltk::event_t event) {
+ std::vector<node>::iterator i;
+ action * a;
+ int n;
+
+ switch (event) {
+ case E_MOUSE_MOVE:
+ sticky = false;
+ selected = -1;
+ for (i = nodes.begin(), n = 0; i != nodes.end(); i++, n++) {
+ if (!i->GetLine()) {
+ int ax, ax2, ay, ay2;
+
+ ax = GetAX() + 2;
+ ay = GetAY() + i->GetY();
+ ax2 = GetAX() + GetW() - 2;
+ ay2 = GetAY() + i->GetY() + i->GetH();
+
+ if (!((xe < ax) || (xe > ax2) || (ye < ay) || (ye > ay2))) {
+ selected = n;
+ if (subselected) {
+ subselected->SetVisible(false);
+ subselected->selected = -1;
+ subselected->subselected = 0;
+ }
+ if ((subselected = i->GetSub())) {
+ subselected->SetVisible(true);
+ subselected->selected = -1;
+ subselected->subselected = 0;
+ }
+ }
+ }
+ }
+ 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);
+ in_click = false;
+ SetVisible(false);
+ return true;
+ }
+ }
+ in_click = true;
+ break;
+ case E_MOUSE_DOWN:
+ in_click = true;
+ break;
+ case E_MOUSE_OUT:
+ selected = -1;
+ remove_out_move();
+ in_click = false;
+ return true;
+ case E_MOUSE_OUT_CLICK:
+ if (iin_click())
+ return true;
+ selected = -1;
+ subselected = 0;
+ SetVisible(false);
+ return true;
+ }
+
+ return false;
+}
+
+bool mogltk::widgets::ContextMenu::iin_click() {
+ if (in_click)
+ return true;
+
+ if (subselected)
+ return subselected->iin_click();
+
+ return false;
+}
+
+
+/********************
+* The Menu topframe *
+********************/
+
+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;
+}
+
+void mogltk::widgets::Menu::node::SetCaption(const String & s) {
+ caption = s;
+}
+
+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);
+}
+
+void mogltk::widgets::Menu::resize_notify() {
+ rect r = Father()->GetDrawRect();
+ 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::SetCaption(int i, const String & s) {
+ nodes[i].SetCaption(s);
+}
+
+void mogltk::widgets::Menu::draw(void) {
+ 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;
+}
+
+
+/*
+ * The mainloop widget thing.
+ */
+
+void mogltk::widget::mainloop() {
+ bool end_event_loop = false;
+ widget_mouse_event * mouse = new widget_mouse_event(this);
+ widget * w;
+ int mx, my;
+
+ while (!end_event_loop && !engine::quitrequested()) {
+ root->fulldraw();
+ mx = mogltk::engine::mouseX();
+ my = mogltk::engine::mouseY();
+
+ mogltk::ColorP::Max.A = 50;
+ Sprite::Cursor->draw(mx - 6, my - 3, BLACK);
+ mogltk::ColorP::Max.A = 255;
+ Sprite::Cursor->draw(mx - 8, my - 6);
+
+ if (w = root->find_widget(mx, my)) {
+ sh->box(w->GetAX(), w->GetAY(), w->GetAX2(), w->GetAY2(), Color(100, 150, 60, 50));
+ }
+
+ engine::base_o->Flip();
+ widget::check_timed_events();
+ }
+
+ delete mouse;
+}