aboutsummaryrefslogtreecommitdiff
path: root/src/MenuCreator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/MenuCreator.cc')
-rw-r--r--src/MenuCreator.cc186
1 files changed, 50 insertions, 136 deletions
diff --git a/src/MenuCreator.cc b/src/MenuCreator.cc
index 9f20155..34dce94 100644
--- a/src/MenuCreator.cc
+++ b/src/MenuCreator.cc
@@ -28,6 +28,7 @@
28#include "fluxbox.hh" 28#include "fluxbox.hh"
29#include "Window.hh" 29#include "Window.hh"
30#include "WindowCmd.hh" 30#include "WindowCmd.hh"
31#include "WindowMenuAccessor.hh"
31 32
32#include "ClientMenu.hh" 33#include "ClientMenu.hh"
33#include "WorkspaceMenu.hh" 34#include "WorkspaceMenu.hh"
@@ -59,6 +60,7 @@ using std::string;
59using std::vector; 60using std::vector;
60using std::list; 61using std::list;
61using std::less; 62using std::less;
63using FbTk::AutoReloadHelper;
62 64
63list<string> MenuCreator::encoding_stack; 65list<string> MenuCreator::encoding_stack;
64list<size_t> MenuCreator::stacksize_stack; 66list<size_t> MenuCreator::stacksize_stack;
@@ -68,13 +70,16 @@ FbTk::StringConvertor MenuCreator::m_stringconvertor(FbTk::StringConvertor::ToFb
68namespace { 70namespace {
69 71
70void createStyleMenu(FbTk::Menu &parent, const string &label, 72void createStyleMenu(FbTk::Menu &parent, const string &label,
71 const string &directory) { 73 AutoReloadHelper *reloader, const string &directory) {
72 // perform shell style ~ home directory expansion 74 // perform shell style ~ home directory expansion
73 string stylesdir(FbTk::StringUtil::expandFilename(directory)); 75 string stylesdir(FbTk::StringUtil::expandFilename(directory));
74 76
75 if (!FbTk::FileUtil::isDirectory(stylesdir.c_str())) 77 if (!FbTk::FileUtil::isDirectory(stylesdir.c_str()))
76 return; 78 return;
77 79
80 if (reloader)
81 reloader->addFile(stylesdir);
82
78 FbTk::Directory dir(stylesdir.c_str()); 83 FbTk::Directory dir(stylesdir.c_str());
79 84
80 // create a vector of all the filenames in the directory 85 // create a vector of all the filenames in the directory
@@ -99,18 +104,21 @@ void createStyleMenu(FbTk::Menu &parent, const string &label,
99 } 104 }
100 // update menu graphics 105 // update menu graphics
101 parent.updateMenu(); 106 parent.updateMenu();
102 Fluxbox::instance()->saveMenuFilename(stylesdir.c_str());
103 107
104} 108}
105 109
106void createRootCmdMenu(FbTk::Menu &parent, const string &label, 110void createRootCmdMenu(FbTk::Menu &parent, const string &label,
107 const string &directory, const string &cmd) { 111 const string &directory, AutoReloadHelper *reloader,
112 const string &cmd) {
108 // perform shell style ~ home directory expansion 113 // perform shell style ~ home directory expansion
109 string rootcmddir(FbTk::StringUtil::expandFilename(directory)); 114 string rootcmddir(FbTk::StringUtil::expandFilename(directory));
110 115
111 if (!FbTk::FileUtil::isDirectory(rootcmddir.c_str())) 116 if (!FbTk::FileUtil::isDirectory(rootcmddir.c_str()))
112 return; 117 return;
113 118
119 if (reloader)
120 reloader->addFile(rootcmddir);
121
114 FbTk::Directory dir(rootcmddir.c_str()); 122 FbTk::Directory dir(rootcmddir.c_str());
115 123
116 // create a vector of all the filenames in the directory 124 // create a vector of all the filenames in the directory
@@ -134,7 +142,6 @@ void createRootCmdMenu(FbTk::Menu &parent, const string &label,
134 } 142 }
135 // update menu graphics 143 // update menu graphics
136 parent.updateMenu(); 144 parent.updateMenu();
137 Fluxbox::instance()->saveMenuFilename(rootcmddir.c_str());
138 145
139} 146}
140 147
@@ -172,20 +179,26 @@ public:
172 179
173}; 180};
174 181
175void translateMenuItem(FbTk::Parser &parse, ParseItem &item, FbTk::StringConvertor &labelconvertor); 182void translateMenuItem(FbTk::Parser &parse, ParseItem &item,
183 FbTk::StringConvertor &labelconvertor,
184 AutoReloadHelper *reloader);
176 185
177 186
178void parseMenu(FbTk::Parser &pars, FbTk::Menu &menu, FbTk::StringConvertor &label_convertor) { 187void parseMenu(FbTk::Parser &pars, FbTk::Menu &menu,
188 FbTk::StringConvertor &label_convertor,
189 AutoReloadHelper *reloader) {
179 ParseItem pitem(&menu); 190 ParseItem pitem(&menu);
180 while (!pars.eof()) { 191 while (!pars.eof()) {
181 pitem.load(pars, label_convertor); 192 pitem.load(pars, label_convertor);
182 if (pitem.key() == "end") 193 if (pitem.key() == "end")
183 return; 194 return;
184 translateMenuItem(pars, pitem, label_convertor); 195 translateMenuItem(pars, pitem, label_convertor, reloader);
185 } 196 }
186} 197}
187 198
188void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConvertor &labelconvertor) { 199void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem,
200 FbTk::StringConvertor &labelconvertor,
201 AutoReloadHelper *reloader) {
189 if (pitem.menu() == 0) 202 if (pitem.menu() == 0)
190 throw string("translateMenuItem: We must have a menu in ParseItem!"); 203 throw string("translateMenuItem: We must have a menu in ParseItem!");
191 204
@@ -255,13 +268,13 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
255 if (FbTk::FileUtil::isRegularFile(thisfile.c_str()) && 268 if (FbTk::FileUtil::isRegularFile(thisfile.c_str()) &&
256 (filelist[file_index][0] != '.') && 269 (filelist[file_index][0] != '.') &&
257 (thisfile[thisfile.length() - 1] != '~')) { 270 (thisfile[thisfile.length() - 1] != '~')) {
258 MenuCreator::createFromFile(thisfile, menu, false); 271 MenuCreator::createFromFile(thisfile, menu, reloader, false);
259 } 272 }
260 } 273 }
261 274
262 } else { 275 } else {
263 // inject this file into the current menu 276 // inject this file into the current menu
264 MenuCreator::createFromFile(newfile, menu, false); 277 MenuCreator::createFromFile(newfile, menu, reloader, false);
265 } 278 }
266 279
267 safe_counter--; 280 safe_counter--;
@@ -278,26 +291,22 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
278 else 291 else
279 submenu->setLabel(str_label); 292 submenu->setLabel(str_label);
280 293
281 parseMenu(parse, *submenu, labelconvertor); 294 parseMenu(parse, *submenu, labelconvertor, reloader);
282 submenu->updateMenu(); 295 submenu->updateMenu();
283 menu.insert(str_label, submenu); 296 menu.insert(str_label, submenu);
284 // save to screen list so we can delete it later
285 BScreen *screen = Fluxbox::instance()->findScreen(screen_number);
286 if (screen != 0)
287 screen->saveMenu(*submenu);
288 297
289 } // end of submenu 298 } // end of submenu
290 else if (str_key == "stylesdir" || str_key == "stylesmenu") { 299 else if (str_key == "stylesdir" || str_key == "stylesmenu") {
291 createStyleMenu(menu, str_label, 300 createStyleMenu(menu, str_label, reloader,
292 str_key == "stylesmenu" ? str_cmd : str_label); 301 str_key == "stylesmenu" ? str_cmd : str_label);
293 } // end of stylesdir 302 } // end of stylesdir
294 else if (str_key == "themesdir" || str_key == "themesmenu") { 303 else if (str_key == "themesdir" || str_key == "themesmenu") {
295 createStyleMenu(menu, str_label, 304 createStyleMenu(menu, str_label, reloader,
296 str_key == "themesmenu" ? str_cmd : str_label); 305 str_key == "themesmenu" ? str_cmd : str_label);
297 } // end of themesdir 306 } // end of themesdir
298 else if (str_key == "wallpapers" || str_key == "wallpapermenu" || 307 else if (str_key == "wallpapers" || str_key == "wallpapermenu" ||
299 str_key == "rootcommands") { 308 str_key == "rootcommands") {
300 createRootCmdMenu(menu, str_label, str_label, 309 createRootCmdMenu(menu, str_label, str_label, reloader,
301 str_cmd == "" ? realProgramName("fbsetbg") : str_cmd); 310 str_cmd == "" ? realProgramName("fbsetbg") : str_cmd);
302 } // end of wallpapers 311 } // end of wallpapers
303 else if (str_key == "workspaces") { 312 else if (str_key == "workspaces") {
@@ -312,9 +321,9 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
312 MenuCreator::startEncoding(str_cmd); 321 MenuCreator::startEncoding(str_cmd);
313 } else if (str_key == "endencoding") { 322 } else if (str_key == "endencoding") {
314 MenuCreator::endEncoding(); 323 MenuCreator::endEncoding();
315 } 324 } else if (!MenuCreator::createWindowMenuItem(str_key, str_label, menu)) {
316 else { // ok, if we didn't find any special menu item we try with command parser 325 // if we didn't find any special menu item we try with command parser
317 // we need to attach command with arguments so command parser can parse it 326 // we need to attach command to arguments so command parser can parse it
318 string line = str_key + " " + str_cmd; 327 string line = str_key + " " + str_cmd;
319 FbTk::RefCount<FbTk::Command<void> > command(FbTk::CommandParser<void>::instance().parse(line)); 328 FbTk::RefCount<FbTk::Command<void> > command(FbTk::CommandParser<void>::instance().parse(line));
320 if (*command != 0) { 329 if (*command != 0) {
@@ -338,30 +347,6 @@ void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConver
338 } 347 }
339} 348}
340 349
341
342void parseWindowMenu(FbTk::Parser &parse, FbTk::Menu &menu, FbTk::StringConvertor &labelconvertor) {
343
344 ParseItem pitem(&menu);
345 while (!parse.eof()) {
346 pitem.load(parse, labelconvertor);
347 if (MenuCreator::createWindowMenuItem(pitem.key(), pitem.label(), menu))
348 continue;
349
350 if (pitem.key() == "end") {
351 return;
352 } else if (pitem.key() == "submenu") {
353 FbTk::Menu *submenu = MenuCreator::createMenu(pitem.label(), menu.screenNumber());
354 parseWindowMenu(parse, *submenu, labelconvertor);
355 submenu->updateMenu();
356 menu.insert(pitem.label(), submenu);
357
358 } else { // try non window menu specific stuff
359 translateMenuItem(parse, pitem, labelconvertor);
360 }
361 }
362}
363
364
365bool getStart(FbMenuParser &parser, string &label, FbTk::StringConvertor &labelconvertor) { 350bool getStart(FbMenuParser &parser, string &label, FbTk::StringConvertor &labelconvertor) {
366 ParseItem pitem(0); 351 ParseItem pitem(0);
367 while (!parser.eof()) { 352 while (!parser.eof()) {
@@ -380,12 +365,12 @@ bool getStart(FbMenuParser &parser, string &label, FbTk::StringConvertor &labelc
380 365
381}; // end of anonymous namespace 366}; // end of anonymous namespace
382 367
383FbTk::Menu *MenuCreator::createMenu(const string &label, int screen_number) { 368FbMenu *MenuCreator::createMenu(const string &label, int screen_number) {
384 BScreen *screen = Fluxbox::instance()->findScreen(screen_number); 369 BScreen *screen = Fluxbox::instance()->findScreen(screen_number);
385 if (screen == 0) 370 if (screen == 0)
386 return 0; 371 return 0;
387 372
388 FbTk::Menu *menu = new FbMenu(screen->menuTheme(), 373 FbMenu *menu = new FbMenu(screen->menuTheme(),
389 screen->imageControl(), 374 screen->imageControl(),
390 *screen->layerManager().getLayer(Layer::MENU)); 375 *screen->layerManager().getLayer(Layer::MENU));
391 if (!label.empty()) 376 if (!label.empty())
@@ -394,33 +379,9 @@ FbTk::Menu *MenuCreator::createMenu(const string &label, int screen_number) {
394 return menu; 379 return menu;
395} 380}
396 381
397FbTk::Menu *MenuCreator::createFromFile(const string &filename, int screen_number, bool require_begin) {
398 string real_filename = FbTk::StringUtil::expandFilename(filename);
399 Fluxbox::instance()->saveMenuFilename(real_filename.c_str());
400
401 FbMenuParser parser(real_filename);
402 if (!parser.isLoaded())
403 return 0;
404
405 startFile();
406 string label;
407 if (require_begin && !getStart(parser, label, m_stringconvertor)) {
408 endFile();
409 return 0;
410 }
411
412 FbTk::Menu *menu = createMenu(label, screen_number);
413 if (menu != 0)
414 parseMenu(parser, *menu, m_stringconvertor);
415
416 endFile();
417
418 return menu;
419}
420
421
422bool MenuCreator::createFromFile(const string &filename, 382bool MenuCreator::createFromFile(const string &filename,
423 FbTk::Menu &inject_into, bool require_begin) { 383 FbTk::Menu &inject_into,
384 AutoReloadHelper *reloader, bool begin) {
424 string real_filename = FbTk::StringUtil::expandFilename(filename); 385 string real_filename = FbTk::StringUtil::expandFilename(filename);
425 386
426 FbMenuParser parser(real_filename); 387 FbMenuParser parser(real_filename);
@@ -428,81 +389,34 @@ bool MenuCreator::createFromFile(const string &filename,
428 return false; 389 return false;
429 390
430 startFile(); 391 startFile();
431 string label; 392 if (begin) {
432 if (require_begin && !getStart(parser, label, m_stringconvertor)) { 393 string label;
433 endFile(); 394 if (!getStart(parser, label, m_stringconvertor)) {
434 return false; 395 endFile();
396 return false;
397 }
398 inject_into.setLabel(label);
435 } 399 }
436 400
437 // save menu filename, so we can check if it changes 401 // save menu filename, so we can check if it changes
438 Fluxbox::instance()->saveMenuFilename(real_filename.c_str()); 402 if (reloader)
403 reloader->addFile(real_filename);
439 404
440 parseMenu(parser, inject_into, m_stringconvertor); 405 parseMenu(parser, inject_into, m_stringconvertor, reloader);
441 endFile(); 406 endFile();
442 407
443 return true; 408 return true;
444} 409}
445 410
446 411FbMenu *MenuCreator::createMenuType(const string &type, int screen_num) {
447bool MenuCreator::createWindowMenuFromFile(const string &filename,
448 FbTk::Menu &inject_into,
449 bool require_begin) {
450 string real_filename = FbTk::StringUtil::expandFilename(filename);
451 FbMenuParser parser(real_filename);
452 if (!parser.isLoaded())
453 return false;
454
455 string label;
456
457 startFile();
458 if (require_begin && !getStart(parser, label, m_stringconvertor)) {
459 endFile();
460 return false;
461 }
462
463 parseWindowMenu(parser, inject_into, m_stringconvertor);
464 endFile();
465
466 return true;
467}
468
469
470FbTk::Menu *MenuCreator::createMenuType(const string &type, int screen_num) {
471 BScreen *screen = Fluxbox::instance()->findScreen(screen_num); 412 BScreen *screen = Fluxbox::instance()->findScreen(screen_num);
472 if (screen == 0) 413 if (screen == 0)
473 return 0; 414 return 0;
474 if (type == "iconmenu") { 415 if (type == "iconmenu")
475 return new ClientMenu(*screen, screen->iconList(), 416 return new ClientMenu(*screen, screen->iconList(),
476 &screen->iconListSig()); 417 &screen->iconListSig());
477 } else if (type == "workspacemenu") { 418 else if (type == "workspacemenu")
478 return new WorkspaceMenu(*screen); 419 return new WorkspaceMenu(*screen);
479 } else if (type == "windowmenu") {
480 FbTk::Menu *menu = screen->createMenu("");
481
482 menu->disableTitle(); // not titlebar
483 if (screen->windowMenuFilename().empty() ||
484 ! createWindowMenuFromFile(screen->windowMenuFilename(), *menu, true)) {
485 const char *default_menu[] = {
486 "shade",
487 "stick",
488 "maximize",
489 "iconify",
490 "raise",
491 "lower",
492 "sendto",
493 "layer",
494 "alpha",
495 "extramenus",
496 "separator",
497 "close",
498 0
499 };
500 for (unsigned int i=0; default_menu[i]; ++i)
501 createWindowMenuItem(default_menu[i], "", *menu);
502 }
503 menu->reconfigure(); // update graphics
504 return menu;
505 }
506 420
507 return 0; 421 return 0;
508} 422}
@@ -516,7 +430,7 @@ bool MenuCreator::createWindowMenuItem(const string &type,
516 static MenuContext context; 430 static MenuContext context;
517 431
518 if (type == "shade") { 432 if (type == "shade") {
519 static WindowAccessor<bool> res(&FluxboxWindow::isShaded, &FluxboxWindow::setShaded, false); 433 static WindowMenuAccessor<bool> res(&FluxboxWindow::isShaded, &FluxboxWindow::setShaded, false);
520 menu.insert(new FbTk::BoolMenuItem( 434 menu.insert(new FbTk::BoolMenuItem(
521 label.empty()?_FB_XTEXT(Windowmenu, Shade, "Shade", "Shade the window"):label, 435 label.empty()?_FB_XTEXT(Windowmenu, Shade, "Shade", "Shade the window"):label,
522 res)); 436 res));
@@ -540,7 +454,7 @@ bool MenuCreator::createWindowMenuItem(const string &type,
540 maximize_item->setCommand(3, maximize_horiz_cmd); 454 maximize_item->setCommand(3, maximize_horiz_cmd);
541 menu.insert(maximize_item); 455 menu.insert(maximize_item);
542 } else if (type == "iconify") { 456 } else if (type == "iconify") {
543 static WindowAccessor<bool> res(&FluxboxWindow::isIconic, &FluxboxWindow::setIconic, false); 457 static WindowMenuAccessor<bool> res(&FluxboxWindow::isIconic, &FluxboxWindow::setIconic, false);
544 menu.insert(new FbTk::BoolMenuItem( 458 menu.insert(new FbTk::BoolMenuItem(
545 label.empty() ? 459 label.empty() ?
546 _FB_XTEXT(Windowmenu, Iconify, 460 _FB_XTEXT(Windowmenu, Iconify,
@@ -572,7 +486,7 @@ bool MenuCreator::createWindowMenuItem(const string &type,
572 label, raise_cmd); 486 label, raise_cmd);
573 487
574 } else if (type == "stick") { 488 } else if (type == "stick") {
575 static WindowAccessor<bool> res(&FluxboxWindow::isStuck, &FluxboxWindow::setStuck, false); 489 static WindowMenuAccessor<bool> res(&FluxboxWindow::isStuck, &FluxboxWindow::setStuck, false);
576 menu.insert(new FbTk::BoolMenuItem( 490 menu.insert(new FbTk::BoolMenuItem(
577 label.empty() ? 491 label.empty() ?
578 _FB_XTEXT(Windowmenu, Stick, 492 _FB_XTEXT(Windowmenu, Stick,