summaryrefslogtreecommitdiff
path: root/lib/contextmenu.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/contextmenu.cc')
-rw-r--r--lib/contextmenu.cc416
1 files changed, 416 insertions, 0 deletions
diff --git a/lib/contextmenu.cc b/lib/contextmenu.cc
new file mode 100644
index 0000000..5b8309e
--- /dev/null
+++ b/lib/contextmenu.cc
@@ -0,0 +1,416 @@
+/*
+ * mogltk
+ * Copyright (C) 1999-2005 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: contextmenu.cc,v 1.1 2005-12-02 16:21:59 pixel Exp $ */
+
+#include <SDL.h>
+#include <vector>
+#include <Input.h>
+#include "font.h"
+#include "engine.h"
+#include "widgets.h"
+#include "sprite.h"
+
+/***********************************
+* 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), subselected(0) {
+ 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;
+}