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