/* ui/inputbox.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/definitions.h" #include "ui/inputbox.h" #include "ui/paint.h" #include "auxiliary/functions.h" #include "math/functions.h" #include "core/application.h" namespace ui { InputBox::InputBox(Widget *parent) : Widget(parent) { _text.clear(); _pos = 0; _max = 512; set_label("input"); set_background(false); set_border(false); set_alignment(AlignLeft | AlignTop); } InputBox::~InputBox() { } void InputBox::clear() { _text.clear(); _pos = 0; } void InputBox::set_text(std::string const &text) { _text.assign(text); _pos = _text.size(); } void InputBox::set_text(const char *text) { if (text) _text.assign(text); else _text.clear(); _pos = _text.size(); } void InputBox::set_prompt(const std::string &prompt) { _prompt.assign(prompt); } void InputBox::set_prompt(const char *prompt) { if (!prompt) _prompt.clear(); else _prompt.assign(prompt); } void InputBox::set_max(const size_t max) { _max = max; } void InputBox::set_alignment(const unsigned int alignment) { _alignment = alignment; } void InputBox::draw() { size_t text_width = (size_t) floorf(width() / font()->width()); size_t prompt_width = aux::text_length(_prompt); math::Vector2f v(global_location()); Paint::set_color(palette()->text()); // Horizontal alignment // FIXME horizontal alignment is not supported // Vertical alignment if (alignment() & ui::AlignVCenter) { v.get_y() += (height() - font()->height()) * 0.5f; } else if (alignment() & ui::AlignBottom) { v.get_y() += height() - font()->height(); } // draw the prompt if (prompt_width) { Paint::draw_text(v, font(), _prompt); v[0] += prompt_width * font()->width(); } Paint::set_color(palette()->text()); // draw the part before the cursor std::string firstpart(_text.substr(0, _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 - prompt_width - 1) { if (aux::is_color_code(c)) { c++; Paint::set_system_color(*c); } else { draw_width--; } c++; } if (*c) { Paint::draw_text(v, font(), std::string(c)); } // draw the part behind the cursor v[0] += draw_width * font()->width(); if (_pos < _text.size()) { if (_pos > 1 && aux::is_color_code(_text.c_str() + _pos - 1)) { Paint::set_system_color(_text[_pos]); } // limit to width std::string secondpart; c = &_text.c_str()[_pos]; while (*c && (draw_width <= (text_width - prompt_width - 1))) { if (aux::is_color_code(c)) { c++; } else { draw_width++; secondpart += *c; } c++; } Paint::draw_text(v, font(), secondpart); } // draw the cursor if (has_input_focus() && (core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { std::string cursor("^B"); cursor += (char) 11; Paint::draw_text(v, font(), cursor); } // reset color Paint::set_color(palette()->foreground()); } void InputBox::complete() { core::CommandBuffer::complete(_text, _pos); } bool InputBox::on_keypress(const int key, const unsigned int modifier) { switch (key) { case SDLK_HOME: _pos = 0; return true; break; case SDLK_END: _pos = _text.size(); return true; break; case SDLK_LEFT: if (_pos > 0) _pos--; return true; break; case SDLK_RIGHT: if (_pos < _text.size()) _pos++; return true; break; case SDLK_DELETE: if (_text.size() && _pos < _text.size()) { _text.erase(_pos, 1); } return true; break; case SDLK_BACKSPACE: if (_text.size() && _pos) { _text.erase(_pos - 1, 1); _pos--; } return true; break; default: if ((key >= 32) && (key < 175)) { if (_text.size() < _max) { // TODO bell sound if (_pos == _text.size()) _text += (char)key; else _text.insert(_pos, 1, (char)key); _pos++; } return true; } break; } return false; } bool InputBox::on_keyrelease(const int key, const unsigned int modifier) { return false; } bool InputBox::on_mousepress(const unsigned int button) { if (button == SDL_BUTTON_LEFT) { set_focus(); return true; } return false; } }