X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=otk%2Flabel.cc;h=8ec03dd9b805b361408d57d306c1983e3864fd99;hb=7f590e53607ef1592d65a425b9cdcaa181912465;hp=8c429dba92157bc962b0362c9eefe52369cc3b47;hpb=d8d9b42777ace234f3471918e1210062578f8188;p=chaz%2Fopenbox diff --git a/otk/label.cc b/otk/label.cc index 8c429dba..8ec03dd9 100644 --- a/otk/label.cc +++ b/otk/label.cc @@ -1,67 +1,176 @@ // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*- -#ifdef HAVE_CONFIG_H -# include "../config.h" -#endif +#include "config.h" #include "label.hh" +#include "display.hh" +#include "rendercontrol.hh" + +#include namespace otk { +Label::Label(int screen, EventDispatcher *ed, int bevel) + : Widget(screen, ed, Widget::Horizontal, bevel, true), + _text(""), + _font(0), + _justify_horz(RenderStyle::LeftTopJustify), + _justify_vert(RenderStyle::LeftTopJustify), + _highlight(false) +{ + styleChanged(*RenderStyle::style(screen)); +} + Label::Label(Widget *parent) - : Widget(parent), _text("") + : Widget(parent), + _text(""), + _font(0), + _justify_horz(RenderStyle::LeftTopJustify), + _justify_vert(RenderStyle::LeftTopJustify), + _highlight(false) { + styleChanged(*RenderStyle::style(screen())); } Label::~Label() { } -void Label::setStyle(Style *style) +void Label::setHorizontalJustify(RenderStyle::Justify j) { - Widget::setStyle(style); + _justify_horz = j; + refresh(); +} - // XXX: do this again - //setTexture(style->getLabelUnfocus()); +void Label::setVerticalJustify(RenderStyle::Justify j) +{ + _justify_vert = j; + refresh(); } +void Label::setHighlighted(bool h) +{ + _highlight = h; + styleChanged(*RenderStyle::style(screen())); + refresh(); +} -void Label::renderForeground(void) +void Label::setText(const ustring &text) { - const Font *ft = style()->getFont(); - unsigned int sidemargin = style()->getBevelWidth() * 2; + bool utf = text.utf8(); + std::string s = text.c_str(); // use a normal string, for its functionality - ustring t = _text; // the actual text to draw - int x = sidemargin; // x coord for the text + _parsedtext.clear(); + _text = text; + + // parse it into multiple lines + std::string::size_type p = 0; + while (p != std::string::npos) { + std::string::size_type p2 = s.find('\n', p); + std::string s(s.substr(p, (p2==std::string::npos?p2:p2-p))); + + // turn tabs into spaces (multiples of 8) + std::string::size_type t; + while ((t = s.find('\t')) != std::string::npos) + s.replace(t, 1, std::string(8 - t % 8, ' ')); + + _parsedtext.push_back(s); + _parsedtext.back().setUtf8(utf); + p = (p2==std::string::npos?p2:p2+1); + } + calcDefaultSizes(); +} + +void Label::setFont(const Font *f) +{ + _font = f; + calcDefaultSizes(); +} - // find a string that will fit inside the area for text - int max_length = width() - sidemargin * 2; - if (max_length <= 0) { - t = ""; // can't fit anything +void Label::calcDefaultSizes() +{ + int longest = 0; + // find the longest line + std::vector::iterator it, end = _parsedtext.end(); + for (it = _parsedtext.begin(); it != end; ++it) { + int length = _font->measureString(*it); + if (length < 0) continue; // lines too long get skipped + if (length > longest) longest = length; + } + setMinSize(Size(longest + borderWidth() * 2 + bevel() * 4, + _parsedtext.size() * _font->height() + borderWidth() * 2 + + bevel() * 2)); +} + +void Label::styleChanged(const RenderStyle &style) +{ + if (_highlight) { + _texture = style.labelFocusBackground(); + _forecolor = style.textFocusColor(); } else { - size_t text_len = t.size(); + _texture = style.labelUnfocusBackground(); + _forecolor = style.textUnfocusColor(); + } + if (_font != style.labelFont()) { + _font = style.labelFont(); + calcDefaultSizes(); + } +} + +void Label::renderForeground(Surface &surface) +{ + const RenderControl *control = display->renderControl(screen()); + int sidemargin = bevel() * 2; + int y = bevel(); + int w = area().width() - borderWidth() * 2 - sidemargin * 2; + int h = area().height() - borderWidth() * 2 - bevel() * 2; + + switch (_justify_vert) { + case RenderStyle::RightBottomJustify: + y += h - (_parsedtext.size() * _font->height()); + if (y < bevel()) y = bevel(); + break; + case RenderStyle::CenterJustify: + y += (h - (_parsedtext.size() * _font->height())) / 2; + if (y < bevel()) y = bevel(); + break; + case RenderStyle::LeftTopJustify: + break; + } + + if (w <= 0) return; // can't fit anything + + std::vector::iterator it, end = _parsedtext.end(); + for (it = _parsedtext.begin(); it != end; ++it, y += _font->height()) { + ustring t = *it; // the actual text to draw + int x = sidemargin; // x coord for the text + + // find a string that will fit inside the area for text + ustring::size_type text_len = t.size(); int length; do { t.resize(text_len); - length = ft->measureString(t); - } while (length > max_length && text_len-- > 0); + length = _font->measureString(t); + } while (length > w && text_len-- > 0); + if (length < 0) continue; // lines too long get skipped + + if (text_len <= 0) continue; // won't fit anything // justify the text - switch (style()->textJustify()) { - case Style::RightJustify: - x += max_length - length; + switch (_justify_horz) { + case RenderStyle::RightBottomJustify: + x += w - length; break; - case Style::CenterJustify: - x += (max_length - length) / 2; + case RenderStyle::CenterJustify: + x += (w - length) / 2; break; - case Style::LeftJustify: + case RenderStyle::LeftTopJustify: break; } - } - - display->renderControl(_screen)-> - drawString(_surface, *ft, x, 0, *style()->getTextUnfocus(), t); + + control->drawString(surface, *_font, x, y, *_forecolor, t); + } } }