/* Copyright (C) 1999-2006 Id Software, Inc. and contributors. For a list of contributors, see the accompanying CONTRIBUTORS file. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "pluginmenu.h" #include "stream/textstream.h" #include #include #include "gtkutil/pointer.h" #include "gtkutil/menu.h" #include "pluginmanager.h" #include "mainframe.h" #include "preferences.h" int m_nNextPlugInID = 0; void plugin_activated( GtkWidget* widget, gpointer data ){ const char* str = (const char*)g_object_get_data( G_OBJECT( widget ),"command" ); GetPlugInMgr().Dispatch( gpointer_to_int( data ), str ); } #include typedef std::stack WidgetStack; void PlugInMenu_Add( GtkMenu* plugin_menu, IPlugIn* pPlugIn ){ GtkWidget *menu, *item, *parent, *subMenu; const char *menuText, *menuCommand; WidgetStack menuStack; parent = gtk_menu_item_new_with_label( pPlugIn->getMenuName() ); gtk_widget_show( parent ); gtk_container_add( GTK_CONTAINER( plugin_menu ), parent ); std::size_t nCount = pPlugIn->getCommandCount(); if ( nCount > 0 ) { menu = gtk_menu_new(); if ( g_Layout_enableDetachableMenus.m_value ) { menu_tearoff( GTK_MENU( menu ) ); } while ( nCount > 0 ) { menuText = pPlugIn->getCommandTitle( --nCount ); menuCommand = pPlugIn->getCommand( nCount ); if ( menuText != 0 && strlen( menuText ) > 0 ) { if ( !strcmp( menuText, "-" ) ) { item = gtk_menu_item_new(); gtk_widget_set_sensitive( item, FALSE ); } else if ( !strcmp( menuText, ">" ) ) { menuText = pPlugIn->getCommandTitle( --nCount ); menuCommand = pPlugIn->getCommand( nCount ); if ( !strcmp( menuText, "-" ) || !strcmp( menuText, ">" ) || !strcmp( menuText, "<" ) ) { globalErrorStream() << pPlugIn->getMenuName() << " Invalid title (" << menuText << ") for submenu.\n"; continue; } item = gtk_menu_item_new_with_label( menuText ); gtk_widget_show( item ); gtk_container_add( GTK_CONTAINER( menu ), item ); subMenu = gtk_menu_new(); gtk_menu_item_set_submenu( GTK_MENU_ITEM( item ), subMenu ); menuStack.push( menu ); menu = subMenu; continue; } else if ( !strcmp( menuText, "<" ) ) { if ( !menuStack.empty() ) { menu = menuStack.top(); menuStack.pop(); } else { globalErrorStream() << pPlugIn->getMenuName() << ": Attempt to end non-existent submenu ignored.\n"; } continue; } else { item = gtk_menu_item_new_with_label( menuText ); g_object_set_data( G_OBJECT( item ),"command", const_cast( static_cast( menuCommand ) ) ); g_signal_connect( G_OBJECT( item ), "activate", G_CALLBACK( plugin_activated ), gint_to_pointer( m_nNextPlugInID ) ); } gtk_widget_show( item ); gtk_container_add( GTK_CONTAINER( menu ), item ); pPlugIn->addMenuID( m_nNextPlugInID++ ); } } if ( !menuStack.empty() ) { std::size_t size = menuStack.size(); if ( size != 0 ) { globalErrorStream() << pPlugIn->getMenuName() << " mismatched > <. " << Unsigned( size ) << " submenu(s) not closed.\n"; } for ( std::size_t i = 0; i < ( size - 1 ); i++ ) { menuStack.pop(); } menu = menuStack.top(); menuStack.pop(); } gtk_menu_item_set_submenu( GTK_MENU_ITEM( parent ), menu ); } } GtkMenu* g_plugins_menu = 0; GtkMenuItem* g_plugins_menu_separator = 0; void PluginsMenu_populate(){ class PluginsMenuConstructor : public PluginsVisitor { GtkMenu* m_menu; public: PluginsMenuConstructor( GtkMenu* menu ) : m_menu( menu ){ } void visit( IPlugIn& plugin ){ PlugInMenu_Add( m_menu, &plugin ); } }; PluginsMenuConstructor constructor( g_plugins_menu ); GetPlugInMgr().constructMenu( constructor ); } void PluginsMenu_clear(){ m_nNextPlugInID = 0; GList* lst = g_list_find( gtk_container_children( GTK_CONTAINER( g_plugins_menu ) ), GTK_WIDGET( g_plugins_menu_separator ) ); while ( lst->next ) { gtk_container_remove( GTK_CONTAINER( g_plugins_menu ), GTK_WIDGET( lst->next->data ) ); lst = g_list_find( gtk_container_children( GTK_CONTAINER( g_plugins_menu ) ), GTK_WIDGET( g_plugins_menu_separator ) ); } } GtkMenuItem* create_plugins_menu(){ // Plugins menu GtkMenuItem* plugins_menu_item = new_sub_menu_item_with_mnemonic( "_Plugins" ); GtkMenu* menu = GTK_MENU( gtk_menu_item_get_submenu( plugins_menu_item ) ); if ( g_Layout_enableDetachableMenus.m_value ) { menu_tearoff( menu ); } g_plugins_menu = menu; //TODO: some modules/plugins do not yet support refresh #if 0 create_menu_item_with_mnemonic( menu, "Refresh", FreeCaller() ); // NOTE: the seperator is used when doing a refresh of the list, everything past the seperator is removed g_plugins_menu_separator = menu_separator( menu ); #endif PluginsMenu_populate(); return plugins_menu_item; }