/* ui/scrollpane.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include #include "ui/scrollpane.h" #include "render/text.h" #include "render/gl.h" namespace ui { ScrollPane::ScrollPane(Widget *parent, ui::Text &text) : Widget(parent), scrollpane_text(text) { set_label("scrollpane"); set_alignment(AlignBottom); scrollpane_scroll = 0; scrollpane_offset = 1; } ScrollPane::~ScrollPane() { } void ScrollPane::set_alignment(const unsigned int alignment) { scrollpane_alignment = alignment; } void ScrollPane::set_scroll(const int scroll) { scrollpane_scroll = scroll; if (scrollpane_scroll > (int) scrollpane_text.size()) scrollpane_scroll = (int) scrollpane_text.size(); else if (scrollpane_scroll < 0) scrollpane_scroll = 0; } void ScrollPane::inc_scroll(const int scroll) { scrollpane_scroll += scroll; if (scrollpane_scroll > (int) scrollpane_text.size()) scrollpane_scroll = (int) scrollpane_text.size(); else if (scrollpane_scroll < 0) scrollpane_scroll = 0; } void ScrollPane::dec_scroll(const int scroll) { scrollpane_scroll -= scroll; if (scrollpane_scroll > (int) scrollpane_text.size()) scrollpane_scroll = (int) scrollpane_text.size(); else if (scrollpane_scroll < 0) scrollpane_scroll = 0; } void ScrollPane::set_offset(const int offset) { scrollpane_offset = offset; } bool ScrollPane::on_mousewheel(const math::Vector2f & direction) { // number of lines to scroll int alignmentmodifier =( (alignment() & AlignTop) == AlignTop) ? -1 : 1; if (direction.y() > 0 ) { inc_scroll(alignmentmodifier * scrollpane_offset); return true; } else if (direction.y() < 0 ) { dec_scroll(alignmentmodifier * scrollpane_offset); return true; } return false; } void ScrollPane::draw() { render::Text::setfont(font()->name().c_str(), font()->width(), font()->height()); gl::enable(GL_TEXTURE_2D); // text size int text_height = (int) floorf(height() / font()->height()); int text_width = (int) floorf(width() / font()->width()); // validate scroll position if (scrollpane_scroll > (int) scrollpane_text.size()) scrollpane_scroll = (int) scrollpane_text.size(); else if (scrollpane_scroll < 0) scrollpane_scroll = 0; int bottom = 0; int current_line = 0; if ((alignment() & AlignTop) == AlignTop) { bottom = text_height + (int) scrollpane_scroll; } else { bottom = (int) scrollpane_text.size() - scrollpane_scroll; } ui::Text lines; for (ui::Text::const_iterator it = scrollpane_text.begin(); it != scrollpane_text.end() && current_line < bottom; it++) { if (current_line >= bottom - text_height) { std::string linedata(*it); linedata += '\n'; std::string word; size_t word_length = 0; std::string line; size_t line_length = 0; const char *c = linedata.c_str(); char pen = 'N'; char wordpen = 'N'; while (*c) { // color code if (aux::is_color_code(c)) { c++; pen = *c; word += '^'; word += pen; } // new word, wrap if necessary else if ((*c == '\n') || (*c == ' ')) { if (line_length + word_length > (size_t) text_width) { if (line.size()) { lines.push_back(line); line.clear(); line += '^'; line += wordpen; line_length = 0; } } line.append(word); line_length += word_length; word.clear(); word_length = 0; wordpen = pen; // new line if (*c == '\n') { lines.push_back(line); line.clear(); line_length = 0; pen = 'N'; wordpen = 'N'; // new word } else if (*c == ' ') { line += ' '; line_length++; } } // new character else { word += *c; word_length++; if (word_length == (size_t) text_width) { if (line.size()) { lines.push_back(line); line.clear(); line += '^'; line += wordpen; line_length = 0; } line.append(word); line_length = word_length; word.clear(); word_length = 0; wordpen = pen; } } c++; } } current_line++; } gl::color(palette()->text()); const math ::Vector2f gl(global_location()); float y = 0; if ((alignment() & AlignTop) == AlignTop) { for (ui::Text::iterator it = lines.begin(); (y + font()->height() < height()) && (it != lines.end()); it++) { render::Text::draw(gl.x(), gl.y() + y, (*it)); y += font()->height(); } } else { y = height() - font()->height(); for (ui::Text::reverse_iterator rit = lines.rbegin(); (y >= 0) && (rit != lines.rend()); ++rit) { render::Text::draw(gl.x(), gl.y() + y, (*rit)); y -= font()->height(); } } gl::disable(GL_TEXTURE_2D); } }