diff options
author | Stijn Buys <ingar@osirion.org> | 2008-10-05 19:03:25 +0000 |
---|---|---|
committer | Stijn Buys <ingar@osirion.org> | 2008-10-05 19:03:25 +0000 |
commit | da9beb729c58ca2d91f67ab85a6728b628c27cf2 (patch) | |
tree | 96fd5df00a2431f40f515aa9fdf722377a0b6079 | |
parent | 381c729e777b50771626703e60b422aafc791513 (diff) |
user interface library
-rw-r--r-- | src/ui/Makefile.am | 9 | ||||
-rw-r--r-- | src/ui/button.cc | 29 | ||||
-rw-r--r-- | src/ui/button.h | 30 | ||||
-rw-r--r-- | src/ui/label.cc | 46 | ||||
-rw-r--r-- | src/ui/label.h | 32 | ||||
-rw-r--r-- | src/ui/menu.cc | 58 | ||||
-rw-r--r-- | src/ui/menu.h | 32 | ||||
-rw-r--r-- | src/ui/palette.cc | 40 | ||||
-rw-r--r-- | src/ui/palette.h | 43 | ||||
-rw-r--r-- | src/ui/ui.cc | 214 | ||||
-rw-r--r-- | src/ui/ui.h | 57 | ||||
-rw-r--r-- | src/ui/widget.cc | 190 | ||||
-rw-r--r-- | src/ui/widget.h | 147 | ||||
-rw-r--r-- | src/ui/window.cc | 68 | ||||
-rw-r--r-- | src/ui/window.h | 34 |
15 files changed, 1029 insertions, 0 deletions
diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am new file mode 100644 index 0000000..c64860a --- /dev/null +++ b/src/ui/Makefile.am @@ -0,0 +1,9 @@ +INCLUDES = -I$(top_srcdir)/src +METASOURCES = AUTO + +noinst_LTLIBRARIES = libui.la +noinst_HEADERS = button.h label.h menu.h palette.h ui.h widget.h window.h + +libui_la_SOURCES = button.cc label.cc menu.cc palette.cc ui.cc widget.cc \ + window.cc +libui_la_LDFLAGS = -avoid-version -no-undefined diff --git a/src/ui/button.cc b/src/ui/button.cc new file mode 100644 index 0000000..09e8695 --- /dev/null +++ b/src/ui/button.cc @@ -0,0 +1,29 @@ +/* + ui/button.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "ui/button.h" + +namespace ui { + +Button::Button (Widget *parent, char const *text, char const *command) : Label(parent, text) +{ + set_label("button"); + if (command) + button_command.assign(command); +} + +Button::~Button() +{ +} + +void Button::draw() +{ + Label::draw(); +} + +} + + diff --git a/src/ui/button.h b/src/ui/button.h new file mode 100644 index 0000000..eac5f1d --- /dev/null +++ b/src/ui/button.h @@ -0,0 +1,30 @@ +/* + ui/button.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_BUTTON_H__ +#define __INCLUDED_UI_BUTTON_H__ + +#include <string> +#include "ui/label.h" + +namespace ui { + +class Button : public Label { +public: + Button (Widget *parent, char const *text=0, char const *command=0); + ~Button(); + +protected: + virtual void draw(); + +private: + std::string button_command; +}; + +} + +#endif // __INCLUDED_UI_BUTTON_H__ + diff --git a/src/ui/label.cc b/src/ui/label.cc new file mode 100644 index 0000000..f924452 --- /dev/null +++ b/src/ui/label.cc @@ -0,0 +1,46 @@ +/* + ui/label.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "math/vector2f.h" +#include "render/primitives.h" +#include "ui/label.h" + +using math::Vector2f; + +namespace ui { + +Label::Label(Widget *parent, char const *text) : Widget(parent) +{ + set_label("label"); + if (text) + label_text.assign(text); +} + +Label::~Label() +{ +} + +void Label::draw() +{ + Widget::draw(); + + draw_text(); +} + +void Label::draw_text() +{ + if (!label_text.size()) + return; + + if (palette()) + render::gl::color(palette()->foreground()); + + render::primitives::text_centered(to_global(location()), size(), label_text); +} + +} + + diff --git a/src/ui/label.h b/src/ui/label.h new file mode 100644 index 0000000..f88f808 --- /dev/null +++ b/src/ui/label.h @@ -0,0 +1,32 @@ +/* + ui/label.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_LABEL_H__ +#define __INCLUDED_UI_LABEL_H__ + +#include <string> +#include "ui/widget.h" + +namespace ui { + +class Label : public Widget { +public: + Label(Widget *parent, char const *text=0); + ~Label(); + +protected: + virtual void draw(); + + virtual void draw_text(); + +private: + std::string label_text; +}; + +} + +#endif // __INCLUDED_UI_LABEL_H__ + diff --git a/src/ui/menu.cc b/src/ui/menu.cc new file mode 100644 index 0000000..c20457d --- /dev/null +++ b/src/ui/menu.cc @@ -0,0 +1,58 @@ +/* + ui/menu.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "ui/label.h" +#include "ui/button.h" +#include "ui/menu.h" +#include "ui/ui.h" + +namespace ui { + +const float element_width = 256.0f; +const float element_height = 64.0f; +const float element_margin = 24.0f; + +Menu::Menu(Window *parent, const char *label) : Window(parent), menu_container(this) +{ + set_label(label); + set_border(false); + + menu_container.set_label("container"); +} + +Menu::~Menu() +{ +} + +void Menu::add_label(char const * text) +{ + new Label(&menu_container, text); +} + +void Menu::add_button(char const *text, char const *command) +{ + new Button(&menu_container, text, command); +} + +void Menu::resize() +{ + set_size(parent()->size().x, parent()->size().y); + + float n = (float) menu_container.children().size(); + menu_container.set_size(2.0f * element_width, n * (element_height + element_margin) + element_height); + menu_container.set_location(element_margin, (height() - menu_container.height()) / 2.0f); + + // reposition all children within the container + size_t i = 0; + for (Children::iterator it = menu_container.children().begin(); it != menu_container.children().end(); it++) { + Widget *w = (*it); + w->set_size(element_width, element_height); + w->set_location(element_width * 0.5f, element_height * 0.5f + i * (element_height + element_margin)); + i++; + } +} + +} diff --git a/src/ui/menu.h b/src/ui/menu.h new file mode 100644 index 0000000..7ed905b --- /dev/null +++ b/src/ui/menu.h @@ -0,0 +1,32 @@ +/* + ui/menu.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_MENU_H__ +#define __INCLUDED_UI_MENU_H__ + +#include "ui/window.h" + +namespace ui { + +class Menu : public Window { + +public: + Menu(Window *parent, const char * label); + ~Menu(); + + void add_label(char const * text); + void add_button(char const *text, char const *command); + +protected: + virtual void resize(); + +private: + Window menu_container; +}; + +} + +#endif // __INCLUDED_UI_MENU_H__ diff --git a/src/ui/palette.cc b/src/ui/palette.cc new file mode 100644 index 0000000..04d7f00 --- /dev/null +++ b/src/ui/palette.cc @@ -0,0 +1,40 @@ +/* + ui/palette.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "ui/palette.h" +#include "sys/sys.h" + +namespace ui { + +Palette::Palette() +{ + palette_foreground.assign(1.0f, 1.0f); + palette_background.assign(0.8f, 0.5f); + palette_border.assign(0.0f, 8.0f, 0.0f); +} + +Palette::~Palette() +{ +} + +void Palette::set_foreground(math::Color const &color) +{ + palette_foreground.assign(color); +} + +void Palette::set_background(math::Color const &color) +{ + palette_background.assign(color); +} + +void Palette::set_border(math::Color const &color) +{ + palette_border.assign(color); +} + +} + + diff --git a/src/ui/palette.h b/src/ui/palette.h new file mode 100644 index 0000000..1b9eeb8 --- /dev/null +++ b/src/ui/palette.h @@ -0,0 +1,43 @@ +/* + ui/palette.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_PALETTE_H__ +#define __INCLUDED_UI_PALETTE_H__ + +#include "math/color.h" + +namespace ui { + +class Palette +{ + +public: + Palette(); + ~Palette(); + + void set_foreground(math::Color const &color); + + void set_background(math::Color const &color); + + void set_border(math::Color const &color); + + inline math::Color const &foreground() const { return palette_foreground; } + + inline math::Color const &background() const { return palette_background; } + + inline math::Color const &border() const { return palette_border; } + +private: + + math::Color palette_foreground; + math::Color palette_background; + math::Color palette_border; +}; + +} + +#endif // __INCLUDED_UI_PALETTE_H__ + diff --git a/src/ui/ui.cc b/src/ui/ui.cc new file mode 100644 index 0000000..be75f11 --- /dev/null +++ b/src/ui/ui.cc @@ -0,0 +1,214 @@ +/* + ui/ui.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include <string> +#include <sstream> + +#include "auxiliary/functions.h" +#include "core/core.h" +#include "sys/sys.h" +#include "ui/button.h" +#include "ui/label.h" +#include "ui/menu.h" +#include "ui/ui.h" +#include "ui/widget.h" +#include "ui/window.h" + +namespace ui { + +UI *global_ui = 0; + +void func_list_ui(std::string const &args) +{ + if (global_ui) { + global_ui->list(); + } +} + +void help() +{ + con_print << "^BUser interface functions" << std::endl; + con_print << " ui help show this help" << std::endl; + con_print << " ui list list widgets" << std::endl; + con_print << " ui show show user interface" << std::endl; + con_print << " ui hide hide user interface" << std::endl; +} + +void func_ui(std::string const &args) +{ + if (!global_ui) { + con_warn << "User Interface not available!" << std::endl; + return; + } + + if (!args.size()) { + help(); + return; + } + std::stringstream argstr(args); + std::string command; + argstr >> command; + aux::to_label(command); + + if (command.compare("help") == 0) { + help(); + } else if (command.compare("list") == 0) { + global_ui->list(); + } else if (command.compare("show") == 0) { + global_ui->show(); + } else if (command.compare("hide") == 0) { + global_ui->hide(); + } else { + help(); + } +} + +void func_menu(std::string const &args) +{ + if (!global_ui) { + con_warn << "User Interface not available!" << std::endl; + return; + } + + if (!args.size()) { + return; + } + std::stringstream argstr(args); + std::string command; + argstr >> command; + + aux::to_label(command); + + if (command.compare("hide") == 0) { + root()->hide_window(); + + } else if (command.compare("close") == 0) { + root()->hide_window(); + + } else if (command.compare("list") == 0) { + + } else { + root()->show_window(command.c_str()); + } +} + +UI *root() +{ + return global_ui; +} + +void init() +{ + con_print << "^BInitializing user interface..." << std::endl; + if (!global_ui) + global_ui = new UI(); + + core::Func *func = core::Func::add("list_ui", func_list_ui); + func->set_info("list user interface widgets"); + + func = core::Func::add("ui", func_ui); + func->set_info("[command] [options] user interface subcommands"); + + func = core::Func::add("menu", func_menu); + func->set_info("[hide|close|menuname] show or hide a menu"); +} + +void shutdown() +{ + con_print << "^BShutting down user interface..." << std::endl; + + core::Func::remove("list_ui"); + core::Func::remove("menu"); + core::Func::remove("ui"); + + if (global_ui) { + delete global_ui; + global_ui = 0; + } +} + +void frame() +{ + if (global_ui) + global_ui->draw_event(); +} + +UI::UI() : Window(0) +{ + set_palette(new Palette()); + set_label("user interface"); + set_size(1024, 768); + set_border(false); + + ui_active_window = 0; + + Menu *menu = 0; + + menu = new Menu(this, "main"); + menu->add_label("Main menu"); + menu->add_button("New Game", "connect"); + menu->add_button("Connect to...", "menu connect"); + menu->add_button("Options...", "menu options"); + menu->add_button("Quit", "quit"); + + menu = new Menu(this, "options"); + menu->add_label("Options menu"); + + menu = new Menu(this, "connect"); + menu->add_label("Connect to..."); +} + +UI::~UI() +{ + if (palette()) + delete palette(); +} + +void UI::list() +{ + size_t n = Widget::list(0); + con_print << n << " user interface widgets" << std::endl; +} + +void UI::add_window(Window *window) +{ + Window::add_window(window); + window->hide(); +} + +void UI::remove_window(Window *window) +{ + if (ui_active_window == window) + ui_active_window = 0; + Window::remove_window(window); +} + +void UI::show_window(char const *label) +{ + Windows::iterator it; + for (it = window_children.begin(); it != window_children.end(); it++) { + if ((*it)->label().compare(label) == 0) { + if (ui_active_window) + ui_active_window->hide(); + ui_active_window = (*it); + ui_active_window->resize_event(); + ui_active_window->show(); + return; + } + } + + con_warn << "Unknown window '" << label << "'" << std::endl; +} + +void UI::hide_window() +{ + if (ui_active_window) { + ui_active_window->hide(); + ui_active_window = 0; + } +} + +} diff --git a/src/ui/ui.h b/src/ui/ui.h new file mode 100644 index 0000000..c516d47 --- /dev/null +++ b/src/ui/ui.h @@ -0,0 +1,57 @@ +/* + ui/ui.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_H__ +#define __INCLUDED_UI_H__ + +#include "ui/palette.h" +#include "ui/widget.h" +#include "ui/window.h" + +namespace ui { + +class UI : public Window { +public: + /// constructor + UI(); + + /// destructor + ~UI(); + + /// list widgets + void list(); + + /// make a window the active window + void show_window(char const *label); + + /// hide the active window + void hide_window(); + + /// return the active window + Window *active() { return ui_active_window; } + +protected: + virtual void add_window(Window *window); + virtual void remove_window(Window *window); + +private: + Window *ui_active_window; +}; + +/// initialize the user interface +void init(); + +/// shutdown the user interface +void shutdown(); + +void frame(); + +/// the global root window +UI *root(); + +} + +#endif // __INCLUDED_UI_H__ diff --git a/src/ui/widget.cc b/src/ui/widget.cc new file mode 100644 index 0000000..94260cb --- /dev/null +++ b/src/ui/widget.cc @@ -0,0 +1,190 @@ +/* + ui/widget.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "auxiliary/functions.h" +#include "render/primitives.h" +#include "sys/sys.h" +#include "ui/widget.h" + +namespace ui { + +Widget::Widget(Widget *parent) { + widget_parent = parent; + widget_visible = true; + widget_border = true; + widget_background = false; + widget_label.assign("widget"); + + if (widget_parent) { + widget_palette = parent->widget_palette; + parent->add_child(this); + } else { + widget_palette = 0; + } +} + +Widget::~Widget() +{ + if (widget_parent) { + widget_parent->remove_child(this); + } + + for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) { + (*it)->widget_parent = 0; + delete (*it); + } + + widget_children.clear(); +} + +size_t Widget::list(size_t indent) +{ + size_t n = 1; + std::string marker(""); + con_print << aux::pad_left(marker, indent*2) << label() << " " << (size_t)(this) << std::endl; + + for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) { + n += (*it)->list(indent+1); + } + return n; +} + +void Widget::show() +{ + widget_visible = true; +} + +void Widget::hide() +{ + widget_visible = false; +} + +void Widget::set_border(bool border) +{ + widget_border = border; +} + + +void Widget::set_background(bool background) +{ + widget_background = background; +} + +void Widget::set_label(std::string const & label) +{ + set_label(label.c_str()); +} + +void Widget::set_label(char const *label) +{ + widget_label.assign(label); + aux::to_label(widget_label); +} + +void Widget::set_palette(Palette *palette) +{ + widget_palette = palette; +} + +void Widget::set_location(float const x, float const y) { + widget_location.assign(x, y); +} + +void Widget::set_size(float const w, float const h) +{ + widget_size.assign(w, h); +} + +void Widget::set_width(float const w) +{ + widget_size.x = w; +} +void Widget::set_height(float const h) +{ + widget_size.y = h; +} + +Widget::Children::iterator Widget::find_child(Widget *child) +{ + Children::iterator it; + for (it = widget_children.begin(); it != widget_children.end(); it++) { + if ((*it) == child) + return it; + } + + return it; +} + +void Widget::add_child(Widget *child) +{ + Children::iterator it = find_child(child); + if (it == widget_children.end()) { + widget_children.push_back(child); + } +} + +void Widget::remove_child(Widget *child) +{ + + Children::iterator it = find_child(child); + if (it != widget_children.end()) { + widget_children.erase(it); + } +} + +void Widget::resize_event() +{ + resize(); + for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) { + (*it)->resize_event(); + } +} + +void Widget::resize() +{ +} + +void Widget::draw_event() +{ + if (!widget_visible) + return; + + draw(); + for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) { + if ((*it)->visible()) + (*it)->draw_event(); + } +} + +void Widget::draw() +{ + draw_background(); + draw_border(); +} + +void Widget::draw_background() +{ + if (!widget_background) + return; + + if (palette()) + render::gl::color(palette()->background()); + math::Vector2f v(to_global(location())); + render::primitives::rectangle(v, size()); +} + +void Widget::draw_border() +{ + if (!widget_border) + return; + + if (palette()) + render::gl::color(palette()->border()); + math::Vector2f v(to_global(location())); + render::primitives::border(v, size()); +} + +} diff --git a/src/ui/widget.h b/src/ui/widget.h new file mode 100644 index 0000000..97c6a01 --- /dev/null +++ b/src/ui/widget.h @@ -0,0 +1,147 @@ +/* + ui/widget.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_WIDGET_H__ +#define __INCLUDED_UI_WIDGET_H__ + +#include <string> +#include <list> + +#include "math/vector2f.h" +#include "ui/palette.h" + +namespace ui { + +class Widget { + +public: + /// create a new widget + Widget(Widget *parent=0); + + /// destroy a widget + virtual ~Widget(); + + /* -- inspectors -------------------------------------------- */ + inline bool visible() const { return widget_visible; } + + inline math::Vector2f &location() { return widget_location; } + + inline math::Vector2f &size() { return widget_size; } + + inline float const left() const { return widget_location.x; } + + inline float const top() const { return widget_location.y; } + + inline float const width() const { return widget_size.x; } + + inline float const height() const { return widget_size.y; } + + inline Palette const *palette() const { return widget_palette; } + + inline std::string const &label() const { return widget_label; } + + inline bool border() const { return widget_border; } + + inline bool background() { return widget_background; } + + inline Widget *parent() { return widget_parent; } + + + /* -- mutators --------------------------------------------- */ + + /// show the widget + void show(); + + /// hide the widget + void hide(); + + /// set location of the top-left corner + void set_location(float const x, float const y); + + /// set the widgets width and height + void set_size(float const w, float const h); + + /// set the widgets width + void set_width(float const w); + + /// set the widgets height + void set_height(float const h); + + /// set the widgets palette + void set_palette(Palette *palette); + + /// set the widgets label + void set_label(std::string const &label); + + /// set the widgets label + void set_label(char const *label); + + void set_border(bool border); + + void set_background(bool background); + + /// resize event + virtual void resize_event(); + + /// draw event + virtual void draw_event(); + + /// type definition for child widgets + typedef std::list<Widget *> Children; + + /// child widgets + inline Children &children() { return widget_children; } + +protected: + /// draw the widget + virtual void draw(); + + /// resize the widget + virtual void resize(); + + /// draw the widget background + virtual void draw_background(); + + /// draw the widget border + virtual void draw_border(); + + /// list widget content + size_t list(size_t indent); + + /// map local widget coordinates to global coordinates + inline math::Vector2f to_global(math::Vector2f v) { + Widget *parent = widget_parent; + while (parent) { + v += parent->location(); + parent = parent->widget_parent; + } + return v; + } + +private: + + Palette *widget_palette; + bool widget_visible; + bool widget_background; + bool widget_border; + math::Vector2f widget_location; + math::Vector2f widget_size; + std::string widget_label; + + Children widget_children; + Widget *widget_parent; + + Children::iterator find_child(Widget *child); + + void add_child(Widget *child); + + void remove_child(Widget *child); +}; + +} + +#endif // __INCLUDED_UI_WIDGET_H__ + diff --git a/src/ui/window.cc b/src/ui/window.cc new file mode 100644 index 0000000..8763b53 --- /dev/null +++ b/src/ui/window.cc @@ -0,0 +1,68 @@ +/* + ui/window.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "ui/window.h" +#include "render/primitives.h" + +namespace ui { + +Window::Window(Window *parent) : Widget(static_cast<Widget *>(parent)) +{ + set_label("window"); + set_border(true); + + if (parent) { + parent->add_window(this); + } +} + +Window::~Window() +{ + if (parent()) { + static_cast<Window *>(parent())->remove_window(this); + } + window_children.clear(); +} + +void Window::draw_border() +{ + if (!border()) + return; + + if (palette()) + render::gl::color(palette()->foreground()); + math::Vector2f v(to_global(location())); + render::primitives::border(v, size()); +} + +Window::Windows::iterator Window::find_window(Window *window) +{ + Windows::iterator it; + for (it = window_children.begin(); it != window_children.end(); it++) { + if ((*it) == window) + return it; + } + + return it; +} + +void Window::add_window(Window *window) +{ + Windows::iterator it = find_window(window); + if (it == window_children.end()) { + window_children.push_back(window); + } +} + +void Window::remove_window(Window *window) +{ + + Windows::iterator it = find_window(window); + if (it != window_children.end()) { + window_children.erase(it); + } +} +} diff --git a/src/ui/window.h b/src/ui/window.h new file mode 100644 index 0000000..f88d5aa --- /dev/null +++ b/src/ui/window.h @@ -0,0 +1,34 @@ +/* + ui/window.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_WINDOW_H__ +#define __INCLUDED_UI_WINDOW_H__ + +#include "ui/widget.h" + +namespace ui { + +class Window : public Widget { + +public: + Window(Window *parent=0); + ~Window(); + + virtual void draw_border(); + +protected: + typedef std::list<Window *> Windows; + Windows window_children; + + Windows::iterator find_window(Window *window); + + virtual void add_window(Window *window); + virtual void remove_window(Window *window); +}; + +} + +#endif // __INCLUDED_UI_WINDOW_H__ |