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"
24 #include "stream/textstream.h"
26 #include <gtk/gtkmenu.h>
27 #include <gtk/gtkmenuitem.h>
29 #include "gtkutil/pointer.h"
30 #include "gtkutil/menu.h"
32 #include "pluginmanager.h"
33 #include "mainframe.h"
34 #include "preferences.h"
37 int m_nNextPlugInID = 0;
39 void plugin_activated(GtkWidget* widget, gpointer data)
41 const char* str = (const char*)g_object_get_data(G_OBJECT(widget),"command");
42 GetPlugInMgr().Dispatch(gpointer_to_int(data), str);
46 typedef std::stack<GtkWidget*> WidgetStack;
48 void PlugInMenu_Add(GtkMenu* plugin_menu, IPlugIn* pPlugIn)
50 GtkWidget *menu, *item, *parent, *subMenu;
51 const char *menuText, *menuCommand;
52 WidgetStack menuStack;
54 parent = gtk_menu_item_new_with_label (pPlugIn->getMenuName());
55 gtk_widget_show (parent);
56 gtk_container_add (GTK_CONTAINER (plugin_menu), parent);
58 std::size_t nCount = pPlugIn->getCommandCount();
61 menu = gtk_menu_new();
62 if (g_Layout_enableDetachableMenus.m_value)
63 menu_tearoff (GTK_MENU(menu));
66 menuText = pPlugIn->getCommandTitle(--nCount);
67 menuCommand = pPlugIn->getCommand(nCount);
69 if (menuText != 0 && strlen(menuText) > 0)
71 if (!strcmp(menuText, "-"))
73 item = gtk_menu_item_new();
74 gtk_widget_set_sensitive (item, FALSE);
76 else if (!strcmp(menuText, ">"))
78 menuText = pPlugIn->getCommandTitle(--nCount);
79 menuCommand = pPlugIn->getCommand(nCount);
80 if (!strcmp(menuText, "-") || !strcmp(menuText, ">") || !strcmp(menuText, "<"))
82 globalErrorStream() << pPlugIn->getMenuName() << " Invalid title (" << menuText << ") for submenu.\n";
86 item = gtk_menu_item_new_with_label(menuText);
87 gtk_widget_show (item);
88 gtk_container_add (GTK_CONTAINER (menu), item);
90 subMenu = gtk_menu_new();
91 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), subMenu);
96 else if (!strcmp(menuText, "<"))
98 if (!menuStack.empty())
100 menu = menuStack.top();
105 globalErrorStream() << pPlugIn->getMenuName() << ": Attempt to end non-existent submenu ignored.\n";
111 item = gtk_menu_item_new_with_label (menuText);
112 g_object_set_data(G_OBJECT(item),"command", const_cast<gpointer>(static_cast<const void*>(menuCommand)));
113 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(plugin_activated), gint_to_pointer(m_nNextPlugInID));
115 gtk_widget_show (item);
116 gtk_container_add (GTK_CONTAINER (menu), item);
117 pPlugIn->addMenuID(m_nNextPlugInID++);
120 if (!menuStack.empty())
122 std::size_t size = menuStack.size();
125 globalErrorStream() << pPlugIn->getMenuName() << " mismatched > <. " << Unsigned(size) << " submenu(s) not closed.\n";
127 for (std::size_t i = 0; i < (size -1); i++)
131 menu = menuStack.top();
134 gtk_menu_item_set_submenu (GTK_MENU_ITEM (parent), menu);
138 GtkMenu* g_plugins_menu = 0;
139 GtkMenuItem* g_plugins_menu_separator = 0;
141 void PluginsMenu_populate()
143 class PluginsMenuConstructor : public PluginsVisitor
147 PluginsMenuConstructor(GtkMenu* menu) : m_menu(menu)
150 void visit(IPlugIn& plugin)
152 PlugInMenu_Add(m_menu, &plugin);
156 PluginsMenuConstructor constructor(g_plugins_menu);
157 GetPlugInMgr().constructMenu(constructor);
160 void PluginsMenu_clear()
164 GList* lst = g_list_find (gtk_container_children(GTK_CONTAINER(g_plugins_menu)), GTK_WIDGET(g_plugins_menu_separator));
167 gtk_container_remove (GTK_CONTAINER(g_plugins_menu), GTK_WIDGET (lst->next->data));
168 lst = g_list_find (gtk_container_children(GTK_CONTAINER(g_plugins_menu)), GTK_WIDGET(g_plugins_menu_separator));
172 GtkMenuItem* create_plugins_menu()
175 GtkMenuItem* plugins_menu_item = new_sub_menu_item_with_mnemonic("_Plugins");
176 GtkMenu* menu = GTK_MENU(gtk_menu_item_get_submenu(plugins_menu_item));
177 if (g_Layout_enableDetachableMenus.m_value)
182 g_plugins_menu = menu;
184 //TODO: some modules/plugins do not yet support refresh
186 create_menu_item_with_mnemonic(menu, "Refresh", FreeCaller<Restart>());
188 // NOTE: the seperator is used when doing a refresh of the list, everything past the seperator is removed
189 g_plugins_menu_separator = menu_separator(menu);
192 PluginsMenu_populate();
194 return plugins_menu_item;