Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-10-05 19:03:25 +0000
committerStijn Buys <ingar@osirion.org>2008-10-05 19:03:25 +0000
commitda9beb729c58ca2d91f67ab85a6728b628c27cf2 (patch)
tree96fd5df00a2431f40f515aa9fdf722377a0b6079
parent381c729e777b50771626703e60b422aafc791513 (diff)
user interface library
-rw-r--r--src/ui/Makefile.am9
-rw-r--r--src/ui/button.cc29
-rw-r--r--src/ui/button.h30
-rw-r--r--src/ui/label.cc46
-rw-r--r--src/ui/label.h32
-rw-r--r--src/ui/menu.cc58
-rw-r--r--src/ui/menu.h32
-rw-r--r--src/ui/palette.cc40
-rw-r--r--src/ui/palette.h43
-rw-r--r--src/ui/ui.cc214
-rw-r--r--src/ui/ui.h57
-rw-r--r--src/ui/widget.cc190
-rw-r--r--src/ui/widget.h147
-rw-r--r--src/ui/window.cc68
-rw-r--r--src/ui/window.h34
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__