2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "pluginmenu.h"
26 #include "stream/textstream.h"
28 #include "gtkutil/pointer.h"
29 #include "gtkutil/menu.h"
31 #include "pluginmanager.h"
32 #include "mainframe.h"
33 #include "preferences.h"
36 int m_nNextPlugInID = 0;
38 void plugin_activated(ui::Widget widget, gpointer data)
40 const char *str = (const char *) g_object_get_data(G_OBJECT(widget), "command");
41 GetPlugInMgr().Dispatch(gpointer_to_int(data), str);
46 void PlugInMenu_Add(ui::Menu plugin_menu, IPlugIn *pPlugIn)
48 ui::Widget item{ui::null}, parent{ui::null};
49 ui::Menu menu{ui::null}, subMenu{ui::null};
50 const char *menuText, *menuCommand;
51 std::stack<ui::Menu> menuStack;
53 parent = ui::MenuItem(pPlugIn->getMenuName());
55 plugin_menu.add(parent);
57 std::size_t nCount = pPlugIn->getCommandCount();
59 menu = ui::Menu(ui::New);
60 if (g_Layout_enableDetachableMenus.m_value) {
64 menuText = pPlugIn->getCommandTitle(--nCount);
65 menuCommand = pPlugIn->getCommand(nCount);
67 if (menuText != 0 && strlen(menuText) > 0) {
68 if (!strcmp(menuText, "-")) {
69 item = ui::Widget::from(gtk_menu_item_new());
70 gtk_widget_set_sensitive(item, FALSE);
71 } else if (!strcmp(menuText, ">")) {
72 menuText = pPlugIn->getCommandTitle(--nCount);
73 menuCommand = pPlugIn->getCommand(nCount);
74 if (!strcmp(menuText, "-") || !strcmp(menuText, ">") || !strcmp(menuText, "<")) {
75 globalErrorStream() << pPlugIn->getMenuName() << " Invalid title (" << menuText
76 << ") for submenu.\n";
80 item = ui::MenuItem(menuText);
84 subMenu = ui::Menu(ui::New);
85 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), subMenu);
89 } else if (!strcmp(menuText, "<")) {
90 if (!menuStack.empty()) {
91 menu = menuStack.top();
94 globalErrorStream() << pPlugIn->getMenuName()
95 << ": Attempt to end non-existent submenu ignored.\n";
99 item = ui::MenuItem(menuText);
100 g_object_set_data(G_OBJECT(item), "command",
101 const_cast<gpointer>( static_cast<const void *>( menuCommand )));
102 item.connect("activate", G_CALLBACK(plugin_activated), gint_to_pointer(m_nNextPlugInID));
106 pPlugIn->addMenuID(m_nNextPlugInID++);
109 if (!menuStack.empty()) {
110 std::size_t size = menuStack.size();
112 globalErrorStream() << pPlugIn->getMenuName() << " mismatched > <. " << Unsigned(size)
113 << " submenu(s) not closed.\n";
115 for (std::size_t i = 0; i < (size - 1); i++) {
118 menu = menuStack.top();
121 gtk_menu_item_set_submenu(GTK_MENU_ITEM(parent), menu);
125 ui::Menu g_plugins_menu{ui::null};
126 ui::MenuItem g_plugins_menu_separator{ui::null};
128 void PluginsMenu_populate()
130 class PluginsMenuConstructor : public PluginsVisitor {
133 PluginsMenuConstructor(ui::Menu menu) : m_menu(menu)
137 void visit(IPlugIn &plugin)
139 PlugInMenu_Add(m_menu, &plugin);
143 PluginsMenuConstructor constructor(g_plugins_menu);
144 GetPlugInMgr().constructMenu(constructor);
147 void PluginsMenu_clear()
151 GList *lst = g_list_find(gtk_container_get_children(GTK_CONTAINER(g_plugins_menu)),
152 g_plugins_menu_separator._handle);
154 g_plugins_menu.remove(ui::Widget::from(lst->next->data));
155 lst = g_list_find(gtk_container_get_children(GTK_CONTAINER(g_plugins_menu)), g_plugins_menu_separator._handle);
159 ui::MenuItem create_plugins_menu()
162 auto plugins_menu_item = new_sub_menu_item_with_mnemonic("_Plugins");
163 auto menu = ui::Menu::from(gtk_menu_item_get_submenu(plugins_menu_item));
164 if (g_Layout_enableDetachableMenus.m_value) {
168 g_plugins_menu = menu;
170 //TODO: some modules/plugins do not yet support refresh
172 create_menu_item_with_mnemonic( menu, "Refresh", makeCallbackF(Restart) );
174 // NOTE: the seperator is used when doing a refresh of the list, everything past the seperator is removed
175 g_plugins_menu_separator = menu_separator( menu );
178 PluginsMenu_populate();
180 return plugins_menu_item;