(start) some style syntax revisions after a discussion on the mailing
[blackbox.git] / src / ScreenResource.cc
blob1241d8ac6089a47a7ca895db2b659a3dc60fb7fc
1 #include "ScreenResource.hh"
3 #include "Screen.hh"
4 #include "Slit.hh"
5 #include "Toolbar.hh"
7 #include <Menu.hh>
8 #include <Resource.hh>
10 #include <assert.h>
13 static const int iconify_width = 9;
14 static const int iconify_height = 9;
15 static const unsigned char iconify_bits[] =
16 { 0x00, 0x00, 0x82, 0x00, 0xc6, 0x00, 0x6c, 0x00, 0x38,
17 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01 };
19 static const int maximize_width = 9;
20 static const int maximize_height = 9;
21 static const unsigned char maximize_bits[] =
22 { 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
23 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01 };
25 static const int restore_width = 9;
26 static const int restore_height = 9;
27 static const unsigned char restore_bits[] =
28 { 0xf8, 0x01, 0xf8, 0x01, 0x08, 0x01, 0x3f, 0x01, 0x3f,
29 0x01, 0xe1, 0x01, 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00 };
31 static const int close_width = 9;
32 static const int close_height = 9;
33 static const unsigned char close_bits[] =
34 { 0x83, 0x01, 0xc7, 0x01, 0xee, 0x00, 0x7c, 0x00, 0x38,
35 0x00, 0x7c, 0x00, 0xee, 0x00, 0xc7, 0x01, 0x83, 0x01 };
38 void ScreenResource::save(bt::Resource& res, BScreen* screen) {
39 char rc_string[128];
40 char *placement = (char *) 0;
41 unsigned int number = screen->screenNumber();
43 switch (_slitOptions.placement) {
44 case Slit::TopLeft: placement = "TopLeft"; break;
45 case Slit::CenterLeft: placement = "CenterLeft"; break;
46 case Slit::BottomLeft: placement = "BottomLeft"; break;
47 case Slit::TopCenter: placement = "TopCenter"; break;
48 case Slit::BottomCenter: placement = "BottomCenter"; break;
49 case Slit::TopRight: placement = "TopRight"; break;
50 case Slit::BottomRight: placement = "BottomRight"; break;
51 case Slit::CenterRight: default: placement = "CenterRight"; break;
54 sprintf(rc_string, "session.screen%u.slit.placement", number);
55 res.write(rc_string, placement);
57 sprintf(rc_string, "session.screen%u.slit.direction", number);
58 res.write(rc_string, (_slitOptions.direction == Slit::Horizontal) ?
59 "Horizontal" : "Vertical");
61 sprintf(rc_string, "session.screen%u.slit.onTop", number);
62 res.write(rc_string, _slitOptions.always_on_top);
64 sprintf(rc_string, "session.screen%u.slit.autoHide", number);
65 res.write(rc_string, _slitOptions.auto_hide);
68 sprintf(rc_string, "session.screen%u.enableToolbar", number);
69 res.write(rc_string, _toolbarOptions.enabled);
71 sprintf(rc_string, "session.screen%u.toolbar.onTop", number);
72 res.write(rc_string, _toolbarOptions.always_on_top);
74 sprintf(rc_string, "session.screen%u.toolbar.autoHide", number);
75 res.write(rc_string, _toolbarOptions.auto_hide);
77 switch (_toolbarOptions.placement) {
78 case Toolbar::TopLeft: placement = "TopLeft"; break;
79 case Toolbar::BottomLeft: placement = "BottomLeft"; break;
80 case Toolbar::TopCenter: placement = "TopCenter"; break;
81 case Toolbar::TopRight: placement = "TopRight"; break;
82 case Toolbar::BottomRight: placement = "BottomRight"; break;
83 case Toolbar::BottomCenter: default: placement = "BottomCenter"; break;
86 sprintf(rc_string, "session.screen%u.toolbar.placement", number);
87 res.write(rc_string, placement);
89 sprintf(rc_string, "session.screen%u.workspaces", number);
90 res.write(rc_string, workspace_count);
92 std::vector<bt::ustring>::const_iterator it = workspace_names.begin(),
93 end = workspace_names.end();
94 bt::ustring save_string = *it++;
95 for (; it != end; ++it) {
96 save_string += ',';
97 save_string += *it;
100 sprintf(rc_string, "session.screen%u.workspaceNames", number);
101 res.write(rc_string, bt::toLocale(save_string).c_str());
103 // these options can not be modified at runtime currently
105 sprintf(rc_string, "session.screen%u.toolbar.widthPercent", number);
106 res.write(rc_string, _toolbarOptions.width_percent);
108 sprintf(rc_string, "session.screen%u.strftimeFormat", number);
109 res.write(rc_string, _toolbarOptions.strftime_format.c_str());
112 void ScreenResource::load(bt::Resource& res, unsigned int screen) {
113 char name_lookup[128], class_lookup[128];
114 std::string str;
116 // toolbar settings
117 sprintf(name_lookup, "session.screen%u.enableToolbar", screen);
118 sprintf(class_lookup, "Session.screen%u.enableToolbar", screen);
119 _toolbarOptions.enabled = res.read(name_lookup, class_lookup, true);
121 sprintf(name_lookup, "session.screen%u.toolbar.widthPercent", screen);
122 sprintf(class_lookup, "Session.screen%u.Toolbar.WidthPercent", screen);
123 _toolbarOptions.width_percent = res.read(name_lookup, class_lookup, 66);
125 sprintf(name_lookup, "session.screen%u.toolbar.placement", screen);
126 sprintf(class_lookup, "Session.screen%u.Toolbar.Placement", screen);
127 str = res.read(name_lookup, class_lookup, "BottomCenter");
128 if (! strcasecmp(str.c_str(), "TopLeft"))
129 _toolbarOptions.placement = Toolbar::TopLeft;
130 else if (! strcasecmp(str.c_str(), "BottomLeft"))
131 _toolbarOptions.placement = Toolbar::BottomLeft;
132 else if (! strcasecmp(str.c_str(), "TopCenter"))
133 _toolbarOptions.placement = Toolbar::TopCenter;
134 else if (! strcasecmp(str.c_str(), "TopRight"))
135 _toolbarOptions.placement = Toolbar::TopRight;
136 else if (! strcasecmp(str.c_str(), "BottomRight"))
137 _toolbarOptions.placement = Toolbar::BottomRight;
138 else
139 _toolbarOptions.placement = Toolbar::BottomCenter;
141 sprintf(name_lookup, "session.screen%u.toolbar.onTop", screen);
142 sprintf(class_lookup, "Session.screen%u.Toolbar.OnTop", screen);
143 _toolbarOptions.always_on_top = res.read(name_lookup, class_lookup, false);
145 sprintf(name_lookup, "session.screen%u.toolbar.autoHide", screen);
146 sprintf(class_lookup, "Session.screen%u.Toolbar.autoHide", screen);
147 _toolbarOptions.auto_hide = res.read(name_lookup, class_lookup, false);
149 sprintf(name_lookup, "session.screen%u.strftimeFormat", screen);
150 sprintf(class_lookup, "Session.screen%u.StrftimeFormat", screen);
151 _toolbarOptions.strftime_format =
152 res.read(name_lookup, class_lookup, "%I:%M %p");
154 // slit settings
155 sprintf(name_lookup, "session.screen%u.slit.placement", screen);
156 sprintf(class_lookup, "Session.screen%u.Slit.Placement", screen);
157 str = res.read(name_lookup, class_lookup, "CenterRight");
158 if (! strcasecmp(str.c_str(), "TopLeft"))
159 _slitOptions.placement = Slit::TopLeft;
160 else if (! strcasecmp(str.c_str(), "CenterLeft"))
161 _slitOptions.placement = Slit::CenterLeft;
162 else if (! strcasecmp(str.c_str(), "BottomLeft"))
163 _slitOptions.placement = Slit::BottomLeft;
164 else if (! strcasecmp(str.c_str(), "TopCenter"))
165 _slitOptions.placement = Slit::TopCenter;
166 else if (! strcasecmp(str.c_str(), "BottomCenter"))
167 _slitOptions.placement = Slit::BottomCenter;
168 else if (! strcasecmp(str.c_str(), "TopRight"))
169 _slitOptions.placement = Slit::TopRight;
170 else if (! strcasecmp(str.c_str(), "BottomRight"))
171 _slitOptions.placement = Slit::BottomRight;
172 else
173 _slitOptions.placement = Slit::CenterRight;
175 sprintf(name_lookup, "session.screen%u.slit.direction", screen);
176 sprintf(class_lookup, "Session.screen%u.Slit.Direction", screen);
177 str = res.read(name_lookup, class_lookup, "Vertical");
178 if (! strcasecmp(str.c_str(), "Horizontal"))
179 _slitOptions.direction = Slit::Horizontal;
180 else
181 _slitOptions.direction = Slit::Vertical;
183 sprintf(name_lookup, "session.screen%u.slit.onTop", screen);
184 sprintf(class_lookup, "Session.screen%u.Slit.OnTop", screen);
185 _slitOptions.always_on_top = res.read(name_lookup, class_lookup, false);
187 sprintf(name_lookup, "session.screen%u.slit.autoHide", screen);
188 sprintf(class_lookup, "Session.screen%u.Slit.AutoHide", screen);
189 _slitOptions.auto_hide = res.read(name_lookup, class_lookup, false);
191 // general screen settings
193 sprintf(name_lookup, "session.screen%u.workspaces", screen);
194 sprintf(class_lookup, "Session.screen%u.Workspaces", screen);
195 workspace_count = res.read(name_lookup, class_lookup, 4);
197 if (! workspace_names.empty())
198 workspace_names.clear();
200 sprintf(name_lookup, "session.screen%u.workspaceNames", screen);
201 sprintf(class_lookup, "Session.screen%u.WorkspaceNames", screen);
202 bt::ustring ustr = bt::toUnicode(res.read(name_lookup, class_lookup));
203 if (!ustr.empty()) {
204 bt::ustring::const_iterator it = ustr.begin();
205 const bt::ustring::const_iterator end = ustr.end();
206 for (;;) {
207 const bt::ustring::const_iterator i =
208 std::find(it, end, static_cast<bt::ustring::value_type>(','));
209 workspace_names.push_back(bt::ustring(it, i));
210 it = i;
211 if (it == end)
212 break;
213 ++it;
219 void ScreenResource::loadStyle(BScreen* screen, const std::string& style) {
220 const bt::Display& display = screen->blackbox()->display();
221 unsigned int screen_num = screen->screenNumber();
223 // use the user selected style
224 bt::Resource res(style);
225 if (! res.valid())
226 res.load(DEFAULTSTYLE);
228 // load menu style
229 bt::MenuStyle::get(*screen->blackbox(), screen_num)->load(res);
231 // load window style
232 _windowStyle.font.setFontName(res.read("window.font", "Window.Font"));
234 _windowStyle.iconify.load(screen_num, iconify_bits,
235 iconify_width, iconify_height);
236 _windowStyle.maximize.load(screen_num, maximize_bits,
237 maximize_width, maximize_height);
238 _windowStyle.restore.load(screen_num, restore_bits,
239 restore_width, restore_height);
240 _windowStyle.close.load(screen_num, close_bits,
241 close_width, close_height);
243 // focused window style
244 _windowStyle.focus.text =
245 bt::Color::namedColor(display, screen_num,
246 res.read("window.label.focus.textColor",
247 "Window.Label.Focus.TextColor",
248 "black"));
249 _windowStyle.focus.foreground =
250 bt::Color::namedColor(display, screen_num,
251 res.read("window.button.focus.foregroundColor",
252 "Window.Button.Focus.ForegroundColor",
253 res.read("window.button.focus.picColor",
254 "Window.Button.Focus.PicColor",
255 "black")));
256 _windowStyle.focus.title =
257 bt::textureResource(display, screen_num, res,
258 "window.title.focus",
259 "Window.Title.Focus",
260 "white");
261 _windowStyle.focus.label =
262 bt::textureResource(display, screen_num, res,
263 "window.label.focus",
264 "Window.Label.Focus",
265 "white");
266 _windowStyle.focus.button =
267 bt::textureResource(display, screen_num, res,
268 "window.button.focus",
269 "Window.Button.Focus",
270 "white");
271 _windowStyle.focus.handle =
272 bt::textureResource(display, screen_num, res,
273 "window.handle.focus",
274 "Window.Handle.Focus",
275 "white");
276 _windowStyle.focus.grip =
277 bt::textureResource(display, screen_num, res,
278 "window.grip.focus",
279 "Window.Grip.Focus",
280 "white");
282 // unfocused window style
283 _windowStyle.unfocus.text =
284 bt::Color::namedColor(display, screen_num,
285 res.read("window.label.unfocus.textColor",
286 "Window.Label.Unfocus.TextColor",
287 "white"));
288 _windowStyle.unfocus.foreground =
289 bt::Color::namedColor(display, screen_num,
290 res.read("window.button.unfocus.foregroundColor",
291 "Window.Button.Unfocus.ForegroundColor",
292 res.read("window.button.unfocus.picColor",
293 "Window.Button.Unfocus.PicColor",
294 "white")));
295 _windowStyle.unfocus.title =
296 bt::textureResource(display, screen_num, res,
297 "window.title.unfocus",
298 "Window.Title.Unfocus",
299 "black");
300 _windowStyle.unfocus.label =
301 bt::textureResource(display, screen_num, res,
302 "window.label.unfocus",
303 "Window.Label.Unfocus",
304 "black");
305 _windowStyle.unfocus.button =
306 bt::textureResource(display, screen_num, res,
307 "window.button.unfocus",
308 "Window.Button.Unfocus",
309 "black");
310 _windowStyle.unfocus.handle =
311 bt::textureResource(display, screen_num, res,
312 "window.handle.unfocus",
313 "Window.Handle.Unfocus",
314 "black");
315 _windowStyle.unfocus.grip =
316 bt::textureResource(display, screen_num, res,
317 "window.grip.unfocus",
318 "Window.Grip.Unfocus",
319 "black");
321 _windowStyle.frame_border =
322 bt::Color::namedColor(display, screen_num,
323 res.read("window.frame.borderColor",
324 "Window.Frame.BorderColor",
325 "black"));
326 _windowStyle.pressed =
327 bt::textureResource(display, screen_num, res,
328 "window.button.pressed",
329 "Window.Button.Pressed",
330 "black");
332 _windowStyle.alignment =
333 bt::alignResource(res, "window.alignment", "Window.Alignment");
335 _windowStyle.title_margin =
336 res.read("window.title.marginWidth", "Window.Title.MarginWidth", 2);
337 _windowStyle.label_margin =
338 res.read("window.label.marginWidth", "Window.Label.MarginWidth", 2);
339 _windowStyle.button_margin =
340 res.read("window.button.marginWidth", "Window.Button.MarginWidth", 2);
341 _windowStyle.frame_border_width =
342 res.read("window.frame.borderWidth", "Window.Frame.BorderWidth", 1);
343 _windowStyle.handle_height =
344 res.read("window.handleHeight", "Window.HandleHeight", 6);
346 // the height of the titlebar is based upon the height of the font being
347 // used to display the window's title
348 _windowStyle.button_width =
349 std::max(std::max(std::max(std::max(_windowStyle.iconify.width(),
350 _windowStyle.iconify.height()),
351 std::max(_windowStyle.maximize.width(),
352 _windowStyle.maximize.height())),
353 std::max(_windowStyle.restore.width(),
354 _windowStyle.restore.height())),
355 std::max(_windowStyle.close.width(),
356 _windowStyle.close.height())) +
357 ((std::max(_windowStyle.focus.button.borderWidth(),
358 _windowStyle.unfocus.button.borderWidth()) +
359 _windowStyle.button_margin) * 2);
360 _windowStyle.label_height =
361 std::max(bt::textHeight(screen_num, _windowStyle.font) +
362 ((std::max(_windowStyle.focus.label.borderWidth(),
363 _windowStyle.unfocus.label.borderWidth()) +
364 _windowStyle.label_margin) * 2),
365 _windowStyle.button_width);
366 _windowStyle.button_width = std::max(_windowStyle.button_width,
367 _windowStyle.label_height);
368 _windowStyle.title_height =
369 _windowStyle.label_height +
370 ((std::max(_windowStyle.focus.title.borderWidth(),
371 _windowStyle.unfocus.title.borderWidth()) +
372 _windowStyle.title_margin) * 2);
373 _windowStyle.grip_width = (_windowStyle.button_width * 2);
374 _windowStyle.handle_height +=
375 (std::max(_windowStyle.focus.handle.borderWidth(),
376 _windowStyle.unfocus.handle.borderWidth()) * 2);
378 // load toolbar style
379 _toolbarStyle.font.setFontName(res.read("toolbar.font", "Toolbar.Font"));
381 _toolbarStyle.toolbar =
382 bt::textureResource(display, screen_num, res,
383 "toolbar",
384 "Toolbar",
385 "white");
386 _toolbarStyle.slabel =
387 bt::textureResource(display, screen_num, res,
388 "toolbar.label",
389 "Toolbar.Label",
390 "white");
391 _toolbarStyle.wlabel =
392 bt::textureResource(display, screen_num, res,
393 "toolbar.windowLabel",
394 "Toolbar.Label",
395 "white");
396 _toolbarStyle.button =
397 bt::textureResource(display, screen_num, res,
398 "toolbar.button",
399 "Toolbar.Button",
400 "white");
401 _toolbarStyle.pressed =
402 bt::textureResource(display, screen_num, res,
403 "toolbar.button.pressed",
404 "Toolbar.Button.Pressed",
405 "black");
407 _toolbarStyle.clock =
408 bt::textureResource(display, screen_num, res,
409 "toolbar.clock",
410 "Toolbar.Label",
411 "white");
413 _toolbarStyle.slabel_text =
414 bt::Color::namedColor(display, screen_num,
415 res.read("toolbar.label.textColor",
416 "Toolbar.Label.TextColor",
417 "black"));
418 _toolbarStyle.wlabel_text =
419 bt::Color::namedColor(display, screen_num,
420 res.read("toolbar.windowLabel.textColor",
421 "Toolbar.Label.TextColor",
422 "black"));
423 _toolbarStyle.clock_text =
424 bt::Color::namedColor(display, screen_num,
425 res.read("toolbar.clock.textColor",
426 "Toolbar.Label.TextColor",
427 "white"));
428 _toolbarStyle.foreground =
429 bt::Color::namedColor(display, screen_num,
430 res.read("toolbar.button.foregroundColor",
431 "Toolbar.Button.ForegroundColor",
432 res.read("toolbar.button.picColor",
433 "Toolbar.Button.PicColor",
434 "black")));
435 _toolbarStyle.alignment =
436 bt::alignResource(res, "toolbar.alignment", "Toolbar.Alignment");
438 _toolbarStyle.frame_margin =
439 res.read("toolbar.marginWidth", "Toolbar.MarginWidth", 2);
440 _toolbarStyle.label_margin =
441 res.read("toolbar.label.marginWidth", "Toolbar.Label.MarginWidth", 2);
442 _toolbarStyle.button_margin =
443 res.read("toolbar.button.marginWidth", "Toolbar.Button.MarginWidth", 2);
445 const bt::Bitmap &left = bt::Bitmap::leftArrow(screen_num),
446 &right = bt::Bitmap::rightArrow(screen_num);
447 _toolbarStyle.button_width =
448 std::max(std::max(left.width(), left.height()),
449 std::max(right.width(), right.height()))
450 + ((_toolbarStyle.button.borderWidth() + _toolbarStyle.button_margin) * 2);
451 _toolbarStyle.label_height =
452 std::max(bt::textHeight(screen_num, _toolbarStyle.font)
453 + ((std::max(std::max(_toolbarStyle.slabel.borderWidth(),
454 _toolbarStyle.wlabel.borderWidth()),
455 _toolbarStyle.clock.borderWidth())
456 + _toolbarStyle.label_margin) * 2),
457 _toolbarStyle.button_width);
458 _toolbarStyle.button_width = std::max(_toolbarStyle.button_width,
459 _toolbarStyle.label_height);
460 _toolbarStyle.toolbar_height = _toolbarStyle.label_height
461 + ((_toolbarStyle.toolbar.borderWidth()
462 + _toolbarStyle.frame_margin) * 2);
463 _toolbarStyle.hidden_height =
464 std::max(_toolbarStyle.toolbar.borderWidth()
465 + _toolbarStyle.frame_margin, 1u);
467 // load slit style
468 _slitStyle.slit = bt::textureResource(display, screen_num, res,
469 "slit",
470 "Slit",
471 "white");
472 _slitStyle.margin = res.read("slit.marginWidth", "Slit.MarginWidth", 2);
474 root_command = res.read("rootCommand", "RootCommand");
476 // sanity checks
477 bt::Texture flat_black;
478 flat_black.setDescription("flat solid");
479 flat_black.setColor1(bt::Color(0, 0, 0));
481 if (_windowStyle.focus.title.texture() == bt::Texture::Parent_Relative)
482 _windowStyle.focus.title = flat_black;
483 if (_windowStyle.unfocus.title.texture() == bt::Texture::Parent_Relative)
484 _windowStyle.unfocus.title = flat_black;
485 if (_windowStyle.focus.handle.texture() == bt::Texture::Parent_Relative)
486 _windowStyle.focus.handle = flat_black;
487 if (_windowStyle.unfocus.handle.texture() == bt::Texture::Parent_Relative)
488 _windowStyle.unfocus.handle = flat_black;
490 if (_toolbarStyle.toolbar.texture() == bt::Texture::Parent_Relative)
491 _toolbarStyle.toolbar = flat_black;
493 if (_slitStyle.slit.texture() == bt::Texture::Parent_Relative)
494 _slitStyle.slit = flat_black;
497 const bt::ustring ScreenResource::workspaceName(unsigned int i) const {
498 // handle both requests for new workspaces beyond what we started with
499 // and for those that lack a name
500 if (i > workspace_count || i >= workspace_names.size())
501 return bt::ustring();
502 return workspace_names[i];
505 void ScreenResource::setWorkspaceName(unsigned int i,
506 const bt::ustring &name) {
507 if (i >= workspace_names.size()) {
508 workspace_names.reserve(i + 1);
509 workspace_names.insert(workspace_names.begin() + i, name);
510 } else {
511 workspace_names[i] = name;