diff options
author | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2009-04-07 23:47:57 +0200 |
---|---|---|
committer | Bjørn Lindeijer <bjorn@lindeijer.nl> | 2009-04-07 23:52:46 +0200 |
commit | d69d85f06fa6dc22ac4c7789e4140e32d119a7f1 (patch) | |
tree | 1d2311bfdba616136d0ac26f8cbe9ab73c88f0e4 /src/gui/browserbox.cpp | |
parent | 303c1f69761e90b83d4809e911f7785ec66b46aa (diff) | |
download | mana-client-d69d85f06fa6dc22ac4c7789e4140e32d119a7f1.tar.gz mana-client-d69d85f06fa6dc22ac4c7789e4140e32d119a7f1.tar.bz2 mana-client-d69d85f06fa6dc22ac4c7789e4140e32d119a7f1.tar.xz mana-client-d69d85f06fa6dc22ac4c7789e4140e32d119a7f1.zip |
Moved basic widgets into the gui/widgets directory
In an attempt to make the GUI code a little more structured, basic
widgets are now put in gui/widgets. Many includes were also cleaned up.
Diffstat (limited to 'src/gui/browserbox.cpp')
-rw-r--r-- | src/gui/browserbox.cpp | 417 |
1 files changed, 0 insertions, 417 deletions
diff --git a/src/gui/browserbox.cpp b/src/gui/browserbox.cpp deleted file mode 100644 index 0240b67b..00000000 --- a/src/gui/browserbox.cpp +++ /dev/null @@ -1,417 +0,0 @@ -/* - * The Mana World - * Copyright (C) 2004 The Mana World Development Team - * - * This file is part of The Mana World. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <algorithm> - -#include <guichan/graphics.hpp> - -#include "browserbox.h" -#include "linkhandler.h" -#include "palette.h" -#include "truetypefont.h" - -BrowserBox::BrowserBox(unsigned int mode, bool opaque): - gcn::Widget(), - mMode(mode), mHighMode(UNDERLINE | BACKGROUND), - mOpaque(opaque), - mUseLinksAndUserColors(true), - mSelectedLink(-1), - mMaxRows(0) -{ - setFocusable(true); - addMouseListener(this); -} - -BrowserBox::~BrowserBox() -{ -} - -void BrowserBox::setLinkHandler(LinkHandler* linkHandler) -{ - mLinkHandler = linkHandler; -} - -void BrowserBox::setOpaque(bool opaque) -{ - mOpaque = opaque; -} - -void BrowserBox::setHighlightMode(unsigned int highMode) -{ - mHighMode = highMode; -} - -void BrowserBox::disableLinksAndUserColors() -{ - mUseLinksAndUserColors = false; -} - -void BrowserBox::addRow(const std::string &row) -{ - std::string tmp = row; - std::string newRow; - BROWSER_LINK bLink; - int idx1, idx2, idx3; - TrueTypeFont *font = static_cast<TrueTypeFont*>(getFont()); - - // Use links and user defined colors - if (mUseLinksAndUserColors) - { - // Check for links in format "@@link|Caption@@" - idx1 = tmp.find("@@"); - while (idx1 >= 0) - { - idx2 = tmp.find("|", idx1); - idx3 = tmp.find("@@", idx2); - bLink.link = tmp.substr(idx1 + 2, idx2 - (idx1 + 2)); - bLink.caption = tmp.substr(idx2 + 1, idx3 - (idx2 + 1)); - bLink.y1 = mTextRows.size() * font->getHeight(); - bLink.y2 = bLink.y1 + font->getHeight(); - - newRow += tmp.substr(0, idx1); - - std::string tmp2 = newRow; - idx1 = tmp2.find("##"); - while (idx1 >= 0) - { - tmp2.erase(idx1, 3); - idx1 = tmp2.find("##"); - } - bLink.x1 = font->getWidth(tmp2) - 1; - bLink.x2 = bLink.x1 + font->getWidth(bLink.caption) + 1; - - mLinks.push_back(bLink); - - newRow += "##<" + bLink.caption; - - tmp.erase(0, idx3 + 2); - if (!tmp.empty()) - { - newRow += "##>"; - } - idx1 = tmp.find("@@"); - } - - newRow += tmp; - } - - // Don't use links and user defined colors - else - { - newRow = row; - } - - mTextRows.push_back(newRow); - - //discard older rows when a row limit has been set - if (mMaxRows > 0) - { - while (mTextRows.size() > mMaxRows) - { - mTextRows.pop_front(); - for (unsigned int i = 0; i < mLinks.size(); i++) - { - mLinks[i].y1 -= font->getHeight(); - mLinks[i].y2 -= font->getHeight(); - - if (mLinks[i].y1 < 0) - mLinks.erase(mLinks.begin() + i); - } - } - } - - // Auto size mode - if (mMode == AUTO_SIZE) - { - std::string plain = newRow; - for (idx1 = plain.find("##"); idx1 >= 0; idx1 = plain.find("##")) - plain.erase(idx1, 3); - - // Adjust the BrowserBox size - int w = font->getWidth(plain); - if (w > getWidth()) - setWidth(w); - } - - if (mMode == AUTO_WRAP) - { - unsigned int y = 0; - unsigned int nextChar; - const char *hyphen = "~"; - int hyphenWidth = font->getWidth(hyphen); - int x = 0; - - for (TextRowIterator i = mTextRows.begin(); i != mTextRows.end(); i++) - { - std::string row = *i; - for (unsigned int j = 0; j < row.size(); j++) - { - std::string character = row.substr(j, 1); - x += font->getWidth(character); - nextChar = j + 1; - - // Wraping between words (at blank spaces) - if ((nextChar < row.size()) && (row.at(nextChar) == ' ')) - { - int nextSpacePos = row.find(" ", (nextChar + 1)); - if (nextSpacePos <= 0) - { - nextSpacePos = row.size() - 1; - } - int nextWordWidth = font->getWidth( - row.substr(nextChar, - (nextSpacePos - nextChar))); - - if ((x + nextWordWidth + 10) > getWidth()) - { - x = 15; // Ident in new line - y += 1; - j++; - } - } - // Wrapping looong lines (brutal force) - else if ((x + 2 * hyphenWidth) > getWidth()) - { - x = 15; // Ident in new line - y += 1; - } - } - } - - setHeight(font->getHeight() * (mTextRows.size() + y)); - } - else - { - setHeight(font->getHeight() * mTextRows.size()); - } -} - -void BrowserBox::clearRows() -{ - mTextRows.clear(); - mLinks.clear(); - setWidth(0); - mSelectedLink = -1; -} - -struct MouseOverLink -{ - MouseOverLink(int x, int y) : mX(x),mY(y) { } - bool operator() (BROWSER_LINK &link) - { - return (mX >= link.x1 && mX < link.x2 && - mY >= link.y1 && mY < link.y2); - } - int mX, mY; -}; - -void BrowserBox::mousePressed(gcn::MouseEvent &event) -{ - if (!mLinkHandler) return; - LinkIterator i = find_if(mLinks.begin(), mLinks.end(), - MouseOverLink(event.getX(), event.getY())); - - if (i != mLinks.end()) { - mLinkHandler->handleLink(i->link); - } -} - -void BrowserBox::mouseMoved(gcn::MouseEvent &event) -{ - LinkIterator i = find_if(mLinks.begin(), mLinks.end(), - MouseOverLink(event.getX(), event.getY())); - - mSelectedLink = (i != mLinks.end()) ? (i - mLinks.begin()) : -1; -} - -void BrowserBox::draw(gcn::Graphics *graphics) -{ - if (mOpaque) - { - graphics->setColor(guiPalette->getColor(Palette::BACKGROUND)); - graphics->fillRectangle(gcn::Rectangle(0, 0, getWidth(), getHeight())); - } - - if (mSelectedLink >= 0) - { - if ((mHighMode & BACKGROUND)) - { - graphics->setColor(guiPalette->getColor(Palette::HIGHLIGHT)); - graphics->fillRectangle(gcn::Rectangle( - mLinks[mSelectedLink].x1, - mLinks[mSelectedLink].y1, - mLinks[mSelectedLink].x2 - mLinks[mSelectedLink].x1, - mLinks[mSelectedLink].y2 - mLinks[mSelectedLink].y1 - )); - } - - if ((mHighMode & UNDERLINE)) - { - graphics->setColor(guiPalette->getColor(Palette::HYPERLINK)); - graphics->drawLine( - mLinks[mSelectedLink].x1, - mLinks[mSelectedLink].y2, - mLinks[mSelectedLink].x2, - mLinks[mSelectedLink].y2); - } - } - - int x = 0, y = 0; - int wrappedLines = 0; - int link = 0; - TrueTypeFont *font = static_cast<TrueTypeFont*>(getFont()); - - graphics->setColor(guiPalette->getColor(Palette::TEXT)); - for (TextRowIterator i = mTextRows.begin(); i != mTextRows.end(); i++) - { - const gcn::Color *selColor = &guiPalette->getColor(Palette::TEXT); - const gcn::Color *prevColor = selColor; - std::string row = *(i); - bool wrapped = false; - x = 0; - - // Check for separator lines - if (row.find("---", 0) == 0) - { - for (x = 0; x < getWidth(); x++) - { - font->drawString(graphics, "-", x, y); - x += font->getWidth("-") - 2; - } - y += font->getHeight(); - continue; - } - - // TODO: Check if we must take texture size limits into account here - // TODO: Check if some of the O(n) calls can be removed - for (std::string::size_type start = 0, end = std::string::npos; - start != std::string::npos; - start = end, end = std::string::npos) - { - // Wrapped line continuation shall be indented - if (wrapped) - { - y += font->getHeight(); - x = 15; - } - - // "Tokenize" the string at control sequences - if (mUseLinksAndUserColors) - end = row.find("##", start + 1); - - if (mUseLinksAndUserColors || - (!mUseLinksAndUserColors && (start == 0))) - { - // Check for color change in format "##x", x = [L,P,0..9] - if (row.find("##", start) == start && row.size() > start + 2) - { - char c = row.at(start + 2); - if (c == '>') - { - selColor = prevColor; - } - else - { - bool valid; - const gcn::Color *col = &guiPalette->getColor(c, valid); - if (c == '<') - { - const int size = mLinks[link].x2 - mLinks[link].x1; - mLinks[link].x1 = x; - mLinks[link].y1 = y; - mLinks[link].x2 = mLinks[link].x1 + size; - mLinks[link].y2 = y + font->getHeight(); - link++; - prevColor = selColor; - } - if (valid) - { - selColor = col; - } - } - start += 3; - - if (start == row.size()) - { - break; - } - } - graphics->setColor(*selColor); - } - - std::string::size_type len = - end == std::string::npos ? end : end - start; - std::string part = row.substr(start, len); - - // Auto wrap mode - if (mMode == AUTO_WRAP && - (x + font->getWidth(part.c_str()) + 10) > getWidth()) - { - bool forced = false; - char const *hyphen = "~"; - int hyphenWidth = font->getWidth(hyphen); - - /* FIXME: This code layout makes it easy to crash remote - clients by talking garbage. Forged long utf-8 characters - will cause either a buffer underflow in substr or an - infinite loop in the main loop. */ - do - { - if (!forced) - end = row.rfind(" ", end); - - // Check if we have to (stupidly) force-wrap - if (end == std::string::npos || end <= start) - { - forced = true; - end = row.size(); - x += hyphenWidth * 2; // Account for the wrap-notifier - continue; - } - - // Skip to the start of the current character - while ((row[end] & 192) == 128) - end--; - end--; // And then to the last byte of the previous one - - part = row.substr(start, end - start + 1); - } while ((x + font->getWidth(part.c_str()) + 10) > getWidth()); - - if (forced) - { - x -= hyphenWidth; // Remove the wrap-notifier accounting - font->drawString(graphics, hyphen, - getWidth() - hyphenWidth, y); - end++; // Skip to the next character - } - else - end += 2; // Skip to after the space - - wrapped = true; - wrappedLines++; - } - font->drawString(graphics, part, x, y); - x += font->getWidth(part.c_str()); - } - y += font->getHeight(); - setHeight((mTextRows.size() + wrappedLines) * font->getHeight()); - } -} |