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