summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Fernandez <antonio.fernandez@aentos.es>2012-09-12 20:45:31 +0100
committerBjoern Michaelsen <bjoern.michaelsen@canonical.com>2012-11-14 13:52:48 +0100
commit6b42d547cfbe87e934f65c74cb180f5f1c10c6c2 (patch)
tree8cea204a387f909f34e4210cd1fee2272b8ed55a
parentb789263fb7bf537cc85d3df3022282ab8f32bccb (diff)
Menus are generated on demand now, but with some issues.
Change-Id: Icec9b685e720a369cff4d2bbfc5bf4ba6614e390
-rw-r--r--vcl/inc/unx/gtk/gloactiongroup.h4
-rw-r--r--vcl/inc/unx/gtk/gtksalmenu.hxx4
-rw-r--r--vcl/source/window/menu.cxx5
-rw-r--r--vcl/unx/gtk/window/gloactiongroup.cxx59
-rw-r--r--vcl/unx/gtk/window/gtksalmenu.cxx142
5 files changed, 189 insertions, 25 deletions
diff --git a/vcl/inc/unx/gtk/gloactiongroup.h b/vcl/inc/unx/gtk/gloactiongroup.h
index e0d783fe3778..61ec718d4cd3 100644
--- a/vcl/inc/unx/gtk/gloactiongroup.h
+++ b/vcl/inc/unx/gtk/gloactiongroup.h
@@ -67,11 +67,13 @@ GLOActionGroup * g_lo_action_group_new (gpointer
void g_lo_action_group_insert (GLOActionGroup *group,
const gchar *action_name,
- gint item_id);
+ gint item_id,
+ gboolean submenu);
void g_lo_action_group_insert_stateful (GLOActionGroup *group,
const gchar *action_name,
gint item_id,
+ gboolean submenu,
const GVariantType *parameter_type,
const GVariantType *state_type,
GVariant *state_hint,
diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx
index d7d59662f945..56aed28d8277 100644
--- a/vcl/inc/unx/gtk/gtksalmenu.hxx
+++ b/vcl/inc/unx/gtk/gtksalmenu.hxx
@@ -55,7 +55,7 @@ private:
GMenuModel* mpMenuModel;
GActionGroup* mpActionGroup;
- GtkSalMenu* GetMenuForItemCommand( gchar* aCommand );
+ GtkSalMenu* GetMenuForItemCommand( gchar* aCommand, gboolean bGetSubmenu );
public:
GtkSalMenu( sal_Bool bMenuBar );
@@ -101,6 +101,8 @@ public:
void NativeSetAccelerator( unsigned nSection, unsigned nItemPos, const KeyCode& rKeyCode, const rtl::OUString& rKeyName );
void DispatchCommand( gint itemId, const gchar* aCommand );
+ void Activate( const gchar* aMenuCommand );
+ void Deactivate( const gchar* aMenuCommand );
};
class GtkSalMenuItem : public SalMenuItem
diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx
index 10bcdf66da3f..00abe068dfee 100644
--- a/vcl/source/window/menu.cxx
+++ b/vcl/source/window/menu.cxx
@@ -1135,8 +1135,7 @@ void Menu::Select()
}
}
-// FIXME: Workaround to make GLOMenu without defining macros.
-//#if defined(QUARTZ)
+#if defined(QUARTZ)
void Menu::ImplSelectWithStart( Menu* pSMenu )
{
Menu* pOldStartedFrom = pStartedFrom;
@@ -1147,7 +1146,7 @@ void Menu::ImplSelectWithStart( Menu* pSMenu )
pOldStartedFrom->pStartedFrom = pOldStartedStarted;
pStartedFrom = pOldStartedFrom;
}
-//#endif
+#endif
void Menu::RequestHelp( const HelpEvent& )
{
diff --git a/vcl/unx/gtk/window/gloactiongroup.cxx b/vcl/unx/gtk/window/gloactiongroup.cxx
index 171341dcd4a7..11173880774e 100644
--- a/vcl/unx/gtk/window/gloactiongroup.cxx
+++ b/vcl/unx/gtk/window/gloactiongroup.cxx
@@ -43,7 +43,8 @@ struct _GLOAction
GObject parent_instance;
gint item_id; // Menu item ID.
- gboolean enabled; // TRUE if action is enabled, FALSE otherwise.
+ gboolean submenu; // TRUE if action is a submenu action.
+ gboolean enabled; // TRUE if action is enabled.
GVariantType* parameter_type; // A GVariantType with the action parameter type.
GVariantType* state_type; // A GVariantType with item state type
GVariant* state_hint; // A GVariant with state hints.
@@ -65,6 +66,7 @@ static void
g_lo_action_init (GLOAction *action)
{
action->item_id = -1;
+ action->submenu = FALSE;
action->enabled = TRUE;
action->parameter_type = NULL;
action->state_type = NULL;
@@ -174,6 +176,30 @@ g_lo_action_group_query_action (GActionGroup *group,
}
static void
+g_lo_action_group_perform_submenu_action (GLOActionGroup *group,
+ const gchar *action_name,
+ GVariant *state)
+{
+ GTK_YIELD_GRAB();
+
+ GtkSalFrame* pFrame = group->priv->frame;
+
+ if (pFrame == NULL)
+ return;
+
+ GtkSalMenu* pSalMenu = static_cast<GtkSalMenu*> (pFrame->GetMenu());
+
+ if (pSalMenu != NULL) {
+ gboolean bState = g_variant_get_boolean (state);
+
+ if (bState == TRUE)
+ pSalMenu->Activate (action_name);
+ else
+ pSalMenu->Deactivate (action_name);
+ }
+}
+
+static void
g_lo_action_group_change_state (GActionGroup *group,
const gchar *action_name,
GVariant *value)
@@ -182,23 +208,29 @@ g_lo_action_group_change_state (GActionGroup *group,
return;
GLOActionGroup* lo_group = G_LO_ACTION_GROUP (group);
-
GLOAction* action = G_LO_ACTION (g_hash_table_lookup (lo_group->priv->table, action_name));
if (action == NULL)
return;
- if (action->state_type == NULL)
- action->state_type = g_variant_type_copy(g_variant_get_type(value));
-
- g_return_if_fail (g_variant_is_of_type(value, action->state_type) == TRUE);
+ if (action->submenu == TRUE)
+ {
+// g_action_group_action_state_changed(group, action_name, value);
+ g_lo_action_group_perform_submenu_action (lo_group, action_name, value);
+ }
+ else
+ {
+ if (action->state_type == NULL)
+ action->state_type = g_variant_type_copy(g_variant_get_type(value));
- if (action->state)
- g_variant_unref(action->state);
+ g_return_if_fail (g_variant_is_of_type(value, action->state_type) == TRUE);
- action->state = g_variant_take_ref(value);
+ if (action->state)
+ g_variant_unref(action->state);
- g_action_group_action_state_changed(group, action_name, value);
+ action->state = g_variant_take_ref(value);
+ g_action_group_action_state_changed(group, action_name, value);
+ }
}
static void
@@ -226,15 +258,17 @@ g_lo_action_group_activate (GActionGroup *group,
void
g_lo_action_group_insert (GLOActionGroup *group,
const gchar *action_name,
- gint item_id)
+ gint item_id,
+ gboolean submenu)
{
- g_lo_action_group_insert_stateful (group, action_name, item_id, NULL, NULL, NULL, NULL);
+ g_lo_action_group_insert_stateful (group, action_name, item_id, submenu, NULL, NULL, NULL, NULL);
}
void
g_lo_action_group_insert_stateful (GLOActionGroup *group,
const gchar *action_name,
gint item_id,
+ gboolean submenu,
const GVariantType *parameter_type,
const GVariantType *state_type,
GVariant *state_hint,
@@ -254,6 +288,7 @@ g_lo_action_group_insert_stateful (GLOActionGroup *group,
g_hash_table_insert (group->priv->table, g_strdup (action_name), action);
action->item_id = item_id;
+ action->submenu = submenu;
if (parameter_type)
action->parameter_type = (GVariantType*) parameter_type;
diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx
index 98c52e5786e7..1476e61c239b 100644
--- a/vcl/unx/gtk/window/gtksalmenu.cxx
+++ b/vcl/unx/gtk/window/gtksalmenu.cxx
@@ -50,6 +50,106 @@ static gchar* GetCommandForSpecialItem( GtkSalMenuItem* pSalMenuItem )
return aCommand;
}
+static void UpdateNativeMenu2( GtkSalMenu *pMenu )
+{
+ if ( pMenu == NULL )
+ return;
+
+ Menu* pVCLMenu = pMenu->GetMenu();
+ GLOMenu* pLOMenu = G_LO_MENU( pMenu->GetMenuModel() );
+ GActionGroup* pActionGroup = pMenu->GetActionGroup();
+
+ sal_uInt16 nLOMenuSize = g_menu_model_get_n_items( G_MENU_MODEL( pLOMenu ) );
+
+ if ( nLOMenuSize == 0 )
+ g_lo_menu_new_section( pLOMenu, 0, NULL );
+
+ sal_uInt16 nSection = 0;
+ sal_uInt16 nItemPos = 0;
+ sal_uInt16 validItems = 0;
+ sal_uInt16 nItem;
+
+ for ( nItem = 0; nItem < pMenu->GetItemCount(); nItem++ ) {
+ GtkSalMenuItem *pSalMenuItem = pMenu->GetItemAtPos( nItem );
+ sal_uInt16 nId = pSalMenuItem->mnId;
+
+ if ( pSalMenuItem->mnType == MENUITEM_SEPARATOR )
+ {
+ nSection++;
+ nItemPos = 0;
+
+ if ( nLOMenuSize <= nSection )
+ {
+ g_lo_menu_new_section( pLOMenu, nSection, NULL );
+ nLOMenuSize++;
+ }
+
+ continue;
+ }
+
+ if ( nItemPos >= g_lo_menu_get_n_items_from_section( pLOMenu, nSection ) )
+ g_lo_menu_insert_in_section( pLOMenu, nSection, nItemPos, "EMPTY STRING" );
+
+ // Get internal menu item values.
+ String aText = pVCLMenu->GetItemText( nId );
+ rtl::OUString aCommand( pVCLMenu->GetItemCommand( nId ) );
+ sal_Bool itemEnabled = pVCLMenu->IsItemEnabled( nId );
+ KeyCode nAccelKey = pVCLMenu->GetAccelKey( nId );
+ sal_Bool itemChecked = pVCLMenu->IsItemChecked( nId );
+ MenuItemBits itemBits = pVCLMenu->GetItemBits( nId );
+
+ // Convert internal values to native values.
+ gboolean bChecked = ( itemChecked == sal_True ) ? TRUE : FALSE;
+ gboolean bEnabled = ( itemEnabled == sal_True ) ? TRUE : FALSE;
+ gchar* aNativeCommand = g_strdup( rtl::OUStringToOString( aCommand, RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ // Force updating of native menu labels.
+ pMenu->NativeSetItemText( nSection, nItemPos, aText );
+ pMenu->NativeSetAccelerator( nSection, nItemPos, nAccelKey, nAccelKey.GetName( pMenu->GetFrame()->GetWindow() ) );
+
+ // Some items are special, so they have different commands.
+ if ( g_strcmp0( aNativeCommand, "" ) == 0 )
+ {
+ gchar *aSpecialItemCmd = GetCommandForSpecialItem( pSalMenuItem );
+
+ if ( aSpecialItemCmd != NULL )
+ {
+ g_free( aNativeCommand );
+ aNativeCommand = aSpecialItemCmd;
+ }
+ }
+
+ if ( g_strcmp0( aNativeCommand, "" ) != 0 && pSalMenuItem->mpSubMenu == NULL )
+ {
+ pMenu->NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, bChecked, FALSE );
+ pMenu->NativeCheckItem( nSection, nItemPos, itemBits, bChecked );
+ pMenu->NativeSetEnableItem( aNativeCommand, bEnabled );
+ }
+
+ GtkSalMenu* pSubmenu = pSalMenuItem->mpSubMenu;
+
+ if ( pSubmenu && pSubmenu->GetMenu() )
+ {
+ GLOMenu* pSubMenuModel = g_lo_menu_get_submenu_from_item_in_section( pLOMenu, nSection, nItemPos );
+
+ if ( pSubMenuModel == NULL )
+ {
+ pSubMenuModel = g_lo_menu_new();
+ g_lo_menu_set_submenu_to_item_in_section( pLOMenu, nSection, nItemPos, G_MENU_MODEL( pSubMenuModel ) );
+ }
+
+ pMenu->NativeSetItemCommand( nSection, nItemPos, nId, aNativeCommand, itemBits, FALSE, TRUE );
+ pSubmenu->SetMenuModel( G_MENU_MODEL( pSubMenuModel ) );
+ pSubmenu->SetActionGroup( pActionGroup );
+ }
+
+ g_free( aNativeCommand );
+
+ nItemPos++;
+ validItems++;
+ }
+}
+
static void UpdateNativeMenu( GtkSalMenu* pMenu )
{
if ( pMenu == NULL )
@@ -406,10 +506,11 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame )
// Generate the main menu structure.
GenerateMenu( this );
+// UpdateNativeMenu2( this );
// Refresh the menu every second.
// This code is a workaround until required modifications in Gtk+ are available.
- g_timeout_add_seconds( 1, GenerateMenu, this );
+// g_timeout_add_seconds( 1, GenerateMenu, this );
}
}
@@ -511,7 +612,7 @@ void GtkSalMenu::NativeSetItemCommand( unsigned nSection,
GVariantType* pStateType = g_variant_type_new( (gchar*) G_VARIANT_TYPE_BOOLEAN );
GVariant* pState = g_variant_new_boolean( bChecked );
- g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, NULL, pStateType, NULL, pState );
+ g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, bIsSubmenu, NULL, pStateType, NULL, pState );
}
else if ( nBits & MIB_RADIOCHECK )
{
@@ -521,12 +622,12 @@ void GtkSalMenu::NativeSetItemCommand( unsigned nSection,
GVariant* pState = g_variant_new_string( "" );
pTarget = g_variant_new_string( aCommand );
- g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, pParameterType, pStateType, NULL, pState );
+ g_lo_action_group_insert_stateful( pActionGroup, aCommand, nId, FALSE, pParameterType, pStateType, NULL, pState );
}
else
{
// Item is not special, so insert a stateless action.
- g_lo_action_group_insert( pActionGroup, aCommand, nId );
+ g_lo_action_group_insert( pActionGroup, aCommand, nId, FALSE );
}
}
@@ -553,7 +654,7 @@ void GtkSalMenu::NativeSetItemCommand( unsigned nSection,
g_free( aCurrentCommand );
}
-GtkSalMenu* GtkSalMenu::GetMenuForItemCommand( gchar* aCommand )
+GtkSalMenu* GtkSalMenu::GetMenuForItemCommand( gchar* aCommand, gboolean bGetSubmenu )
{
GtkSalMenu* pMenu = NULL;
@@ -566,13 +667,13 @@ GtkSalMenu* GtkSalMenu::GetMenuForItemCommand( gchar* aCommand )
if ( g_strcmp0( aItemCommandStr, aCommand ) == 0 )
{
- pMenu = this;
+ pMenu = ( bGetSubmenu == TRUE ) ? pSalItem->mpSubMenu : this;
break;
}
else
{
if ( pSalItem->mpSubMenu != NULL )
- pMenu = pSalItem->mpSubMenu->GetMenuForItemCommand( aCommand );
+ pMenu = pSalItem->mpSubMenu->GetMenuForItemCommand( aCommand, bGetSubmenu );
if ( pMenu != NULL )
break;
@@ -588,7 +689,7 @@ void GtkSalMenu::DispatchCommand( gint itemId, const gchar *aCommand )
if ( mbMenuBar != TRUE )
return;
- GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aCommand );
+ GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aCommand, FALSE );
Menu* pSubMenu = ( pSalSubMenu != NULL ) ? pSalSubMenu->GetMenu() : NULL;
MenuBar* pMenuBar = static_cast< MenuBar* >( mpVCLMenu );
@@ -596,6 +697,31 @@ void GtkSalMenu::DispatchCommand( gint itemId, const gchar *aCommand )
pMenuBar->HandleMenuCommandEvent( pSubMenu, itemId );
}
+void GtkSalMenu::Activate( const gchar* aMenuCommand )
+{
+ if ( mbMenuBar != TRUE )
+ return;
+
+ GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aMenuCommand, TRUE );
+
+ if ( pSalSubMenu != NULL ) {
+ pSalSubMenu->mpVCLMenu->Activate();
+ UpdateNativeMenu2( pSalSubMenu );
+ }
+}
+
+void GtkSalMenu::Deactivate( const gchar* aMenuCommand )
+{
+ if ( mbMenuBar != TRUE )
+ return;
+
+ GtkSalMenu* pSalSubMenu = GetMenuForItemCommand( (gchar*) aMenuCommand, TRUE );
+
+ if ( pSalSubMenu != NULL ) {
+ pSalSubMenu->mpVCLMenu->Deactivate();
+ }
+}
+
void GtkSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck )
{
}