diff options
author | pixel <pixel> | 2004-11-27 21:48:01 +0000 |
---|---|---|
committer | pixel <pixel> | 2004-11-27 21:48:01 +0000 |
commit | f9969775e6d2f798a3bfea5c58fc5478dad07eae (patch) | |
tree | c82d4ed9c87d7e09c71be3554ac5d0486c774eda /lib/widgets.cc | |
parent | 1ae229afb9bff4a3636c08632032b509e1e80ec4 (diff) |
Large dos2unix commit...
Diffstat (limited to 'lib/widgets.cc')
-rw-r--r-- | lib/widgets.cc | 2364 |
1 files changed, 1182 insertions, 1182 deletions
diff --git a/lib/widgets.cc b/lib/widgets.cc index c70ad95..55c709c 100644 --- a/lib/widgets.cc +++ b/lib/widgets.cc @@ -1,1182 +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.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;
-}
+/* + * 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.10 2004-11-27 21:48:03 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; +} |