LCOV - code coverage report
Current view: top level - vcl/unx/gtk/window - gtksalmenu.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 0 410 0.0 %
Date: 2014-04-11 Functions: 0 43 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <unx/gtk/gtksalmenu.hxx>
      11             : 
      12             : #ifdef ENABLE_GMENU_INTEGRATION
      13             : 
      14             : #include <unx/gtk/glomenu.h>
      15             : #include <unx/gtk/gloactiongroup.h>
      16             : #include <vcl/menu.hxx>
      17             : #include <unx/gtk/gtkinst.hxx>
      18             : 
      19             : #if GTK_CHECK_VERSION(3,0,0)
      20             : #  include <gdk/gdkkeysyms-compat.h>
      21             : #endif
      22             : 
      23             : #include <sal/log.hxx>
      24             : 
      25             : // FIXME Copied from framework/inc/framework/menuconfiguration.hxx to
      26             : // avoid circular dependency between modules. It should be in a common
      27             : // header (probably in vcl).
      28             : const sal_uInt16 START_ITEMID_WINDOWLIST    = 4600;
      29             : const sal_uInt16 END_ITEMID_WINDOWLIST      = 4699;
      30             : 
      31             : static bool bMenuVisibility = false;
      32             : 
      33             : /*
      34             :  * This function generates the proper command name for all actions, including
      35             :  * duplicated or special ones.
      36             :  */
      37           0 : static gchar* GetCommandForItem( GtkSalMenuItem* pSalMenuItem, gchar* aCurrentCommand, GActionGroup* pActionGroup )
      38             : {
      39           0 :     gchar* aCommand = NULL;
      40             : 
      41           0 :     sal_uInt16 nId = pSalMenuItem->mnId;
      42           0 :     Menu* pMenu = pSalMenuItem->mpVCLMenu;
      43             : 
      44             :     // If item belongs to window list, generate a command with "window-(id)" format.
      45           0 :     if ( ( nId >= START_ITEMID_WINDOWLIST ) && ( nId <= END_ITEMID_WINDOWLIST ) )
      46           0 :         aCommand = g_strdup_printf( "window-%d", nId );
      47             :     else
      48             :     {
      49           0 :         if ( !pMenu )
      50           0 :             return NULL;
      51             : 
      52           0 :         OUString aMenuCommand = pMenu->GetItemCommand( nId );
      53           0 :         gchar* aCommandStr = g_strdup( OUStringToOString( aMenuCommand, RTL_TEXTENCODING_UTF8 ).getStr() );
      54           0 :         aCommand = g_strdup( aCommandStr );
      55             : 
      56             :         // Some items could have duplicated commands. A new one should be generated.
      57           0 :         for ( sal_uInt16 i = 2; ; i++ )
      58             :         {
      59           0 :             if ( !g_action_group_has_action( pActionGroup, aCommand )
      60           0 :                     || ( aCurrentCommand && g_strcmp0( aCurrentCommand, aCommand ) == 0 ) )
      61           0 :                 break;
      62             : 
      63           0 :             g_free( aCommand );
      64           0 :             aCommand = g_strdup_printf("%s%d", aCommandStr, i);
      65           0 :         }
      66             : 
      67           0 :         g_free( aCommandStr );
      68             :     }
      69             : 
      70           0 :     return aCommand;
      71             : }
      72             : 
      73           0 : static void KeyCodeToGdkKey ( const KeyCode& rKeyCode, guint* pGdkKeyCode, GdkModifierType *pGdkModifiers )
      74             : {
      75           0 :     if ( pGdkKeyCode == NULL || pGdkModifiers == NULL )
      76           0 :         return;
      77             : 
      78             :     // Get GDK key modifiers
      79           0 :     GdkModifierType nModifiers = (GdkModifierType) 0;
      80             : 
      81           0 :     if ( rKeyCode.IsShift() )
      82           0 :         nModifiers = (GdkModifierType) ( nModifiers | GDK_SHIFT_MASK );
      83             : 
      84           0 :     if ( rKeyCode.IsMod1() )
      85           0 :         nModifiers = (GdkModifierType) ( nModifiers | GDK_CONTROL_MASK );
      86             : 
      87           0 :     if ( rKeyCode.IsMod2() )
      88           0 :         nModifiers = (GdkModifierType) ( nModifiers | GDK_MOD1_MASK );
      89             : 
      90           0 :     *pGdkModifiers = nModifiers;
      91             : 
      92             :     // Get GDK keycode.
      93           0 :     guint nKeyCode = 0;
      94             : 
      95           0 :     guint nCode = rKeyCode.GetCode();
      96             : 
      97           0 :     if ( nCode >= KEY_0 && nCode <= KEY_9 )
      98           0 :         nKeyCode = ( nCode - KEY_0 ) + GDK_0;
      99           0 :     else if ( nCode >= KEY_A && nCode <= KEY_Z )
     100           0 :         nKeyCode = ( nCode - KEY_A ) + GDK_A;
     101           0 :     else if ( nCode >= KEY_F1 && nCode <= KEY_F26 )
     102           0 :         nKeyCode = ( nCode - KEY_F1 ) + GDK_F1;
     103             :     else
     104             :     {
     105           0 :         switch( nCode )
     106             :         {
     107           0 :         case KEY_DOWN:          nKeyCode = GDK_Down;            break;
     108           0 :         case KEY_UP:            nKeyCode = GDK_Up;              break;
     109           0 :         case KEY_LEFT:          nKeyCode = GDK_Left;            break;
     110           0 :         case KEY_RIGHT:         nKeyCode = GDK_Right;           break;
     111           0 :         case KEY_HOME:          nKeyCode = GDK_Home;            break;
     112           0 :         case KEY_END:           nKeyCode = GDK_End;             break;
     113           0 :         case KEY_PAGEUP:        nKeyCode = GDK_Page_Up;         break;
     114           0 :         case KEY_PAGEDOWN:      nKeyCode = GDK_Page_Down;       break;
     115           0 :         case KEY_RETURN:        nKeyCode = GDK_Return;          break;
     116           0 :         case KEY_ESCAPE:        nKeyCode = GDK_Escape;          break;
     117           0 :         case KEY_TAB:           nKeyCode = GDK_Tab;             break;
     118           0 :         case KEY_BACKSPACE:     nKeyCode = GDK_BackSpace;       break;
     119           0 :         case KEY_SPACE:         nKeyCode = GDK_space;           break;
     120           0 :         case KEY_INSERT:        nKeyCode = GDK_Insert;          break;
     121           0 :         case KEY_DELETE:        nKeyCode = GDK_Delete;          break;
     122           0 :         case KEY_ADD:           nKeyCode = GDK_plus;            break;
     123           0 :         case KEY_SUBTRACT:      nKeyCode = GDK_minus;           break;
     124           0 :         case KEY_MULTIPLY:      nKeyCode = GDK_asterisk;        break;
     125           0 :         case KEY_DIVIDE:        nKeyCode = GDK_slash;           break;
     126           0 :         case KEY_POINT:         nKeyCode = GDK_period;          break;
     127           0 :         case KEY_COMMA:         nKeyCode = GDK_comma;           break;
     128           0 :         case KEY_LESS:          nKeyCode = GDK_less;            break;
     129           0 :         case KEY_GREATER:       nKeyCode = GDK_greater;         break;
     130           0 :         case KEY_EQUAL:         nKeyCode = GDK_equal;           break;
     131           0 :         case KEY_FIND:          nKeyCode = GDK_Find;            break;
     132           0 :         case KEY_CONTEXTMENU:   nKeyCode = GDK_Menu;            break;
     133           0 :         case KEY_HELP:          nKeyCode = GDK_Help;            break;
     134           0 :         case KEY_UNDO:          nKeyCode = GDK_Undo;            break;
     135           0 :         case KEY_REPEAT:        nKeyCode = GDK_Redo;            break;
     136           0 :         case KEY_DECIMAL:       nKeyCode = GDK_KP_Decimal;      break;
     137           0 :         case KEY_TILDE:         nKeyCode = GDK_asciitilde;      break;
     138           0 :         case KEY_QUOTELEFT:     nKeyCode = GDK_quoteleft;       break;
     139           0 :         case KEY_BRACKETLEFT:   nKeyCode = GDK_bracketleft;     break;
     140           0 :         case KEY_BRACKETRIGHT:  nKeyCode = GDK_bracketright;    break;
     141           0 :         case KEY_SEMICOLON:     nKeyCode = GDK_semicolon;       break;
     142             : 
     143             :         // Special cases
     144           0 :         case KEY_COPY:          nKeyCode = GDK_Copy;            break;
     145           0 :         case KEY_CUT:           nKeyCode = GDK_Cut;             break;
     146           0 :         case KEY_PASTE:         nKeyCode = GDK_Paste;           break;
     147           0 :         case KEY_OPEN:          nKeyCode = GDK_Open;            break;
     148             :         }
     149             :     }
     150             : 
     151           0 :     *pGdkKeyCode = nKeyCode;
     152             : }
     153             : 
     154           0 : bool GtkSalMenu::PrepUpdate()
     155             : {
     156           0 :     const GtkSalFrame* pFrame = GetFrame();
     157           0 :     if (pFrame)
     158             :     {
     159           0 :         GtkSalFrame* pNonConstFrame = ( GtkSalFrame* ) pFrame;
     160           0 :         GtkSalMenu* pSalMenu = ((GtkSalMenu*) this);
     161             : 
     162           0 :         if ( !pNonConstFrame->GetMenu() )
     163           0 :             pNonConstFrame->SetMenu( pSalMenu );
     164             : 
     165           0 :         if ( bMenuVisibility && mpMenuModel && mpActionGroup )
     166           0 :             return true;
     167             :     }
     168             : 
     169           0 :     return false;
     170             : }
     171             : 
     172             : /*
     173             :  * Menu updating methods
     174             :  */
     175             : 
     176           0 : void RemoveSpareItemsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, unsigned nSection, unsigned nValidItems )
     177             : {
     178           0 :     sal_Int32 nSectionItems = g_lo_menu_get_n_items_from_section( pMenu, nSection );
     179             : 
     180           0 :     while ( nSectionItems > (sal_Int32) nValidItems )
     181             :     {
     182           0 :         gchar* aCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, --nSectionItems );
     183             : 
     184           0 :         if ( aCommand != NULL && pOldCommandList != NULL )
     185           0 :             *pOldCommandList = g_list_append( *pOldCommandList, g_strdup( aCommand ) );
     186             : 
     187           0 :         g_free( aCommand );
     188             : 
     189           0 :         g_lo_menu_remove_from_section( pMenu, nSection, nSectionItems );
     190             :     }
     191           0 : }
     192             : 
     193           0 : void RemoveSpareSectionsFromNativeMenu( GLOMenu* pMenu, GList** pOldCommandList, unsigned nLastSection )
     194             : {
     195           0 :     if ( pMenu == NULL || pOldCommandList == NULL )
     196           0 :         return;
     197             : 
     198           0 :     sal_Int32 n = g_menu_model_get_n_items( G_MENU_MODEL( pMenu ) ) - 1;
     199             : 
     200           0 :     for ( ; n > (sal_Int32) nLastSection; n-- )
     201             :     {
     202           0 :         RemoveSpareItemsFromNativeMenu( pMenu, pOldCommandList, n, 0 );
     203           0 :         g_lo_menu_remove( pMenu, n );
     204             :     }
     205             : }
     206             : 
     207           0 : gint CompareStr( gpointer str1, gpointer str2 )
     208             : {
     209           0 :     return g_strcmp0( (const gchar*) str1, (const gchar*) str2 );
     210             : }
     211             : 
     212           0 : void RemoveUnusedCommands( GLOActionGroup* pActionGroup, GList* pOldCommandList, GList* pNewCommandList )
     213             : {
     214           0 :     if ( pActionGroup == NULL || pOldCommandList == NULL )
     215           0 :         return;
     216             : 
     217           0 :     while ( pNewCommandList != NULL )
     218             :     {
     219           0 :         GList* pNewCommand = g_list_first( pNewCommandList );
     220           0 :         pNewCommandList = g_list_remove_link( pNewCommandList, pNewCommand );
     221             : 
     222           0 :         gpointer aCommand = g_list_nth_data( pNewCommand, 0 );
     223             : 
     224           0 :         GList* pOldCommand = g_list_find_custom( pOldCommandList, aCommand, (GCompareFunc) CompareStr );
     225             : 
     226           0 :         if ( pOldCommand != NULL )
     227             :         {
     228           0 :             pOldCommandList = g_list_remove_link( pOldCommandList, pOldCommand );
     229           0 :             g_list_free_full( pOldCommand, g_free );
     230             :         }
     231             : 
     232           0 :         g_list_free_full( pNewCommand, g_free );
     233             :     }
     234             : 
     235           0 :     while ( pOldCommandList != NULL )
     236             :     {
     237           0 :         GList* pCommand = g_list_first( pOldCommandList );
     238           0 :         pOldCommandList = g_list_remove_link( pOldCommandList, pCommand );
     239             : 
     240           0 :         gchar* aCommand = (gchar*) g_list_nth_data( pCommand, 0 );
     241             : 
     242           0 :         g_lo_action_group_remove( pActionGroup, aCommand );
     243             : 
     244           0 :         g_list_free_full( pCommand, g_free );
     245             :     }
     246             : }
     247             : 
     248           0 : void GtkSalMenu::ImplUpdate( gboolean bRecurse )
     249             : {
     250           0 :     SolarMutexGuard aGuard;
     251             : 
     252             :     SAL_INFO("vcl.unity", "ImplUpdate pre PrepUpdate");
     253           0 :     if( !PrepUpdate() )
     254           0 :         return;
     255             : 
     256           0 :     Menu* pVCLMenu = mpVCLMenu;
     257           0 :     GLOMenu* pLOMenu = G_LO_MENU( mpMenuModel );
     258           0 :     GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
     259             :     SAL_INFO("vcl.unity", "Syncing vcl menu " << pVCLMenu << " to menu model " << pLOMenu << " and action group " << pActionGroup);
     260           0 :     GList *pOldCommandList = NULL;
     261           0 :     GList *pNewCommandList = NULL;
     262             : 
     263           0 :     sal_uInt16 nLOMenuSize = g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) );
     264             : 
     265           0 :     if ( nLOMenuSize == 0 )
     266           0 :         g_lo_menu_new_section( pLOMenu, 0, NULL );
     267             : 
     268           0 :     sal_Int32 nSection = 0;
     269           0 :     sal_Int32 nItemPos = 0;
     270           0 :     sal_Int32 validItems = 0;
     271             :     sal_Int32 nItem;
     272             : 
     273           0 :     for ( nItem = 0; nItem < ( sal_Int32 ) GetItemCount(); nItem++ ) {
     274           0 :         if ( !IsItemVisible( nItem ) )
     275           0 :             continue;
     276             : 
     277           0 :         GtkSalMenuItem *pSalMenuItem = GetItemAtPos( nItem );
     278           0 :         sal_uInt16 nId = pSalMenuItem->mnId;
     279             : 
     280           0 :         if ( pSalMenuItem->mnType == MENUITEM_SEPARATOR )
     281             :         {
     282             :             // Delete extra items from current section.
     283           0 :             RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
     284             : 
     285           0 :             nSection++;
     286           0 :             nItemPos = 0;
     287           0 :             validItems = 0;
     288             : 
     289           0 :             if ( nLOMenuSize <= nSection )
     290             :             {
     291           0 :                 g_lo_menu_new_section( pLOMenu, nSection, NULL );
     292           0 :                 nLOMenuSize++;
     293             :             }
     294             : 
     295           0 :             continue;
     296             :         }
     297             : 
     298           0 :         if ( nItemPos >= g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
     299           0 :             g_lo_menu_insert_in_section( pLOMenu, nSection, nItemPos, "EMPTY STRING" );
     300             : 
     301             :         // Get internal menu item values.
     302           0 :         OUString aText = pVCLMenu->GetItemText( nId );
     303           0 :         bool bEnabled = pVCLMenu->IsItemEnabled( nId );
     304           0 :         KeyCode nAccelKey = pVCLMenu->GetAccelKey( nId );
     305           0 :         bool bChecked = pVCLMenu->IsItemChecked( nId );
     306           0 :         MenuItemBits itemBits = pVCLMenu->GetItemBits( nId );
     307             : 
     308             :         // Store current item command in command list.
     309           0 :         gchar *aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pLOMenu, nSection, nItemPos );
     310             : 
     311           0 :         if ( aCurrentCommand != NULL )
     312           0 :             pOldCommandList = g_list_append( pOldCommandList, aCurrentCommand );
     313             : 
     314             :         // Get the new command for the item.
     315           0 :         gchar* aNativeCommand = GetCommandForItem( pSalMenuItem, aCurrentCommand, mpActionGroup );
     316             : 
     317             :         // Force updating of native menu labels.
     318           0 :         NativeSetItemText( nSection, nItemPos, aText );
     319           0 :         NativeSetAccelerator( nSection, nItemPos, nAccelKey, nAccelKey.GetName( GetFrame()->GetWindow() ) );
     320             : 
     321           0 :         if ( g_strcmp0( aNativeCommand, "" ) != 0 && pSalMenuItem->mpSubMenu == NULL )
     322             :         {
     323           0 :             NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, FALSE );
     324           0 :             NativeCheckItem( nSection, nItemPos, itemBits, bChecked );
     325           0 :             NativeSetEnableItem( aNativeCommand, bEnabled );
     326             : 
     327           0 :             pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
     328             :         }
     329             : 
     330           0 :         GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
     331             : 
     332           0 :         if ( pSubmenu && pSubmenu->GetMenu() )
     333             :         {
     334           0 :             NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
     335           0 :             pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
     336             : 
     337           0 :             GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
     338             : 
     339           0 :             if ( pSubMenuModel == NULL )
     340             :             {
     341           0 :                 g_lo_menu_new_submenu_in_item_in_section( pLOMenu, nSection, nItemPos );
     342           0 :                 pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
     343             :             }
     344             : 
     345           0 :             g_object_unref( pSubMenuModel );
     346             : 
     347           0 :             if ( bRecurse )
     348             :             {
     349             :                 SAL_INFO("vcl.unity", "preparing submenu  " << pSubMenuModel << " to menu model " << G_MENU_MODEL(pSubMenuModel) << " and action group " << G_ACTION_GROUP(pActionGroup));
     350           0 :                 pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
     351           0 :                 pSubmenu->SetActionGroup( G_ACTION_GROUP( pActionGroup ) );
     352           0 :                 pSubmenu->ImplUpdate( bRecurse );
     353             :             }
     354             :         }
     355             : 
     356           0 :         g_free( aNativeCommand );
     357             : 
     358           0 :         ++nItemPos;
     359           0 :         ++validItems;
     360           0 :     }
     361             : 
     362             :     // Delete extra items in last section.
     363           0 :     RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
     364             : 
     365             :     // Delete extra sections.
     366           0 :     RemoveSpareSectionsFromNativeMenu( pLOMenu, &pOldCommandList, nSection );
     367             : 
     368             :     // Delete unused commands.
     369           0 :     RemoveUnusedCommands( pActionGroup, pOldCommandList, pNewCommandList );
     370             : }
     371             : 
     372           0 : void GtkSalMenu::Update()
     373             : {
     374           0 :     ImplUpdate( FALSE );
     375           0 : }
     376             : 
     377           0 : void GtkSalMenu::UpdateFull()
     378             : {
     379           0 :     ImplUpdate( TRUE );
     380           0 : }
     381             : 
     382             : /*
     383             :  * GtkSalMenu
     384             :  */
     385             : 
     386           0 : GtkSalMenu::GtkSalMenu( bool bMenuBar ) :
     387             :     mbMenuBar( bMenuBar ),
     388             :     mpVCLMenu( NULL ),
     389             :     mpOldSalMenu( NULL ),
     390             :     mpParentSalMenu( NULL ),
     391             :     mpFrame( NULL ),
     392             :     mpMenuModel( NULL ),
     393           0 :     mpActionGroup( NULL )
     394             : {
     395           0 : }
     396             : 
     397           0 : GtkSalMenu::~GtkSalMenu()
     398             : {
     399           0 :     SolarMutexGuard aGuard;
     400             : 
     401           0 :     if ( mbMenuBar )
     402             :     {
     403           0 :         if ( mpMenuModel )
     404             :         {
     405             : //            g_lo_menu_remove( G_LO_MENU( mpMenuModel ), 0 );
     406           0 :             g_object_unref( mpMenuModel );
     407             :         }
     408             :     }
     409             : 
     410           0 :     maItems.clear();
     411           0 : }
     412             : 
     413           0 : bool GtkSalMenu::VisibleMenuBar()
     414             : {
     415           0 :     return bMenuVisibility;
     416             : }
     417             : 
     418           0 : void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
     419             : {
     420           0 :     SolarMutexGuard aGuard;
     421           0 :     GtkSalMenuItem *pItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
     422             : 
     423           0 :     if ( nPos == MENU_APPEND )
     424           0 :         maItems.push_back( pItem );
     425             :     else
     426           0 :         maItems.insert( maItems.begin() + nPos, pItem );
     427             : 
     428           0 :     pItem->mpParentMenu = this;
     429           0 : }
     430             : 
     431           0 : void GtkSalMenu::RemoveItem( unsigned nPos )
     432             : {
     433           0 :     SolarMutexGuard aGuard;
     434           0 :     maItems.erase( maItems.begin() + nPos );
     435           0 : }
     436             : 
     437           0 : void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned )
     438             : {
     439           0 :     SolarMutexGuard aGuard;
     440           0 :     GtkSalMenuItem *pItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
     441           0 :     GtkSalMenu *pGtkSubMenu = static_cast< GtkSalMenu* >( pSubMenu );
     442             : 
     443           0 :     if ( pGtkSubMenu == NULL )
     444           0 :         return;
     445             : 
     446           0 :     pGtkSubMenu->mpParentSalMenu = this;
     447           0 :     pItem->mpSubMenu = pGtkSubMenu;
     448             : }
     449             : 
     450           0 : void GtkSalMenu::SetFrame( const SalFrame* pFrame )
     451             : {
     452           0 :     SolarMutexGuard aGuard;
     453             : 
     454             :     assert(mbMenuBar);
     455             :     SAL_INFO("vcl.unity", "GtkSalMenu set to frame");
     456           0 :     mpFrame = static_cast< const GtkSalFrame* >( pFrame );
     457           0 :     GtkSalFrame* pFrameNonConst = const_cast<GtkSalFrame*>(mpFrame);
     458             : 
     459             :     // if we had a menu on the GtkSalMenu we have to free it as we generate a
     460             :     // full menu anyway and we might need to reuse an existing model and
     461             :     // actiongroup
     462           0 :     mpOldSalMenu = static_cast< GtkSalMenu* >( pFrameNonConst->GetMenu() );
     463           0 :     pFrameNonConst->SetMenu( this );
     464           0 :     pFrameNonConst->EnsureAppMenuWatch();
     465             : 
     466             :     // Clean menu model and action group if needed.
     467           0 :     GtkWidget* pWidget = pFrameNonConst->getWindow();
     468           0 :     GdkWindow* gdkWindow = gtk_widget_get_window( pWidget );
     469             : 
     470           0 :     GLOMenu* pMenuModel = G_LO_MENU( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
     471           0 :     GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
     472             :     SAL_INFO("vcl.unity", "Found menu model: " << pMenuModel << " and action group: " << pActionGroup);
     473             : 
     474           0 :     if ( pMenuModel )
     475             :     {
     476           0 :         if ( g_menu_model_get_n_items( G_MENU_MODEL( pMenuModel ) ) > 0 )
     477           0 :             g_lo_menu_remove( pMenuModel, 0 );
     478             : 
     479           0 :         mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
     480             :     }
     481             : 
     482           0 :     if ( pActionGroup )
     483             :     {
     484           0 :         g_lo_action_group_clear( pActionGroup );
     485           0 :         mpActionGroup = G_ACTION_GROUP( pActionGroup );
     486             :     }
     487             : 
     488             :     // Generate the main menu structure.
     489           0 :     if (bMenuVisibility)
     490           0 :         UpdateFull();
     491             : 
     492           0 :     g_lo_menu_insert_section( pMenuModel, 0, NULL, mpMenuModel );
     493           0 : }
     494             : 
     495           0 : const GtkSalFrame* GtkSalMenu::GetFrame() const
     496             : {
     497           0 :     SolarMutexGuard aGuard;
     498           0 :     const GtkSalMenu* pMenu = this;
     499           0 :     while( pMenu && ! pMenu->mpFrame )
     500           0 :         pMenu = pMenu->mpParentSalMenu;
     501           0 :     return pMenu ? pMenu->mpFrame : NULL;
     502             : }
     503             : 
     504           0 : void GtkSalMenu::NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItemBits bits, gboolean bCheck )
     505             : {
     506           0 :     SolarMutexGuard aGuard;
     507             : 
     508           0 :     if ( mpActionGroup == NULL )
     509           0 :         return;
     510             : 
     511           0 :     gchar* aCommand = g_lo_menu_get_command_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
     512             : 
     513           0 :     if ( aCommand != NULL || g_strcmp0( aCommand, "" ) != 0 )
     514             :     {
     515           0 :         GVariant *pCheckValue = NULL;
     516           0 :         GVariant *pCurrentState = g_action_group_get_action_state( mpActionGroup, aCommand );
     517             : 
     518           0 :         if ( bits & MIB_RADIOCHECK )
     519           0 :             pCheckValue = bCheck ? g_variant_new_string( aCommand ) : g_variant_new_string( "" );
     520             :         else
     521             :         {
     522             :             // By default, all checked items are checkmark buttons.
     523           0 :             if ( bCheck || ( !bCheck && pCurrentState != NULL ) )
     524           0 :                 pCheckValue = g_variant_new_boolean( bCheck );
     525             :         }
     526             : 
     527           0 :         if ( pCheckValue != NULL && ( pCurrentState == NULL || g_variant_equal( pCurrentState, pCheckValue ) == FALSE ) )
     528           0 :             g_action_group_change_action_state( mpActionGroup, aCommand, pCheckValue );
     529             : 
     530           0 :         if ( pCurrentState != NULL )
     531           0 :             g_variant_unref( pCurrentState );
     532             :     }
     533             : 
     534           0 :     if ( aCommand )
     535           0 :         g_free( aCommand );
     536             : }
     537             : 
     538           0 : void GtkSalMenu::NativeSetEnableItem( gchar* aCommand, gboolean bEnable )
     539             : {
     540           0 :     SolarMutexGuard aGuard;
     541           0 :     GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
     542             : 
     543           0 :     if ( g_action_group_get_action_enabled( G_ACTION_GROUP( pActionGroup ), aCommand ) != bEnable )
     544           0 :         g_lo_action_group_set_action_enabled( pActionGroup, aCommand, bEnable );
     545           0 : }
     546             : 
     547           0 : void GtkSalMenu::NativeSetItemText( unsigned nSection, unsigned nItemPos, const OUString& rText )
     548             : {
     549           0 :     SolarMutexGuard aGuard;
     550             :     // Escape all underscores so that they don't get interpreted as hotkeys
     551           0 :     OUString aText = rText.replaceAll( "_", "__" );
     552             :     // Replace the LibreOffice hotkey identifier with an underscore
     553           0 :     aText = aText.replace( '~', '_' );
     554           0 :     OString aConvertedText = OUStringToOString( aText, RTL_TEXTENCODING_UTF8 );
     555             : 
     556             :     // Update item text only when necessary.
     557           0 :     gchar* aLabel = g_lo_menu_get_label_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
     558             : 
     559           0 :     if ( aLabel == NULL || g_strcmp0( aLabel, aConvertedText.getStr() ) != 0 )
     560           0 :         g_lo_menu_set_label_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aConvertedText.getStr() );
     561             : 
     562           0 :     if ( aLabel )
     563           0 :         g_free( aLabel );
     564           0 : }
     565             : 
     566           0 : void GtkSalMenu::NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const KeyCode& rKeyCode, const OUString& rKeyName )
     567             : {
     568           0 :     SolarMutexGuard aGuard;
     569             : 
     570           0 :     if ( rKeyName.isEmpty() )
     571           0 :         return;
     572             : 
     573             :     guint nKeyCode;
     574             :     GdkModifierType nModifiers;
     575             : 
     576           0 :     KeyCodeToGdkKey( rKeyCode, &nKeyCode, &nModifiers );
     577             : 
     578           0 :     gchar* aAccelerator = gtk_accelerator_name( nKeyCode, nModifiers );
     579             : 
     580           0 :     gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
     581             : 
     582           0 :     if ( aCurrentAccel == NULL && g_strcmp0( aCurrentAccel, aAccelerator ) != 0 )
     583           0 :         g_lo_menu_set_accelerator_to_item_in_section ( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aAccelerator );
     584             : 
     585           0 :     g_free( aAccelerator );
     586             : }
     587             : 
     588           0 : void GtkSalMenu::NativeSetItemCommand( unsigned nSection,
     589             :                                        unsigned nItemPos,
     590             :                                        sal_uInt16 nId,
     591             :                                        const gchar* aCommand,
     592             :                                        MenuItemBits nBits,
     593             :                                        gboolean bChecked,
     594             :                                        gboolean bIsSubmenu )
     595             : {
     596           0 :     SolarMutexGuard aGuard;
     597           0 :     GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
     598             : 
     599           0 :     GVariant *pTarget = NULL;
     600             : 
     601           0 :     if ( g_action_group_has_action( mpActionGroup, aCommand ) == FALSE ) {
     602           0 :         if ( ( nBits & MIB_CHECKABLE ) || bIsSubmenu )
     603             :         {
     604             :             // Item is a checkmark button.
     605           0 :             GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_BOOLEAN );
     606           0 :             GVariant* pState = g_variant_new_boolean( bChecked );
     607             : 
     608           0 :             g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, NULL, pStateType, NULL, pState );
     609             :         }
     610           0 :         else if ( nBits & MIB_RADIOCHECK )
     611             :         {
     612             :             // Item is a radio button.
     613           0 :             GVariantType* pParameterType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
     614           0 :             GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
     615           0 :             GVariant* pState = g_variant_new_string( "" );
     616           0 :             pTarget = g_variant_new_string( aCommand );
     617             : 
     618           0 :             g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, NULL, pState );
     619             :         }
     620             :         else
     621             :         {
     622             :             // Item is not special, so insert a stateless action.
     623           0 :             g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
     624             :         }
     625             :     }
     626             : 
     627           0 :     GLOMenu* pMenu = G_LO_MENU( mpMenuModel );
     628             : 
     629             :     // Menu item is not updated unless it's necessary.
     630           0 :     gchar* aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, nItemPos );
     631             : 
     632           0 :     if ( aCurrentCommand == NULL || g_strcmp0( aCurrentCommand, aCommand ) != 0 )
     633             :     {
     634           0 :         g_lo_menu_set_command_to_item_in_section( pMenu, nSection, nItemPos, aCommand );
     635             : 
     636           0 :         gchar* aItemCommand = g_strconcat("win.", aCommand, NULL );
     637             : 
     638           0 :         if ( bIsSubmenu )
     639           0 :             g_lo_menu_set_submenu_action_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand );
     640             :         else
     641           0 :             g_lo_menu_set_action_and_target_value_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand, pTarget );
     642             : 
     643           0 :         g_free( aItemCommand );
     644             :     }
     645             : 
     646           0 :     if ( aCurrentCommand )
     647           0 :         g_free( aCurrentCommand );
     648           0 : }
     649             : 
     650           0 : GtkSalMenu* GtkSalMenu::GetMenuForItemCommand( gchar* aCommand, gboolean bGetSubmenu )
     651             : {
     652           0 :     SolarMutexGuard aGuard;
     653           0 :     GtkSalMenu* pMenu = NULL;
     654           0 :     for ( sal_uInt16 nPos = 0; nPos < maItems.size(); nPos++ )
     655             :     {
     656           0 :         GtkSalMenuItem *pSalItem = maItems[ nPos ];
     657             : 
     658           0 :         OUString aItemCommand = mpVCLMenu->GetItemCommand( pSalItem->mnId );
     659           0 :         gchar* aItemCommandStr = (gchar*) OUStringToOString( aItemCommand, RTL_TEXTENCODING_UTF8 ).getStr();
     660             : 
     661           0 :         if ( g_strcmp0( aItemCommandStr, aCommand ) == 0 )
     662             :         {
     663           0 :             pMenu = bGetSubmenu ? pSalItem->mpSubMenu : this;
     664           0 :             break;
     665             :         }
     666             :         else
     667             :         {
     668           0 :             if ( pSalItem->mpSubMenu != NULL )
     669           0 :                 pMenu = pSalItem->mpSubMenu->GetMenuForItemCommand( aCommand, bGetSubmenu );
     670             : 
     671           0 :             if ( pMenu != NULL )
     672           0 :                break;
     673             :         }
     674           0 :     }
     675             : 
     676           0 :     return pMenu;
     677             : }
     678             : 
     679           0 : void GtkSalMenu::DispatchCommand( gint itemId, const gchar *aCommand )
     680             : {
     681           0 :     SolarMutexGuard aGuard;
     682             :     // Only the menubar is allowed to dispatch commands.
     683           0 :     if ( !mbMenuBar )
     684           0 :         return;
     685             : 
     686           0 :     GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aCommand, FALSE );
     687           0 :     Menu* pSubMenu = ( pSalSubMenu != NULL ) ? pSalSubMenu->GetMenu() : NULL;
     688             : 
     689           0 :     MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
     690           0 :     pMenuBar->HandleMenuCommandEvent( pSubMenu, itemId );
     691             : }
     692             : 
     693           0 : void GtkSalMenu::ActivateAllSubmenus(MenuBar* pMenuBar)
     694             : {
     695           0 :     pMenuBar->HandleMenuActivateEvent(mpVCLMenu);
     696           0 :     for ( sal_uInt16 nPos = 0; nPos < maItems.size(); nPos++ )
     697             :     {
     698           0 :         GtkSalMenuItem *pSalItem = maItems[ nPos ];
     699           0 :         if ( pSalItem->mpSubMenu != NULL )
     700             :         {
     701           0 :             pSalItem->mpSubMenu->ActivateAllSubmenus(pMenuBar);
     702           0 :             pSalItem->mpSubMenu->Update();
     703             :         }
     704             :     }
     705           0 : }
     706             : 
     707           0 : void GtkSalMenu::Activate()
     708             : {
     709           0 :     if ( !mbMenuBar )
     710           0 :         return;
     711           0 :     ActivateAllSubmenus(static_cast<MenuBar*>(mpVCLMenu));
     712             : }
     713             : 
     714           0 : void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
     715             : {
     716           0 :     if ( !mbMenuBar )
     717           0 :         return;
     718             : 
     719           0 :     GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aMenuCommand, TRUE );
     720             : 
     721           0 :     if ( pSalSubMenu != NULL ) {
     722           0 :         MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
     723           0 :         pMenuBar->HandleMenuDeActivateEvent( pSalSubMenu->mpVCLMenu );
     724             :     }
     725             : }
     726             : 
     727           0 : void GtkSalMenu::Display( bool bVisible )
     728             : {
     729           0 :     if ( !mbMenuBar || mpVCLMenu == NULL )
     730           0 :         return;
     731             : 
     732           0 :     bMenuVisibility = bVisible;
     733             : 
     734           0 :     bool bVCLMenuVisible = ( bVisible ) ? false : true;
     735             : 
     736           0 :     MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
     737           0 :     pMenuBar->SetDisplayable( bVCLMenuVisible );
     738             : }
     739             : 
     740           0 : bool GtkSalMenu::IsItemVisible( unsigned nPos )
     741             : {
     742           0 :     SolarMutexGuard aGuard;
     743           0 :     bool bVisible = false;
     744             : 
     745           0 :     if ( nPos < maItems.size() )
     746           0 :         bVisible = ( ( GtkSalMenuItem* ) maItems[ nPos ])->mbVisible;
     747             : 
     748           0 :     return bVisible;
     749             : }
     750             : 
     751           0 : void GtkSalMenu::CheckItem( unsigned, bool )
     752             : {
     753           0 : }
     754             : 
     755           0 : void GtkSalMenu::EnableItem( unsigned, bool )
     756             : {
     757           0 : }
     758             : 
     759           0 : void GtkSalMenu::ShowItem( unsigned nPos, bool bShow )
     760             : {
     761           0 :     SolarMutexGuard aGuard;
     762           0 :     if ( nPos < maItems.size() )
     763           0 :         ( ( GtkSalMenuItem* ) maItems[ nPos ] )->mbVisible = bShow;
     764           0 : }
     765             : 
     766           0 : void GtkSalMenu::SetItemText( unsigned, SalMenuItem*, const OUString& )
     767             : {
     768           0 : }
     769             : 
     770           0 : void GtkSalMenu::SetItemImage( unsigned, SalMenuItem*, const Image& )
     771             : {
     772           0 : }
     773             : 
     774           0 : void GtkSalMenu::SetAccelerator( unsigned, SalMenuItem*, const KeyCode&, const OUString& )
     775             : {
     776           0 : }
     777             : 
     778           0 : void GtkSalMenu::GetSystemMenuData( SystemMenuData* )
     779             : {
     780           0 : }
     781             : 
     782             : /*
     783             :  * GtkSalMenuItem
     784             :  */
     785             : 
     786           0 : GtkSalMenuItem::GtkSalMenuItem( const SalItemParams* pItemData ) :
     787             :     mnId( pItemData->nId ),
     788             :     mnType( pItemData->eType ),
     789             :     mbVisible( true ),
     790             :     mpVCLMenu( pItemData->pMenu ),
     791             :     mpParentMenu( NULL ),
     792           0 :     mpSubMenu( NULL )
     793             : {
     794           0 : }
     795             : 
     796           0 : GtkSalMenuItem::~GtkSalMenuItem()
     797             : {
     798           0 : }
     799             : 
     800             : #endif
     801             : 
     802             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10