diff options
Diffstat (limited to 'src/MenuCreator.cc')
-rw-r--r-- | src/MenuCreator.cc | 186 |
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; | |||
59 | using std::vector; | 60 | using std::vector; |
60 | using std::list; | 61 | using std::list; |
61 | using std::less; | 62 | using std::less; |
63 | using FbTk::AutoReloadHelper; | ||
62 | 64 | ||
63 | list<string> MenuCreator::encoding_stack; | 65 | list<string> MenuCreator::encoding_stack; |
64 | list<size_t> MenuCreator::stacksize_stack; | 66 | list<size_t> MenuCreator::stacksize_stack; |
@@ -68,13 +70,16 @@ FbTk::StringConvertor MenuCreator::m_stringconvertor(FbTk::StringConvertor::ToFb | |||
68 | namespace { | 70 | namespace { |
69 | 71 | ||
70 | void createStyleMenu(FbTk::Menu &parent, const string &label, | 72 | void 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 | ||
106 | void createRootCmdMenu(FbTk::Menu &parent, const string &label, | 110 | void 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 | ||
175 | void translateMenuItem(FbTk::Parser &parse, ParseItem &item, FbTk::StringConvertor &labelconvertor); | 182 | void translateMenuItem(FbTk::Parser &parse, ParseItem &item, |
183 | FbTk::StringConvertor &labelconvertor, | ||
184 | AutoReloadHelper *reloader); | ||
176 | 185 | ||
177 | 186 | ||
178 | void parseMenu(FbTk::Parser &pars, FbTk::Menu &menu, FbTk::StringConvertor &label_convertor) { | 187 | void 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 | ||
188 | void translateMenuItem(FbTk::Parser &parse, ParseItem &pitem, FbTk::StringConvertor &labelconvertor) { | 199 | void 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 | |||
342 | void 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 | |||
365 | bool getStart(FbMenuParser &parser, string &label, FbTk::StringConvertor &labelconvertor) { | 350 | bool 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 | ||
383 | FbTk::Menu *MenuCreator::createMenu(const string &label, int screen_number) { | 368 | FbMenu *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 | ||
397 | FbTk::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 | |||
422 | bool MenuCreator::createFromFile(const string &filename, | 382 | bool 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 | 411 | FbMenu *MenuCreator::createMenuType(const string &type, int screen_num) { | |
447 | bool 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 | |||
470 | FbTk::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, |