Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-10-12 14:55:10 +0000
committerStijn Buys <ingar@osirion.org>2008-10-12 14:55:10 +0000
commitb417df720584c101f3799874a0c836a543a8d0a8 (patch)
treefb7105ed662f13753a6ab8d3efb047bad04f2316 /src/ui
parent18383a5fc596bf9546f14d7393ee66c57720b116 (diff)
user interface updates, work-in-progress
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/Makefile.am6
-rw-r--r--src/ui/bitmap.cc11
-rw-r--r--src/ui/bitmap.h33
-rw-r--r--src/ui/button.cc32
-rw-r--r--src/ui/button.h45
-rw-r--r--src/ui/container.h36
-rw-r--r--src/ui/definitions.h7
-rw-r--r--src/ui/font.cc13
-rw-r--r--src/ui/font.h51
-rw-r--r--src/ui/input.cc174
-rw-r--r--src/ui/input.h55
-rw-r--r--src/ui/label.cc13
-rw-r--r--src/ui/label.h38
-rw-r--r--src/ui/menu.cc47
-rw-r--r--src/ui/menu.h22
-rw-r--r--src/ui/paint.cc66
-rw-r--r--src/ui/paint.h12
-rw-r--r--src/ui/palette.cc16
-rw-r--r--src/ui/palette.h51
-rw-r--r--src/ui/ui.cc191
-rw-r--r--src/ui/ui.h99
-rw-r--r--src/ui/widget.cc253
-rw-r--r--src/ui/widget.h330
-rw-r--r--src/ui/window.cc9
-rw-r--r--src/ui/window.h24
25 files changed, 1122 insertions, 512 deletions
diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am
index 5c7815b..b0f1625 100644
--- a/src/ui/Makefile.am
+++ b/src/ui/Makefile.am
@@ -7,9 +7,9 @@ else
noinst_LTLIBRARIES = libui.la
endif
-noinst_HEADERS = bitmap.h button.h definitions.h font.h label.h \
+noinst_HEADERS = bitmap.h button.h container.h definitions.h font.h input.h label.h \
menu.h paint.h palette.h ui.h widget.h window.h
-libui_la_SOURCES = bitmap.cc button.cc font.cc label.cc menu.cc paint.cc \
- palette.cc ui.cc widget.cc window.cc
+libui_la_SOURCES = bitmap.cc button.cc font.cc input.cc label.cc menu.cc \
+ paint.cc palette.cc ui.cc widget.cc window.cc
libui_la_LDFLAGS = -avoid-version -no-undefined
diff --git a/src/ui/bitmap.cc b/src/ui/bitmap.cc
index c14ccff..fcf141c 100644
--- a/src/ui/bitmap.cc
+++ b/src/ui/bitmap.cc
@@ -24,13 +24,13 @@ Bitmap::Bitmap(Widget *parent, const char *texture) : Widget(parent)
Bitmap::~Bitmap()
{}
-void Bitmap::print(size_t indent)
+void Bitmap::print(const size_t indent) const
{
std::string marker("");
con_print << aux::pad_left(marker, indent*2) << label() << " \"" << texture() << "\"" << std::endl;
}
-void Bitmap::set_texture(std::string const & texture)
+void Bitmap::set_texture(const std::string & texture)
{
bitmap_texture.assign(texture);
}
@@ -43,10 +43,15 @@ void Bitmap::set_texture(const char *texture)
bitmap_texture.clear();
}
+void Bitmap::set_color(const math::Color & color)
+{
+ bitmap_color.assign(color);
+}
+
void Bitmap::draw_background()
{
if (bitmap_texture.size()) {
- paint::color(1.0f, 1.0f, 1.0f, 1.0f);
+ paint::color(bitmap_color);
paint::bitmap(global_location(), size(), bitmap_texture);
}
}
diff --git a/src/ui/bitmap.h b/src/ui/bitmap.h
index 1f60ef9..9bc1776 100644
--- a/src/ui/bitmap.h
+++ b/src/ui/bitmap.h
@@ -9,25 +9,38 @@
#include "ui/widget.h"
-namespace ui {
+namespace ui
+{
-class Bitmap : public Widget {
+class Bitmap : public Widget
+{
public:
- Bitmap (Widget *parent, const char *texture=0);
+ Bitmap(Widget *parent, const char *texture=0);
~Bitmap();
-
- inline std::string const &texture() const { return bitmap_texture; }
- void set_texture(std::string const & texture);
+
+ inline std::string const &texture() const {
+ return bitmap_texture;
+ }
+
+ inline math::Color const &color() const {
+ return bitmap_color;
+ }
+
+ void set_texture(const std::string & texture);
void set_texture(const char *texture);
-
+
+ void set_color(const math::Color &color);
+
/// print bitmap description
- virtual void print(size_t indent);
-
+ virtual void print(const size_t indent) const;
+
protected:
+ /// draw the bitmap as background
virtual void draw_background();
-
+
private:
std::string bitmap_texture;
+ math::Color bitmap_color;
};
}
diff --git a/src/ui/button.cc b/src/ui/button.cc
index 1ac5fd8..08fd0e9 100644
--- a/src/ui/button.cc
+++ b/src/ui/button.cc
@@ -11,9 +11,10 @@
#include "ui/button.h"
#include "core/commandbuffer.h"
-namespace ui {
+namespace ui
+{
-Button::Button (Widget *parent, const char *text, const char *command) : Label(parent, text)
+Button::Button(Widget *parent, const char *text, const char *command) : Label(parent, text)
{
set_label("button");
set_command(command);
@@ -24,7 +25,7 @@ Button::~Button()
{
}
-void Button::print(size_t indent)
+void Button::print(const size_t indent) const
{
std::string marker("");
con_print << aux::pad_left(marker, indent*2) << label() << " \"" << text() << "\" \"" << command() << "\"" << std::endl;
@@ -38,7 +39,7 @@ void Button::set_command(const char *command)
button_command.clear();
}
-void Button::set_command(std::string const &command)
+void Button::set_command(const std::string &command)
{
button_command.assign(command);
}
@@ -47,12 +48,12 @@ void Button::draw_border()
{
if (!border())
return;
-
- if (has_focus())
+
+ if (has_mouse_focus())
paint::color(palette()->foreground());
else
paint::color(palette()->border());
-
+
paint::border(global_location(), size());
}
@@ -60,29 +61,34 @@ void Button::draw_text()
{
if (!text().size())
return;
-
- if (has_focus())
+
+ if (has_mouse_focus())
paint::color(palette()->highlight());
else
paint::color(palette()->foreground());
-
+
paint::text(global_location(), size(), font(), text(), alignment());
}
-bool Button::keypress(unsigned int key, unsigned int modifier)
+bool Button::on_keypress(const int key, const unsigned int modifier)
{
return false;
}
-bool Button::keyrelease(unsigned int key, unsigned int modifier)
+bool Button::on_keyrelease(const int key, const unsigned int modifier)
{
if (key == 512 + SDL_BUTTON_LEFT) {
core::cmd() << button_command << std::endl;
audio::play("ui/button");
return true;
}
-
+
return false;
}
+void Button::on_mouseover(const math::Vector2f &cursor)
+{
+ audio::play("ui/select");
+}
+
}
diff --git a/src/ui/button.h b/src/ui/button.h
index c074467..b1bb522 100644
--- a/src/ui/button.h
+++ b/src/ui/button.h
@@ -10,32 +10,45 @@
#include <string>
#include "ui/label.h"
-namespace ui {
+namespace ui
+{
-class Button : public Label {
+class Button : public Label
+{
public:
- Button (Widget *parent, const char *text=0, const char *command=0);
+ Button(Widget *parent, const char *text=0, const char *command=0);
~Button();
-
- void set_command(std::string const &command);
+
+ /// set the command this button will execute
+ void set_command(const std::string &command);
+
+ /// set the command this button will execute
void set_command(const char *command);
-
- inline std::string const & command() const { return button_command; }
-
+
+ /// the command this button executes
+ inline const std::string & command() const {
+ return button_command;
+ }
+
/// print button description
- virtual void print(size_t indent);
-
- /// handle keyboard events
- virtual bool keypress(unsigned int key, unsigned int modifier);
- virtual bool keyrelease(unsigned int key, unsigned int modifier);
-
+ virtual void print(const size_t indent) const;
+
+ /// called when the mouse enters the widget
+ virtual void on_mouseover(const math::Vector2f &cursor);
+
+ /// called when the widget receives a key press
+ virtual bool on_keypress(const int key, const unsigned int modifier);
+
+ /// called when the widget receives a key release
+ virtual bool on_keyrelease(const int key, const unsigned int modifier);
+
protected:
/// draw the button border
virtual void draw_border();
-
+
/// draw the button text
virtual void draw_text();
-
+
private:
std::string button_command;
};
diff --git a/src/ui/container.h b/src/ui/container.h
new file mode 100644
index 0000000..77e987e
--- /dev/null
+++ b/src/ui/container.h
@@ -0,0 +1,36 @@
+/*
+ ui/container.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_CONTAINER_H__
+#define __INCLUDED_UI_CONTAINER_H__
+
+#include <string>
+#include "ui/widget.h"
+
+namespace ui {
+
+/// a widget containing childs of equal size
+class Container : public Widget {
+public:
+ Container(Widget *parent);
+ ~Container();
+
+ void set_margin(const float h, const float v);
+ void set_child_size(const float width, const float height);
+
+protected:
+ virtual void resize();
+
+private:
+ math::Vector2f container_child_size;
+};
+
+}
+
+#endif // __INCLUDED_UI_CONTAINER_H__
+*/
+
diff --git a/src/ui/definitions.h b/src/ui/definitions.h
index d5d7fe9..b9b4e3c 100644
--- a/src/ui/definitions.h
+++ b/src/ui/definitions.h
@@ -7,18 +7,19 @@
#ifndef __INCLUDED_UI_DEFINITIONS_H__
#define __INCLUDED_UI_DEFINITIONS_H__
-namespace ui {
+namespace ui
+{
enum Alignment {
AlignAuto = 0x0000,
AlignLeft = 0x0001,
AlignHCenter = 0x0002,
AlignRight = 0x0004,
-
+
AlignTop = 0x0010,
AlignVCenter = 0x0020,
AlignBottom = 0x0040,
-
+
AlignCenter = AlignHCenter | AlignVCenter
};
diff --git a/src/ui/font.cc b/src/ui/font.cc
index 26d4155..9d721fd 100644
--- a/src/ui/font.cc
+++ b/src/ui/font.cc
@@ -6,7 +6,8 @@
#include "ui/font.h"
-namespace ui {
+namespace ui
+{
Font::Font(const char *name, const float width, const float height)
{
@@ -23,17 +24,17 @@ void Font::set_size(const float width, const float height)
font_size.assign(width, height);
}
-void Font::set_size(math::Vector2f const &size)
+void Font::set_size(const math::Vector2f &size)
{
font_size.assign(size);
}
-void Font::set_width(float width)
+void Font::set_width(const float width)
{
font_size.x = width;
}
-void Font::set_height(float height)
+void Font::set_height(const float height)
{
font_size.y = height;
}
@@ -46,12 +47,10 @@ void Font::set_name(const char *name)
font_name.clear();
}
-void Font::set_name(std::string const & name)
+void Font::set_name(const std::string & name)
{
font_name.assign(name);
}
}
-
-
diff --git a/src/ui/font.h b/src/ui/font.h
index a68dec8..1261427 100644
--- a/src/ui/font.h
+++ b/src/ui/font.h
@@ -10,38 +10,47 @@
#include <string>
#include "math/vector2f.h"
-namespace ui {
+namespace ui
+{
class Font
{
public:
Font(const char *name, const float width, const float height);
~Font();
-
- inline std::string const & name() const { return font_name; }
-
- inline math::Vector2f const & size() const { return font_size; }
-
- inline float const width() const { return font_size.x; }
-
- inline float const height() const { return font_size.y; }
-
+
+ inline const std::string & name() const {
+ return font_name;
+ }
+
+ inline const math::Vector2f & size() const {
+ return font_size;
+ }
+
+ inline float width() const {
+ return font_size.x;
+ }
+
+ inline float height() const {
+ return font_size.y;
+ }
+
void set_size(const float width, const float height);
-
- void set_size(math::Vector2f const &size);
-
- void set_width(float width);
-
- void set_height(float height);
-
+
+ void set_size(const math::Vector2f &size);
+
+ void set_width(const float width);
+
+ void set_height(const float height);
+
void set_name(const char *name);
-
- void set_name(std::string const & name);
-
+
+ void set_name(const std::string & name);
+
private:
std::string font_name;
-
+
math::Vector2f font_size;
};
diff --git a/src/ui/input.cc b/src/ui/input.cc
new file mode 100644
index 0000000..0c4ea32
--- /dev/null
+++ b/src/ui/input.cc
@@ -0,0 +1,174 @@
+/*
+ ui/input.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/input.h"
+#include "ui/paint.h"
+#include "auxiliary/functions.h"
+#include "core/core.h"
+#include "render/render.h"
+
+namespace ui
+{
+
+Input::Input(Widget *parent) : Widget(parent)
+{
+ input_text.clear();
+ input_pos = 0;
+
+ set_label("input");
+ set_background(false);
+ set_border(false);
+}
+
+Input::~Input()
+{
+}
+
+void Input::clear()
+{
+ input_text.clear();
+ input_pos = 0;
+}
+void Input::set_text(std::string const &text)
+{
+ input_text.assign(text);
+ input_pos = input_text.size();
+}
+
+void Input::set_text(const char *text)
+{
+ if (text)
+ input_text.assign(text);
+ else
+ input_text.clear();
+ input_pos = input_text.size();
+}
+
+void Input::draw()
+{
+ draw_background();
+ draw_border();
+
+ using namespace render;
+ size_t text_width = (size_t) width() / font()->width();
+ math::Vector2f v(global_location());
+ paint::color(palette()->foreground());
+
+ std::string firstpart(input_text.substr(0, input_pos));
+ size_t draw_width = 0;
+ const char *c = firstpart.c_str();
+
+ while (*c) {
+ if (aux::is_color_code(c)) {
+ c++;
+ } else {
+ draw_width++;
+ }
+ c++;
+ }
+
+ c = firstpart.c_str();
+ while (*c && draw_width > text_width - 2) {
+ if (aux::is_color_code(c)) {
+ c++;
+ Text::setcolor(*c);
+ } else {
+ draw_width--;
+ }
+ c++;
+ }
+
+ // draw the part before the cursor
+ if (*c) {
+ paint::text(v, size(), font(), std::string(c), AlignLeft | AlignVCenter);
+ }
+
+ // draw the part behind the cursor
+ v.x += draw_width * font()->width();
+ if (input_pos < input_text.size()) {
+ // FIXME limit to width
+ if (input_pos > 1 && aux::is_color_code(input_text.c_str() + input_pos -1)) {
+ Text::setcolor(input_text[input_pos]);
+ }
+ c = input_text.c_str() + input_pos;
+ paint::text(v, size(), font(), std::string(c), AlignLeft | AlignVCenter);
+ }
+
+ // draw cursor
+ if (has_input_focus() && (core::application()->time() - ::floorf(core::application()->time())) < 0.5f) {
+ std::string cursor("^B");
+ cursor += (char) 11;
+ paint::text(v, size(), font(), cursor, AlignLeft | AlignVCenter);
+ }
+}
+
+bool Input::on_keypress(const int key, const unsigned int modifier)
+{
+ switch (key) {
+ case SDLK_TAB:
+ core::CommandBuffer::complete(input_text, input_pos);
+ return true;
+ break;
+
+ case SDLK_HOME:
+ input_pos = 0;
+ return true;
+ break;
+
+ case SDLK_END:
+ input_pos = input_text.size();
+ return true;
+ break;
+
+ case SDLK_LEFT:
+ if (input_pos > 0)
+ input_pos--;
+ return true;
+ break;
+
+ case SDLK_RIGHT:
+ if (input_pos < input_text.size())
+ input_pos++;
+ return true;
+ break;
+
+ case SDLK_DELETE:
+ if (input_text.size() && input_pos < input_text.size()) {
+ input_text.erase(input_pos, 1);
+ }
+ return true;
+ break;
+
+ case SDLK_BACKSPACE:
+ if (input_text.size() && input_pos) {
+ input_text.erase(input_pos-1, 1);
+ input_pos--;
+ }
+ return true;
+ break;
+
+ default:
+ if ((key >= 32) && (key <175)) {
+ if (input_pos == input_text.size())
+ input_text += (char)key;
+ else
+ input_text.insert(input_pos, 1, (char)key);
+ input_pos++;
+ return true;
+ }
+ break;
+ }
+
+ return false;
+}
+bool Input::on_keyrelease(const int key, const unsigned int modifier)
+{
+ return false;
+}
+
+}
+
+
diff --git a/src/ui/input.h b/src/ui/input.h
new file mode 100644
index 0000000..214f63e
--- /dev/null
+++ b/src/ui/input.h
@@ -0,0 +1,55 @@
+/*
+ ui/input.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_INPUT_H__
+#define __INCLUDED_UI_INPUT_H__
+
+#include "ui/widget.h"
+
+namespace ui
+{
+
+/// text input widget
+class Input : public Widget
+{
+public:
+ Input(Widget *parent);
+ ~Input();
+
+ /// set the text displayed by the label
+ void set_text(std::string const &text);
+
+ /// set the text displayed by the label
+ void set_text(const char *text);
+
+ /// return the text displayed by the label
+ inline std::string const &text() const {
+ return input_text;
+ }
+
+ /// clear the text
+ void clear();
+
+protected:
+ /// draw the widget
+ virtual void draw();
+
+ /// called when the widget receives a key press
+ virtual bool on_keypress(const int key, const unsigned int modifier);
+
+ /// called when the widget receives a key release
+ virtual bool on_keyrelease(const int key, const unsigned int modifier);
+
+private:
+
+ std::string input_text;
+ size_t input_pos;
+};
+
+}
+
+#endif // __INCLUDED_UI_INPUT_H__
+
diff --git a/src/ui/label.cc b/src/ui/label.cc
index 6f496fc..80e493e 100644
--- a/src/ui/label.cc
+++ b/src/ui/label.cc
@@ -10,7 +10,8 @@
using math::Vector2f;
-namespace ui {
+namespace ui
+{
Label::Label(Widget *parent, const char *text) : Widget(parent)
{
@@ -23,7 +24,7 @@ Label::~Label()
{
}
-void Label::print(size_t indent)
+void Label::print(const size_t indent) const
{
std::string marker("");
con_print << aux::pad_left(marker, indent*2) << label() << " \"" << text() << "\"" << std::endl;
@@ -37,12 +38,12 @@ void Label::set_text(const char *text)
label_text.clear();
}
-void Label::set_text(std::string const &text)
+void Label::set_text(const std::string &text)
{
label_text.assign(text);
}
-void Label::set_alignment(unsigned int alignment)
+void Label::set_alignment(const unsigned int alignment)
{
label_alignment = alignment;
}
@@ -50,7 +51,7 @@ void Label::set_alignment(unsigned int alignment)
void Label::draw()
{
Widget::draw();
-
+
draw_text();
}
@@ -58,7 +59,7 @@ void Label::draw_text()
{
if (!label_text.size())
return;
-
+
paint::color(palette()->foreground());
paint::text(global_location(), size(), font(), text(), alignment());
}
diff --git a/src/ui/label.h b/src/ui/label.h
index 45171b2..b7925c7 100644
--- a/src/ui/label.h
+++ b/src/ui/label.h
@@ -10,39 +10,45 @@
#include <string>
#include "ui/widget.h"
-namespace ui {
+namespace ui
+{
/// a widget displaying centered text
-class Label : public Widget {
+class Label : public Widget
+{
public:
Label(Widget *parent, const char *text=0);
~Label();
-
+
/// set the text displayed by the label
- void set_text(std::string const &text);
-
+ void set_text(const std::string &text);
+
/// set the text displayed by the label
void set_text(const char *text);
-
+
/// set the text alignment
- void set_alignment(unsigned int alignment);
-
+ void set_alignment(const unsigned int alignment);
+
/// return the text displayed by the label
- inline std::string const &text() const { return label_text; }
-
+ inline const std::string &text() const {
+ return label_text;
+ }
+
/// text alignment
- inline unsigned int alignment() const { return label_alignment; }
-
+ inline unsigned int alignment() const {
+ return label_alignment;
+ }
+
/// print label description
- virtual void print(size_t indent);
-
+ virtual void print(const size_t indent) const;
+
protected:
/// draw the label
virtual void draw();
-
+
/// draw the label text
virtual void draw_text();
-
+
private:
std::string label_text;
unsigned int label_alignment;
diff --git a/src/ui/menu.cc b/src/ui/menu.cc
index af9929c..2a1829f 100644
--- a/src/ui/menu.cc
+++ b/src/ui/menu.cc
@@ -10,22 +10,23 @@
#include "ui/menu.h"
#include "ui/ui.h"
-namespace ui {
+namespace ui
+{
Menu::Menu(Window *parent, const char *label) : Window(parent)
{
set_label(label);
set_border(false);
-
+
menu_element_width = 256.0f;
menu_element_height = 48.0f;
menu_element_margin = 24.0f;
-
+
menu_background = new Bitmap(this);
menu_container = new Window(this);
menu_container->set_border(true);
menu_container->set_background(true);
-
+
menu_container->set_label("container");
}
@@ -38,41 +39,41 @@ void Menu::load()
{
std::string filename("menus/");
filename.append(label());
-
+
filesystem::IniFile ini;
-
+
ini.open(filename);
-
+
if (!ini.is_open()) {
con_error << "Could not open " << ini.name() << std::endl;
return;
}
-
+
std::string strval;
Button *button = 0;
Label *label = 0;
while (ini.getline()) {
if (ini.got_section()) {
-
+
//con_debug << " " << ini.name() << " [" << ini.section() << "]" << std::endl;
-
+
if (ini.got_section("menu")) {
} else if (ini.got_section("button")) {
button = add_button();
-
+
} else if (ini.got_section("label")) {
label = add_label();
-
+
} else if (ini.got_section()) {
ini.unknown_section();
}
-
+
} else if (ini.got_key()) {
-
+
//con_debug << " " << ini.name() << " " << ini.key() << "=" << ini.value() << std::endl;
-
+
if (ini.in_section("menu")) {
if (ini.got_key_string("background", strval)) {
set_background(strval.c_str());
@@ -88,10 +89,10 @@ void Menu::load()
} else if (ini.in_section("button")) {
if (ini.got_key_string("text", strval)) {
button->set_text(strval);
-
+
} else if (ini.got_key_string("command", strval)) {
button->set_command(strval);
-
+
} else if (ini.got_key_string("align", strval)) {
aux::to_label(strval);
if (strval.compare("left") == 0) {
@@ -99,7 +100,7 @@ void Menu::load()
} else if (strval.compare("center") == 0) {
button->set_alignment(AlignCenter);
} else if (strval.compare("right") == 0) {
- button->set_alignment(AlignRight | AlignVCenter);
+ button->set_alignment(AlignRight | AlignVCenter);
} else {
ini.unknown_value();
}
@@ -124,10 +125,10 @@ void Menu::load()
ini.unkown_key();
}
}
-
+
}
}
-
+
con_debug << " " << ini.name() << " " << children().size() << " widgets" << std::endl;
ini.close();
}
@@ -153,9 +154,9 @@ Button *Menu::add_button(char const *text, char const *command)
void Menu::resize()
{
- size().assign(parent()->size());
- menu_background->size().assign(size());
-
+ set_size(parent()->size());
+ menu_background->set_size(size());
+
float n = (float) menu_container->children().size();
menu_container->set_size(1.5f * menu_element_width, n * (menu_element_height + menu_element_margin) + menu_element_height);
menu_container->set_location(menu_element_width * 0.25, (height() - menu_container->height()) / 2.0f);
diff --git a/src/ui/menu.h b/src/ui/menu.h
index 376e069..1b4f17e 100644
--- a/src/ui/menu.h
+++ b/src/ui/menu.h
@@ -12,36 +12,38 @@
#include "ui/label.h"
#include "ui/window.h"
-namespace ui {
+namespace ui
+{
/// a menu container
-class Menu : public Window {
+class Menu : public Window
+{
public:
/// create a new menu
Menu(Window *parent, const char * label);
~Menu();
-
+
/// load a menu from ini/menus/label.ini
void load();
-
+
void set_background(const char *texture);
-
+
Label *add_label(char const * text=0);
-
+
Button *add_button(char const *text=0, char const *command=0);
-
+
protected:
virtual void resize();
-
+
private:
float menu_element_width;
float menu_element_height;
float menu_element_margin;
-
+
Bitmap *menu_background;
Window *menu_container;
-
+
};
}
diff --git a/src/ui/paint.cc b/src/ui/paint.cc
index ce5a5c2..33ee54f 100644
--- a/src/ui/paint.cc
+++ b/src/ui/paint.cc
@@ -11,7 +11,8 @@
#include "render/textures.h"
#include "ui/paint.h"
-namespace ui {
+namespace ui
+{
// contains the interface between the user interface and the render library
namespace paint {
@@ -26,10 +27,15 @@ void color(math::Color const & color)
render::gl::color(color);
}
+void color_code(const char *c)
+{
+ render::Text::setcolor(*c);
+}
+
void border(math::Vector2f const &location, math::Vector2f const &size)
{
using namespace render::gl;
-
+
begin(LineLoop);
vertex(location.x +1 , location.y);
vertex(location.x + size.x, location.y);
@@ -41,7 +47,7 @@ void border(math::Vector2f const &location, math::Vector2f const &size)
void rectangle(math::Vector2f const &location, math::Vector2f const &size)
{
using namespace render::gl;
-
+
begin(Quads);
vertex(location.x +1 , location.y);
vertex(location.x + size.x, location.y);
@@ -57,39 +63,39 @@ void bitmap(math::Vector2f const &location, math::Vector2f const &size, std::str
render::Textures::bind("bitmaps/" + texture);
enable(GL_TEXTURE_2D);
-
+
begin(Quads);
-
+
glTexCoord2f(0.0f, 0.0f);
vertex(location.x +1 , location.y);
-
+
glTexCoord2f(1.0f, 0.0f);
vertex(location.x + size.x, location.y);
-
+
glTexCoord2f(1.0f, 1.0f);
vertex(location.x + size.x, location.y + size.y -1);
-
+
glTexCoord2f(0.0f, 1.0f);
vertex(location.x +1, location.y + size.y - 1);
end();
-
+
disable(GL_TEXTURE_2D);
}
void text_centered(math::Vector2f const &location, math::Vector2f const &size, std::string const &text, Font const *font)
{
using namespace render::gl;
-
+
render::Text::setfont(font->name().c_str(), font->width(), font->height());
enable(GL_TEXTURE_2D);
math::Vector2f v(location);
-
+
v.x += (size.x - aux::text_strip(text).size() * font->width()) /2.0f;
v.y += (size.y - font->height()) / 2.0f;
-
+
render::Text::draw(v.x, v.y, text);
-
+
disable(GL_TEXTURE_2D);
}
@@ -97,45 +103,45 @@ void text(math::Vector2f const &location, Font const *font, std::stringstream &
{
using namespace render::gl;
render::Text::setfont(font->name().c_str(), font->width(), font->height());
-
+
// enable OpenGL textures
enable(GL_TEXTURE_2D);
-
+
render::Text::draw(location.x, location.y, textstream);
-
+
// disable texturing
disable(GL_TEXTURE_2D);
}
void text(math::Vector2f const &location, math::Vector2f const &size,
- Font const *font,
- std::string const &text,
- unsigned int align)
+ Font const *font,
+ std::string const &text,
+ unsigned int align)
{
unsigned int align_horizontal = (align & 0x000F);
if (!align_horizontal)
align_horizontal = AlignLeft;
-
+
unsigned int align_vertical = (align & 0x00F0);
if (!align_vertical)
align_vertical = AlignTop;
-
+
// apply text font
using namespace render::gl;
render::Text::setfont(font->name().c_str(), font->width(), font->height());
-
+
// enable OpenGL textures
enable(GL_TEXTURE_2D);
-
+
// determine the width and height of the text
// FIXME support multiline text
float text_height = 1.0f * font->height();
float text_width = (float) aux::text_strip(text).size() * font->width();
-
+
// calculate drawing position
math::Vector2f v(location);
-
- switch(align_horizontal) {
+
+ switch (align_horizontal) {
case AlignLeft:
v.x += font->width();
break;
@@ -147,7 +153,7 @@ void text(math::Vector2f const &location, math::Vector2f const &size,
break;
}
- switch(align_vertical) {
+ switch (align_vertical) {
case AlignTop:
v.y += font->height()*0.5f;
break;
@@ -158,12 +164,12 @@ void text(math::Vector2f const &location, math::Vector2f const &size,
v.y += size.y - text_height - font->height()*0.5f;
break;
}
-
+
render::Text::draw(v.x, v.y, text);
-
+
// disable texturing
disable(GL_TEXTURE_2D);
-
+
}
}
diff --git a/src/ui/paint.h b/src/ui/paint.h
index 3128481..367b001 100644
--- a/src/ui/paint.h
+++ b/src/ui/paint.h
@@ -9,7 +9,8 @@
#include "ui/widget.h"
-namespace ui {
+namespace ui
+{
/// low-level widget paint functions
namespace paint {
@@ -20,6 +21,9 @@ void color(float r=0.0f, float g=0.0f, float b=0.0f, float a=1.0f);
/// set paint color
void color(math::Color const & color);
+/// set paint color
+void color_code(const char *c);
+
/// draw a border
void border(math::Vector2f const &location, math::Vector2f const &size);
@@ -30,9 +34,9 @@ void rectangle(math::Vector2f const &location, math::Vector2f const &size);
void bitmap(math::Vector2f const &location, math::Vector2f const &size, std::string const &texture);
/// draw text
-void text(math::Vector2f const &location, math::Vector2f const &size, Font const *font, std::string const &text,
- unsigned int align = AlignCenter);
-
+void text(math::Vector2f const &location, math::Vector2f const &size, Font const *font,
+ std::string const &text, unsigned int align = AlignCenter);
+
/// draw textstream
void text(math::Vector2f const &location, Font const *font, std::stringstream & textstream);
diff --git a/src/ui/palette.cc b/src/ui/palette.cc
index cb6ee91..20d1e93 100644
--- a/src/ui/palette.cc
+++ b/src/ui/palette.cc
@@ -7,14 +7,17 @@
#include "ui/palette.h"
#include "sys/sys.h"
-namespace ui {
+namespace ui
+{
Palette::Palette()
{
palette_foreground.assign(0.8f, 1.0f);
palette_highlight.assign(1.0f, 1.0f);
palette_background.assign(0.5f, 0.5f);
- palette_border.assign(0.0f, 8.0f, 0.0f);
+ palette_border.assign(0.0f, 0.8f, 0.0f);
+ palette_pointer.assign(0.0f, 0.5f, 0.0f);
+ palette_active.assign(0.0f, 1.0f, 0.0f);
}
Palette::~Palette()
@@ -41,6 +44,15 @@ void Palette::set_border(math::Color const &color)
palette_border.assign(color);
}
+void Palette::set_pointer(math::Color const &color)
+{
+ palette_pointer.assign(color);
+}
+
+void Palette::set_active(math::Color const &color)
+{
+ palette_active.assign(color);
}
+}
diff --git a/src/ui/palette.h b/src/ui/palette.h
index edd738f..9d27f95 100644
--- a/src/ui/palette.h
+++ b/src/ui/palette.h
@@ -9,7 +9,8 @@
#include "math/color.h"
-namespace ui {
+namespace ui
+{
class Palette
{
@@ -17,28 +18,50 @@ class Palette
public:
Palette();
~Palette();
-
+
void set_foreground(math::Color const &color);
-
+
void set_highlight(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 &highlight() const { return palette_highlight; }
-
- inline math::Color const &background() const { return palette_background; }
-
- inline math::Color const &border() const { return palette_border; }
-
+
+ void set_pointer(math::Color const &color);
+
+ void set_active(math::Color const &color);
+
+ inline math::Color const &foreground() const {
+ return palette_foreground;
+ }
+
+ inline math::Color const &highlight() const {
+ return palette_highlight;
+ }
+
+ inline math::Color const &background() const {
+ return palette_background;
+ }
+
+ inline math::Color const &border() const {
+ return palette_border;
+ }
+
+ inline math::Color const &pointer() const {
+ return palette_pointer;
+ }
+
+ inline math::Color const &active() const {
+ return palette_active;
+ }
+
private:
math::Color palette_foreground;
math::Color palette_highlight;
math::Color palette_background;
+ math::Color palette_pointer;
+ math::Color palette_active;
math::Color palette_border;
};
diff --git a/src/ui/ui.cc b/src/ui/ui.cc
index 8242381..8d60543 100644
--- a/src/ui/ui.cc
+++ b/src/ui/ui.cc
@@ -18,7 +18,10 @@
#include "ui/widget.h"
#include "ui/window.h"
-namespace ui {
+namespace ui
+{
+
+/* -- static functions --------------------------------------------- */
UI *global_ui = 0;
@@ -59,7 +62,7 @@ void func_ui(std::string const &args)
con_warn << "User Interface not available!" << std::endl;
return;
}
-
+
if (!args.size()) {
help();
return;
@@ -68,7 +71,7 @@ void func_ui(std::string const &args)
std::string command;
argstr >> command;
aux::to_label(command);
-
+
if (command.compare("help") == 0) {
help();
} else if (command.compare("list") == 0) {
@@ -103,28 +106,28 @@ void func_menu(std::string const &args)
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("back") == 0) {
root()->previous_window();
-
+
} else if (command.compare("previous") == 0) {
root()->previous_window();
-
+
} else if (command.compare("list") == 0) {
root()->list_menus();
} else {
@@ -132,6 +135,8 @@ void func_menu(std::string const &args)
}
}
+/* -- class UI ----------------------------------------------------- */
+
UI *root()
{
return global_ui;
@@ -140,28 +145,28 @@ UI *root()
void init()
{
con_print << "^BInitializing user interface..." << std::endl;
-
+
if (!global_ui) {
global_ui = new UI();
} else {
con_warn << "User interface already initialized!" << std::endl;
return;
}
-
+
global_ui->load();
-
+
core::Func *func = core::Func::add("list_ui", func_list_ui);
func->set_info("list user interface widgets");
-
+
func = core::Func::add("list_menu", func_list_menu);
func->set_info("list available menus");
-
+
func = core::Func::add("ui", func_ui);
func->set_info("[command] user interface functions");
-
+
func = core::Func::add("ui_restart", func_ui_restart);
func->set_info("[command] [options] reload user interface files");
-
+
func = core::Func::add("menu", func_menu);
func->set_info("[command] menu functions");
}
@@ -169,42 +174,51 @@ void init()
void shutdown()
{
con_print << "^BShutting down user interface..." << std::endl;
-
+
core::Func::remove("list_ui");
core::Func::remove("list_menu");
core::Func::remove("menu");
core::Func::remove("ui");
-
+
if (global_ui) {
delete global_ui;
global_ui = 0;
}
}
+/* -- class UI ----------------------------------------------------- */
+
UI::UI() : Window(0)
{
set_label("root");
set_size(1024, 768);
set_border(false);
-
+
// default palette
ui_palette = new Palette();
set_palette(ui_palette);
-
+
// default fonts
ui_font_small = new Font("gui", 12, 18);
ui_font_large = new Font("gui", 14, 24);
set_font(ui_font_small);
+
+ ui_mouse_focus = this;
+ ui_input_focus = this;
+ set_focus();
}
UI::~UI()
{
delete ui_palette;
-
+
delete ui_font_small;
delete ui_font_large;
}
+/*
+ remove all existing child windows and load ini/ui.ini
+*/
void UI::load()
{
Windows::iterator it;
@@ -213,47 +227,47 @@ void UI::load()
remove_child(window);
}
window_children.clear();
- ui_focus = this;
+ ui_mouse_focus = this;
ui_active_window = 0;
-
+
std::string filename("ui");
-
+
filesystem::IniFile ini;
-
+
ini.open(filename);
-
+
if (!ini.is_open()) {
con_error << "Could not open " << ini.name() << std::endl;
return;
}
-
+
std::string strval;
math::Color color;
Menu *menu = 0;
while (ini.getline()) {
-
+
if (ini.got_section()) {
-
+
//con_debug << " " << ini.name() << " [" << ini.section() << "]" << std::endl;
-
+
if (ini.got_section("ui")) {
continue;
-
+
} else if (ini.got_section("colors")) {
continue;
-
- } else {
+
+ } else {
ini.unknown_section();
continue;
}
-
+
} else if (ini.got_key()) {
-
+
//con_debug << " " << ini.name() << " " << ini.key() << "=" << ini.value() << std::endl;
-
+
if (ini.in_section("ui")) {
-
+
if (ini.got_key_string("menu", strval)) {
aux::to_label(strval);
menu = new Menu(this, strval.c_str());
@@ -262,9 +276,9 @@ void UI::load()
} else {
ini.unkown_key();
}
-
+
} else if (ini.in_section("colors")) {
-
+
if (ini.got_key_color("foreground", color)) {
ui_palette->set_foreground(color);
continue;
@@ -277,6 +291,10 @@ void UI::load()
} else if (ini.got_key_color("border", color)) {
ui_palette->set_border(color);
continue;
+ } else if (ini.got_key_color("pointer", color)) {
+ ui_palette->set_pointer(color);
+ } else if (ini.got_key_color("active", color)) {
+ ui_palette->set_active(color);
} else {
ini.unkown_key();
}
@@ -286,7 +304,7 @@ void UI::load()
con_debug << " " << ini.name() << " " << window_children.size() << " menus" << std::endl;
ini.close();
-
+
// fallback main menu
if (!find_window("main")) {
con_warn << "menu 'main' not found, using default" << std::endl;
@@ -295,7 +313,7 @@ void UI::load()
menu->add_button("Connect", "connect");
menu->add_button("Quit", "quit");
}
-
+
// fallback game menu
if (!find_window("game")) {
con_warn << "menu 'game' not found, using default" << std::endl;
@@ -306,17 +324,16 @@ void UI::load()
}
}
-void UI::list()
+void UI::list() const
{
size_t n = Widget::list(0);
con_print << n << " user interface widgets" << std::endl;
}
-void UI::list_menus()
+void UI::list_menus() const
{
- Windows::iterator it;
- for (it = window_children.begin(); it != window_children.end(); it++) {
- Window *window = (*it);
+ for (Windows::const_iterator it = window_children.begin(); it != window_children.end(); it++) {
+ const Window *window = (*it);
con_print << " " << window->label() << std::endl;
}
con_print << window_children.size() << " menus" << std::endl;
@@ -332,15 +349,16 @@ void UI::remove_window(Window *window)
{
if (ui_active_window == window) {
ui_active_window = 0;
- ui_focus = this;
+ ui_mouse_focus = this;
+ ui_input_focus = this;
}
-
+
Window::remove_window(window);
}
-Window *UI::find_window(const char *label)
+Window *UI::find_window(const char *label) const
{
- for (Windows::iterator it = window_children.begin(); it != window_children.end(); it++) {
+ for (Windows::const_iterator it = window_children.begin(); it != window_children.end(); it++) {
if ((*it)->label().compare(label) == 0) {
return (*it);
}
@@ -351,19 +369,21 @@ Window *UI::find_window(const char *label)
void UI::show_window(const char *label)
{
Window *window = find_window(label);
-
+
if (window) {
- if (ui_active_window) {
- ui_active_window->hide();
- window->set_previous(ui_active_window);
- } else {
- window->clear_previous();
- }
- ui_active_window = window;
- ui_active_window->event_resize();
- ui_active_window->raise();
- ui_active_window->show();
- ui_focus = window;
+ if (ui_active_window) {
+ ui_active_window->hide();
+ window->set_previous(ui_active_window);
+ } else {
+ window->clear_previous();
+ }
+ ui_active_window = window;
+ ui_active_window->event_resize();
+ ui_active_window->raise();
+ ui_active_window->show();
+ ui_active_window->set_focus();
+ ui_mouse_focus = this;
+ ui_input_focus = this;
} else {
con_warn << "Unknown window '" << label << "'" << std::endl;
}
@@ -390,28 +410,57 @@ void UI::previous_window()
void UI::frame()
{
- ui_focus = event_focus(mouse_cursor);
+ if (ui_active_window && !ui_active_window->visible()) {
+ ui_active_window = 0;
+ }
+
event_draw();
}
-void UI::input_mouse(float x, float y)
+/* -- global event handlers ---------------------------------------- */
+/*
+ These functions receive input events from the client input
+ subsystem and distributes them to the widget hierarchy
+*/
+void UI::input_mouse(const float x, const float y)
{
mouse_cursor.assign(x, y);
+ Widget *f = find_mouse_focus(mouse_cursor);
+ if (f) {
+ f->event_mouse(mouse_cursor);
+ }
+ ui_mouse_focus = f;
}
-void UI::input_key(bool pressed, unsigned int key, unsigned int modifier)
+void UI::input_key(const bool pressed, const int key, const unsigned int modifier)
{
- ui_focus->event_key(pressed, key, modifier);
+ if (key < 512) {
+ // keyboard keys
+ Widget *f = find_input_focus();
+ if (f) {
+ f->event_key(pressed, key, modifier);
+ }
+ ui_input_focus = f;
+ } else {
+ // mosue buttons
+ if (ui_mouse_focus)
+ ui_mouse_focus->event_key(pressed, key, modifier);
+ }
}
-bool UI::keypress(unsigned int key, unsigned int modifier)
+/* -- event handlers ----------------------------------------------- */
+/*
+ These functions handle events for this widget only. They are
+ the fallback input handlers
+*/
+bool UI::on_keypress(const int key, const unsigned int modifier)
{
- return true;
+ return true;
}
-bool UI::keyrelease(unsigned int key, unsigned int modifier)
+bool UI::on_keyrelease(const int key, const unsigned int modifier)
{
- return true;
+ return true;
}
}
diff --git a/src/ui/ui.h b/src/ui/ui.h
index a555e97..eb2d4e0 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -12,73 +12,96 @@
#include "ui/widget.h"
#include "ui/window.h"
-namespace ui {
+namespace ui
+{
-class UI : public Window {
+class UI : public Window
+{
public:
/// constructor
UI();
-
+
/// destructor
~UI();
-
+
/// list widgets
- void list();
-
+ void list() const;
+
/// list meus
- void list_menus();
-
+ void list_menus() const;
+
/// reload menu files
void load();
-
+
/// make a window the active window
void show_window(const char *label);
-
+
/// hide the active window
void hide_window();
-
+
/// show previous window
void previous_window();
-
+
/// return the active window
- Window *active() { return ui_active_window; }
-
- /// mouse cursor input
- void input_mouse(float x, float y);
-
- /// keyboard input
- void input_key(bool pressed, unsigned int key, unsigned int modifier);
-
+ Window *active() {
+ return ui_active_window;
+ }
+
+ /// return the widget with global mouse focus
+ inline Widget *mouse_focus() const {
+ return ui_mouse_focus;
+ }
+
+ /// return the widget with global input focus
+ inline Widget *input_focus() const {
+ return ui_input_focus;
+ }
+
+ /// receive global mouse movement
+ void input_mouse(const float x, const float y);
+
+ /// receive global key input
+ void input_key(const bool pressed, const int key, const unsigned int modifier);
+
/// run a user interface frame
void frame();
-
- /// return the widget which has the focus
- inline Widget *focus() { return ui_focus; }
-
- /* -- Fonts ------------------------------------------------ */
+
+ /* -- fonts ------------------------------------------------ */
+
/// default small font
- inline Font *font_small() { return ui_font_small; }
-
+ inline const Font *font_small() const {
+ return ui_font_small;
+ }
+
/// default medium font
- inline Font *font_large() { return ui_font_large; }
-
+ inline const Font *font_large() const {
+ return ui_font_large;
+ }
+
protected:
- Window *find_window(const char *label);
-
+ Window *find_window(const char *label) const;
+
virtual void add_window(Window *window);
virtual void remove_window(Window *window);
-
- /// handle keyboard input
- virtual bool keypress(unsigned int key, unsigned int modifier);
- virtual bool keyrelease(unsigned int key, unsigned int modifier);
-
+
+ /* -- event handlers --------------------------------------- */
+
+ /// handle keypress events
+ virtual bool on_keypress(const int key, const unsigned int modifier);
+
+ /// handle key release events
+ virtual bool on_keyrelease(const int key, const unsigned int modifier);
+
private:
Palette *ui_palette;
Font *ui_font_small;
Font *ui_font_large;
-
+
Window *ui_active_window;
- Widget *ui_focus;
+ Widget *ui_mouse_focus;
+ Widget *ui_input_focus;
+
+ /// TODO move to separate object to handle mouse cursor drawing
math::Vector2f mouse_cursor;
};
diff --git a/src/ui/widget.cc b/src/ui/widget.cc
index b2c436d..e17e5ab 100644
--- a/src/ui/widget.cc
+++ b/src/ui/widget.cc
@@ -10,22 +10,25 @@
#include "ui/ui.h"
#include "ui/widget.h"
-namespace ui {
+namespace ui
+{
-Widget::Widget(Widget *parent) {
+Widget::Widget(Widget *parent)
+{
+ widget_focus = false;
widget_visible = true;
widget_border = true;
widget_background = false;
widget_palette = 0;
widget_font = 0;
widget_label.assign("widget");
-
+
if (!parent) {
widget_parent = root();
} else {
widget_parent = parent;
}
-
+
if (widget_parent)
widget_parent->add_child(this);
}
@@ -33,39 +36,47 @@ Widget::Widget(Widget *parent) {
Widget::~Widget()
{
for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) {
- delete (*it);
+ delete(*it);
(*it) = 0;
}
widget_children.clear();
}
-size_t Widget::list(size_t indent)
+size_t Widget::list(const size_t indent) const
{
print(indent);
size_t n = 1;
- for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) {
+ for (Children::const_iterator it = widget_children.begin(); it != widget_children.end(); it++) {
n += (*it)->list(indent+1);
}
return n;
}
-void Widget::print(size_t indent)
+void Widget::print(const size_t indent) const
{
- std::string marker("");
- con_print << aux::pad_left(marker, indent*2) << label() << std::endl;
+ if (indent) {
+ std::string marker;
+ if (widget_focus)
+ marker.assign("^B* ^N");
+ else
+ marker.assign(" ");
+ con_print << aux::pad_left(marker, indent*2) << label() << std::endl;
+ }
}
-Palette const *Widget::palette() const {
+const Palette *Widget::palette() const
+{
if (widget_palette) {
- return widget_palette;
+ return widget_palette;
} else {
return parent()->palette();
}
}
-Font const *Widget::font() const {
+const Font *Widget::font() const
+{
if (widget_font) {
- return widget_font;
+ return widget_font;
} else {
return parent()->font();
}
@@ -75,7 +86,7 @@ void Widget::lower()
{
if (!parent())
return;
-
+
Children::iterator it = parent()->find_child(this);
if (it != parent()->children().end()) {
parent()->children().erase(it);
@@ -87,7 +98,7 @@ void Widget::raise()
{
if (!parent())
return;
-
+
Children::iterator it = parent()->find_child(this);
if (it != parent()->children().end()) {
parent()->children().erase(it);
@@ -95,6 +106,20 @@ void Widget::raise()
}
}
+void Widget::set_focus()
+{
+ if (!parent()) {
+ widget_focus = true;
+ return;
+ }
+
+ for (Children::iterator it = parent()->children().begin(); it != parent()->children().end(); it++) {
+ (*it)->widget_focus = false;
+ }
+
+ widget_focus = true;
+}
+
void Widget::show()
{
widget_visible = true;
@@ -108,7 +133,10 @@ void Widget::hide()
void Widget::set_visible(bool visible)
{
- widget_visible = visible;
+ if (visible)
+ show();
+ else
+ hide();
}
void Widget::set_border(bool border)
@@ -133,20 +161,26 @@ void Widget::set_label(char const *label)
aux::to_label(widget_label);
}
-void Widget::set_palette(Palette *palette)
+void Widget::set_palette(const Palette *palette)
{
widget_palette = palette;
}
-void Widget::set_font(Font *font)
+void Widget::set_font(const Font *font)
{
widget_font = font;
}
-void Widget::set_location(float const x, float const y) {
+void Widget::set_location(float const x, float const y)
+{
widget_location.assign(x, y);
}
+void Widget::set_location(const math::Vector2f &location)
+{
+ widget_location.assign(location);
+}
+
void Widget::set_size(float const w, float const h)
{
widget_size.assign(w, h);
@@ -173,7 +207,7 @@ Widget::Children::iterator Widget::find_child(Widget *child)
if ((*it) == child)
return it;
}
-
+
return it;
}
@@ -184,118 +218,167 @@ void Widget::add_child(Widget *child)
widget_children.push_back(child);
}
}
-
+
void Widget::remove_child(Widget *child)
{
Children::iterator it = find_child(child);
if (it != widget_children.end()) {
- delete (*it);
+ delete(*it);
widget_children.erase(it);
}
}
-void Widget::event_resize()
+Widget *Widget::find_input_focus()
{
- resize();
- for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) {
- (*it)->event_resize();
+ if (!visible() || !widget_focus)
+ return 0;
+
+ for (Children::const_reverse_iterator rit = widget_children.rbegin(); rit != widget_children.rend(); ++rit) {
+ Widget *w = (*rit);
+ if (w->visible() && w->widget_focus) {
+ Widget *f = w->find_input_focus();
+ if (f)
+ return f;
+ }
}
+
+ // no child with input focus
+ return this;
}
-void Widget::resize()
+Widget *Widget::find_mouse_focus(const math::Vector2f & pos)
{
+ // this widget is not visible
+ if (!visible() || !size().contains(pos))
+ return 0;
+
+ // reverse-iterate children
+ for (Children::const_reverse_iterator rit = widget_children.rbegin(); rit != widget_children.rend(); ++rit) {
+ Widget *w = (*rit);
+ if (w->visible()) {
+ Widget *f = w->find_mouse_focus(pos - w->location());
+ if (f)
+ return f;
+ }
+
+ }
+
+ // no child with mouse focus
+ return this;
}
-void Widget::event_draw()
+bool Widget::has_mouse_focus() const
{
- if (!widget_visible)
- return;
-
- draw();
- for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) {
- if ((*it)->visible())
- (*it)->event_draw();
- }
+ return (root()->mouse_focus() == this);
}
-void Widget::draw()
+bool Widget::has_input_focus() const
{
- draw_background();
- draw_border();
+ return (root()->input_focus() == this);
}
-void Widget::draw_background()
+/* -- event distributors ------------------------------------------- */
+
+bool Widget::event_key(const bool pressed, const int key, const unsigned int modifier)
{
- if (!widget_background)
- return;
+ bool handled = false;
+
+ if (pressed) {
+ handled = on_keypress(key, modifier);
+ } else {
+ handled = on_keyrelease(key, modifier);
+ }
+
+ if (!handled && parent())
+ handled = parent()->event_key(pressed, key, modifier);
+
+ return handled;
+}
- paint::color(palette()->background());
- paint::rectangle(global_location(), size());
+bool Widget::event_mouse(const math::Vector2f &cursor)
+{
+ math::Vector2f local_cursor = to_local_coords(cursor);
+ bool handled = false;
+
+ if (root()->mouse_focus() != this) {
+ on_mouseover(local_cursor);
+ }
+
+ on_mousemove(local_cursor);
+ return handled;
}
-void Widget::draw_border()
+void Widget::event_draw()
{
- if (!widget_border)
+ if (!visible())
return;
-
- paint::color(palette()->border());
- paint::border(global_location(), size());
+
+ draw();
+
+ for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) {
+ if ((*it)->visible())
+ (*it)->event_draw();
+ }
}
-Widget *Widget::event_focus(math::Vector2f const & pos)
+void Widget::event_resize()
{
- // this widget is not visible
- if (!visible())
- return 0;
+ resize();
+ for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) {
+ (*it)->event_resize();
+ }
+}
- // pos is outside this
- if ((pos.x < 0) || (pos.y < 0) || (pos.x > size().x) || (pos.y > size().y))
- return 0;
+/* -- event handlers ----------------------------------------------- */
- // reverse-iterate children
- for (Children::reverse_iterator rit = widget_children.rbegin(); rit != widget_children.rend(); ++rit) {
- Widget *w = (*rit);
- if (w->visible()) {
- Widget *f = w->event_focus(pos - w->location());
- if (f)
- return f;
- }
+void Widget::on_mouseover(const math::Vector2f &cursor)
+{
+ return;
+}
- }
-
- // no child has focus
- return this;
+void Widget::on_mousemove(const math::Vector2f &cursor)
+{
+ return;
}
-bool Widget::has_focus() const
+bool Widget::on_keypress(const int key, const unsigned int modifier)
{
- return (root()->focus() == this);
+ return false;
}
-bool Widget::event_key(bool pressed, unsigned int key, unsigned int modifier)
+bool Widget::on_keyrelease(const int key, const unsigned int modifier)
{
- bool handled;
+ return false;
+}
- if (pressed) {
- handled = keypress(key, modifier);
- } else {
- handled = keyrelease(key, modifier);
- }
+/* -- draw functions ----------------------------------------------- */
- if (!handled && parent())
- handled = parent()->event_key(pressed, key, modifier);
+void Widget::resize()
+{
+}
- return handled;
+void Widget::draw()
+{
+ draw_background();
+ draw_border();
}
-bool Widget::keypress(unsigned int key, unsigned int modifier)
+void Widget::draw_background()
{
- return false;
+ if (!widget_background)
+ return;
+
+ paint::color(palette()->background());
+ paint::rectangle(global_location(), size());
}
-bool Widget::keyrelease(unsigned int key, unsigned int modifier)
+void Widget::draw_border()
{
- return false;
+ if (!widget_border)
+ return;
+
+ paint::color(palette()->border());
+ paint::border(global_location(), size());
}
}
diff --git a/src/ui/widget.h b/src/ui/widget.h
index 2078134..e069220 100644
--- a/src/ui/widget.h
+++ b/src/ui/widget.h
@@ -20,199 +20,283 @@
#include "ui/definitions.h"
#include "sys/sys.h"
-namespace ui {
+namespace ui
+{
-class Widget {
+class Widget
+{
public:
/// type definition for child widgets
typedef std::list<Widget *> Children;
-
+
/// create a new widget
Widget(Widget *parent=0);
-
+
/// destroy a widget
virtual ~Widget();
-
+
+ /// parent widget this widget belongs to
+ inline Widget *parent() const {
+ return widget_parent;
+ }
+
/* -- inspectors -------------------------------------------- */
- 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 std::string const &label() const { return widget_label; }
-
- inline bool border() const { return widget_border; }
-
- inline bool background() const { return widget_background; }
-
- inline Widget *parent() const { return widget_parent; }
-
- inline bool visible() const { return widget_visible; }
-
- Palette const *palette() const;
-
- Font const *font() const;
-
- bool has_focus() const;
-
-
+ /// pixel coordinates of the top-left corner of this widget within its parent
+ inline const math::Vector2f &location() const {
+ return widget_location;
+ }
+
+ /// size of this widget in pixels
+ inline const math::Vector2f &size() const {
+ return widget_size;
+ }
+
+ /// left coordinate of location()
+ /**
+ * @see location
+ */
+ inline float left() const {
+ return widget_location.x;
+ }
+
+ /// top coordinate of location()
+ /**
+ * @see location
+ */
+ inline float top() const {
+ return widget_location.y;
+ }
+
+ /// width of the widget in pixels
+ /**
+ * @see size()
+ */
+ inline float width() const {
+ return widget_size.x;
+ }
+
+ /// height of the widget in pixels
+ /**
+ * @see size()
+ */
+ inline float height() const {
+ return widget_size.y;
+ }
+
+ /// widget label
+ inline const std::string &label() const {
+ return widget_label;
+ }
+
+ /// true if this widget will draw a background
+ inline bool background() const {
+ return widget_background;
+ }
+
+ /// true if this widget will draw a border
+ inline bool border() const {
+ return widget_border;
+ }
+
+ /// true if this widget is visible
+ inline bool visible() const {
+ return widget_visible;
+ }
+
+ /// true if this widget is not visible
+ inline bool hidden() const {
+ return !widget_visible;
+ }
+
+ /// the palette used to draw this widget
+ const Palette *palette() const;
+
+ /// the font used to draw this widget
+ const Font *font() const;
+
+ /// return true if the widget has input focus
+ bool has_input_focus() const;
+
+ /// returns true if the widget has mouse focus
+ bool has_mouse_focus() const;
+
/* -- mutators --------------------------------------------- */
-
+
/// raise the widget to the top of the widget stack
void raise();
-
+
/// lower the widget to the bottom of the widget stack
void lower();
-
+
/// show the widget
- void show();
-
+ virtual void show();
+
/// hide the widget
- void hide();
-
+ virtual void hide();
+
/// set visibility
void set_visible(bool visible = true);
-
- /// set location of the top-left corner
+
+ /// set input focus
+ void set_focus();
+
+ /// set location of the top-left corner, relative to the parent
void set_location(float const x, float const y);
-
+
+ /// set location of the top-left corner, relative to the parent
+ void set_location(const math::Vector2f &location);
+
/// set the widgets width and height
void set_size(float const w, float const h);
-
+
/// set the widgets width and height
void set_size(math::Vector2f const &size);
-
+
/// 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);
-
+ void set_palette(const Palette *palette);
+
/// set the widgets font
- void set_font(Font *font);
-
+ void set_font(const Font *font);
+
/// 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
+ void set_label(const char *label);
+
+ /// enable or disable widget border
+ void set_border(bool border = true);
+
+ ///enable or disable widget background
+ void set_background(bool background = true);
+
+ /// child widgets
+ inline Children &children() {
+ return widget_children;
+ }
+
+
+ /* -- event distributors ----------------------------------- */
+
+ /// distribute resize event
virtual void event_resize();
-
- /// draw event
+
+ /// distribute draw event
virtual void event_draw();
-
- /// keyboard event
- virtual bool event_key(bool pressed, unsigned int key, unsigned int modifier);
-
- /// find the child widget with focus
- /** @param pos local position within the widget
- */
- Widget *event_focus(math::Vector2f const & pos);
-
- /// child widgets
- inline Children &children() { return widget_children; }
-
+
+ /// distribute keyboard events
+ virtual bool event_key(const bool pressed, const int key, const unsigned int modifier);
+
+ /// distribute mouse movement events
+ virtual bool event_mouse(const math::Vector2f &cursor);
+
protected:
- /// handle keyboard events
- /** returns true if the event was handled by this widget
- */
- virtual bool keypress(unsigned int key, unsigned int modifier);
-
- /// handle keyboard events
- /** returns true if the event was handled by this widget
- */
- virtual bool keyrelease(unsigned int key, unsigned int modifier);
-
- /// 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();
-
+ /// find the widget that has input focus
+ virtual Widget *find_input_focus();
+
+ /// find widget that has mosue focus
+ /** @param cursor mouse cursor position relative to this widget's location
+ */
+ Widget *find_mouse_focus(const math::Vector2f & cursor);
+
/// list widget content
- size_t list(size_t indent);
-
+ size_t list(const size_t indent) const;
+
/// print widget description
- virtual void print(size_t indent);
-
+ virtual void print(const size_t indent) const;
+
+ /* -- coordinate mapping ----------------------------------- */
+
/// map local coordinates to global coordinates
- inline math::Vector2f to_global_coords(math::Vector2f const &local)
- {
+ inline math::Vector2f to_global_coords(const math::Vector2f &local) {
math::Vector2f v(local);
Widget *parent = widget_parent;
do {
v -= parent->location();
- parent = parent->widget_parent;
- } while(parent);
+ parent = parent->parent();
+ } while (parent);
return v;
}
-
+
/// map global coordinates to local coordinates
- inline math::Vector2f to_local_coords(math::Vector2f const &global) {
+ inline math::Vector2f to_local_coords(const math::Vector2f &global) {
math::Vector2f v(global);
Widget *parent = this;
while (parent) {
v += parent->location();
- parent = parent->widget_parent;
+ parent = parent->parent();
}
return v;
}
-
+
/// map local widget location to global location
- inline math::Vector2f global_location() const {
+ inline math::Vector2f global_location() {
math::Vector2f v(widget_location);
Widget *parent = widget_parent;
while (parent) {
v += parent->location();
- parent = parent->widget_parent;
+ parent = parent->parent();
}
return v;
}
-
- /// remove a child widget
+
+ /* -- event handlers --------------------------------------- */
+
+ /// called when the mouse receives mouse movement
+ virtual void on_mousemove(const math::Vector2f &cursor);
+
+ /// called when the mouse enters the widget
+ virtual void on_mouseover(const math::Vector2f &cursor);
+
+ /// called when the widget receives a key press
+ virtual bool on_keypress(const int key, const unsigned int modifier);
+
+ /// called when the widget receives a key release
+ virtual bool on_keyrelease(const int key, const unsigned int modifier);
+
+ /* -- draw functions --------------------------------------- */
+
+ /// resize event
+ virtual void resize();
+
+ /// draw the widget
+ virtual void draw();
+
+ /// draw the widget background
+ virtual void draw_background();
+
+ /// draw the widget border
+ virtual void draw_border();
+
+ void add_child(Widget *child);
void remove_child(Widget *child);
-
+
private:
- bool widget_visible;
- bool widget_background;
- bool widget_border;
- math::Vector2f widget_location;
- math::Vector2f widget_size;
- std::string widget_label;
+ bool widget_visible;
+ bool widget_background;
+ bool widget_border;
+ bool widget_focus;
+
+ math::Vector2f widget_location;
+ math::Vector2f widget_size;
+ std::string widget_label;
Children widget_children;
-
- Palette *widget_palette;
- Font *widget_font;
+
+ const Palette *widget_palette;
+ const Font *widget_font;
Widget *widget_parent;
Children::iterator find_child(Widget *child);
-
- void add_child(Widget *child);
+
};
}
diff --git a/src/ui/window.cc b/src/ui/window.cc
index cc9f3b5..4a60056 100644
--- a/src/ui/window.cc
+++ b/src/ui/window.cc
@@ -7,7 +7,8 @@
#include "ui/paint.h"
#include "ui/window.h"
-namespace ui {
+namespace ui
+{
Window::Window(Window *parent) : Widget(static_cast<Widget *>(parent))
{
@@ -38,7 +39,7 @@ void Window::draw_border()
{
if (!border())
return;
-
+
paint::color(palette()->foreground());
paint::border(global_location(), size());
}
@@ -50,7 +51,7 @@ Window::Windows::iterator Window::find_window(Window *window)
if ((*it) == window)
return it;
}
-
+
return it;
}
@@ -61,7 +62,7 @@ void Window::add_window(Window *window)
window_children.push_back(window);
}
}
-
+
void Window::remove_window(Window *window)
{
Windows::iterator it = find_window(window);
diff --git a/src/ui/window.h b/src/ui/window.h
index a134f04..919559f 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -9,32 +9,36 @@
#include "ui/widget.h"
-namespace ui {
+namespace ui
+{
-class Window : public Widget {
+class Window : public Widget
+{
public:
Window(Window *parent=0);
~Window();
-
+
virtual void draw_border();
-
+
/// set the label of the previous window
void set_previous(Window *previous);
/// clear the label of the previous window
void clear_previous();
-
- inline std::string const &previous() const { return window_previous; }
-
+
+ inline const std::string &previous() const {
+ return window_previous;
+ }
+
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);
-
+
/// label of the previous window that got activated
/** This label is used to implement the 'menu previous'
* command