LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/vcl/unx/gtk/window - gtksalmenu.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 411 0.0 %
Date: 2013-07-09 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 sal_Bool bMenuVisibility = sal_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 ) == sal_False )
     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 :         String aText = pVCLMenu->GetItemText( nId );
     303           0 :         sal_Bool itemEnabled = pVCLMenu->IsItemEnabled( nId );
     304           0 :         KeyCode nAccelKey = pVCLMenu->GetAccelKey( nId );
     305           0 :         sal_Bool itemChecked = pVCLMenu->IsItemChecked( nId );
     306           0 :         MenuItemBits itemBits = pVCLMenu->GetItemBits( nId );
     307             : 
     308             :         // Convert internal values to native values.
     309           0 :         gboolean bChecked = ( itemChecked == sal_True ) ? TRUE : FALSE;
     310           0 :         gboolean bEnabled = ( itemEnabled == sal_True ) ? TRUE : FALSE;
     311             : 
     312             :         // Store current item command in command list.
     313           0 :         gchar *aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pLOMenu, nSection, nItemPos );
     314             : 
     315           0 :         if ( aCurrentCommand != NULL )
     316           0 :             pOldCommandList = g_list_append( pOldCommandList, aCurrentCommand );
     317             : 
     318             :         // Get the new command for the item.
     319           0 :         gchar* aNativeCommand = GetCommandForItem( pSalMenuItem, aCurrentCommand, mpActionGroup );
     320             : 
     321             :         // Force updating of native menu labels.
     322           0 :         NativeSetItemText( nSection, nItemPos, aText );
     323           0 :         NativeSetAccelerator( nSection, nItemPos, nAccelKey, nAccelKey.GetName( GetFrame()->GetWindow() ) );
     324             : 
     325           0 :         if ( g_strcmp0( aNativeCommand, "" ) != 0 && pSalMenuItem->mpSubMenu == NULL )
     326             :         {
     327           0 :             NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, FALSE );
     328           0 :             NativeCheckItem( nSection, nItemPos, itemBits, bChecked );
     329           0 :             NativeSetEnableItem( aNativeCommand, bEnabled );
     330             : 
     331           0 :             pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
     332             :         }
     333             : 
     334           0 :         GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
     335             : 
     336           0 :         if ( pSubmenu && pSubmenu->GetMenu() )
     337             :         {
     338           0 :             NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
     339           0 :             pNewCommandList = g_list_append( pNewCommandList, g_strdup( aNativeCommand ) );
     340             : 
     341           0 :             GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
     342             : 
     343           0 :             if ( pSubMenuModel == NULL )
     344             :             {
     345           0 :                 g_lo_menu_new_submenu_in_item_in_section( pLOMenu, nSection, nItemPos );
     346           0 :                 pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
     347             :             }
     348             : 
     349           0 :             g_object_unref( pSubMenuModel );
     350             : 
     351           0 :             if ( bRecurse )
     352             :             {
     353             :                 SAL_INFO("vcl.unity", "preparing submenu  " << pSubMenuModel << " to menu model " << G_MENU_MODEL(pSubMenuModel) << " and action group " << G_ACTION_GROUP(pActionGroup));
     354           0 :                 pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
     355           0 :                 pSubmenu->SetActionGroup( G_ACTION_GROUP( pActionGroup ) );
     356           0 :                 pSubmenu->ImplUpdate( bRecurse );
     357             :             }
     358             :         }
     359             : 
     360           0 :         g_free( aNativeCommand );
     361             : 
     362           0 :         ++nItemPos;
     363           0 :         ++validItems;
     364           0 :     }
     365             : 
     366             :     // Delete extra items in last section.
     367           0 :     RemoveSpareItemsFromNativeMenu( pLOMenu, &pOldCommandList, nSection, validItems );
     368             : 
     369             :     // Delete extra sections.
     370           0 :     RemoveSpareSectionsFromNativeMenu( pLOMenu, &pOldCommandList, nSection );
     371             : 
     372             :     // Delete unused commands.
     373           0 :     RemoveUnusedCommands( pActionGroup, pOldCommandList, pNewCommandList );
     374             : }
     375             : 
     376           0 : void GtkSalMenu::Update()
     377             : {
     378           0 :     ImplUpdate( FALSE );
     379           0 : }
     380             : 
     381           0 : void GtkSalMenu::UpdateFull()
     382             : {
     383           0 :     ImplUpdate( TRUE );
     384           0 : }
     385             : 
     386             : 
     387             : /*
     388             :  * GtkSalMenu
     389             :  */
     390             : 
     391           0 : GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) :
     392             :     mbMenuBar( bMenuBar ),
     393             :     mpVCLMenu( NULL ),
     394             :     mpOldSalMenu( NULL ),
     395             :     mpParentSalMenu( NULL ),
     396             :     mpFrame( NULL ),
     397             :     mpMenuModel( NULL ),
     398           0 :     mpActionGroup( NULL )
     399             : {
     400           0 : }
     401             : 
     402           0 : GtkSalMenu::~GtkSalMenu()
     403             : {
     404           0 :     SolarMutexGuard aGuard;
     405             : 
     406           0 :     if ( mbMenuBar == sal_True )
     407             :     {
     408           0 :         if ( mpMenuModel )
     409             :         {
     410             : //            g_lo_menu_remove( G_LO_MENU( mpMenuModel ), 0 );
     411           0 :             g_object_unref( mpMenuModel );
     412             :         }
     413             :     }
     414             : 
     415           0 :     maItems.clear();
     416           0 : }
     417             : 
     418           0 : sal_Bool GtkSalMenu::VisibleMenuBar()
     419             : {
     420           0 :     return bMenuVisibility;
     421             : }
     422             : 
     423           0 : void GtkSalMenu::InsertItem( SalMenuItem* pSalMenuItem, unsigned nPos )
     424             : {
     425           0 :     SolarMutexGuard aGuard;
     426           0 :     GtkSalMenuItem *pItem = static_cast<GtkSalMenuItem*>( pSalMenuItem );
     427             : 
     428           0 :     if ( nPos == MENU_APPEND )
     429           0 :         maItems.push_back( pItem );
     430             :     else
     431           0 :         maItems.insert( maItems.begin() + nPos, pItem );
     432             : 
     433           0 :     pItem->mpParentMenu = this;
     434           0 : }
     435             : 
     436           0 : void GtkSalMenu::RemoveItem( unsigned nPos )
     437             : {
     438           0 :     SolarMutexGuard aGuard;
     439           0 :     maItems.erase( maItems.begin() + nPos );
     440           0 : }
     441             : 
     442           0 : void GtkSalMenu::SetSubMenu( SalMenuItem* pSalMenuItem, SalMenu* pSubMenu, unsigned )
     443             : {
     444           0 :     SolarMutexGuard aGuard;
     445           0 :     GtkSalMenuItem *pItem = static_cast< GtkSalMenuItem* >( pSalMenuItem );
     446           0 :     GtkSalMenu *pGtkSubMenu = static_cast< GtkSalMenu* >( pSubMenu );
     447             : 
     448           0 :     if ( pGtkSubMenu == NULL )
     449           0 :         return;
     450             : 
     451           0 :     pGtkSubMenu->mpParentSalMenu = this;
     452           0 :     pItem->mpSubMenu = pGtkSubMenu;
     453             : }
     454             : 
     455           0 : void GtkSalMenu::SetFrame( const SalFrame* pFrame )
     456             : {
     457           0 :     SolarMutexGuard aGuard;
     458             : 
     459             :     assert(mbMenuBar);
     460             :     SAL_INFO("vcl.unity", "GtkSalMenu set to frame");
     461           0 :     mpFrame = static_cast< const GtkSalFrame* >( pFrame );
     462           0 :     GtkSalFrame* pFrameNonConst = const_cast<GtkSalFrame*>(mpFrame);
     463             : 
     464             :     // if we had a menu on the GtkSalMenu we have to free it as we generate a
     465             :     // full menu anyway and we might need to reuse an existing model and
     466             :     // actiongroup
     467           0 :     mpOldSalMenu = static_cast< GtkSalMenu* >( pFrameNonConst->GetMenu() );
     468           0 :     pFrameNonConst->SetMenu( this );
     469           0 :     pFrameNonConst->EnsureAppMenuWatch();
     470             : 
     471             :     // Clean menu model and action group if needed.
     472           0 :     GtkWidget* pWidget = pFrameNonConst->getWindow();
     473           0 :     GdkWindow* gdkWindow = gtk_widget_get_window( pWidget );
     474             : 
     475           0 :     GLOMenu* pMenuModel = G_LO_MENU( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-menubar" ) );
     476           0 :     GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( g_object_get_data( G_OBJECT( gdkWindow ), "g-lo-action-group" ) );
     477             :     SAL_INFO("vcl.unity", "Found menu model: " << pMenuModel << " and action group: " << pActionGroup);
     478             : 
     479           0 :     if ( pMenuModel )
     480             :     {
     481           0 :         if ( g_menu_model_get_n_items( G_MENU_MODEL( pMenuModel ) ) > 0 )
     482           0 :             g_lo_menu_remove( pMenuModel, 0 );
     483             : 
     484           0 :         mpMenuModel = G_MENU_MODEL( g_lo_menu_new() );
     485             :     }
     486             : 
     487           0 :     if ( pActionGroup )
     488             :     {
     489           0 :         g_lo_action_group_clear( pActionGroup );
     490           0 :         mpActionGroup = G_ACTION_GROUP( pActionGroup );
     491             :     }
     492             : 
     493             :     // Generate the main menu structure.
     494           0 :     if (bMenuVisibility)
     495           0 :         UpdateFull();
     496             : 
     497           0 :     g_lo_menu_insert_section( pMenuModel, 0, NULL, mpMenuModel );
     498           0 : }
     499             : 
     500           0 : const GtkSalFrame* GtkSalMenu::GetFrame() const
     501             : {
     502           0 :     SolarMutexGuard aGuard;
     503           0 :     const GtkSalMenu* pMenu = this;
     504           0 :     while( pMenu && ! pMenu->mpFrame )
     505           0 :         pMenu = pMenu->mpParentSalMenu;
     506           0 :     return pMenu ? pMenu->mpFrame : NULL;
     507             : }
     508             : 
     509           0 : void GtkSalMenu::NativeCheckItem( unsigned nSection, unsigned nItemPos, MenuItemBits bits, gboolean bCheck )
     510             : {
     511           0 :     SolarMutexGuard aGuard;
     512             : 
     513           0 :     if ( mpActionGroup == NULL )
     514           0 :         return;
     515             : 
     516           0 :     gchar* aCommand = g_lo_menu_get_command_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
     517             : 
     518           0 :     if ( aCommand != NULL || g_strcmp0( aCommand, "" ) != 0 )
     519             :     {
     520           0 :         GVariant *pCheckValue = NULL;
     521           0 :         GVariant *pCurrentState = g_action_group_get_action_state( mpActionGroup, aCommand );
     522             : 
     523           0 :         if ( bits & MIB_RADIOCHECK )
     524           0 :             pCheckValue = bCheck ? g_variant_new_string( aCommand ) : g_variant_new_string( "" );
     525             :         else
     526             :         {
     527             :             // By default, all checked items are checkmark buttons.
     528           0 :             if ( bCheck || ( !bCheck && pCurrentState != NULL ) )
     529           0 :                 pCheckValue = g_variant_new_boolean( bCheck );
     530             :         }
     531             : 
     532           0 :         if ( pCheckValue != NULL && ( pCurrentState == NULL || g_variant_equal( pCurrentState, pCheckValue ) == FALSE ) )
     533           0 :             g_action_group_change_action_state( mpActionGroup, aCommand, pCheckValue );
     534             : 
     535           0 :         if ( pCurrentState != NULL )
     536           0 :             g_variant_unref( pCurrentState );
     537             :     }
     538             : 
     539           0 :     if ( aCommand )
     540           0 :         g_free( aCommand );
     541             : }
     542             : 
     543           0 : void GtkSalMenu::NativeSetEnableItem( gchar* aCommand, gboolean bEnable )
     544             : {
     545           0 :     SolarMutexGuard aGuard;
     546           0 :     GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
     547             : 
     548           0 :     if ( g_action_group_get_action_enabled( G_ACTION_GROUP( pActionGroup ), aCommand ) != bEnable )
     549           0 :         g_lo_action_group_set_action_enabled( pActionGroup, aCommand, bEnable );
     550           0 : }
     551             : 
     552           0 : void GtkSalMenu::NativeSetItemText( unsigned nSection, unsigned nItemPos, const OUString& rText )
     553             : {
     554           0 :     SolarMutexGuard aGuard;
     555             :     // Replace the '~' character with '_'.
     556           0 :     OUString aText = rText.replace( '~', '_' );
     557           0 :     OString aConvertedText = OUStringToOString( aText, RTL_TEXTENCODING_UTF8 );
     558             : 
     559             :     // Update item text only when necessary.
     560           0 :     gchar* aLabel = g_lo_menu_get_label_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
     561             : 
     562           0 :     if ( aLabel == NULL || g_strcmp0( aLabel, aConvertedText.getStr() ) != 0 )
     563           0 :         g_lo_menu_set_label_to_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aConvertedText.getStr() );
     564             : 
     565           0 :     if ( aLabel )
     566           0 :         g_free( aLabel );
     567           0 : }
     568             : 
     569           0 : void GtkSalMenu::NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const KeyCode& rKeyCode, const OUString& rKeyName )
     570             : {
     571           0 :     SolarMutexGuard aGuard;
     572             : 
     573           0 :     if ( rKeyName.isEmpty() )
     574           0 :         return;
     575             : 
     576             :     guint nKeyCode;
     577             :     GdkModifierType nModifiers;
     578             : 
     579           0 :     KeyCodeToGdkKey( rKeyCode, &nKeyCode, &nModifiers );
     580             : 
     581           0 :     gchar* aAccelerator = gtk_accelerator_name( nKeyCode, nModifiers );
     582             : 
     583           0 :     gchar* aCurrentAccel = g_lo_menu_get_accelerator_from_item_in_section( G_LO_MENU( mpMenuModel ), nSection, nItemPos );
     584             : 
     585           0 :     if ( aCurrentAccel == NULL && g_strcmp0( aCurrentAccel, aAccelerator ) != 0 )
     586           0 :         g_lo_menu_set_accelerator_to_item_in_section ( G_LO_MENU( mpMenuModel ), nSection, nItemPos, aAccelerator );
     587             : 
     588           0 :     g_free( aAccelerator );
     589             : }
     590             : 
     591           0 : void GtkSalMenu::NativeSetItemCommand( unsigned nSection,
     592             :                                        unsigned nItemPos,
     593             :                                        sal_uInt16 nId,
     594             :                                        const gchar* aCommand,
     595             :                                        MenuItemBits nBits,
     596             :                                        gboolean bChecked,
     597             :                                        gboolean bIsSubmenu )
     598             : {
     599           0 :     SolarMutexGuard aGuard;
     600           0 :     GLOActionGroup* pActionGroup = G_LO_ACTION_GROUP( mpActionGroup );
     601             : 
     602           0 :     GVariant *pTarget = NULL;
     603             : 
     604           0 :     if ( g_action_group_has_action( mpActionGroup, aCommand ) == FALSE ) {
     605           0 :         if ( ( nBits & MIB_CHECKABLE ) || bIsSubmenu )
     606             :         {
     607             :             // Item is a checkmark button.
     608           0 :             GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_BOOLEAN );
     609           0 :             GVariant* pState = g_variant_new_boolean( bChecked );
     610             : 
     611           0 :             g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, NULL, pStateType, NULL, pState );
     612             :         }
     613           0 :         else if ( nBits & MIB_RADIOCHECK )
     614             :         {
     615             :             // Item is a radio button.
     616           0 :             GVariantType* pParameterType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
     617           0 :             GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_STRING );
     618           0 :             GVariant* pState = g_variant_new_string( "" );
     619           0 :             pTarget = g_variant_new_string( aCommand );
     620             : 
     621           0 :             g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, NULL, pState );
     622             :         }
     623             :         else
     624             :         {
     625             :             // Item is not special, so insert a stateless action.
     626           0 :             g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
     627             :         }
     628             :     }
     629             : 
     630           0 :     GLOMenu* pMenu = G_LO_MENU( mpMenuModel );
     631             : 
     632             :     // Menu item is not updated unless it's necessary.
     633           0 :     gchar* aCurrentCommand = g_lo_menu_get_command_from_item_in_section( pMenu, nSection, nItemPos );
     634             : 
     635           0 :     if ( aCurrentCommand == NULL || g_strcmp0( aCurrentCommand, aCommand ) != 0 )
     636             :     {
     637           0 :         g_lo_menu_set_command_to_item_in_section( pMenu, nSection, nItemPos, aCommand );
     638             : 
     639           0 :         gchar* aItemCommand = g_strconcat("win.", aCommand, NULL );
     640             : 
     641           0 :         if ( bIsSubmenu )
     642           0 :             g_lo_menu_set_submenu_action_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand );
     643             :         else
     644           0 :             g_lo_menu_set_action_and_target_value_to_item_in_section( pMenu, nSection, nItemPos, aItemCommand, pTarget );
     645             : 
     646           0 :         g_free( aItemCommand );
     647             :     }
     648             : 
     649           0 :     if ( aCurrentCommand )
     650           0 :         g_free( aCurrentCommand );
     651           0 : }
     652             : 
     653           0 : GtkSalMenu* GtkSalMenu::GetMenuForItemCommand( gchar* aCommand, gboolean bGetSubmenu )
     654             : {
     655           0 :     SolarMutexGuard aGuard;
     656           0 :     GtkSalMenu* pMenu = NULL;
     657           0 :     for ( sal_uInt16 nPos = 0; nPos < maItems.size(); nPos++ )
     658             :     {
     659           0 :         GtkSalMenuItem *pSalItem = maItems[ nPos ];
     660             : 
     661           0 :         String aItemCommand = mpVCLMenu->GetItemCommand( pSalItem->mnId );
     662           0 :         gchar* aItemCommandStr = (gchar*) OUStringToOString( aItemCommand, RTL_TEXTENCODING_UTF8 ).getStr();
     663             : 
     664           0 :         if ( g_strcmp0( aItemCommandStr, aCommand ) == 0 )
     665             :         {
     666           0 :             pMenu = bGetSubmenu ? pSalItem->mpSubMenu : this;
     667           0 :             break;
     668             :         }
     669             :         else
     670             :         {
     671           0 :             if ( pSalItem->mpSubMenu != NULL )
     672           0 :                 pMenu = pSalItem->mpSubMenu->GetMenuForItemCommand( aCommand, bGetSubmenu );
     673             : 
     674           0 :             if ( pMenu != NULL )
     675           0 :                break;
     676             :         }
     677           0 :     }
     678             : 
     679           0 :     return pMenu;
     680             : }
     681             : 
     682           0 : void GtkSalMenu::DispatchCommand( gint itemId, const gchar *aCommand )
     683             : {
     684           0 :     SolarMutexGuard aGuard;
     685             :     // Only the menubar is allowed to dispatch commands.
     686           0 :     if ( mbMenuBar != TRUE )
     687           0 :         return;
     688             : 
     689           0 :     GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aCommand, FALSE );
     690           0 :     Menu* pSubMenu = ( pSalSubMenu != NULL ) ? pSalSubMenu->GetMenu() : NULL;
     691             : 
     692           0 :     MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
     693           0 :     pMenuBar->HandleMenuCommandEvent( pSubMenu, itemId );
     694             : }
     695             : 
     696           0 : void GtkSalMenu::ActivateAllSubmenus(MenuBar* pMenuBar)
     697             : {
     698           0 :     pMenuBar->HandleMenuActivateEvent(mpVCLMenu);
     699           0 :     for ( sal_uInt16 nPos = 0; nPos < maItems.size(); nPos++ )
     700             :     {
     701           0 :         GtkSalMenuItem *pSalItem = maItems[ nPos ];
     702           0 :         if ( pSalItem->mpSubMenu != NULL )
     703             :         {
     704           0 :             pSalItem->mpSubMenu->ActivateAllSubmenus(pMenuBar);
     705           0 :             pSalItem->mpSubMenu->Update();
     706             :         }
     707             :     }
     708           0 : }
     709             : 
     710           0 : void GtkSalMenu::Activate()
     711             : {
     712           0 :     if ( mbMenuBar != TRUE )
     713           0 :         return;
     714           0 :     ActivateAllSubmenus(static_cast<MenuBar*>(mpVCLMenu));
     715             : }
     716             : 
     717             : 
     718           0 : void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
     719             : {
     720           0 :     if ( mbMenuBar == sal_False )
     721           0 :         return;
     722             : 
     723           0 :     GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aMenuCommand, TRUE );
     724             : 
     725           0 :     if ( pSalSubMenu != NULL ) {
     726           0 :         MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
     727           0 :         pMenuBar->HandleMenuDeActivateEvent( pSalSubMenu->mpVCLMenu );
     728             :     }
     729             : }
     730             : 
     731           0 : void GtkSalMenu::Display( sal_Bool bVisible )
     732             : {
     733           0 :     if ( mbMenuBar == sal_False || mpVCLMenu == NULL )
     734           0 :         return;
     735             : 
     736           0 :     bMenuVisibility = bVisible;
     737             : 
     738           0 :     sal_Bool bVCLMenuVisible = ( bVisible == sal_True ) ? sal_False : sal_True;
     739             : 
     740           0 :     MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
     741           0 :     pMenuBar->SetDisplayable( bVCLMenuVisible );
     742             : }
     743             : 
     744           0 : sal_Bool GtkSalMenu::IsItemVisible( unsigned nPos )
     745             : {
     746           0 :     SolarMutexGuard aGuard;
     747           0 :     sal_Bool bVisible = sal_False;
     748             : 
     749           0 :     if ( nPos < maItems.size() )
     750           0 :         bVisible = ( ( GtkSalMenuItem* ) maItems[ nPos ])->mbVisible;
     751             : 
     752           0 :     return bVisible;
     753             : }
     754             : 
     755           0 : void GtkSalMenu::CheckItem( unsigned, sal_Bool )
     756             : {
     757           0 : }
     758             : 
     759           0 : void GtkSalMenu::EnableItem( unsigned, sal_Bool )
     760             : {
     761           0 : }
     762             : 
     763           0 : void GtkSalMenu::ShowItem( unsigned nPos, sal_Bool bShow )
     764             : {
     765           0 :     SolarMutexGuard aGuard;
     766           0 :     if ( nPos < maItems.size() )
     767           0 :         ( ( GtkSalMenuItem* ) maItems[ nPos ] )->mbVisible = bShow;
     768           0 : }
     769             : 
     770             : 
     771           0 : void GtkSalMenu::SetItemText( unsigned, SalMenuItem*, const OUString& )
     772             : {
     773           0 : }
     774             : 
     775           0 : void GtkSalMenu::SetItemImage( unsigned, SalMenuItem*, const Image& )
     776             : {
     777           0 : }
     778             : 
     779           0 : void GtkSalMenu::SetAccelerator( unsigned, SalMenuItem*, const KeyCode&, const OUString& )
     780             : {
     781           0 : }
     782             : 
     783           0 : void GtkSalMenu::GetSystemMenuData( SystemMenuData* )
     784             : {
     785           0 : }
     786             : 
     787             : // =======================================================================
     788             : 
     789             : /*
     790             :  * GtkSalMenuItem
     791             :  */
     792             : 
     793           0 : GtkSalMenuItem::GtkSalMenuItem( const SalItemParams* pItemData ) :
     794             :     mnId( pItemData->nId ),
     795             :     mnType( pItemData->eType ),
     796             :     mbVisible( sal_True ),
     797             :     mpVCLMenu( pItemData->pMenu ),
     798             :     mpParentMenu( NULL ),
     799           0 :     mpSubMenu( NULL )
     800             : {
     801           0 : }
     802             : 
     803           0 : GtkSalMenuItem::~GtkSalMenuItem()
     804             : {
     805           0 : }
     806             : 
     807             : #endif
     808             : 
     809             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10