diff options
author | Antonio Fernandez <antonio.fernandez@aentos.es> | 2012-08-08 16:18:14 +0100 |
---|---|---|
committer | Bjoern Michaelsen <bjoern.michaelsen@canonical.com> | 2012-11-14 13:52:40 +0100 |
commit | 36c1c2c2754dda6e8d2b2802e3881465adaafbec (patch) | |
tree | 2ca7be5a645ce06fac0b5b09c1258b3906f6f8a2 | |
parent | ba8ab7935c9d12b3f5ce1df64fafc2e4f68c4510 (diff) |
Added GLOMenu and GLOActionGroup. Menu is published with actions (not working)
Change-Id: I3400980e4605fbf78755532c696e021d3466675b
-rw-r--r-- | vcl/Library_vclplug_gtk.mk | 2 | ||||
-rw-r--r-- | vcl/inc/salmenu.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gloactiongroup.h | 62 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/glomenu.h | 87 | ||||
-rw-r--r-- | vcl/inc/unx/gtk/gtksalmenu.hxx | 10 | ||||
-rw-r--r-- | vcl/source/window/menu.cxx | 7 | ||||
-rw-r--r-- | vcl/unx/gtk/window/gloactiongroup.cxx | 325 | ||||
-rw-r--r-- | vcl/unx/gtk/window/glomenu.cxx | 574 | ||||
-rw-r--r-- | vcl/unx/gtk/window/gtksalmenu.cxx | 284 |
9 files changed, 1238 insertions, 115 deletions
diff --git a/vcl/Library_vclplug_gtk.mk b/vcl/Library_vclplug_gtk.mk index 9414326a26a1..441f0042b3a7 100644 --- a/vcl/Library_vclplug_gtk.mk +++ b/vcl/Library_vclplug_gtk.mk @@ -89,7 +89,9 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gtk,\ vcl/unx/gtk/gdi/salnativewidgets-gtk \ vcl/unx/gtk/window/gtkframe \ vcl/unx/gtk/window/gtkobject \ + vcl/unx/gtk/window/gloactiongroup \ vcl/unx/gtk/window/gtksalmenu \ + vcl/unx/gtk/window/glomenu \ vcl/unx/gtk/fpicker/resourceprovider \ vcl/unx/gtk/fpicker/SalGtkPicker \ vcl/unx/gtk/fpicker/SalGtkFilePicker \ diff --git a/vcl/inc/salmenu.hxx b/vcl/inc/salmenu.hxx index 83f6fdc25641..50d4ed93e7fc 100644 --- a/vcl/inc/salmenu.hxx +++ b/vcl/inc/salmenu.hxx @@ -81,6 +81,8 @@ public: virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, sal_uLong nFlags); virtual bool AddMenuBarButton( const SalMenuButtonItem& ); // return false if not implemented or failure virtual void RemoveMenuBarButton( sal_uInt16 nId ); + + virtual void SetItemCommand( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& aCommandStr ) {} virtual void Freeze() {} // return an empty rectangle if not implemented diff --git a/vcl/inc/unx/gtk/gloactiongroup.h b/vcl/inc/unx/gtk/gloactiongroup.h new file mode 100644 index 000000000000..b71ae47d20d9 --- /dev/null +++ b/vcl/inc/unx/gtk/gloactiongroup.h @@ -0,0 +1,62 @@ +#ifndef GLOACTIONGROUP_H +#define GLOACTIONGROUP_H + +#include <gio/gio.h> +//#include "gactionmap.h" + +G_BEGIN_DECLS + +#define G_TYPE_LO_ACTION_GROUP (g_lo_action_group_get_type ()) +#define G_LO_ACTION_GROUP(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), \ + G_TYPE_LO_ACTION_GROUP, GLOActionGroup)) +#define G_LO_ACTION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), \ + G_TYPE_LO_ACTION_GROUP, GLOActionGroupClass)) +#define G_IS_LO_ACTION_GROUP(inst) (G_TYPE_CHECK_INSTANCE_TYPE ((inst), \ + G_TYPE_LO_ACTION_GROUP)) +#define G_IS_LO_ACTION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + G_TYPE_LO_ACTION_GROUP)) +#define G_LO_ACTION_GROUP_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_CLASS ((inst), \ + G_TYPE_LO_ACTION_GROUP, GLOActionGroupClass)) + +typedef struct _GLOActionGroupPrivate GLOActionGroupPrivate; +typedef struct _GLOActionGroupClass GLOActionGroupClass; +typedef struct _GLOActionGroup GLOActionGroup; + +struct _GLOActionGroup +{ + /*< private >*/ + GObject parent_instance; + + GLOActionGroupPrivate *priv; +}; + +struct _GLOActionGroupClass +{ + /*< private >*/ + GObjectClass parent_class; + + /*< private >*/ + gpointer padding[12]; +}; + +GType g_lo_action_group_get_type (void) G_GNUC_CONST; + +GLOActionGroup * g_lo_action_group_new (void); + +GAction * g_lo_action_group_lookup (GLOActionGroup *group, + const gchar *action_name); + +void g_lo_action_group_insert (GLOActionGroup *group, + GAction *action); + +void g_lo_action_group_remove (GLOActionGroup *group, + const gchar *action_name); + +void g_lo_action_group_add_entries (GLOActionGroup *group, + const GActionEntry *entries, + gint n_entries, + gpointer user_data); + +G_END_DECLS + +#endif // GLOACTIONGROUP_H diff --git a/vcl/inc/unx/gtk/glomenu.h b/vcl/inc/unx/gtk/glomenu.h new file mode 100644 index 000000000000..d1df68301aaf --- /dev/null +++ b/vcl/inc/unx/gtk/glomenu.h @@ -0,0 +1,87 @@ +#ifndef GLOMENU_H +#define GLOMENU_H + +#include <glib-object.h> +#include <gio/gio.h> + +G_BEGIN_DECLS + +#define G_TYPE_LO_MENU (g_lo_menu_get_type()) +#define G_LO_MENU(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_LO_MENU, GLOMenu)) +#define G_IS_LO_MENU(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_LO_MENU)) + +#define G_TYPE_LO_MENU_ITEM (g_lo_menu_item_get_type()) +#define G_LO_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_LO_MENU_ITEM, GLOMenuItem)) +#define G_IS_LO_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), G_TYPE_LO_MENU_ITEM)) + +typedef struct _GLOMenuItem GLOMenuItem; +typedef struct _GLOMenu GLOMenu; + +GLIB_AVAILABLE_IN_2_32 +GType g_lo_menu_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_2_32 + +GLOMenu * g_lo_menu_new (void); +void g_lo_menu_insert_item (GLOMenu *menu, + gint position, + GLOMenuItem *item); +void g_lo_menu_insert (GLOMenu *menu, + gint position, + const gchar *label, + const gchar *detailed_action); +void g_lo_menu_append (GLOMenu *menu, + const gchar *label, + const gchar *detailed_action); +void g_lo_menu_append_item (GLOMenu *menu, + GLOMenuItem *item); +void g_lo_menu_insert_section (GLOMenu *menu, + gint position, + const gchar *label, + GMenuModel *section); +void g_lo_menu_prepend_section (GLOMenu *menu, + const gchar *label, + GMenuModel *section); +void g_lo_menu_append_section (GLOMenu *menu, + const gchar *label, + GMenuModel *section); +void g_lo_menu_insert_submenu (GLOMenu *menu, + gint position, + const gchar *label, + GMenuModel *submenu); +void g_lo_menu_append_submenu (GLOMenu *menu, + const gchar *label, + GMenuModel *submenu); + +GType g_lo_menu_item_get_type (void) G_GNUC_CONST; +GLOMenuItem * g_lo_menu_item_new (const gchar *label, + const gchar *detailed_action); +GLOMenuItem * g_lo_menu_item_new_submenu (const gchar *label, + GMenuModel *submenu); +GLOMenuItem * g_lo_menu_item_new_section (const gchar *label, + GMenuModel *section); +void g_lo_menu_item_set_attribute_value (GLOMenuItem *menu_item, + const gchar *attribute, + GVariant *value); +void g_lo_menu_item_set_link (GLOMenuItem *menu_item, + const gchar *link, + GMenuModel *model); +void g_lo_menu_item_set_label (GLOMenuItem *menu_item, + const gchar *label); +void g_lo_menu_item_set_submenu (GLOMenuItem *menu_item, + GMenuModel *submenu); +void g_lo_menu_item_set_section (GLOMenuItem *menu_item, + GMenuModel *section); +void g_lo_menu_item_set_action_and_target_value (GLOMenuItem *menu_item, + const gchar *action, + GVariant *target_value); +void g_lo_menu_item_set_action_and_target (GLOMenuItem *menu_item, + const gchar *action, + const gchar *format_string, + ...); +void g_lo_menu_item_set_detailed_action (GLOMenuItem *menu_item, + const gchar *detailed_action); + +G_END_DECLS + + +#endif // GLOMENU_H diff --git a/vcl/inc/unx/gtk/gtksalmenu.hxx b/vcl/inc/unx/gtk/gtksalmenu.hxx index 65c2bc8051e8..03c07bb4eea7 100644 --- a/vcl/inc/unx/gtk/gtksalmenu.hxx +++ b/vcl/inc/unx/gtk/gtksalmenu.hxx @@ -34,6 +34,7 @@ #include <unx/gtk/gtkframe.hxx> #include <unx/salmenu.h> #include <gio/gio.h> +#include "gloactiongroup.h" #include <vector> @@ -43,15 +44,16 @@ class GtkSalMenuSection; class GtkSalMenu : public SalMenu { private: - +// static GLOActionGroup* pCurrentActionGroup; sal_Bool mbMenuBar; - virtual void publishMenu( GMenuModel* ); + virtual void publishMenu( GMenuModel*, GActionGroup* ); public: std::vector< GtkSalMenuSection* > maSections; std::vector< GtkSalMenuItem* > maItems; GtkSalMenuSection* mpCurrentSection; + GActionEntry* mpActionEntry; Menu* mpVCLMenu; const GtkSalFrame* mpFrame; @@ -59,6 +61,7 @@ public: GDBusConnection* pSessionBus; sal_Int32 mBusId; sal_Int32 mMenubarId; + sal_Int32 mActionGroupId; GtkSalMenu( sal_Bool bMenuBar ); virtual ~GtkSalMenu(); @@ -76,6 +79,8 @@ public: virtual void SetItemImage( unsigned nPos, SalMenuItem* pSalMenuItem, const Image& rImage); virtual void SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const KeyCode& rKeyCode, const rtl::OUString& rKeyName ); virtual void GetSystemMenuData( SystemMenuData* pData ); + virtual void SetItemCommand( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& aCommandStr ); + virtual bool ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, sal_uLong nFlags); virtual void Freeze(); }; @@ -100,6 +105,7 @@ public: GtkSalMenu* mpParentMenu; // The menu in which this menu item is inserted GtkSalMenu* mpSubMenu; // Sub menu of this item (if defined) GMenuItem* mpMenuItem; // The GMenuItem + GAction* mpAction; // The GAction associated with this item }; #endif // GTKSALMENU_HXX diff --git a/vcl/source/window/menu.cxx b/vcl/source/window/menu.cxx index bd9ca95b3c96..e713b1696c3e 100644 --- a/vcl/source/window/menu.cxx +++ b/vcl/source/window/menu.cxx @@ -1947,10 +1947,15 @@ sal_Bool Menu::GetItemImageMirrorMode( sal_uInt16 nItemId ) const void Menu::SetItemCommand( sal_uInt16 nItemId, const String& rCommand ) { - MenuItemData* pData = pItemList->GetData( nItemId ); + size_t nPos; + MenuItemData* pData = pItemList->GetData( nItemId, nPos ); if ( pData ) pData->aCommandStr = rCommand; + + // update native menu + if( ImplGetSalMenu() && pData->pSalMenuItem ) + ImplGetSalMenu()->SetItemCommand( nPos, pData->pSalMenuItem, rCommand ); } const XubString& Menu::GetItemCommand( sal_uInt16 nItemId ) const diff --git a/vcl/unx/gtk/window/gloactiongroup.cxx b/vcl/unx/gtk/window/gloactiongroup.cxx new file mode 100644 index 000000000000..dc3fb3927250 --- /dev/null +++ b/vcl/unx/gtk/window/gloactiongroup.cxx @@ -0,0 +1,325 @@ +#include <unx/gtk/gloactiongroup.h> + +//#include "gsimpleaction.h" +//#include "gactionmap.h" +//#include "gaction.h" + +#include <stdio.h> + + +struct _GLOActionGroupPrivate +{ + GHashTable *table; /* string -> GAction */ +}; + +static void g_lo_action_group_iface_init (GActionGroupInterface *); +static void g_lo_action_group_map_iface_init (GActionMapInterface *); + +G_DEFINE_TYPE_WITH_CODE (GLOActionGroup, + g_lo_action_group, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_GROUP, + g_lo_action_group_iface_init); + G_IMPLEMENT_INTERFACE (G_TYPE_ACTION_MAP, + g_lo_action_group_map_iface_init)) + +static gchar ** +g_lo_action_group_list_actions (GActionGroup *group) +{ + puts(__FUNCTION__); + GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group); + GHashTableIter iter; + gint n, i = 0; + gchar **keys; + gpointer key; + + n = g_hash_table_size (loGroup->priv->table); + keys = g_new (gchar *, n + 1); + + g_hash_table_iter_init (&iter, loGroup->priv->table); + while (g_hash_table_iter_next (&iter, &key, NULL)) + keys[i++] = g_strdup ((gchar*) key); + g_assert_cmpint (i, ==, n); + keys[n] = NULL; + + return keys; +} + +static gboolean +g_lo_action_group_query_action (GActionGroup *group, + const gchar *action_name, + gboolean *enabled, + const GVariantType **parameter_type, + const GVariantType **state_type, + GVariant **state_hint, + GVariant **state) +{ + puts(__FUNCTION__); + GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group); + GAction *action; + + action = G_ACTION( g_hash_table_lookup (loGroup->priv->table, action_name) ); + + if (action == NULL) + return FALSE; + + if (enabled) + *enabled = g_action_get_enabled (action); + + if (parameter_type) + *parameter_type = g_action_get_parameter_type (action); + + if (state_type) + *state_type = g_action_get_state_type (action); + + if (state_hint) + *state_hint = g_action_get_state_hint (action); + + if (state) + *state = g_action_get_state (action); + + return TRUE; +} + +static void +g_lo_action_group_change_state (GActionGroup *group, + const gchar *action_name, + GVariant *value) +{ + puts(__FUNCTION__); + GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group); + GAction *action; + + action = G_ACTION( g_hash_table_lookup (loGroup->priv->table, action_name) ); + + if (action == NULL) + return; + + g_action_change_state (action, value); +} + +static void +g_lo_action_group_activate (GActionGroup *group, + const gchar *action_name, + GVariant *parameter) +{ + + + puts(__FUNCTION__); + GLOActionGroup *loGroup = G_LO_ACTION_GROUP (group); + GAction *action; + + action = G_ACTION( g_hash_table_lookup (loGroup->priv->table, action_name) ); + + if (action == NULL) + return; + + g_action_activate (action, parameter); + + +} + +static void +action_enabled_notify (GAction *action, + GParamSpec *pspec, + gpointer user_data) +{ + puts(__FUNCTION__); + g_action_group_action_enabled_changed (G_ACTION_GROUP( user_data ), + g_action_get_name (action), + g_action_get_enabled (action)); +} + +static void +action_state_notify (GAction *action, + GParamSpec *pspec, + gpointer user_data) +{ + puts(__FUNCTION__); + GVariant *value; + + value = g_action_get_state (action); + g_action_group_action_state_changed (G_ACTION_GROUP( user_data ), + g_action_get_name (action), + value); + g_variant_unref (value); +} + +static void +g_lo_action_group_disconnect (gpointer key, + gpointer value, + gpointer user_data) +{ + puts(__FUNCTION__); + g_signal_handlers_disconnect_by_func (value, (gpointer) action_enabled_notify, + user_data); + g_signal_handlers_disconnect_by_func (value, (gpointer) action_state_notify, + user_data); +} + +static GAction * +g_lo_action_group_lookup_action (GActionMap *action_map, + const gchar *action_name) +{ + puts(__FUNCTION__); + GLOActionGroup *loGroup = G_LO_ACTION_GROUP (action_map); + + return G_ACTION( g_hash_table_lookup (loGroup->priv->table, action_name) ); +} + +static void +g_lo_action_group_add_action (GActionMap *action_map, + GAction *action) +{ + puts(__FUNCTION__); + GLOActionGroup *loGroup = G_LO_ACTION_GROUP (action_map); + const gchar *action_name; + GAction *old_action; + + action_name = g_action_get_name (action); + old_action = G_ACTION( g_hash_table_lookup (loGroup->priv->table, action_name) ); + + if (old_action != action) + { + if (old_action != NULL) + { + g_action_group_action_removed (G_ACTION_GROUP (loGroup), + action_name); + g_lo_action_group_disconnect (NULL, old_action, loGroup); + } + + g_signal_connect (action, "notify::enabled", + G_CALLBACK (action_enabled_notify), loGroup); + + if (g_action_get_state_type (action) != NULL) + g_signal_connect (action, "notify::state", + G_CALLBACK (action_state_notify), loGroup); + + g_hash_table_insert (loGroup->priv->table, + g_strdup (action_name), + g_object_ref (action)); + + g_action_group_action_added (G_ACTION_GROUP (loGroup), action_name); + } +} + +static void +g_lo_action_group_remove_action (GActionMap *action_map, + const gchar *action_name) +{ + puts(__FUNCTION__); + GLOActionGroup *loGroup = G_LO_ACTION_GROUP (action_map); + GAction *action; + + action = G_ACTION( g_hash_table_lookup (loGroup->priv->table, action_name) ); + + if (action != NULL) + { + g_action_group_action_removed (G_ACTION_GROUP (loGroup), action_name); + g_lo_action_group_disconnect (NULL, action, loGroup); + g_hash_table_remove (loGroup->priv->table, action_name); + } +} + +static void +g_lo_action_group_finalize (GObject *object) +{ + puts(__FUNCTION__); + GLOActionGroup *loGroup = G_LO_ACTION_GROUP (object); + + g_hash_table_foreach (loGroup->priv->table, + g_lo_action_group_disconnect, + loGroup); + g_hash_table_unref (loGroup->priv->table); + + G_OBJECT_CLASS (g_lo_action_group_parent_class) + ->finalize (object); +} + +static void +g_lo_action_group_init (GLOActionGroup *group) +{ + puts(__FUNCTION__); + group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group, + G_TYPE_LO_ACTION_GROUP, + GLOActionGroupPrivate); + group->priv->table = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); +} + +static void +g_lo_action_group_class_init (GLOActionGroupClass *klass) +{ + puts(__FUNCTION__); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = g_lo_action_group_finalize; + + g_type_class_add_private (klass, sizeof (GLOActionGroupPrivate)); +} + +static void +g_lo_action_group_iface_init (GActionGroupInterface *iface) +{ + puts(__FUNCTION__); + iface->list_actions = g_lo_action_group_list_actions; + iface->query_action = g_lo_action_group_query_action; + iface->change_action_state = g_lo_action_group_change_state; + iface->activate_action = g_lo_action_group_activate; +} + +static void +g_lo_action_group_map_iface_init (GActionMapInterface *iface) +{ + puts(__FUNCTION__); + iface->add_action = g_lo_action_group_add_action; + iface->remove_action = g_lo_action_group_remove_action; + iface->lookup_action = g_lo_action_group_lookup_action; +} + +GLOActionGroup * +g_lo_action_group_new (void) +{ + puts(__FUNCTION__); + return G_LO_ACTION_GROUP( g_object_new (G_TYPE_LO_ACTION_GROUP, NULL) ); +} + +GAction * +g_lo_action_group_lookup (GLOActionGroup *group, + const gchar *action_name) +{ + puts(__FUNCTION__); + g_return_val_if_fail (G_IS_LO_ACTION_GROUP (group), NULL); + + return g_action_map_lookup_action (G_ACTION_MAP (group), action_name); +} + +void +g_lo_action_group_insert (GLOActionGroup *group, + GAction *action) +{ + puts(__FUNCTION__); + g_return_if_fail (G_IS_LO_ACTION_GROUP (group)); + + g_action_map_add_action (G_ACTION_MAP (group), action); +} + +void +g_lo_action_group_remove (GLOActionGroup *group, + const gchar *action_name) +{ + puts(__FUNCTION__); + g_return_if_fail (G_IS_LO_ACTION_GROUP (group)); + + g_action_map_remove_action (G_ACTION_MAP (group), action_name); +} + +void +g_lo_action_group_add_entries (GLOActionGroup *group, + const GActionEntry *entries, + gint n_entries, + gpointer user_data) +{ + puts(__FUNCTION__); + g_action_map_add_action_entries (G_ACTION_MAP (group), entries, n_entries, user_data); +} + diff --git a/vcl/unx/gtk/window/glomenu.cxx b/vcl/unx/gtk/window/glomenu.cxx new file mode 100644 index 000000000000..0da72453a28e --- /dev/null +++ b/vcl/unx/gtk/window/glomenu.cxx @@ -0,0 +1,574 @@ +#include <stdio.h> +#include <string.h> + +#include <unx/gtk/glomenu.h> + +struct _GLOMenuItem +{ + GObject parent_instance; + + GHashTable *attributes; + GHashTable *links; + gboolean cow; +}; + +typedef GObjectClass GLOMenuItemClass; + + +struct _GLOMenu +{ + GMenuModel parent_instance; + + GArray *items; +// gboolean mutable; +}; + +typedef GMenuModelClass GLOMenuClass; + +G_DEFINE_TYPE (GLOMenu, g_lo_menu, G_TYPE_MENU_MODEL); +G_DEFINE_TYPE (GLOMenuItem, g_lo_menu_item, G_TYPE_OBJECT); + +struct item +{ + GHashTable *attributes; + GHashTable *links; +}; + +static gboolean +g_lo_menu_is_mutable (GMenuModel *model) +{ + puts(__FUNCTION__); +// GMenu *menu = G_MENU (model); + +// return menu->mutable; + return TRUE; +} + +static gint +g_lo_menu_get_n_items (GMenuModel *model) +{ + puts(__FUNCTION__); + GLOMenu *menu = G_LO_MENU (model); + + return menu->items->len; +} + +static void +g_lo_menu_get_item_attributes (GMenuModel *model, + gint position, + GHashTable **table) +{ + puts(__FUNCTION__); + GLOMenu *menu = G_LO_MENU (model); + + *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).attributes); +} + +static void +g_lo_menu_get_item_links (GMenuModel *model, + gint position, + GHashTable **table) +{ + puts(__FUNCTION__); + GLOMenu *menu = G_LO_MENU (model); + + *table = g_hash_table_ref (g_array_index (menu->items, struct item, position).links); +} + +static GMenuLinkIter * +g_lo_menu_real_iterate_item_links (GMenuModel *model, + gint item_index) +{ + puts(__FUNCTION__); + GHashTable *table = NULL; + GMenuLinkIter *result; + + G_MENU_MODEL_GET_CLASS (model) + ->get_item_links (model, item_index, &table); + + if (table) + { +// GMenuLinkHashIter *iter = g_object_new (g_menu_link_hash_iter_get_type (), NULL); +// g_hash_table_iter_init (&iter->iter, table); +// iter->table = g_hash_table_ref (table); +// result = G_MENU_LINK_ITER (iter); + } + else + { + g_critical ("GMenuModel implementation '%s' doesn't override iterate_item_links() " + "and fails to return sane values from get_item_links()", + G_OBJECT_TYPE_NAME (model)); + result = NULL; + } + + if (table != NULL) + g_hash_table_unref (table); + + return result; +} + +static GMenuModel * +g_lo_menu_real_get_item_link (GMenuModel *model, + gint item_index, + const gchar *link) +{ + puts(__FUNCTION__); + GHashTable *table = NULL; + GMenuModel *value = NULL; + + G_MENU_MODEL_GET_CLASS (model) + ->get_item_links (model, item_index, &table); + + if (table != NULL) + value = G_MENU_MODEL( g_hash_table_lookup (table, link) ); + else + g_assert_not_reached (); + + if (value != NULL) + g_object_ref (value); + + if (table != NULL) + g_hash_table_unref (table); + + return value; +} + +GLOMenu * +g_lo_menu_new (void) +{ + puts(__FUNCTION__); + return G_LO_MENU( g_object_new (G_TYPE_LO_MENU, NULL) ); +} + +void +g_lo_menu_insert (GLOMenu *menu, + gint position, + const gchar *label, + const gchar *detailed_action) +{ + puts(__FUNCTION__); + GLOMenuItem *menu_item; + + menu_item = g_lo_menu_item_new (label, detailed_action); + g_lo_menu_insert_item (menu, position, menu_item); + g_object_unref (menu_item); +} + +void +g_lo_menu_append (GLOMenu *menu, + const gchar *label, + const gchar *detailed_action) +{ + puts(__FUNCTION__); + g_lo_menu_insert (menu, -1, label, detailed_action); +} + +void +g_lo_menu_insert_section (GLOMenu *menu, + gint position, + const gchar *label, + GMenuModel *section) +{ + GLOMenuItem *menu_item; + + menu_item = g_lo_menu_item_new_section (label, section); + g_lo_menu_insert_item (menu, position, menu_item); + g_object_unref (menu_item); +} + +void +g_lo_menu_prepend_section (GLOMenu *menu, + const gchar *label, + GMenuModel *section) +{ + g_lo_menu_insert_section (menu, 0, label, section); +} + +void +g_lo_menu_append_section (GLOMenu *menu, + const gchar *label, + GMenuModel *section) +{ + g_lo_menu_insert_section (menu, -1, label, section); +} + + + +void +g_lo_menu_insert_submenu (GLOMenu *menu, + gint position, + const gchar *label, + GMenuModel *submenu) +{ + GLOMenuItem *menu_item; + + menu_item = g_lo_menu_item_new_submenu (label, submenu); + g_lo_menu_insert_item (menu, position, menu_item); + g_object_unref (menu_item); +} + +void +g_lo_menu_append_submenu (GLOMenu *menu, + const gchar *label, + GMenuModel *submenu) +{ + puts(__FUNCTION__); + g_lo_menu_insert_submenu (menu, -1, label, submenu); +} + +static void +g_lo_menu_clear_item (struct item *item) +{ + puts(__FUNCTION__); + if (item->attributes != NULL) + g_hash_table_unref (item->attributes); + if (item->links != NULL) + g_hash_table_unref (item->links); +} + +static void +g_lo_menu_dispose (GObject *gobject) +{ + puts(__FUNCTION__); + G_OBJECT_CLASS (g_lo_menu_parent_class)->dispose (gobject); +} + +static void +g_lo_menu_finalize (GObject *gobject) +{ + puts(__FUNCTION__); + GLOMenu *menu = G_LO_MENU (gobject); + struct item *items; + gint n_items; + gint i; + + n_items = menu->items->len; + items = (struct item *) g_array_free (menu->items, FALSE); + for (i = 0; i < n_items; i++) + g_lo_menu_clear_item (&items[i]); + g_free (items); + + G_OBJECT_CLASS (g_lo_menu_parent_class)->finalize (gobject); +} + +static void +g_lo_menu_class_init (GLOMenuClass *klass) +{ + puts(__FUNCTION__); + GMenuModelClass *model_class = G_MENU_MODEL_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = g_lo_menu_finalize; + + model_class->is_mutable = g_lo_menu_is_mutable; + model_class->get_n_items = g_lo_menu_get_n_items; + model_class->get_item_attributes = g_lo_menu_get_item_attributes; + model_class->get_item_links = g_lo_menu_get_item_links; + model_class->iterate_item_links = g_lo_menu_real_iterate_item_links; + model_class->get_item_link = g_lo_menu_real_get_item_link; +} + +static void +g_lo_menu_init (GLOMenu *self) +{ + puts(__FUNCTION__); + self->items = g_array_new (FALSE, FALSE, sizeof (struct item)); +} + +void +g_lo_menu_insert_item (GLOMenu *menu, + gint position, + GLOMenuItem *item) +{ + puts(__FUNCTION__); + struct item new_item; + + g_return_if_fail (G_IS_LO_MENU (menu)); + g_return_if_fail (G_IS_LO_MENU_ITEM (item)); + + if (position < 0 || position > menu->items->len) + position = menu->items->len; + + new_item.attributes = g_hash_table_ref (item->attributes); + new_item.links = g_hash_table_ref (item->links); + item->cow = TRUE; + + g_array_insert_val (menu->items, position, new_item); + g_menu_model_items_changed (G_MENU_MODEL (menu), position, 0, 1); +} + +void +g_lo_menu_append_item (GLOMenu *menu, + GLOMenuItem *item) +{ + g_lo_menu_insert_item (menu, -1, item); +} + +/* + * GLOMenuItem + */ + +static void +g_lo_menu_item_clear_cow (GLOMenuItem *menu_item) +{ + if (menu_item->cow) + { + GHashTableIter iter; + GHashTable *newHash; + gpointer key; + gpointer val; + + newHash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + g_hash_table_iter_init (&iter, menu_item->attributes); + while (g_hash_table_iter_next (&iter, &key, &val)) + g_hash_table_insert (newHash, g_strdup ((gchar*) key), g_variant_ref ((GVariant*) val)); + g_hash_table_unref (menu_item->attributes); + menu_item->attributes = newHash; + + newHash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_object_unref); + g_hash_table_iter_init (&iter, menu_item->links); + while (g_hash_table_iter_next (&iter, &key, &val)) + g_hash_table_insert (newHash, g_strdup ((gchar*) key), g_object_ref ((GVariant*) val)); + g_hash_table_unref (menu_item->links); + menu_item->links = newHash; + + menu_item->cow = FALSE; + } +} + +static void +g_lo_menu_item_finalize (GObject *object) +{ + puts(__FUNCTION__); + GLOMenuItem *menu_item = G_LO_MENU_ITEM (object); + + g_hash_table_unref (menu_item->attributes); + g_hash_table_unref (menu_item->links); + + G_OBJECT_CLASS (g_lo_menu_item_parent_class)->finalize (object); +} + +static void +g_lo_menu_item_init (GLOMenuItem *menu_item) +{ + puts(__FUNCTION__); + menu_item->attributes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + menu_item->links = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + menu_item->cow = FALSE; +} + +static void +g_lo_menu_item_class_init (GLOMenuItemClass *klass) +{ + puts(__FUNCTION__); + klass->finalize = g_lo_menu_item_finalize; +} + +static gboolean +valid_attribute_name (const gchar *name) +{ + gint i; + + if (!g_ascii_islower (name[0])) + return FALSE; + + for (i = 1; name[i]; i++) + { + if (name[i] != '-' && + !g_ascii_islower (name[i]) && + !g_ascii_isdigit (name[i])) + return FALSE; + + if (name[i] == '-' && name[i + 1] == '-') + return FALSE; + } + + if (name[i - 1] == '-') + return FALSE; + + if (i > 1024) + return FALSE; + + return TRUE; +} + +void +g_lo_menu_item_set_attribute_value (GLOMenuItem *menu_item, + const gchar *attribute, + GVariant *value) +{ + puts(__FUNCTION__); + g_return_if_fail (G_IS_LO_MENU_ITEM (menu_item)); + g_return_if_fail (attribute != NULL); + g_return_if_fail (valid_attribute_name (attribute)); + + g_lo_menu_item_clear_cow (menu_item); + + if (value != NULL) + g_hash_table_insert (menu_item->attributes, g_strdup (attribute), g_variant_ref_sink (value)); + else + g_hash_table_remove (menu_item->attributes, attribute); +} + +void +g_lo_menu_item_set_link (GLOMenuItem *menu_item, + const gchar *link, + GMenuModel *model) +{ + g_return_if_fail (G_IS_LO_MENU_ITEM (menu_item)); + g_return_if_fail (link != NULL); + g_return_if_fail (valid_attribute_name (link)); + + g_lo_menu_item_clear_cow (menu_item); + + if (model != NULL) + g_hash_table_insert (menu_item->links, g_strdup (link), g_object_ref (model)); + else + g_hash_table_remove (menu_item->links, link); +} + +void +g_lo_menu_item_set_label (GLOMenuItem *menu_item, + const gchar *label) +{ + puts(__FUNCTION__); + GVariant *value; + + if (label != NULL) + value = g_variant_new_string (label); + else + value = NULL; + + g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_LABEL, value); +} + +void +g_lo_menu_item_set_submenu (GLOMenuItem *menu_item, + GMenuModel *submenu) +{ + g_lo_menu_item_set_link (menu_item, G_MENU_LINK_SUBMENU, submenu); +} + +void +g_lo_menu_item_set_section (GLOMenuItem *menu_item, + GMenuModel *section) +{ + g_lo_menu_item_set_link (menu_item, G_MENU_LINK_SECTION, section); +} + +void +g_lo_menu_item_set_action_and_target_value (GLOMenuItem *menu_item, + const gchar *action, + GVariant *target_value) +{ + GVariant *action_value; + + if (action != NULL) + { + action_value = g_variant_new_string (action); + } + else + { + action_value = NULL; + target_value = NULL; + } + + g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_ACTION, action_value); + g_lo_menu_item_set_attribute_value (menu_item, G_MENU_ATTRIBUTE_TARGET, target_value); +} + +void +g_lo_menu_item_set_action_and_target (GLOMenuItem *menu_item, + const gchar *action, + const gchar *format_string, + ...) +{ + GVariant *value; + + if (format_string != NULL) + { + va_list ap; + + va_start (ap, format_string); + value = g_variant_new_va (format_string, NULL, &ap); + va_end (ap); + } + else + value = NULL; + + g_lo_menu_item_set_action_and_target_value (menu_item, action, value); +} + +void +g_lo_menu_item_set_detailed_action (GLOMenuItem *menu_item, + const gchar *detailed_action) +{ + puts(__FUNCTION__); + const gchar *sep; + + sep = strstr (detailed_action, "::"); + + if (sep != NULL) + { + gchar *action; + + action = g_strndup (detailed_action, sep - detailed_action); + g_lo_menu_item_set_action_and_target (menu_item, action, "s", sep + 2); + g_free (action); + } + + else + g_lo_menu_item_set_action_and_target_value (menu_item, detailed_action, NULL); +} + +GLOMenuItem * +g_lo_menu_item_new (const gchar *label, + const gchar *detailed_action) +{ + puts(__FUNCTION__); + GLOMenuItem *menu_item; + + menu_item = G_LO_MENU_ITEM( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) ); + + if (label != NULL) + g_lo_menu_item_set_label (menu_item, label); + + if (detailed_action != NULL) + g_lo_menu_item_set_detailed_action (menu_item, detailed_action); + + return menu_item; +} + +GLOMenuItem * +g_lo_menu_item_new_submenu (const gchar *label, + GMenuModel *submenu) +{ + GLOMenuItem *menu_item; + + menu_item = G_LO_MENU_ITEM( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) ); + + if (label != NULL) + g_lo_menu_item_set_label (menu_item, label); + + g_lo_menu_item_set_submenu (menu_item, submenu); + + return menu_item; +} + +GLOMenuItem * +g_lo_menu_item_new_section (const gchar *label, + GMenuModel *section) +{ + GLOMenuItem *menu_item; + + menu_item = G_LO_MENU_ITEM ( g_object_new (G_TYPE_LO_MENU_ITEM, NULL) ); + + if (label != NULL) + g_lo_menu_item_set_label (menu_item, label); + + g_lo_menu_item_set_section (menu_item, section); + + return menu_item; +} + + diff --git a/vcl/unx/gtk/window/gtksalmenu.cxx b/vcl/unx/gtk/window/gtksalmenu.cxx index f612a23a7013..134d5e274140 100644 --- a/vcl/unx/gtk/window/gtksalmenu.cxx +++ b/vcl/unx/gtk/window/gtksalmenu.cxx @@ -1,87 +1,125 @@ #include "unx/gtk/gtksalmenu.hxx" -#include <gtk/gtk.h> +//#include <gtk/gtk.h> +#include <unx/gtk/glomenu.h> +#include <unx/gtk/gloactiongroup.h> + #include <iostream> using namespace std; - -//const GtkSalMenu * GtkSalMenu::pCurrentMenubar = NULL; - -#define BUS_NAME "org.gtk.LibreOffice" -#define OBJ_PATH "/org/gtk/LibreOffice" +#define GTK_MENU_BUS_NAME "org.libreoffice" +#define GTK_MENU_OBJ_PATH "/org/libreoffice" static void -quit (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) +dispatchAction (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) { - exit(1); + cout << "ACTION: " << g_action_get_name( G_ACTION( action ) ) << " triggered." << endl; + + if ( user_data ) { + GtkSalMenuItem *pSalMenuItem = static_cast< GtkSalMenuItem* >( user_data ); + + if ( !pSalMenuItem->mpSubMenu ) { + if ( !pSalMenuItem->mpVCLMenu->IsMenuBar() ) { +// ((PopupMenu*) pSalMenuItem->mpVCLMenu)->SetSelectedEntry( pSalMenuItem->mnId ); +// pSalMenuItem->mpVCLMenu->Select(); +// pSalMenuItem->mpVCLMenu->DeSelect(); + } + } + } } -GMenuModel* generateMenuModel2( Menu *pVCLMenu ) -{ - if (!pVCLMenu) - return NULL; +//GMenuModel* generateMenuModel2( Menu *pVCLMenu ) +//{ +// if (!pVCLMenu) +// return NULL; - GMenu *pMenuModel = g_menu_new(); - GMenu *pSectionMenuModel = g_menu_new(); +// GMenu *pMenuModel = g_menu_new(); +// GMenu *pSectionMenuModel = g_menu_new(); - for (int i = 0; i < pVCLMenu->GetItemCount(); i++) { - MenuItemType itemType = pVCLMenu->GetItemType( i ); +// for (int i = 0; i < pVCLMenu->GetItemCount(); i++) { +// MenuItemType itemType = pVCLMenu->GetItemType( i ); - if ( itemType == MENUITEM_SEPARATOR ) { - g_menu_append_section( pMenuModel, NULL, G_MENU_MODEL( pSectionMenuModel ) ); - pSectionMenuModel = g_menu_new(); - } else { - sal_Int16 nId = pVCLMenu->GetItemId( i ); +// if ( itemType == MENUITEM_SEPARATOR ) { +// g_menu_append_section( pMenuModel, NULL, G_MENU_MODEL( pSectionMenuModel ) ); +// pSectionMenuModel = g_menu_new(); +// } else { +// sal_Int16 nId = pVCLMenu->GetItemId( i ); - // Menu item label - rtl::OUString aTextLabel = pVCLMenu->GetItemText( nId ); - rtl::OUString aText = aTextLabel.replace( '~', '_' ); - rtl::OString aConvertedText = OUStringToOString(aText, RTL_TEXTENCODING_UTF8); +// // Menu item label +// rtl::OUString aTextLabel = pVCLMenu->GetItemText( nId ); +// rtl::OUString aText = aTextLabel.replace( '~', '_' ); +// rtl::OString aConvertedText = OUStringToOString(aText, RTL_TEXTENCODING_UTF8); - // Menu item accelerator key -// KeyCode accelKey = pVCLMenu->GetAccelKey( nId ); +// // Menu item accelerator key +//// KeyCode accelKey = pVCLMenu->GetAccelKey( nId ); - GMenuItem *menuItem = g_menu_item_new( (char*) aConvertedText.getStr(), NULL); +// GMenuItem *menuItem = g_menu_item_new( (char*) aConvertedText.getStr(), NULL); - GMenuModel *pSubmenu = generateMenuModel2( pVCLMenu->GetPopupMenu( nId ) ); +// GMenuModel *pSubmenu = generateMenuModel2( pVCLMenu->GetPopupMenu( nId ) ); - g_menu_item_set_submenu( menuItem, pSubmenu ); +// g_menu_item_set_submenu( menuItem, pSubmenu ); - g_menu_append_item( pSectionMenuModel, menuItem ); - } - } +// g_menu_append_item( pSectionMenuModel, menuItem ); +// } +// } - g_menu_append_section( pMenuModel, NULL, G_MENU_MODEL( pSectionMenuModel ) ); +// g_menu_append_section( pMenuModel, NULL, G_MENU_MODEL( pSectionMenuModel ) ); - return G_MENU_MODEL( pMenuModel ); -} +// return G_MENU_MODEL( pMenuModel ); +//} GMenuModel *generateMockMenuModel() { - GMenu *menu = g_menu_new (); - // g_menu_append (menu, "Add", "app.add"); - // g_menu_append (menu, "Del", "app.del"); +// GLOMenu *menu = g_lo_menu_new (); + +// GLOMenu *fileMenu = g_lo_menu_new(); +// GLOMenu *fileSubmenu = g_lo_menu_new (); +// g_lo_menu_append( fileSubmenu, "NewMenuOption1", NULL ); +// g_lo_menu_append_submenu( fileMenu, "New", G_MENU_MODEL( fileSubmenu ) ); +// g_lo_menu_append( fileMenu, "Quit", "app.quit" ); + +// GLOMenu *editMenu = g_lo_menu_new(); +// GLOMenu *editSubmenu = g_lo_menu_new (); +// g_lo_menu_append( editSubmenu, "EditMenuOption1", NULL ); +// g_lo_menu_append_item( editSubmenu, editMenuItem ); +// g_lo_menu_append_submenu( editMenu, "Format", G_MENU_MODEL( editSubmenu ) ); + +// g_lo_menu_append_submenu( menu, "File", G_MENU_MODEL( fileMenu ) ); +// g_lo_menu_append_submenu( menu, "Edit", G_MENU_MODEL( editMenu ) ); + + GMenu *menu = g_menu_new(); + GMenu *fileMenu = g_menu_new(); - GMenu *submenu = g_menu_new (); - g_menu_append( submenu, "Option1", NULL ); - g_menu_append( submenu, "Option2", NULL ); + GMenu *fileSubmenu = g_menu_new(); + g_menu_append( fileSubmenu, "Text Document", "app.private:factory/swriter" ); + g_menu_append_submenu( fileMenu, "New", G_MENU_MODEL( fileSubmenu ) ); + g_menu_append( fileMenu, "Exit", "app..uno:Quit" ); - g_menu_append_section( fileMenu, NULL, G_MENU_MODEL(submenu)); +// g_lo_menu_append_section( fileMenu, NULL, G_MENU_MODEL(submenu)); +// GMenu *editMenu = g_menu_new(); +// GMenu *editSubmenu = g_menu_new(); +// g_menu_append( editSubmenu, "EditMenuOption1", "app.dispatch" ); +// g_lo_menu_append_item( editSubmenu, editMenuItem ); +// g_menu_append_submenu( editMenu, "Format", G_MENU_MODEL( editSubmenu ) ); +// g_lo_menu_append( editMenu, "Quit", "app.quit" ); - g_menu_append (fileMenu, "Quit", "app.quit"); - g_menu_append_submenu( menu, "Test", G_MENU_MODEL( fileMenu )); + g_menu_append_submenu( menu, "File", G_MENU_MODEL( fileMenu ) ); +// g_menu_append_submenu( menu, "Edit", G_MENU_MODEL( editMenu ) ); + +// g_menu_append_submenu( menu, "Test", G_MENU_MODEL( fileMenu )); + return G_MENU_MODEL( menu ); } -GMenuModel *generateMenuModel( GtkSalMenu* ); +GMenuModel *generateMenuModelAndActions( GtkSalMenu*, GLOActionGroup* ); -GMenuModel *generateSectionMenuModel( GtkSalMenuSection *pSection ) +GMenuModel *generateSectionMenuModel( GtkSalMenuSection *pSection, GLOActionGroup *pActionGroup ) { if ( !pSection ) return NULL; @@ -93,17 +131,21 @@ GMenuModel *generateSectionMenuModel( GtkSalMenuSection *pSection ) GMenuItem *pMenuItem = pSalMenuItem->mpMenuItem; if (pSalMenuItem->mpSubMenu) { - GMenuModel *pSubmenu = generateMenuModel( pSalMenuItem->mpSubMenu ); + GMenuModel *pSubmenu = generateMenuModelAndActions( pSalMenuItem->mpSubMenu, pActionGroup ); g_menu_item_set_submenu( pMenuItem, pSubmenu ); } g_menu_append_item( pSectionMenuModel, pMenuItem ); + + if (pSalMenuItem->mpAction) { + g_lo_action_group_insert( pActionGroup, pSalMenuItem->mpAction ); + } } return G_MENU_MODEL( pSectionMenuModel ); } -GMenuModel *generateMenuModel( GtkSalMenu *pMenu ) +GMenuModel *generateMenuModelAndActions( GtkSalMenu *pMenu, GLOActionGroup *pActionGroup ) { if ( !pMenu ) return NULL; @@ -115,17 +157,18 @@ GMenuModel *generateMenuModel( GtkSalMenu *pMenu ) GMenuItem *pMenuItem = pSalMenuItem->mpMenuItem; if (pSalMenuItem->mpSubMenu) { - GMenuModel *pSubmenu = generateMenuModel( pSalMenuItem->mpSubMenu ); + GMenuModel *pSubmenu = generateMenuModelAndActions( pSalMenuItem->mpSubMenu, pActionGroup ); g_menu_item_set_submenu( pMenuItem, pSubmenu ); } g_menu_append_item( pMenuModel, pMenuItem ); + g_lo_action_group_insert( pActionGroup, pSalMenuItem->mpAction ); } for (int i=0; i < pMenu->maSections.size(); i++) { GtkSalMenuSection *pSection = pMenu->maSections[ i ]; - GMenuModel *pSectionMenuModel = generateSectionMenuModel( pSection ); + GMenuModel *pSectionMenuModel = generateSectionMenuModel( pSection, pActionGroup ); g_menu_append_section( pMenuModel, NULL, pSectionMenuModel ); } @@ -161,19 +204,20 @@ gdk_x11_window_set_utf8_property (GdkWindow *window, } } -void GtkSalMenu::publishMenu( GMenuModel *pMenu ) +void GtkSalMenu::publishMenu( GMenuModel *pMenu, GActionGroup *pActionGroup ) { - pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); - if(!pSessionBus) puts ("Fail bus get"); - mBusId = g_bus_own_name_on_connection (pSessionBus, "org.libreoffice", G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL); - if(!mBusId) puts ("Fail own name"); - // guint appmenuID = g_dbus_connection_export_menu_model (bus, "/org/libreoffice/menus/appmenu", mpMenuModel, NULL); // if(!appmenuID) puts("Fail export appmenu"); + + if ( mMenubarId ) { + g_dbus_connection_unexport_menu_model( pSessionBus, mMenubarId ); + mbMenuBar = 0; + } + mMenubarId = g_dbus_connection_export_menu_model (pSessionBus, "/org/libreoffice/menus/menubar", pMenu, NULL); if(!mMenubarId) puts("Fail export menubar"); -// g_object_unref (menu); + g_dbus_connection_export_action_group( pSessionBus, GTK_MENU_OBJ_PATH, pActionGroup, NULL); } GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) : @@ -181,13 +225,22 @@ GtkSalMenu::GtkSalMenu( sal_Bool bMenuBar ) : mpVCLMenu( NULL ), aDBusMenubarPath( NULL ), pSessionBus( NULL ), + mpActionEntry( NULL ), mBusId( 0 ), - mMenubarId( 0 ) + mMenubarId( 0 ), + mActionGroupId ( 0 ) { if (!bMenuBar) { mpCurrentSection = new GtkSalMenuSection(); maSections.push_back( mpCurrentSection ); + } else { + pSessionBus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + if(!pSessionBus) puts ("Fail bus get"); + + mBusId = g_bus_own_name_on_connection (pSessionBus, GTK_MENU_BUS_NAME, G_BUS_NAME_OWNER_FLAGS_NONE, NULL, NULL, NULL, NULL); + if(!mBusId) puts ("Fail own name"); } + } GtkSalMenu::~GtkSalMenu() @@ -274,12 +327,20 @@ void GtkSalMenu::SetFrame( const SalFrame* pFrame ) GdkWindow *gdkWindow = gtk_widget_get_window( widget ); if (gdkWindow) { - gdk_x11_window_set_utf8_property (gdkWindow, "_GTK_APPLICATION_ID", "org.libreoffice"); - gdk_x11_window_set_utf8_property (gdkWindow, "_GTK_UNIQUE_BUS_NAME", "org.libreoffice"); - gdk_x11_window_set_utf8_property (gdkWindow, "_GTK_APPLICATION_OBJECT_PATH", "/org/libreoffice"); - gdk_x11_window_set_utf8_property (gdkWindow, "_GTK_WINDOW_OBJECT_PATH", "/org/libreoffice/windows"); + XLIB_Window windowId = GDK_WINDOW_XID( gdkWindow ); + + gchar *aWindowObjectPath = g_strdup_printf( "%s/window/%u", GTK_MENU_OBJ_PATH, windowId ); + gchar *aMenubarObjectPath = g_strconcat( GTK_MENU_OBJ_PATH, "/menus/menubar", NULL ); + +// gdk_x11_window_set_utf8_property (gdkWindow, "_GTK_APPLICATION_ID", "org.libreoffice"); + gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_UNIQUE_BUS_NAME", g_dbus_connection_get_unique_name( pSessionBus ) ); + gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_APPLICATION_OBJECT_PATH", GTK_MENU_OBJ_PATH ); + gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_WINDOW_OBJECT_PATH", aWindowObjectPath ); // gdk_x11_window_set_utf8_property (gdkWindow, "_GTK_APP_MENU_OBJECT_PATH", "/org/libreoffice/menus/appmenu"); - gdk_x11_window_set_utf8_property (gdkWindow, "_GTK_MENUBAR_OBJECT_PATH", "/org/libreoffice/menus/menubar"); + gdk_x11_window_set_utf8_property ( gdkWindow, "_GTK_MENUBAR_OBJECT_PATH", aMenubarObjectPath ); + + g_free( aWindowObjectPath ); + g_free( aMenubarObjectPath ); } } @@ -291,6 +352,14 @@ void GtkSalMenu::CheckItem( unsigned nPos, sal_Bool bCheck ) void GtkSalMenu::EnableItem( unsigned nPos, sal_Bool bEnable ) { cout << __FUNCTION__ << endl; + + if (nPos < maItems.size()) { + GtkSalMenuItem *pSalMenuItem = maItems[ nPos ]; + + if ( pSalMenuItem->mpAction ) { + g_simple_action_set_enabled( G_SIMPLE_ACTION( pSalMenuItem->mpAction ), (gboolean) bEnable ); + } + } } void GtkSalMenu::SetItemText( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& rText ) @@ -318,7 +387,7 @@ void GtkSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const { cout << __FUNCTION__ << " KeyName: " << rKeyName << endl; -// GtkSalMenuItem *pMenuItem = static_cast< GtkSalMenuItem* >( pSalMenuItem ); + GtkSalMenuItem *pMenuItem = static_cast< GtkSalMenuItem* >( pSalMenuItem ); // rtl::OString aConvertedKeyName = OUStringToOString( rKeyName, RTL_TEXTENCODING_UTF8 ); @@ -326,63 +395,53 @@ void GtkSalMenu::SetAccelerator( unsigned nPos, SalMenuItem* pSalMenuItem, const // g_menu_item_set_attribute_value( pMenuItem->mpMenuItem, "accel", gaKeyCode ); } -void GtkSalMenu::GetSystemMenuData( SystemMenuData* pData ) +void GtkSalMenu::SetItemCommand( unsigned nPos, SalMenuItem* pSalMenuItem, const rtl::OUString& aCommandStr ) { - cout << __FUNCTION__ << endl; -} - -void printMenu( GtkSalMenu * ); + GtkSalMenuItem* pGtkSalMenuItem = static_cast< GtkSalMenuItem* >( pSalMenuItem ); -void printSection ( GtkSalMenuSection *pSection ) -{ - if (pSection) { - for (int i = 0; i < pSection->maItems.size(); i++) { - GtkSalMenuItem *pSalMenuItem = static_cast< GtkSalMenuItem* >(pSection->maItems[ i ]); - cout << pSalMenuItem->mpVCLMenu->GetItemText( pSalMenuItem->mnId ) << endl; - - if (pSalMenuItem->mpSubMenu) { - cout << "--- Submenu ---" << endl; - printMenu( pSalMenuItem->mpSubMenu); - cout << "---------------" << endl; - } - } + if ( pGtkSalMenuItem->mpAction ) { + g_object_unref( pGtkSalMenuItem->mpAction ); } + + rtl::OString aOCommandStr = rtl::OUStringToOString( aCommandStr, RTL_TEXTENCODING_UTF8 ); + + GSimpleAction *pAction = g_simple_action_new( aOCommandStr.getStr(), NULL ); + + // Disable action by default. +// g_simple_action_set_enabled( pAction, FALSE ); + + g_signal_connect(pAction, "activate", G_CALLBACK( dispatchAction ), pGtkSalMenuItem); + + pGtkSalMenuItem->mpAction = G_ACTION( pAction ); + + + rtl::OString aItemCommand = "app." + aOCommandStr; + g_menu_item_set_action_and_target( pGtkSalMenuItem->mpMenuItem, aItemCommand.getStr(), NULL ); +// g_object_unref( aGCommand ); } -void printMenu( GtkSalMenu *pMenu ) +void GtkSalMenu::GetSystemMenuData( SystemMenuData* pData ) { - if ( pMenu ) { - for (int i = 0; i < pMenu->maItems.size(); i++) { - GtkSalMenuItem *pSalMenuItem = static_cast< GtkSalMenuItem* >(pMenu->maItems[ i ]); - cout << pSalMenuItem->mpVCLMenu->GetItemText( pSalMenuItem->mnId ) << endl; - - if (pSalMenuItem->mpSubMenu) { - cout << "--- Submenu ---" << endl; - printMenu( pSalMenuItem->mpSubMenu); - cout << "---------------" << endl; - } - } - - for (int i = 0; i < pMenu->maSections.size(); i++) { - GtkSalMenuSection *pSalMenuSection = static_cast< GtkSalMenuSection* >(pMenu->maSections[ i ]); + cout << __FUNCTION__ << endl; +} - cout << "--- Submenu ---" << endl; - printSection( pSalMenuSection ); - cout << "---------------" << endl; - } - } +bool GtkSalMenu::ShowNativePopupMenu(FloatingWindow * pWin, const Rectangle& rRect, sal_uLong nFlags) +{ + cout << __FUNCTION__ << endl; + return TRUE; } void GtkSalMenu::Freeze() { cout << __FUNCTION__ << endl; - GMenuModel *mpMenuModel = generateMenuModel( this ); - this->publishMenu( mpMenuModel ); - g_object_unref( mpMenuModel ); + GLOActionGroup *mpActionGroup = g_lo_action_group_new(); - cout << "==================== MENUBAR ===================" << endl; - printMenu( this ); - cout << "================================================" << endl; + GMenuModel *mpMenuModel = generateMenuModelAndActions( this, mpActionGroup ); +// GMenuModel *mpMenuModel = generateMockMenuModel(); + +// this->publishMenu( mpMenuModel, G_ACTION_GROUP( mpActionGroup ) ); + this->publishMenu( mpMenuModel, G_ACTION_GROUP( mpActionGroup ) ); + g_object_unref( mpMenuModel ); } // ======================================================================= @@ -407,7 +466,8 @@ GtkSalMenuItem::GtkSalMenuItem( const SalItemParams* pItemData ) : mpVCLMenu( pItemData->pMenu ), mpParentMenu( NULL ), mpSubMenu( NULL ), - mpMenuItem( NULL ) + mpMenuItem( NULL ), + mpAction( NULL ) { cout << __FUNCTION__ << "Type: " << pItemData->eType << endl; |