forked from AuroraMiddleware/gtk
Add support for both prepending and appending custom menu items.
2007-02-09 Emmanuele Bassi <ebassi@gnome.org> * gtk/gtkrecentchoosermenu.c: Add support for both prepending and appending custom menu items. (gtk_recent_chooser_menu_constructor): Add a placeholder menu item for the empty menu case, and for giving us a starting point for the recent items populating process. (gtk_recent_chooser_menu_insert_item), (gtk_recent_chooser_menu_dispose_items): Insert an item at the position following the placeholder (and find that position if needed). (idle_populate_func), (idle_populate_clean_up): Show the placeholder menu item, instead of creating one each time. (gtk_recent_chooser_menu_populate): Kill some indirections and hide the placeholder before populating the menu. (set_recent_manager): Remember to remove the idle population source if the manager changes. * tests/testrecentchoosermenu.c: Test the appending and prepending of the menu items to the recent chooser menu widget. svn path=/trunk/; revision=17281
This commit is contained in:
parent
661a6bc021
commit
4a559d6ec8
27
ChangeLog
27
ChangeLog
@ -1,3 +1,30 @@
|
|||||||
|
2007-02-09 Emmanuele Bassi <ebassi@gnome.org>
|
||||||
|
|
||||||
|
* gtk/gtkrecentchoosermenu.c: Add support for both prepending
|
||||||
|
and appending custom menu items.
|
||||||
|
|
||||||
|
(gtk_recent_chooser_menu_constructor): Add a placeholder menu
|
||||||
|
item for the empty menu case, and for giving us a starting
|
||||||
|
point for the recent items populating process.
|
||||||
|
|
||||||
|
(gtk_recent_chooser_menu_insert_item),
|
||||||
|
(gtk_recent_chooser_menu_dispose_items): Insert an item at
|
||||||
|
the position following the placeholder (and find that position
|
||||||
|
if needed).
|
||||||
|
|
||||||
|
(idle_populate_func), (idle_populate_clean_up): Show the
|
||||||
|
placeholder menu item, instead of creating one each time.
|
||||||
|
|
||||||
|
(gtk_recent_chooser_menu_populate): Kill some indirections
|
||||||
|
and hide the placeholder before populating the menu.
|
||||||
|
|
||||||
|
(set_recent_manager): Remember to remove the idle population
|
||||||
|
source if the manager changes.
|
||||||
|
|
||||||
|
* tests/testrecentchoosermenu.c: Test the appending and
|
||||||
|
prepending of the menu items to the recent chooser menu
|
||||||
|
widget.
|
||||||
|
|
||||||
2007-02-08 Emmanuele Bassi <ebassi@gnome.org>
|
2007-02-08 Emmanuele Bassi <ebassi@gnome.org>
|
||||||
|
|
||||||
* gtk/gtkrecentchoosermenu.c (idle_populate_func): Keep count
|
* gtk/gtkrecentchoosermenu.c (idle_populate_func): Keep count
|
||||||
|
@ -59,6 +59,9 @@ struct _GtkRecentChooserMenuPrivate
|
|||||||
/* max size of the menu item label */
|
/* max size of the menu item label */
|
||||||
gint label_width;
|
gint label_width;
|
||||||
|
|
||||||
|
gint first_recent_item_pos;
|
||||||
|
GtkWidget *placeholder;
|
||||||
|
|
||||||
/* RecentChooser properties */
|
/* RecentChooser properties */
|
||||||
gint limit;
|
gint limit;
|
||||||
guint show_private : 1;
|
guint show_private : 1;
|
||||||
@ -237,6 +240,9 @@ gtk_recent_chooser_menu_init (GtkRecentChooserMenu *menu)
|
|||||||
|
|
||||||
priv->label_width = DEFAULT_LABEL_WIDTH;
|
priv->label_width = DEFAULT_LABEL_WIDTH;
|
||||||
|
|
||||||
|
priv->first_recent_item_pos = -1;
|
||||||
|
priv->placeholder = NULL;
|
||||||
|
|
||||||
priv->current_filter = NULL;
|
priv->current_filter = NULL;
|
||||||
|
|
||||||
priv->tooltips = gtk_tooltips_new ();
|
priv->tooltips = gtk_tooltips_new ();
|
||||||
@ -300,19 +306,43 @@ gtk_recent_chooser_menu_dispose (GObject *object)
|
|||||||
|
|
||||||
static GObject *
|
static GObject *
|
||||||
gtk_recent_chooser_menu_constructor (GType type,
|
gtk_recent_chooser_menu_constructor (GType type,
|
||||||
guint n_construct_properties,
|
guint n_params,
|
||||||
GObjectConstructParam *construct_params)
|
GObjectConstructParam *params)
|
||||||
{
|
{
|
||||||
GtkRecentChooserMenu *menu;
|
GtkRecentChooserMenu *menu;
|
||||||
|
GtkRecentChooserMenuPrivate *priv;
|
||||||
|
GObjectClass *parent_class;
|
||||||
GObject *object;
|
GObject *object;
|
||||||
|
|
||||||
object = G_OBJECT_CLASS (gtk_recent_chooser_menu_parent_class)->constructor (type,
|
parent_class = G_OBJECT_CLASS (gtk_recent_chooser_menu_parent_class);
|
||||||
n_construct_properties,
|
object = parent_class->constructor (type, n_params, params);
|
||||||
construct_params);
|
|
||||||
menu = GTK_RECENT_CHOOSER_MENU (object);
|
menu = GTK_RECENT_CHOOSER_MENU (object);
|
||||||
|
priv = menu->priv;
|
||||||
|
|
||||||
g_assert (menu->priv->manager);
|
g_assert (priv->manager);
|
||||||
|
|
||||||
|
/* we create a placeholder menuitem, to be used in the case
|
||||||
|
* were the menu is empty. this placeholder will stay around
|
||||||
|
* for the entire lifetime of the menu, and we just hide it
|
||||||
|
* when it's not used. we have to do this, and do it here,
|
||||||
|
* because we need a marker for the beginning of the recent
|
||||||
|
* items list, so that we can insert the new items at the
|
||||||
|
* right place when populating the menu, in case the user
|
||||||
|
* appended or prepended custom menuitems to the recent
|
||||||
|
* chooser menu widget.
|
||||||
|
*/
|
||||||
|
priv->placeholder = gtk_menu_item_new_with_label (_("No items found"));
|
||||||
|
gtk_widget_set_sensitive (priv->placeholder, FALSE);
|
||||||
|
g_object_set_data (G_OBJECT (priv->placeholder),
|
||||||
|
"gtk-recent-menu-placeholder",
|
||||||
|
GINT_TO_POINTER (TRUE));
|
||||||
|
|
||||||
|
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), priv->placeholder, 0);
|
||||||
|
gtk_widget_show (priv->placeholder);
|
||||||
|
|
||||||
|
/* (re)populate the menu */
|
||||||
|
gtk_recent_chooser_menu_populate (menu);
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -962,6 +992,41 @@ gtk_recent_chooser_menu_create_item (GtkRecentChooserMenu *menu,
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_recent_chooser_menu_insert_item (GtkRecentChooserMenu *menu,
|
||||||
|
GtkWidget *menuitem,
|
||||||
|
gint position)
|
||||||
|
{
|
||||||
|
GtkRecentChooserMenuPrivate *priv = menu->priv;
|
||||||
|
gint real_position;
|
||||||
|
GList *children, *l;
|
||||||
|
|
||||||
|
if (priv->first_recent_item_pos == -1)
|
||||||
|
{
|
||||||
|
children = gtk_container_get_children (GTK_CONTAINER (menu));
|
||||||
|
for (real_position = 0, l = children;
|
||||||
|
l != NULL;
|
||||||
|
real_position += 1, l = l->next)
|
||||||
|
{
|
||||||
|
GtkWidget *child = l->data;
|
||||||
|
gint mark = 0;
|
||||||
|
|
||||||
|
mark = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (child),
|
||||||
|
"gtk-recent-menu-placeholder"));
|
||||||
|
if (mark == 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_list_free (children);
|
||||||
|
priv->first_recent_item_pos = real_position;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
real_position = priv->first_recent_item_pos;
|
||||||
|
|
||||||
|
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem,
|
||||||
|
real_position + position);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
}
|
||||||
|
|
||||||
/* removes the items we own from the menu */
|
/* removes the items we own from the menu */
|
||||||
static void
|
static void
|
||||||
gtk_recent_chooser_menu_dispose_items (GtkRecentChooserMenu *menu)
|
gtk_recent_chooser_menu_dispose_items (GtkRecentChooserMenu *menu)
|
||||||
@ -992,6 +1057,9 @@ gtk_recent_chooser_menu_dispose_items (GtkRecentChooserMenu *menu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* recalculate the position of the first recent item */
|
||||||
|
menu->priv->first_recent_item_pos = -1;
|
||||||
|
|
||||||
g_list_free (children);
|
g_list_free (children);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1023,29 +1091,15 @@ idle_populate_func (gpointer data)
|
|||||||
pdata->items = gtk_recent_chooser_get_items (GTK_RECENT_CHOOSER (pdata->menu));
|
pdata->items = gtk_recent_chooser_get_items (GTK_RECENT_CHOOSER (pdata->menu));
|
||||||
if (!pdata->items)
|
if (!pdata->items)
|
||||||
{
|
{
|
||||||
item = gtk_menu_item_new_with_label (_("No items found"));
|
/* show the placeholder here */
|
||||||
gtk_widget_set_sensitive (item, FALSE);
|
gtk_widget_show (priv->placeholder);
|
||||||
|
|
||||||
/* we also mark this item, so that it gets removed when rebuilding
|
|
||||||
* the menu on the next map event
|
|
||||||
*/
|
|
||||||
g_object_set_data (G_OBJECT (item), "gtk-recent-menu-mark",
|
|
||||||
GINT_TO_POINTER (1));
|
|
||||||
|
|
||||||
gtk_menu_shell_prepend (GTK_MENU_SHELL (pdata->menu), item);
|
|
||||||
gtk_widget_show (item);
|
|
||||||
|
|
||||||
pdata->displayed_items = 1;
|
pdata->displayed_items = 1;
|
||||||
|
|
||||||
/* no items: add a placeholder menu */
|
|
||||||
GDK_THREADS_LEAVE ();
|
GDK_THREADS_LEAVE ();
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reverse the list */
|
|
||||||
pdata->items = g_list_reverse (pdata->items);
|
|
||||||
|
|
||||||
pdata->n_items = g_list_length (pdata->items);
|
pdata->n_items = g_list_length (pdata->items);
|
||||||
pdata->loaded_items = 0;
|
pdata->loaded_items = 0;
|
||||||
}
|
}
|
||||||
@ -1085,16 +1139,9 @@ idle_populate_func (gpointer data)
|
|||||||
goto check_and_return;
|
goto check_and_return;
|
||||||
|
|
||||||
gtk_recent_chooser_menu_add_tip (pdata->menu, info, item);
|
gtk_recent_chooser_menu_add_tip (pdata->menu, info, item);
|
||||||
|
gtk_recent_chooser_menu_insert_item (pdata->menu, item,
|
||||||
/* FIXME
|
pdata->displayed_items);
|
||||||
*
|
|
||||||
* We should really place our items taking into account user
|
|
||||||
* defined menu items; this would also remove the need of
|
|
||||||
* reverting the scan order.
|
|
||||||
*/
|
|
||||||
gtk_menu_shell_prepend (GTK_MENU_SHELL (pdata->menu), item);
|
|
||||||
gtk_widget_show (item);
|
|
||||||
|
|
||||||
pdata->displayed_items += 1;
|
pdata->displayed_items += 1;
|
||||||
|
|
||||||
/* mark the menu item as one of our own */
|
/* mark the menu item as one of our own */
|
||||||
@ -1129,23 +1176,13 @@ static void
|
|||||||
idle_populate_clean_up (gpointer data)
|
idle_populate_clean_up (gpointer data)
|
||||||
{
|
{
|
||||||
MenuPopulateData *pdata = data;
|
MenuPopulateData *pdata = data;
|
||||||
|
GtkRecentChooserMenuPrivate *priv = pdata->menu->priv;
|
||||||
|
|
||||||
|
/* show the placeholder in case no item survived
|
||||||
|
* the filtering process in the idle loop
|
||||||
|
*/
|
||||||
if (!pdata->displayed_items)
|
if (!pdata->displayed_items)
|
||||||
{
|
gtk_widget_show (priv->placeholder);
|
||||||
GtkWidget *item;
|
|
||||||
|
|
||||||
item = gtk_menu_item_new_with_label (_("No items found"));
|
|
||||||
gtk_widget_set_sensitive (item, FALSE);
|
|
||||||
|
|
||||||
/* we also mark this item, so that it gets removed when rebuilding
|
|
||||||
* the menu on the next map event
|
|
||||||
*/
|
|
||||||
g_object_set_data (G_OBJECT (item), "gtk-recent-menu-mark",
|
|
||||||
GINT_TO_POINTER (1));
|
|
||||||
|
|
||||||
gtk_menu_shell_prepend (GTK_MENU_SHELL (pdata->menu), item);
|
|
||||||
gtk_widget_show (item);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_slice_free (MenuPopulateData, data);
|
g_slice_free (MenuPopulateData, data);
|
||||||
}
|
}
|
||||||
@ -1154,6 +1191,7 @@ static void
|
|||||||
gtk_recent_chooser_menu_populate (GtkRecentChooserMenu *menu)
|
gtk_recent_chooser_menu_populate (GtkRecentChooserMenu *menu)
|
||||||
{
|
{
|
||||||
MenuPopulateData *pdata;
|
MenuPopulateData *pdata;
|
||||||
|
GtkRecentChooserMenuPrivate *priv = menu->priv;
|
||||||
|
|
||||||
if (menu->priv->populate_id)
|
if (menu->priv->populate_id)
|
||||||
return;
|
return;
|
||||||
@ -1165,15 +1203,16 @@ gtk_recent_chooser_menu_populate (GtkRecentChooserMenu *menu)
|
|||||||
pdata->displayed_items = 0;
|
pdata->displayed_items = 0;
|
||||||
pdata->menu = menu;
|
pdata->menu = menu;
|
||||||
|
|
||||||
menu->priv->icon_size = get_icon_size_for_widget (GTK_WIDGET (menu));
|
priv->icon_size = get_icon_size_for_widget (GTK_WIDGET (menu));
|
||||||
|
|
||||||
/* dispose our menu items first */
|
/* remove our menu items first and hide the placeholder */
|
||||||
gtk_recent_chooser_menu_dispose_items (menu);
|
gtk_recent_chooser_menu_dispose_items (menu);
|
||||||
|
gtk_widget_hide (priv->placeholder);
|
||||||
|
|
||||||
menu->priv->populate_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
|
priv->populate_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
|
||||||
idle_populate_func,
|
idle_populate_func,
|
||||||
pdata,
|
pdata,
|
||||||
idle_populate_clean_up);
|
idle_populate_clean_up);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bounce activate signal from the recent menu item widget
|
/* bounce activate signal from the recent menu item widget
|
||||||
@ -1207,7 +1246,16 @@ set_recent_manager (GtkRecentChooserMenu *menu,
|
|||||||
if (priv->manager)
|
if (priv->manager)
|
||||||
{
|
{
|
||||||
if (priv->manager_changed_id)
|
if (priv->manager_changed_id)
|
||||||
g_signal_handler_disconnect (priv->manager, priv->manager_changed_id);
|
{
|
||||||
|
g_signal_handler_disconnect (priv->manager, priv->manager_changed_id);
|
||||||
|
priv->manager_changed_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->populate_id)
|
||||||
|
{
|
||||||
|
g_source_remove (priv->populate_id);
|
||||||
|
priv->populate_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
priv->manager = NULL;
|
priv->manager = NULL;
|
||||||
}
|
}
|
||||||
@ -1221,8 +1269,6 @@ set_recent_manager (GtkRecentChooserMenu *menu,
|
|||||||
priv->manager_changed_id = g_signal_connect (priv->manager, "changed",
|
priv->manager_changed_id = g_signal_connect (priv->manager, "changed",
|
||||||
G_CALLBACK (manager_changed_cb),
|
G_CALLBACK (manager_changed_cb),
|
||||||
menu);
|
menu);
|
||||||
/* (re)populate the menu */
|
|
||||||
gtk_recent_chooser_menu_populate (menu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gint
|
static gint
|
||||||
|
@ -56,6 +56,8 @@ static GtkWidget *
|
|||||||
create_recent_chooser_menu (void)
|
create_recent_chooser_menu (void)
|
||||||
{
|
{
|
||||||
GtkWidget *menu;
|
GtkWidget *menu;
|
||||||
|
GtkRecentFilter *filter;
|
||||||
|
GtkWidget *menuitem;
|
||||||
|
|
||||||
menu = gtk_recent_chooser_menu_new_for_manager (manager);
|
menu = gtk_recent_chooser_menu_new_for_manager (manager);
|
||||||
|
|
||||||
@ -66,12 +68,38 @@ create_recent_chooser_menu (void)
|
|||||||
gtk_recent_chooser_menu_set_show_numbers (GTK_RECENT_CHOOSER_MENU (menu),
|
gtk_recent_chooser_menu_set_show_numbers (GTK_RECENT_CHOOSER_MENU (menu),
|
||||||
TRUE);
|
TRUE);
|
||||||
|
|
||||||
|
filter = gtk_recent_filter_new ();
|
||||||
|
gtk_recent_filter_set_name (filter, "Gedit files");
|
||||||
|
gtk_recent_filter_add_application (filter, "gedit");
|
||||||
|
gtk_recent_chooser_add_filter (GTK_RECENT_CHOOSER (menu), filter);
|
||||||
|
gtk_recent_chooser_set_filter (GTK_RECENT_CHOOSER (menu), filter);
|
||||||
|
|
||||||
g_signal_connect (menu, "item-activated",
|
g_signal_connect (menu, "item-activated",
|
||||||
G_CALLBACK (item_activated_cb),
|
G_CALLBACK (item_activated_cb),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
gtk_widget_show (menu);
|
gtk_widget_show (menu);
|
||||||
|
|
||||||
|
menuitem = gtk_separator_menu_item_new ();
|
||||||
|
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
|
||||||
|
menuitem = gtk_menu_item_new_with_label ("Test prepend");
|
||||||
|
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
|
||||||
|
menuitem = gtk_separator_menu_item_new ();
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
|
||||||
|
menuitem = gtk_menu_item_new_with_label ("Test append");
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
|
||||||
|
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_CLEAR, NULL);
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user