]> Dogcows Code - chaz/openbox/blobdiff - otk/label.cc
layout fixes, give widgets a default texture, etc.
[chaz/openbox] / otk / label.cc
index ceb6a49cc2a9cf7c082f585741f7d8b34d73deb8..587e321250300a287153bcbd7fcc080b5814e8a1 100644 (file)
 // -*- 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 <string>
 
 namespace otk {
 
-OtkLabel::OtkLabel(OtkWidget *parent)
-  : OtkWidget(parent), _text("")
+Label::Label(Widget *parent)
+  : Widget(parent),
+    _text(""),
+    _justify_horz(RenderStyle::LeftTopJustify),
+    _justify_vert(RenderStyle::LeftTopJustify),
+    _highlight(false)
 {
-  const ScreenInfo *info = OBDisplay::screenInfo(getScreen());
-  _xftdraw = XftDrawCreate(OBDisplay::display, getWindow(), info->getVisual(),
-                           info->getColormap());
+  styleChanged(*RenderStyle::style(screen()));
 }
 
-OtkLabel::~OtkLabel()
+Label::~Label()
 {
-  XftDrawDestroy(_xftdraw);
 }
 
-void OtkLabel::setStyle(Style *style)
+void Label::setHorizontalJustify(RenderStyle::Justify j)
 {
-  OtkWidget::setStyle(style);
+  _justify_horz = j;
+  refresh();
+}
 
-  setTexture(getStyle()->getLabelUnfocus());
+void Label::setVerticalJustify(RenderStyle::Justify j)
+{
+  _justify_vert = j;
+  refresh();
 }
 
+void Label::setHighlighted(bool h)
+{
+  _highlight = h;
+  styleChanged(*RenderStyle::style(screen()));
+  refresh();
+}
 
-void OtkLabel::update(void)
+void Label::setText(const ustring &text)
 {
-  if (_dirty) {
-    const BFont &ft = getStyle()->getFont();
-    unsigned int sidemargin = getStyle()->getBevelWidth() * 2;
+  bool utf = text.utf8();
+  std::string s = text.c_str(); // use a normal string, for its functionality
+
+  _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)));
 
-    std::string t = _text; // the actual text to draw
+    // 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();
+}
+
+void Label::calcDefaultSizes()
+{
+  int longest = 0;
+  // find the longest line
+  std::vector<ustring>::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 {
+    _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<ustring>::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
-    int max_length = width() - sidemargin * 2;
-    if (max_length <= 0) {
-      t = ""; // can't fit anything
-    } else {
-      size_t text_len = t.size();
-      int length;
+    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);
-
-      // justify the text
-      switch (getStyle()->textJustify()) {
-      case Style::RightJustify:
-        x += max_length - length;
-        break;
-      case Style::CenterJustify:
-        x += (max_length - length) / 2;
-        break;
-      case Style::LeftJustify:
-        break;
-      }
-    }
+    do {
+      t.resize(text_len);
+      length = _font->measureString(t);
+    } while (length > w && text_len-- > 0);
+    if (length < 0) continue; // lines too long get skipped
 
-    OtkWidget::update();
+    if (text_len <= 0) continue; // won't fit anything
 
-    ft.drawString(_xftdraw, x, 0, *getStyle()->getTextUnfocus(), t);
-  } else
-    OtkWidget::update();
+    // justify the text
+    switch (_justify_horz) {
+    case RenderStyle::RightBottomJustify:
+      x += w - length;
+      break;
+    case RenderStyle::CenterJustify:
+      x += (w - length) / 2;
+      break;
+    case RenderStyle::LeftTopJustify:
+      break;
+    }
+    control->drawString(surface, *_font, x, y, *_forecolor, t);
+ }
 }
 
 }
This page took 0.028788 seconds and 4 git commands to generate.