]> icculus.org git repositories - mikachu/openbox.git/blob - otk/label.cc
dont wrap pointerassassin
[mikachu/openbox.git] / otk / label.cc
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 2; -*-
2
3 #include "config.h"
4
5 #include "label.hh"
6 #include "display.hh"
7 #include "rendercontrol.hh"
8
9 #include <string>
10
11 namespace otk {
12
13 Label::Label(Widget *parent)
14   : Widget(parent),
15     _text(""),
16     _font(0),
17     _justify_horz(RenderStyle::LeftTopJustify),
18     _justify_vert(RenderStyle::LeftTopJustify),
19     _highlight(false)
20 {
21   styleChanged(*RenderStyle::style(screen()));
22 }
23
24 Label::~Label()
25 {
26 }
27
28 void Label::setHorizontalJustify(RenderStyle::Justify j)
29 {
30   _justify_horz = j;
31   refresh();
32 }
33
34 void Label::setVerticalJustify(RenderStyle::Justify j)
35 {
36   _justify_vert = j;
37   refresh();
38 }
39
40 void Label::setHighlighted(bool h)
41 {
42   _highlight = h;
43   styleChanged(*RenderStyle::style(screen()));
44   refresh();
45 }
46
47 void Label::setText(const ustring &text)
48 {
49   bool utf = text.utf8();
50   std::string s = text.c_str(); // use a normal string, for its functionality
51
52   _parsedtext.clear();
53   _text = text;
54   
55   // parse it into multiple lines
56   std::string::size_type p = 0;
57   while (p != std::string::npos) {
58     std::string::size_type p2 = s.find('\n', p);
59     std::string s(s.substr(p, (p2==std::string::npos?p2:p2-p)));
60
61     // turn tabs into spaces (multiples of 8)
62     std::string::size_type t;
63     while ((t = s.find('\t')) != std::string::npos)
64       s.replace(t, 1, std::string(8 - t % 8, ' '));
65
66     _parsedtext.push_back(s);
67     _parsedtext.back().setUtf8(utf);
68     p = (p2==std::string::npos?p2:p2+1);
69   }
70   calcDefaultSizes();
71 }
72
73 void Label::setFont(const Font *f)
74 {
75   _font = f;
76   calcDefaultSizes();
77 }
78
79 void Label::calcDefaultSizes()
80 {
81   int longest = 0;
82   // find the longest line
83   std::vector<ustring>::iterator it, end = _parsedtext.end();
84   for (it = _parsedtext.begin(); it != end; ++it) {
85     int length = _font->measureString(*it);
86     if (length < 0) continue; // lines too long get skipped
87     if (length > longest) longest = length;
88   }
89   setMinSize(Size(longest + borderWidth() * 2 + bevel() * 4,
90                   _parsedtext.size() * _font->height() + borderWidth() * 2 +
91                   bevel() * 2));
92 }
93   
94 void Label::styleChanged(const RenderStyle &style)
95 {
96   if (_highlight) {
97     _texture = style.labelFocusBackground();
98     _forecolor = style.textFocusColor();
99   } else {
100     _texture = style.labelUnfocusBackground();
101     _forecolor = style.textUnfocusColor();
102   }
103   if (_font != style.labelFont()) {
104     _font = style.labelFont();
105     calcDefaultSizes();
106   }
107 }
108
109 void Label::renderForeground(Surface &surface)
110 {
111   const RenderControl *control = display->renderControl(screen());
112   int sidemargin = bevel() * 2;
113   int y = bevel();
114   int w = area().width() - borderWidth() * 2 - sidemargin * 2;
115   int h = area().height() - borderWidth() * 2 - bevel() * 2;
116
117   switch (_justify_vert) {
118   case RenderStyle::RightBottomJustify:
119     y += h - (_parsedtext.size() * _font->height());
120     if (y < bevel()) y = bevel();
121     break;
122   case RenderStyle::CenterJustify:
123     y += (h - (_parsedtext.size() * _font->height())) / 2;
124     if (y < bevel()) y = bevel();
125     break;
126   case RenderStyle::LeftTopJustify:
127     break;
128   }
129   
130   if (w <= 0) return; // can't fit anything
131   
132   std::vector<ustring>::iterator it, end = _parsedtext.end();
133   for (it = _parsedtext.begin(); it != end; ++it, y += _font->height()) {
134     ustring t = *it; // the actual text to draw
135     int x = sidemargin;    // x coord for the text
136
137     // find a string that will fit inside the area for text
138     ustring::size_type text_len = t.size();
139     int length;
140       
141     do {
142       t.resize(text_len);
143       length = _font->measureString(t);
144     } while (length > w && text_len-- > 0);
145     if (length < 0) continue; // lines too long get skipped
146
147     if (text_len <= 0) continue; // won't fit anything
148
149     // justify the text
150     switch (_justify_horz) {
151     case RenderStyle::RightBottomJustify:
152       x += w - length;
153       break;
154     case RenderStyle::CenterJustify:
155       x += (w - length) / 2;
156       break;
157     case RenderStyle::LeftTopJustify:
158       break;
159     }
160  
161     control->drawString(surface, *_font, x, y, *_forecolor, t);
162  }
163 }
164
165 }