1 // FbDesk.cc
2 // Copyright (c) 2002 - 2006 Henrik Kinnunen (fluxgen at users.sourceforge.net)
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 // DEALINGS IN THE SOFTWARE.
21
22 // $Id$
23
24 #include "FbDesk.hh"
25
26 #include "InputField.hh"
27 #include "IntResMenuItem.hh"
28
29 #include "FbTk/App.hh"
30 #include "FbTk/Font.hh"
31 #include "FbTk/EventManager.hh"
32 #include "FbTk/SimpleCommand.hh"
33 #include "FbTk/StringUtil.hh"
34 #include "FbTk/XrmDatabaseHelper.hh"
35 #include "FbTk/MenuSeparator.hh"
36
37 #include <iostream>
38 #include <fstream>
39 #include <algorithm>
40 #include <unistd.h>
41 #include <cstdio>
42
43 using namespace std;
44 using namespace FbTk;
45
46
47 namespace FbDesk {
48
FbDesk(const char * config_filename)49 FbDesk::FbDesk(const char *config_filename):
50 m_font("fixed"),
51 m_selected_icon(0),
52 m_last_icon(0),
53 m_config_filename(config_filename ? config_filename : ""),
54 m_button_pos_x(32),
55 m_button_pos_y(32),
56 m_menutheme(0), // menu theme on screen 0
57 m_imagectrl(0), // image control on screen 0
58 m_iconmenu(m_menutheme, m_imagectrl),
59 m_inputfield(0, m_menutheme.frameFont(), m_menutheme.frameTextGC().gc(),
60 m_menutheme.frameTexture().color()),
61 m_textcolor("black", 0),
62 m_resmanager(0, false),
63 m_themefile(m_resmanager, "", "session.styleFile", "Session.StyleFile"),
64 m_doubleclick_interval(m_resmanager, 200, "fbdesk.doubleClickInterval", "FbDesk.DoubleClickInterval"),
65 m_iconfile(m_resmanager, "~/.fluxbox/fbdesk.icons", "fbdesk.iconFile", "FbDesk.IconFile"),
66 m_fontname(m_resmanager, "fixed", "fbdesk.font", "FbDesk.Font"),
67 m_textcolorname(m_resmanager, "black", "fbdesk.textColor", "FbDesk.TextColor"),
68 m_textbackgroundname(m_resmanager, "white", "fbdesk.textBackground", "FbDesk.TextBackground"),
69 m_grid_snap_x(m_resmanager, 5, "fbdesk.snapX", "FbDesk.SnapX"),
70 m_grid_snap_y(m_resmanager, 5, "fbdesk.snapY", "FbDesk.SnapY"),
71 m_textplacement(m_resmanager, Icon::TEXTPLACE_BOTTOM, "fbdesk.textPlacement", "FbDesk.TextPlacement"),
72 m_text_alpha(m_resmanager, 0, "fbdesk.textAlpha", "FbDesk.TextAlpha"),
73 m_icon_alpha(m_resmanager, 255, "fbdesk.iconAlpha", "FbDesk.IconAlpha"),
74 m_lock_positions(m_resmanager, false, "fbdesk.lockPositions", "FbDesk.LockPositions"),
75 m_icon_config(m_menutheme.screenNum()) {
76
77 m_icon_config.setFont(m_font);
78 reloadConfig();
79 setupIconMenu();
80
81 Screen *scr = ScreenOfDisplay(FbTk::App::instance()->display(), 0);
82 m_screen_width = WidthOfScreen(scr);
83 m_screen_height = HeightOfScreen(scr);
84
85
86 }
87
~FbDesk()88 FbDesk::~FbDesk() {
89 // save icon data
90 saveIcons(*m_iconfile);
91 // save to default resource file
92 m_resmanager.save( 0 );
93
94 // delete all icons
95 deleteIcons();
96 }
97
98
loadTheme()99 void FbDesk::loadTheme() {
100 cerr<<"loading style: " << *m_themefile <<endl;
101
102 if (!FbTk::ThemeManager::instance().load(*m_themefile, ""))
103 cerr<<"Failed to load style: "<< *m_themefile<<endl;
104
105 // update for new theme
106 m_iconmenu.reconfigure();
107 }
108
109 /**
110 Destroy old icons and reload icons data and recreate icons
111 */
loadIcons(const std::string & config_filename)112 bool FbDesk::loadIcons(const std::string &config_filename) {
113 ifstream iconfile(StringUtil::expandFilename(config_filename).c_str());
114
115 if (!m_iconlist.empty()) {
116 // delete old icons
117 deleteIcons();
118 }
119
120 vector<int> iconpos;
121
122 while (iconfile && !iconfile.eof()) {
123 string line;
124 getline(iconfile, line);
125 if (line.compare(0, strlen("[Desktop Entry]"),
126 "[Desktop Entry]" )) {
127 continue;
128 }
129
130 int icon_x = 0, icon_y = 0; // position of icon
131 string command; // command for icon
132 string label; // icon label
133 string icon_filename; // icon filename
134
135 while (!iconfile.eof()) {
136 line = "";
137 getline(iconfile, line); // get next line
138
139 //remove any whitespace in the begining
140 FbTk::StringUtil::removeFirstWhitespace(line);
141
142 // get first position after option
143 size_t first_pos = line.find_first_of("=");
144
145 string option;
146 if (first_pos != string::npos)
147 option = line.substr(0, first_pos);
148 else
149 option = line;
150
151 if (option.size() == 0)
152 continue;
153
154 // get option value
155 string option_value;
156 if (first_pos != string::npos && first_pos != line.size() - 1) {
157 option_value = static_cast<const char *>(line.c_str() + first_pos + 1);
158 }
159
160 FbTk::StringUtil::removeFirstWhitespace(option);
161 FbTk::StringUtil::removeTrailingWhitespace(option);
162
163 if (option == "Name") {
164 label = option_value;
165 } else if (option == "Exec") {
166 command = option_value;
167 } else if (option == "Icon") {
168 icon_filename = option_value;
169 } else if (option == "Pos") {
170 sscanf(option_value.c_str(), "%d %d", &icon_x, &icon_y);
171 } else if (option == "[end]") {
172 if (command.size() == 0 && icon_filename.size() == 0
173 && label.size() == 0) {
174 cerr<<"Warning: All options for icon are empty. Icon not added."<<endl;
175 continue;
176 }
177
178 // create new icon from current settings
179 Icon *i = new Icon(StringUtil::expandFilename(icon_filename).c_str(),
180 command, label);
181 // add to event manager
182 FbTk::EventManager::instance()->add(*this, i->iconWindow());
183 FbTk::EventManager::instance()->add(*this, i->labelWindow());
184 // save position
185 iconpos.push_back(icon_x);
186 iconpos.push_back(icon_y);
187 // add it to list
188 m_iconlist.push_back(i);
189 // clear options
190 icon_filename = label = command = "";
191 icon_x = icon_y = 0;
192 } // end if
193
194 } // end while
195
196 } // end while
197
198 // show all icons
199 IconList::iterator icon_it = m_iconlist.begin();
200 IconList::iterator icon_it_end = m_iconlist.end();
201 for (int i = 0; icon_it != icon_it_end; ++icon_it, i += 2) {
202 (*icon_it)->show();
203 (*icon_it)->move(iconpos[i], iconpos[i+1]);
204 }
205
206 // create at lest one icon
207 if (m_iconlist.empty()) {
208 cerr<<"Warning: Empty icon file, creating one icon."<<endl;
209 createIcon();
210 }
211
212 return true;
213 }
214
handleEvent(XEvent & event)215 void FbDesk::handleEvent(XEvent &event) {
216 switch (event.type) {
217 case ClientMessage:
218 clientMessageEvent(event.xclient);
219 break;
220 default:
221 break;
222 }
223 }
224
buttonPressEvent(XButtonEvent & event)225 void FbDesk::buttonPressEvent(XButtonEvent &event) {
226 m_selected_icon = findIcon(event.window);
227 if (!m_selected_icon)
228 return;
229 m_selected_icon->raise();
230 // save last mouse position
231 m_button_pos_x = event.x_root;
232 m_button_pos_y = event.y_root;
233
234 }
235
buttonReleaseEvent(XButtonEvent & event)236 void FbDesk::buttonReleaseEvent(XButtonEvent &event) {
237 static int button_time = 0;
238 if (m_selected_icon == 0)
239 return;
240
241 m_last_icon = m_selected_icon;
242
243 if (event.button == 3) {
244 // show menu
245 m_iconmenu.raise();
246 m_iconmenu.move(event.x_root, event.y_root);
247 m_iconmenu.show();
248
249 } else if (event.button == 1) {
250 // did we doubleclick?
251 if (event.time - button_time <= *m_doubleclick_interval) {
252 execute(m_selected_icon->command());
253 }
254
255 // don't show the icon over another window and make sure it's visible
256 m_selected_icon->lower();
257 int new_x = -1, new_y = -1;
258 if (m_selected_icon->x() < 0)
259 new_x = 0;
260 if (m_selected_icon->x() >= m_screen_width)
261 new_x = m_screen_width - m_selected_icon->width();
262
263 if (m_selected_icon->y() < 0)
264 new_y = 0;
265 if (m_selected_icon->y() >= m_screen_height)
266 new_y = m_screen_height - m_selected_icon->height();
267
268 if (new_x >= 0)
269 m_selected_icon->move(new_x, m_selected_icon->y());
270 if (new_y >= 0)
271 m_selected_icon->move(m_selected_icon->x(), new_y);
272 // update label background
273 m_selected_icon->redrawLabel();
274 }
275
276 m_selected_icon = 0; // unselect icon
277
278 button_time = event.time; // save last timestamp
279 saveIcons(*m_iconfile);
280 }
281
exposeEvent(XExposeEvent & event)282 void FbDesk::exposeEvent(XExposeEvent &event) {
283 Icon *exposed_icon = findIcon( event.window );
284 if (exposed_icon != 0)
285 exposed_icon->update();
286 }
287
motionNotifyEvent(XMotionEvent & event)288 void FbDesk::motionNotifyEvent(XMotionEvent &event) {
289
290 // need a selected icon first, and not locked position
291 if (*m_lock_positions || m_selected_icon == 0)
292 return;
293
294 Display *disp = FbTk::App::instance()->display();
295 Screen *scr = ScreenOfDisplay(disp, 0);
296
297 // calculate new position, using inside pos and last mouse pos
298
299 // snap to grid
300 if (*m_grid_snap_x == 0)
301 *m_grid_snap_x = 1;
302
303 if (*m_grid_snap_y == 0)
304 *m_grid_snap_y = 1;
305
306 event.x_root /= *m_grid_snap_x;
307 event.x_root *= *m_grid_snap_x;
308
309 event.y_root /= *m_grid_snap_y;
310 event.y_root *= *m_grid_snap_y;
311
312 int new_x = m_selected_icon->x() - m_button_pos_x + event.x_root;
313 int new_y = m_selected_icon->y() - m_button_pos_y + event.y_root;
314
315 // set the last known position of mouse
316 m_button_pos_x = event.x_root;
317 m_button_pos_y = event.y_root;
318
319 // Make sure the icon is inside visible area
320 if (new_x < 0)
321 new_x = 0;
322 else if (new_x >= m_screen_width)
323 new_x = m_screen_width - 1;
324
325 if (new_y < 0)
326 new_y = 0;
327 else if (new_y >= m_screen_height)
328 new_y = m_screen_height - 1;
329
330 // move the icon the new position
331 if (m_selected_icon->x() != new_x ||
332 m_selected_icon->y() != new_y) {
333 m_selected_icon->move(new_x, new_y);
334 }
335 }
336
clientMessageEvent(XClientMessageEvent & event)337 void FbDesk::clientMessageEvent(XClientMessageEvent &event) {
338 // TODO drag'n'drop
339 }
340
execute(const std::string & commando) const341 void FbDesk::execute(const std::string &commando) const {
342 if (! fork()) {
343 string displaystring("DISPLAY=");
344 displaystring += DisplayString(FbTk::App::instance()->display());
345 setsid();
346 putenv((char *)displaystring.c_str());
347 execl("/bin/sh", "/bin/sh", "-c", commando.c_str(), 0);
348 exit(0);
349 }
350 }
351
findIcon(Window w)352 Icon *FbDesk::findIcon(Window w) {
353 IconList::iterator it = m_iconlist.begin();
354 IconList::iterator it_end = m_iconlist.end();
355 for (; it != it_end; ++it) {
356 if ((*it)->iconWindow() == w ||
357 (*it)->labelWindow() == w) {
358 return (*it);
359 }
360 }
361
362 return 0; // we didn't find any icon
363 }
364
saveIcons(const std::string & filename) const365 bool FbDesk::saveIcons(const std::string &filename) const {
366 string realfilename(StringUtil::expandFilename(filename));
367 ofstream ofile(realfilename.c_str());
368 if (!ofile) {
369 cerr<<"Warning: Failed to save icons to file: "<<realfilename<<endl;
370 return false; // faild to open file
371 }
372 IconList::const_iterator it = m_iconlist.begin();
373 IconList::const_iterator it_end = m_iconlist.end();
374 for (; it != it_end; ++it) {
375 ofile<<"[Desktop Entry]"<<endl
376 <<"Name="<<(*it)->label()<<endl
377 <<"Exec="<<(*it)->command()<<endl
378 <<"Icon="<<(*it)->imageFilename()<<endl
379 <<"Pos= "<<(*it)->x()<<" "<<(*it)->y()<<endl
380 <<"[end]"<<endl<<endl;
381 }
382
383 return true;
384 }
385
deleteIcons()386 void FbDesk::deleteIcons() {
387 // destroy iconlist
388 while (!m_iconlist.empty()) {
389 FbTk::EventManager::instance()->remove(m_iconlist.back()->iconWindow());
390 FbTk::EventManager::instance()->remove(m_iconlist.back()->labelWindow());
391
392 delete m_iconlist.back();
393 m_iconlist.pop_back();
394 }
395 }
396
reloadConfig()397 void FbDesk::reloadConfig() {
398
399 m_resmanager.load(StringUtil::expandFilename(m_config_filename).c_str());
400 // if style file is empty read fluxbox style
401 if ( (*m_themefile).empty() ) {
402 string filename(StringUtil::expandFilename("~/.fluxbox/init").c_str());
403 ResourceManager rm(filename.c_str(), false);
404 rm.addResource( m_themefile );
405 rm.load(filename.c_str());
406 }
407
408 m_textcolor.setFromString(m_textcolorname->c_str(), 0);
409 if (!m_text_background_color.
410 setFromString(m_textbackgroundname->c_str(), 0)) {
411 m_text_background_color.setFromString("white", 0);
412 }
413
414 // setup icon values
415 m_icon_config.setTextColor(m_textcolor);
416 m_icon_config.setTextBackground(m_text_background_color);
417 m_icon_config.setTextPlacement(*m_textplacement);
418 m_icon_config.setTextAlpha(*m_text_alpha);
419 m_icon_config.setIconAlpha(*m_icon_alpha);
420
421 if (*m_textplacement == Icon::TEXTPLACE_LEFT ||
422 *m_textplacement == Icon::TEXTPLACE_RIGHT)
423 m_font.rotate(90);
424 else
425 m_font.rotate(0);
426
427 loadTheme();
428 loadIcons(*m_iconfile); // reload icons
429 }
430
createIcon()431 void FbDesk::createIcon() {
432 // create a new icon where we last pressed
433 Icon *ico = new Icon("", "", "default");
434 FbTk::EventManager::instance()->add(*this, ico->iconWindow());
435 FbTk::EventManager::instance()->add(*this, ico->labelWindow());
436 ico->move(m_button_pos_x, m_button_pos_y);
437 ico->show();
438 m_iconlist.push_back(ico);
439 m_selected_icon = 0;
440 }
441
deleteLastIcon()442 void FbDesk::deleteLastIcon() {
443 if (m_last_icon != 0 &&
444 find(m_iconlist.begin(), m_iconlist.end(), m_last_icon) != m_iconlist.end()) {
445 m_iconlist.remove(m_last_icon);
446 delete m_last_icon;
447 m_last_icon = 0;
448 }
449 }
450
setIconCommand()451 void FbDesk::setIconCommand() {
452 m_iconmenu.hide();
453 m_inputfield.setTitle("Set Command");
454 if (m_last_icon != 0 &&
455 find(m_iconlist.begin(), m_iconlist.end(), m_last_icon) != m_iconlist.end()) {
456 m_inputfield.setText(m_last_icon->command());
457 }
458
459 m_inputfield.setOnEnter(new FbTk::SimpleCommand<FbDesk>(*this, &FbDesk::setCommandFromInput));
460 m_inputfield.show();
461 m_inputfield.move(m_button_pos_x, m_button_pos_y);
462 m_inputfield.raise();
463 }
464
setIconLabel()465 void FbDesk::setIconLabel() {
466 m_iconmenu.hide();
467
468 m_inputfield.setTitle("Set Label");
469 if (m_last_icon != 0 &&
470 find(m_iconlist.begin(), m_iconlist.end(), m_last_icon) != m_iconlist.end()) {
471 m_inputfield.setText(m_last_icon->label());
472 }
473
474 m_inputfield.setOnEnter(new FbTk::SimpleCommand<FbDesk>(*this, &FbDesk::setLabelFromInput));
475 m_inputfield.show();
476 m_inputfield.move(m_button_pos_x, m_button_pos_y);
477 m_inputfield.raise();
478 }
479
setLabelFromInput()480 void FbDesk::setLabelFromInput() {
481 if (m_last_icon != 0 &&
482 find(m_iconlist.begin(), m_iconlist.end(), m_last_icon) != m_iconlist.end()) {
483 m_last_icon->setLabel(m_inputfield.text());
484 saveIcons(*m_iconfile);
485 }
486 m_inputfield.hide();
487 }
488
setCommandFromInput()489 void FbDesk::setCommandFromInput() {
490 if (m_last_icon != 0 &&
491 find(m_iconlist.begin(), m_iconlist.end(), m_last_icon) != m_iconlist.end()) {
492 m_last_icon->setCommand(m_inputfield.text());
493 saveIcons(*m_iconfile);
494 }
495 m_inputfield.hide();
496 }
497
498
499 class ToggleMenuItem:public MenuItem {
500 public:
ToggleMenuItem(const char * label,bool & val)501 explicit ToggleMenuItem(const char *label,
502 bool &val ):
503 MenuItem(label),
504 m_value( val ) {
505 setToggleItem(true);
506 }
click(int button,int time)507 void click(int button, int time) {
508 setSelected(!m_value);
509 FbTk::MenuItem::click(button, time);
510 }
511
setSelected(bool val)512 void setSelected(bool val) {
513 m_value = val;
514 }
isSelected() const515 bool isSelected() const {
516 return m_value;
517 }
518
519 private:
520 bool &m_value;
521 };
522
setupIconMenu()523 void FbDesk::setupIconMenu() {
524 using namespace FbTk;
525 // setup menu items
526 typedef RefCount<Command> CommandRef;
527 // RefCount<Command> show_iconbrowser(new SimpleCommand<IconBrowser>(m_iconbrowser, &IconBrowser::show));
528 typedef SimpleCommand<FbDesk> FbDeskCmd;
529 CommandRef new_icon(new FbDeskCmd(*this, &FbDesk::createIcon));
530 CommandRef del_last_icon(new FbDeskCmd(*this, &FbDesk::deleteLastIcon));
531 CommandRef set_command(new FbDeskCmd(*this, &FbDesk::setIconCommand));
532 CommandRef set_label(new FbDeskCmd(*this, &FbDesk::setIconLabel));
533 CommandRef reload_style(new FbDeskCmd(*this, &FbDesk::reloadConfig));
534 CommandRef exit_fbdesk(new SimpleCommand<App>(*App::instance(), &App::end));
535 // select_icon_image_hide(select_icon_macro);
536
537 m_iconmenu.setLabel("Icon menu");
538
539 m_iconmenu.insert("Set command", set_command);
540 m_iconmenu.insert("Set label", set_label);
541 m_iconmenu.insert(new FbTk::MenuSeparator());
542 m_iconmenu.insert("New icon", new_icon);
543 m_iconmenu.insert("Delete icon", del_last_icon);
544 m_iconmenu.insert(new FbTk::MenuSeparator());
545 // setup alpha menu
546 FbTk::MenuItem *item = new IntResMenuItem("Text alpha", m_text_alpha,
547 0, 255,
548 m_iconmenu);
549 CommandRef update_alpha(new FbTk::SimpleCommand<FbDesk>(*this, &FbDesk::updateAlpha));
550 item->setCommand(update_alpha);
551 m_iconmenu.insert(item);
552 item = new IntResMenuItem("Icon alpha", m_icon_alpha,
553 0, 255,
554 m_iconmenu);
555 item->setCommand(update_alpha);
556 m_iconmenu.insert(item);
557 m_iconmenu.insert("Reload config", reload_style);
558 m_iconmenu.insert(new FbTk::MenuSeparator());
559 m_iconmenu.insert(new ToggleMenuItem("Lock positions", *m_lock_positions) );
560 m_iconmenu.insert(new FbTk::MenuSeparator());
561 m_iconmenu.insert("Exit FbDesk", exit_fbdesk);
562 // m_iconmenu.insert("Select icon image", select_icon_image_hide);
563 m_iconmenu.reconfigure(); // update graphics
564 }
565
updateAlpha()566 void FbDesk::updateAlpha() {
567 m_resmanager.save(StringUtil::expandFilename(m_config_filename).c_str(),
568 StringUtil::expandFilename(m_config_filename).c_str()); // merge
569 m_icon_config.setTextAlpha(*m_text_alpha);
570 m_icon_config.setIconAlpha(*m_icon_alpha);
571 updateIcons();
572 }
573
updateIcons()574 void FbDesk::updateIcons() {
575 for_each(m_iconlist.begin(),
576 m_iconlist.end(),
577 mem_fun(&Icon::update));
578 }
579
580 }; // end namespace FbDesk
581
582 namespace FbTk {
583
584 template <>
setFromString(const char * str)585 void Resource<int>::setFromString(const char *str) {
586 sscanf(str, "%d", &*(*this));
587 }
588
589 template <>
getString() const590 std::string Resource<int>::getString() const {
591 char strval[256];
592 sprintf(strval, "%d", *(*this));
593 return std::string(strval);
594 }
595
596 template <>
setFromString(const char * str)597 void Resource<std::string>::setFromString(const char *str) {
598 *(*this) = (str ? str : "");
599 }
600
601 template <>
getString() const602 std::string Resource<std::string>::getString() const {
603 return (*this)->c_str();
604 }
605
606
607
608 template <>
getString() const609 std::string Resource<FbDesk::Icon::TextPlacement>::getString() const {
610 switch (*(*this)) {
611 case FbDesk::Icon::TEXTPLACE_LEFT:
612 return "Left";
613 case FbDesk::Icon::TEXTPLACE_RIGHT:
614 return "Right";
615 case FbDesk::Icon::TEXTPLACE_TOP:
616 return "Top";
617 case FbDesk::Icon::TEXTPLACE_BOTTOM:
618 return "Bottom";
619 }
620 return "Bottom";
621
622 }
623
624 template <>
setFromString(const char * str)625 void Resource<FbDesk::Icon::TextPlacement>::setFromString(const char *str) {
626 if (strcmp("Left", str) == 0) {
627 *(*this) = FbDesk::Icon::TEXTPLACE_LEFT;
628 } else if (strcmp("Right", str) == 0) {
629 *(*this) = FbDesk::Icon::TEXTPLACE_RIGHT;
630 } else if (strcmp("Top", str) == 0)
631 *(*this) = FbDesk::Icon::TEXTPLACE_TOP;
632 else if (strcmp("Bottom", str) == 0)
633 *(*this) = FbDesk::Icon::TEXTPLACE_BOTTOM;
634 else
635 *(*this) = FbDesk::Icon::TEXTPLACE_BOTTOM;
636 }
637
638 template<>
639 std::string FbTk::Resource<bool>::
getString() const640 getString() const {
641 return std::string(**this == true ? "true" : "false");
642 }
643
644
645 template<>
646 void FbTk::Resource<bool>::
setFromString(char const * strval)647 setFromString(char const *strval) {
648 *this = (bool)!strcasecmp(strval, "true");
649 }
650
651 } //end namespace FbTk
652