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 "gtkutil/pointer.h"
27 #include "gtkutil/menu.h"
29 #include "pluginmanager.h"
30 #include "mainframe.h"
31 #include "preferences.h"
34 int m_nNextPlugInID = 0;
36 void plugin_activated( ui::Widget widget, gpointer data ){
37 const char* str = (const char*)g_object_get_data( G_OBJECT( widget ),"command" );
38 GetPlugInMgr().Dispatch( gpointer_to_int( data ), str );
43 void PlugInMenu_Add( GtkMenu* plugin_menu, IPlugIn* pPlugIn ){
44 ui::Widget item, parent;
45 ui::Menu menu{nullptr}, subMenu{nullptr};
46 const char *menuText, *menuCommand;
47 std::stack<ui::Menu> menuStack;
49 parent = ui::MenuItem( pPlugIn->getMenuName() );
51 gtk_container_add( GTK_CONTAINER( plugin_menu ), parent );
53 std::size_t nCount = pPlugIn->getCommandCount();
56 if ( g_Layout_enableDetachableMenus.m_value ) {
61 menuText = pPlugIn->getCommandTitle( --nCount );
62 menuCommand = pPlugIn->getCommand( nCount );
64 if ( menuText != 0 && strlen( menuText ) > 0 ) {
65 if ( !strcmp( menuText, "-" ) ) {
66 item = ui::Widget(gtk_menu_item_new());
67 gtk_widget_set_sensitive( item, FALSE );
69 else if ( !strcmp( menuText, ">" ) ) {
70 menuText = pPlugIn->getCommandTitle( --nCount );
71 menuCommand = pPlugIn->getCommand( nCount );
72 if ( !strcmp( menuText, "-" ) || !strcmp( menuText, ">" ) || !strcmp( menuText, "<" ) ) {
73 globalErrorStream() << pPlugIn->getMenuName() << " Invalid title (" << menuText << ") for submenu.\n";
77 item = ui::MenuItem( menuText );
79 gtk_container_add( GTK_CONTAINER( menu ), item );
82 gtk_menu_item_set_submenu( GTK_MENU_ITEM( item ), subMenu );
83 menuStack.push( menu );
87 else if ( !strcmp( menuText, "<" ) ) {
88 if ( !menuStack.empty() ) {
89 menu = menuStack.top();
94 globalErrorStream() << pPlugIn->getMenuName() << ": Attempt to end non-existent submenu ignored.\n";
100 item = ui::MenuItem( menuText );
101 g_object_set_data( G_OBJECT( item ),"command", const_cast<gpointer>( static_cast<const void*>( menuCommand ) ) );
102 g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( plugin_activated ), gint_to_pointer( m_nNextPlugInID ) );
105 gtk_container_add( GTK_CONTAINER( menu ), item );
106 pPlugIn->addMenuID( m_nNextPlugInID++ );
109 if ( !menuStack.empty() ) {
110 std::size_t size = menuStack.size();
112 globalErrorStream() << pPlugIn->getMenuName() << " mismatched > <. " << Unsigned( size ) << " submenu(s) not closed.\n";
114 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 GtkMenu* g_plugins_menu = 0;
126 GtkMenuItem* g_plugins_menu_separator = 0;
128 void PluginsMenu_populate(){
129 class PluginsMenuConstructor : public PluginsVisitor
133 PluginsMenuConstructor( GtkMenu* menu ) : m_menu( menu ){
135 void visit( IPlugIn& plugin ){
136 PlugInMenu_Add( m_menu, &plugin );
140 PluginsMenuConstructor constructor( g_plugins_menu );
141 GetPlugInMgr().constructMenu( constructor );
144 void PluginsMenu_clear(){
147 GList* lst = g_list_find( gtk_container_get_children( GTK_CONTAINER( g_plugins_menu ) ), GTK_WIDGET( g_plugins_menu_separator ) );
150 gtk_container_remove( GTK_CONTAINER( g_plugins_menu ), GTK_WIDGET( lst->next->data ) );
151 lst = g_list_find( gtk_container_get_children( GTK_CONTAINER( g_plugins_menu ) ), GTK_WIDGET( g_plugins_menu_separator ) );
155 ui::MenuItem create_plugins_menu(){
157 auto plugins_menu_item = new_sub_menu_item_with_mnemonic( "_Plugins" );
158 auto menu = ui::Menu(GTK_MENU( gtk_menu_item_get_submenu( plugins_menu_item ) ));
159 if ( g_Layout_enableDetachableMenus.m_value ) {
160 menu_tearoff( menu );
163 g_plugins_menu = menu;
165 //TODO: some modules/plugins do not yet support refresh
167 create_menu_item_with_mnemonic( menu, "Refresh", FreeCaller<Restart>() );
169 // NOTE: the seperator is used when doing a refresh of the list, everything past the seperator is removed
170 g_plugins_menu_separator = menu_separator( menu );
173 PluginsMenu_populate();
175 return plugins_menu_item;