From 95f721e35b91328615b9cb1de45da885ed921797 Mon Sep 17 00:00:00 2001 From: fluxgen Date: Sun, 2 May 2004 20:59:29 +0000 Subject: creates menus... --- src/MenuCreator.cc | 421 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/MenuCreator.hh | 46 ++++++ 2 files changed, 467 insertions(+) create mode 100644 src/MenuCreator.cc create mode 100644 src/MenuCreator.hh diff --git a/src/MenuCreator.cc b/src/MenuCreator.cc new file mode 100644 index 0000000..cdec5c7 --- /dev/null +++ b/src/MenuCreator.cc @@ -0,0 +1,421 @@ +// MenuCreator.cc for Fluxbox +// Copyright (c) 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) +// and Simon Bowden (rathnor at users.sourceforge.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// $Id: MenuCreator.cc,v 1.1 2004/05/02 20:59:29 fluxgen Exp $ + +#include "MenuCreator.hh" + +#include "Screen.hh" +#include "CommandParser.hh" +#include "fluxbox.hh" +#include "CommandParser.hh" +#include "Window.hh" +#include "I18n.hh" + +#include "FbMenu.hh" +#include "IconMenu.hh" +#include "WorkspaceMenu.hh" +#include "LayerMenu.hh" +#include "SendToMenu.hh" + +#include "FbMenuParser.hh" +#include "StyleMenuItem.hh" + +#include "FbTk/MultiButtonMenuItem.hh" +#include "FbTk/RefCount.hh" +#include "FbTk/MacroCommand.hh" +#include "FbTk/SimpleCommand.hh" +#include "FbTk/StringUtil.hh" +#include "FbTk/Directory.hh" + +#include +using namespace std; + +template <> +void LayerMenuItem::click(int button, int time) { + m_object->moveToLayer(m_layernum); +} + +static FbTk::Menu *createStyleMenu(FbTk::Menu &parent, const std::string &label, + const std::string &directory) { + // perform shell style ~ home directory expansion + string stylesdir(FbTk::StringUtil::expandFilename(directory)); + + if (!FbTk::Directory::isDirectory(stylesdir)) + return 0; + + FbTk::Directory dir(stylesdir.c_str()); + + // create a vector of all the filenames in the directory + // add sort it + std::vector filelist(dir.entries()); + for (size_t file_index = 0; file_index < dir.entries(); ++file_index) + filelist[file_index] = dir.readFilename(); + + std::sort(filelist.begin(), filelist.end(), less()); + + // for each file in directory add filename and path to menu + for (size_t file_index = 0; file_index < dir.entries(); file_index++) { + std::string style(stylesdir + '/' + filelist[file_index]); + // add to menu only if the file is a regular file, and not a + // .file or a backup~ file + if ((FbTk::Directory::isRegularFile(style) && + (filelist[file_index][0] != '.') && + (style[style.length() - 1] != '~')) || + FbTk::Directory::isRegularFile(style + "/theme.cfg")) + parent.insert(new StyleMenuItem(filelist[file_index], style)); + } + // update menu graphics + parent.update(); + Fluxbox::instance()->saveMenuFilename(stylesdir.c_str()); +} + +static void translateMenuItem(Parser &parse, + const std::string &str_key, + const std::string &str_label, + const std::string &str_cmd, + FbTk::Menu &menu); + + +static void parseMenu(Parser &pars, FbTk::Menu &menu) { + Parser::Item item, item2, item3; + while (!pars.eof()) { + pars>>item>>item2>>item3; + if (item.second == "end") + return; + translateMenuItem(pars, + item.second, + item2.second, + item3.second, + menu); + + } +} + +static void translateMenuItem(Parser &parse, + const std::string &str_key, + const std::string &str_label, + const std::string &str_cmd, + FbTk::Menu &menu) { + + const int screen_number = menu.screenNumber(); + static I18n &i18n = *I18n::instance(); + using namespace FBNLS; + +#define SCREENNLS(a, b) i18n.getMessage(ScreenSet, a, b) + + if (str_key == "end") { + return; + } else if (str_key == "nop") { + menu.insert(str_label.c_str()); + } else if (str_key == "icons") { + FbTk::Menu *submenu = MenuCreator::createMenuType("iconmenu", menu.screenNumber()); + if (submenu == 0) + return; + if (str_label.empty()) + menu.insert(i18n.getMessage(IconSet, IconIcons, "Icons")); + else + menu.insert(str_label.c_str(), submenu); + } else if (str_key == "exit") { // exit + FbTk::RefCount exit_cmd(CommandParser::instance().parseLine("exit")); + if (str_label.empty()) + menu.insert(SCREENNLS(ScreenExit, "Exit"), exit_cmd); + else + menu.insert(str_label.c_str(), exit_cmd); + } else if (str_key == "exec") { + // execute and hide menu + using namespace FbTk; + RefCount exec_cmd(CommandParser::instance().parseLine("exec " + str_cmd)); + RefCount hide_menu(new SimpleCommand(menu, + &Menu::hide)); + MacroCommand *exec_and_hide = new FbTk::MacroCommand(); + exec_and_hide->add(hide_menu); + exec_and_hide->add(exec_cmd); + RefCount exec_and_hide_cmd(exec_and_hide); + menu.insert(str_label.c_str(), exec_and_hide_cmd); + } + else if (str_key == "style") { // style + menu.insert(new StyleMenuItem(str_label, str_cmd)); + } else if (str_key == "config") { + BScreen *screen = Fluxbox::instance()->findScreen(screen_number); + if (screen != 0) + menu.insert(str_label.c_str(), &screen->configMenu()); + } // end of config + else if (str_key == "include") { // include + string newfile = FbTk::StringUtil::expandFilename(str_label); + // inject this file into the current menu + MenuCreator::createFromFile(newfile, menu); + Fluxbox::instance()->saveMenuFilename(newfile.c_str()); + } // end of include + else if (str_key == "submenu") { + + FbTk::Menu *submenu = MenuCreator::createMenu("", screen_number); + if (submenu == 0) + return; + + if (str_cmd.size()) + submenu->setLabel(str_cmd.c_str()); + else + submenu->setLabel(str_label.c_str()); + + parseMenu(parse, *submenu); + submenu->update(); + menu.insert(str_label.c_str(), submenu); + // save to screen list so we can delete it later + BScreen *screen = Fluxbox::instance()->findScreen(screen_number); + if (screen != 0) + screen->saveMenu(*submenu); + + } // end of submenu + else if (str_key == "restart") { + FbTk::RefCount restart_fb(CommandParser::instance(). + parseLine("restart")); + if (str_label.empty()) + menu.insert(SCREENNLS(ScreenRestart, "Restart"), restart_fb); + else + menu.insert(str_label.c_str(), restart_fb); + } // end of restart + else if (str_key == "reconfig") { // reconf + // + //!! TODO: NLS + // + FbTk::RefCount + reconfig_fb_cmd(CommandParser::instance(). + parseLine("reconfigure")); + menu.insert(str_label.c_str(), reconfig_fb_cmd); + + } else if (str_key == "stylesdir" || str_key == "stylesmenu") { + createStyleMenu(menu, str_label, + str_key == "stylesmenu" ? str_cmd : str_label); + } // end of stylesdir + else if (str_key == "workspaces") { + BScreen *screen = Fluxbox::instance()->findScreen(screen_number); + if (screen != 0) { + screen->getWorkspacemenu().setInternalMenu(); + menu.insert(str_label.c_str(), &screen->getWorkspacemenu()); + } + } else if (str_key == "separator") { + menu.insert("---"); //!! TODO: this will be better in the future + } else { // ok, if we didn't find any special menu item we try with command parser + // we need to attach command with arguments so command parser can parse it + string line = str_key + " " + str_cmd; + FbTk::RefCount command(CommandParser::instance().parseLine(line)); + if (*command != 0) + menu.insert(str_label.c_str(), command); + } +#undef SCREENNLS + +} + + +static void parseWindowMenu(Parser &parse, FbTk::Menu &menu, FluxboxWindow &win) { + + Parser::Item item, item2, item3; + while (!parse.eof()) { + parse>>item>>item2>>item3; + if (MenuCreator::createWindowMenuItem(item.second, item2.second, menu, win)) + continue; + + if (item.second == "end") { + return; + } else if (item.second == "submenu") { + FbTk::Menu *submenu = MenuCreator::createMenu(item2.second, menu.screenNumber()); + parseWindowMenu(parse, *submenu, win); + submenu->update(); + menu.insert(item2.second.c_str(), submenu); + + } else { // try non window menu specific stuff + translateMenuItem(parse, item.second, item2.second, item3.second, menu); + } + } +} + +FbTk::Menu *MenuCreator::createMenu(const std::string &label, int screen_number) { + BScreen *screen = Fluxbox::instance()->findScreen(screen_number); + if (screen == 0) + return 0; + + FbTk::Menu *menu = new FbMenu(screen->menuTheme(), + screen->imageControl(), + *screen->layerManager(). + getLayer(Fluxbox::instance()->getMenuLayer())); + if (!label.empty()) + menu->setLabel(label.c_str()); + + return menu; +} + +bool getStart(FbMenuParser &parser, std::string &label) { + Parser::Item item, item2, item3; + while (!parser.eof()) { + // get first begin line + parser>>item>>item2>>item3; + if (item.second == "begin") { + break; + } + } + if (parser.eof()) + return false; + label = item2.second; + return true; +} + +FbTk::Menu *MenuCreator::createFromFile(const std::string &filename, int screen_number) { + FbMenuParser parser(filename); + if (!parser.isLoaded()) + return 0; + + std::string label; + if (!getStart(parser, label)) + return 0; + + FbTk::Menu *menu = createMenu(label, screen_number); + if (menu != 0) + parseMenu(parser, *menu); + + return menu; +} + + +void MenuCreator::createFromFile(const std::string &filename, + FbTk::Menu &inject_into) { + + std::string real_filename = FbTk::StringUtil::expandFilename(filename); + FbMenuParser parser(real_filename); + if (!parser.isLoaded()) + return; + + std::string label; + if (!getStart(parser, label)) + return; + + parseMenu(parser, inject_into); +} + + +void MenuCreator::createFromFile(const std::string &filename, + FbTk::Menu &inject_into, + FluxboxWindow &win) { + std::string real_filename = FbTk::StringUtil::expandFilename(filename); + FbMenuParser parser(real_filename); + if (!parser.isLoaded()) + return; + + std::string label; + + if (!getStart(parser, label)) + return; + + parseWindowMenu(parser, inject_into, win); +} + + +FbTk::Menu *MenuCreator::createMenuType(const std::string &type, int screen_num) { + BScreen *screen = Fluxbox::instance()->findScreen(screen_num); + if (screen == 0) + return 0; + if (type == "iconmenu") { + return new IconMenu(*screen); + } else if (type == "workspacemenu") { + return new WorkspaceMenu(*screen); + } + +} + +bool MenuCreator::createWindowMenuItem(const std::string &type, + const std::string &label, + FbTk::Menu &menu, + FluxboxWindow &win) { + static I18n &i18n = *I18n::instance(); + typedef FbTk::RefCount RefCmd; + typedef FbTk::SimpleCommand WindowCmd; + using namespace FBNLS; + +#define WINDOWNLS(a, b) std::string real_label = label; if (label.empty()) real_label = i18n.getMessage(FBNLS::WindowmenuSet, a, b) + + if (type == "shade") { + WINDOWNLS(WindowmenuShade, "Shade"); + RefCmd shade_cmd(new WindowCmd(win, &FluxboxWindow::shade)); + menu.insert(real_label.c_str(), shade_cmd); + } else if (type == "maximize") { + WINDOWNLS(WindowmenuMaximize, "Maximize"); + RefCmd maximize_cmd(new WindowCmd(win, &FluxboxWindow::maximizeFull)); + RefCmd maximize_vert_cmd(new WindowCmd(win, &FluxboxWindow::maximizeVertical)); + RefCmd maximize_horiz_cmd(new WindowCmd(win, &FluxboxWindow::maximizeHorizontal)); + FbTk::MultiButtonMenuItem *maximize_item = new FbTk::MultiButtonMenuItem(3, real_label.c_str()); + // create maximize item with: + // button1: Maximize normal + // button2: Maximize Vertical + // button3: Maximize Horizontal + maximize_item->setCommand(1, maximize_cmd); + maximize_item->setCommand(2, maximize_vert_cmd); + maximize_item->setCommand(3, maximize_horiz_cmd); + menu.insert(maximize_item); + } else if (type == "iconify") { + WINDOWNLS(WindowmenuIconify, "Iconify"); + RefCmd iconify_cmd(new WindowCmd(win, &FluxboxWindow::iconify)); + menu.insert(real_label.c_str(), iconify_cmd); + } else if (type == "close") { + WINDOWNLS(WindowmenuClose, "Close"); + RefCmd close_cmd(new WindowCmd(win, &FluxboxWindow::close)); + menu.insert(real_label.c_str(), close_cmd); + } else if (type == "lower") { + WINDOWNLS(WindowmenuLower, "Lower"); + RefCmd lower_cmd(new WindowCmd(win, &FluxboxWindow::lower)); + menu.insert(real_label.c_str(), lower_cmd); + } else if (type == "raise") { + WINDOWNLS(WindowmenuRaise, "Raise"); + RefCmd raise_cmd(new WindowCmd(win, &FluxboxWindow::raise)); + menu.insert(real_label.c_str(), raise_cmd); + } else if (type == "stick") { + WINDOWNLS(WindowmenuStick, "Stick"); + RefCmd stick_cmd(new WindowCmd(win, &FluxboxWindow::stick)); + menu.insert(real_label.c_str(), stick_cmd); + } else if (type == "extramenus") { + FluxboxWindow::ExtraMenus::iterator it = win.extraMenus().begin(); + FluxboxWindow::ExtraMenus::iterator it_end = win.extraMenus().end(); + for (; it != it_end; ++it) { + it->second->disableTitle(); + menu.insert(it->first, it->second); + } + + } else if (type == "sendto") { + WINDOWNLS(WindowmenuSendTo, "Send To ..."); + menu.insert(real_label.c_str(), new SendToMenu(win)); + } else if (type == "layer") { + WINDOWNLS(WindowmenuLayer, "Layer ..."); + BScreen *screen = Fluxbox::instance()->findScreen(menu.screenNumber()); + if (screen == 0) + return false; + menu.insert(real_label.c_str(), + new LayerMenu(screen->menuTheme(), + screen->imageControl(), + *screen->layerManager().getLayer(Fluxbox::instance()->getMenuLayer()), + &win, + false)); + + } else + return false; +#undef WINDOWNLS + + return true; +} diff --git a/src/MenuCreator.hh b/src/MenuCreator.hh new file mode 100644 index 0000000..d9625f3 --- /dev/null +++ b/src/MenuCreator.hh @@ -0,0 +1,46 @@ +// MenuCreator.hh for Fluxbox +// Copyright (c) 2004 Henrik Kinnunen (fluxgen at users.sourceforge.net) +// and Simon Bowden (rathnor at users.sourceforge.net) +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef MENUCREATOR_HH +#define MENUCREATOR_HH + +#include + +namespace FbTk { +class Menu; +} + +class FluxboxWindow; + +class MenuCreator { +public: + static FbTk::Menu *createMenu(const std::string &label, int screen_num); + static FbTk::Menu *createFromFile(const std::string &filename, int screen_num); + static FbTk::Menu *createMenuType(const std::string &label, int screen_num); + static void createFromFile(const std::string &filename, FbTk::Menu &inject_into); + static void createFromFile(const std::string &filename, FbTk::Menu &inject_into, + FluxboxWindow &win); + static bool createWindowMenuItem(const std::string &type, const std::string &label, + FbTk::Menu &inject_into, FluxboxWindow &win); +}; + +#endif // MENUCREATOR_HH -- cgit v0.11.2