]> icculus.org git repositories - mikachu/openbox.git/blob - otk/style.cc
HOOGE improvements. now widgets calculate their size according to the sizes of their...
[mikachu/openbox.git] / otk / style.cc
1 #ifdef    HAVE_CONFIG_H
2 #include "../config.h"
3 #endif // HAVE_CONFIG_H
4
5 #include <assert.h>
6 #include "display.hh"
7
8 #include "util.hh"
9 #include "style.hh"
10
11 namespace otk {
12
13 Style::Style() : font(NULL)
14 {
15 }
16
17 Style::Style(BImageControl *ctrl)
18   : image_control(ctrl), font(0),
19     screen_number(ctrl->getScreenInfo()->getScreenNumber())
20 {
21 }
22
23 Style::~Style() {
24   if (font)
25     delete font;
26
27   if (close_button.mask != None)
28     XFreePixmap(OBDisplay::display, close_button.mask);
29   if (max_button.mask != None)
30     XFreePixmap(OBDisplay::display, max_button.mask);
31   if (icon_button.mask != None)
32     XFreePixmap(OBDisplay::display, icon_button.mask);
33   if (stick_button.mask != None)
34     XFreePixmap(OBDisplay::display, stick_button.mask);
35
36   max_button.mask = None;
37   close_button.mask = None;
38   icon_button.mask = None;
39   stick_button.mask = None;
40 }
41
42 void Style::load(const Configuration &style) {
43   std::string s;
44
45   // load fonts/fontsets
46   if (font)
47     delete font;
48
49   font = readDatabaseFont("window.", style);
50
51   // load window config
52   t_focus = readDatabaseTexture("window.title.focus", "white", style);
53   t_unfocus = readDatabaseTexture("window.title.unfocus", "black", style);
54
55   l_focus = readDatabaseTexture("window.label.focus", "white", style);
56   l_unfocus = readDatabaseTexture("window.label.unfocus", "black", style);
57
58   h_focus = readDatabaseTexture("window.handle.focus", "white", style);
59   h_unfocus = readDatabaseTexture("window.handle.unfocus", "black", style);
60
61   g_focus = readDatabaseTexture("window.grip.focus", "white", style);
62   g_unfocus = readDatabaseTexture("window.grip.unfocus", "black", style);
63
64   b_focus = readDatabaseTexture("window.button.focus", "white", style);
65   b_unfocus = readDatabaseTexture("window.button.unfocus", "black", style);
66   b_pressed = readDatabaseTexture("window.button.pressed", "black", style);
67
68   //if neither of these can be found, we will use the previous resource
69   b_pressed_focus = readDatabaseTexture("window.button.pressed.focus",
70                                         "black", style, true);
71   b_pressed_unfocus = readDatabaseTexture("window.button.pressed.unfocus",
72                                           "black", style, true);
73
74   if (close_button.mask != None)
75     XFreePixmap(OBDisplay::display, close_button.mask);
76   if (max_button.mask != None)
77     XFreePixmap(OBDisplay::display, max_button.mask);
78   if (icon_button.mask != None)
79     XFreePixmap(OBDisplay::display, icon_button.mask);
80   if (stick_button.mask != None)
81     XFreePixmap(OBDisplay::display, stick_button.mask);
82
83   close_button.mask = max_button.mask = icon_button.mask
84                     = icon_button.mask = None;
85   
86   readDatabaseMask("window.button.close.mask", close_button, style);
87   readDatabaseMask("window.button.max.mask", max_button, style);
88   readDatabaseMask("window.button.icon.mask", icon_button, style);
89   readDatabaseMask("window.button.stick.mask", stick_button, style);
90
91   // we create the window.frame texture by hand because it exists only to
92   // make the code cleaner and is not actually used for display
93   BColor color = readDatabaseColor("window.frame.focusColor", "white",
94                                         style);
95   f_focus = BTexture("solid flat", screen_number, image_control);
96   f_focus.setColor(color);
97
98   color = readDatabaseColor("window.frame.unfocusColor", "white", style);
99   f_unfocus = BTexture("solid flat", screen_number, image_control);
100   f_unfocus.setColor(color);
101
102   l_text_focus = readDatabaseColor("window.label.focus.textColor",
103                                    "black", style);
104   l_text_unfocus = readDatabaseColor("window.label.unfocus.textColor",
105                                      "white", style);
106
107   b_pic_focus = readDatabaseColor("window.button.focus.picColor",
108                                   "black", style);
109   b_pic_unfocus = readDatabaseColor("window.button.unfocus.picColor",
110                                     "white", style);
111
112   justify = LeftJustify;
113
114   if (style.getValue("window.justify", s)) {
115     if (s == "right" || s == "Right")
116       justify = RightJustify;
117     else if (s == "center" || s == "Center")
118       justify = CenterJustify;
119   }
120
121   // sanity checks
122   if (t_focus.texture() == BTexture::Parent_Relative)
123     t_focus = f_focus;
124   if (t_unfocus.texture() == BTexture::Parent_Relative)
125     t_unfocus = f_unfocus;
126   if (h_focus.texture() == BTexture::Parent_Relative)
127     h_focus = f_focus;
128   if (h_unfocus.texture() == BTexture::Parent_Relative)
129     h_unfocus = f_unfocus;
130
131   border_color = readDatabaseColor("borderColor", "black", style);
132
133   // load bevel, border and handle widths
134
135   const ScreenInfo *s_info = OBDisplay::screenInfo(screen_number);
136   unsigned int width = s_info->getRect().width();
137
138   if (! style.getValue("handleWidth", handle_width) ||
139       handle_width > width/2 || handle_width == 0)
140     handle_width = 6;
141
142   if (! style.getValue("borderWidth", border_width))
143     border_width = 1;
144
145   if (! style.getValue("bevelWidth", bevel_width)
146       || bevel_width > width/2 || bevel_width == 0)
147     bevel_width = 3;
148
149   if (! style.getValue("frameWidth", frame_width)
150       || frame_width > width/2)
151     frame_width = bevel_width;
152
153   if (style.getValue("rootCommand", s))
154     bexec(s, s_info->displayString());
155 }
156
157
158 void Style::doJustify(const std::string &text, int &start_pos,
159                       unsigned int max_length,
160                       unsigned int modifier) const {
161   size_t text_len = text.size();
162   unsigned int length;
163
164   do {
165     length = font->measureString(std::string(text, 0, text_len)) + modifier;
166   } while (length > max_length && text_len-- > 0);
167
168   switch (justify) {
169   case RightJustify:
170     start_pos += max_length - length;
171     break;
172
173   case CenterJustify:
174     start_pos += (max_length - length) / 2;
175     break;
176
177   case LeftJustify:
178   default:
179     break;
180   }
181 }
182
183
184 void Style::readDatabaseMask(const std::string &rname, PixmapMask &pixmapMask,
185                              const Configuration &style) {
186   Window root_window = OBDisplay::screenInfo(screen_number)->getRootWindow();
187   std::string s;
188   int hx, hy; //ignored
189   int ret = BitmapOpenFailed; //default to failure.
190   
191   if (style.getValue(rname, s))
192   {
193     if (s[0] != '/' && s[0] != '~')
194     {
195       std::string xbmFile = std::string("~/.openbox/buttons/") + s;
196       ret = XReadBitmapFile(OBDisplay::display, root_window,
197                             expandTilde(xbmFile).c_str(), &pixmapMask.w,
198                             &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
199     } else
200       ret = XReadBitmapFile(OBDisplay::display, root_window,
201                             expandTilde(s).c_str(), &pixmapMask.w,
202                             &pixmapMask.h, &pixmapMask.mask, &hx, &hy);
203     
204     if (ret == BitmapSuccess)
205       return;
206   }
207
208   pixmapMask.mask = None;
209   pixmapMask.w = pixmapMask.h = 0;
210 }
211
212
213 BTexture Style::readDatabaseTexture(const std::string &rname,
214                                          const std::string &default_color,
215                                          const Configuration &style, 
216                                          bool allowNoTexture)
217 {
218   BTexture texture;
219   std::string s;
220
221   if (style.getValue(rname, s))
222     texture = BTexture(s);
223   else if (allowNoTexture) //no default
224     texture.setTexture(BTexture::NoTexture);
225   else
226     texture.setTexture(BTexture::Solid | BTexture::Flat);
227
228   // associate this texture with this screen
229   texture.setScreen(screen_number);
230   texture.setImageControl(image_control);
231
232   if (texture.texture() != BTexture::NoTexture) {
233     texture.setColor(readDatabaseColor(rname + ".color", default_color,
234                                        style));
235     texture.setColorTo(readDatabaseColor(rname + ".colorTo", default_color,
236                                          style));
237     texture.setBorderColor(readDatabaseColor(rname + ".borderColor",
238                                              default_color, style));
239   }
240
241   return texture;
242 }
243
244
245 BColor Style::readDatabaseColor(const std::string &rname,
246                                      const std::string &default_color,
247                                      const Configuration &style) {
248   BColor color;
249   std::string s;
250   if (style.getValue(rname, s))
251     color = BColor(s, screen_number);
252   else
253     color = BColor(default_color, screen_number);
254   return color;
255 }
256
257
258 BFont *Style::readDatabaseFont(const std::string &rbasename,
259                                     const Configuration &style) {
260   std::string fontname;
261
262   std::string s;
263
264   int i;
265   if (style.getValue(rbasename + "xft.font", s) &&
266       style.getValue(rbasename + "xft.size", i)) {
267     std::string family = s;
268     bool bold = False;
269     bool italic = False;
270     bool dropShadow = False;
271
272     if (style.getValue(rbasename + "xft.flags", s)) {
273       if (s.find("bold") != std::string::npos)
274         bold = True;
275       if (s.find("italic") != std::string::npos)
276         italic = True;
277       if (s.find("shadow") != std::string::npos)
278         dropShadow = True;
279     }
280     
281     unsigned char offset = 1;
282     if (style.getValue(rbasename + "xft.shadow.offset", s)) {
283       offset = atoi(s.c_str()); //doesn't detect errors
284       if (offset > CHAR_MAX)
285         offset = 1;
286     }
287
288     unsigned char tint = 0x40;
289     if (style.getValue(rbasename + "xft.shadow.tint", s)) {
290       tint = atoi(s.c_str());
291     }
292
293     
294     BFont *b = new BFont(screen_number, family, i, bold, italic,
295                          dropShadow && shadow_fonts,
296                          offset, tint, aa_fonts);
297     if (b->valid())
298       return b;
299     delete b;
300   }
301
302   if (style.getValue(rbasename + "xft.font", s))
303     printf("Unable to load font \"%s\". Exiting\n", s.c_str());
304   else
305     printf("Font not defined by style. Exiting\n");
306   exit(2);  // can't continue without a font
307 }
308
309 }