-/* GTK - The GTK+ Toolkit
+/* GTK - The GIMP Toolkit
* gtkrecentchoosermenu.c - Recently used items menu widget
* Copyright (C) 2005, Emmanuele Bassi
*
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gtkimage.h"
#include "gtklabel.h"
#include "gtktooltip.h"
+#include "gtkactivatable.h"
#include "gtktypebuiltins.h"
#include "gtkprivate.h"
-#include "gtkalias.h"
+
+/**
+ * SECTION:gtkrecentchoosermenu
+ * @Short_description: Displays recently used files in a menu
+ * @Title: GtkRecentChooserMenu
+ * @See_also:#GtkRecentChooser
+ *
+ * #GtkRecentChooserMenu is a widget suitable for displaying recently used files
+ * inside a menu. It can be used to set a sub-menu of a #GtkMenuItem using
+ * gtk_menu_item_set_submenu(), or as the menu of a #GtkMenuToolButton.
+ *
+ * Note that #GtkRecentChooserMenu does not have any methods of its own. Instead,
+ * you should use the functions that work on a #GtkRecentChooser.
+ *
+ * Note also that #GtkRecentChooserMenu does not support multiple filters, as it
+ * has no way to let the user choose between them as the #GtkRecentChooserWidget
+ * and #GtkRecentChooserDialog widgets do. Thus using gtk_recent_chooser_add_filter()
+ * on a #GtkRecentChooserMenu widget will yield the same effects as using
+ * gtk_recent_chooser_set_filter(), replacing any currently set filter
+ * with the supplied filter; gtk_recent_chooser_remove_filter() will remove
+ * any currently set #GtkRecentFilter object and will unset the current filter;
+ * gtk_recent_chooser_list_filters() will return a list containing a single
+ * #GtkRecentFilter object.
+ *
+ * Recently used files are supported since GTK+ 2.10.
+ */
+
struct _GtkRecentChooserMenuPrivate
{
/* the recent manager object */
GtkRecentManager *manager;
- /* size of the icons of the menu items */
- gint icon_size;
-
/* max size of the menu item label */
gint label_width;
enum {
PROP_0,
+ PROP_SHOW_NUMBERS,
- PROP_SHOW_NUMBERS
+ /* activatable properties */
+ PROP_ACTIVATABLE_RELATED_ACTION,
+ PROP_ACTIVATABLE_USE_ACTION_APPEARANCE
};
-#define FALLBACK_ICON_SIZE 32
+
#define FALLBACK_ITEM_LIMIT 10
#define DEFAULT_LABEL_WIDTH 30
-#define GTK_RECENT_CHOOSER_MENU_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_RECENT_CHOOSER_MENU, GtkRecentChooserMenuPrivate))
static void gtk_recent_chooser_menu_finalize (GObject *object);
static void gtk_recent_chooser_menu_dispose (GObject *object);
static void chooser_set_sort_type (GtkRecentChooserMenu *menu,
GtkRecentSortType sort_type);
-static gint get_icon_size_for_widget (GtkWidget *widget);
-
static void item_activate_cb (GtkWidget *widget,
gpointer user_data);
static void manager_changed_cb (GtkRecentManager *manager,
gpointer user_data);
+static void gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface);
+static void gtk_recent_chooser_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name);
+static void gtk_recent_chooser_sync_action_properties (GtkActivatable *activatable,
+ GtkAction *action);
+
G_DEFINE_TYPE_WITH_CODE (GtkRecentChooserMenu,
gtk_recent_chooser_menu,
GTK_TYPE_MENU,
G_IMPLEMENT_INTERFACE (GTK_TYPE_RECENT_CHOOSER,
- gtk_recent_chooser_iface_init))
+ gtk_recent_chooser_iface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE,
+ gtk_recent_chooser_activatable_iface_init))
static void
iface->list_filters = gtk_recent_chooser_menu_list_filters;
}
+static void
+gtk_recent_chooser_activatable_iface_init (GtkActivatableIface *iface)
+{
+ iface->update = gtk_recent_chooser_update;
+ iface->sync_action_properties = gtk_recent_chooser_sync_action_properties;
+}
+
static void
gtk_recent_chooser_menu_class_init (GtkRecentChooserMenuClass *klass)
{
_gtk_recent_chooser_install_properties (gobject_class);
/**
- * GtkRecentChooserMenu:show-numbers
+ * GtkRecentChooserMenu:show-numbers:
*
* Whether the first ten items in the menu should be prepended by
* a number acting as a unique mnemonic.
FALSE,
GTK_PARAM_READWRITE));
+
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_RELATED_ACTION, "related-action");
+ g_object_class_override_property (gobject_class, PROP_ACTIVATABLE_USE_ACTION_APPEARANCE, "use-action-appearance");
+
g_type_class_add_private (klass, sizeof (GtkRecentChooserMenuPrivate));
}
gtk_recent_chooser_menu_init (GtkRecentChooserMenu *menu)
{
GtkRecentChooserMenuPrivate *priv;
-
- priv = GTK_RECENT_CHOOSER_MENU_GET_PRIVATE (menu);
-
- menu->priv = priv;
-
+
+ menu->priv = G_TYPE_INSTANCE_GET_PRIVATE (menu,
+ GTK_TYPE_RECENT_CHOOSER_MENU,
+ GtkRecentChooserMenuPrivate);
+
+ priv = menu->priv;
+
priv->show_icons= TRUE;
priv->show_numbers = FALSE;
priv->show_tips = FALSE;
priv->limit = FALLBACK_ITEM_LIMIT;
priv->sort_type = GTK_RECENT_SORT_NONE;
- priv->icon_size = FALLBACK_ICON_SIZE;
priv->label_width = DEFAULT_LABEL_WIDTH;
priv->first_recent_item_pos = -1;
case GTK_RECENT_CHOOSER_PROP_FILTER:
gtk_recent_chooser_menu_set_current_filter (menu, g_value_get_object (value));
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ _gtk_recent_chooser_set_related_action (GTK_RECENT_CHOOSER (menu), g_value_get_object (value));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ _gtk_recent_chooser_set_use_action_appearance (GTK_RECENT_CHOOSER (menu), g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case GTK_RECENT_CHOOSER_PROP_FILTER:
g_value_set_object (value, priv->current_filter);
break;
+ case PROP_ACTIVATABLE_RELATED_ACTION:
+ g_value_set_object (value, _gtk_recent_chooser_get_related_action (GTK_RECENT_CHOOSER (menu)));
+ break;
+ case PROP_ACTIVATABLE_USE_ACTION_APPEARANCE:
+ g_value_set_boolean (value, _gtk_recent_chooser_get_use_action_appearance (GTK_RECENT_CHOOSER (menu)));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
static void
gtk_recent_chooser_menu_select_all (GtkRecentChooser *chooser)
{
- g_warning (_("This function is not implemented for "
- "widgets of class '%s'"),
+ g_warning ("This function is not implemented for "
+ "widgets of class '%s'",
g_type_name (G_OBJECT_TYPE (chooser)));
}
static void
gtk_recent_chooser_menu_unselect_all (GtkRecentChooser *chooser)
{
- g_warning (_("This function is not implemented for "
- "widgets of class '%s'"),
+ g_warning ("This function is not implemented for "
+ "widgets of class '%s'",
g_type_name (G_OBJECT_TYPE (chooser)));
}
if (priv->current_filter)
g_object_unref (G_OBJECT (priv->current_filter));
- if (filter)
- {
- priv->current_filter = filter;
- g_object_ref_sink (priv->current_filter);
- }
+ priv->current_filter = filter;
+
+ if (priv->current_filter)
+ g_object_ref_sink (priv->current_filter);
gtk_recent_chooser_menu_populate (menu);
GtkRecentChooserMenuPrivate *priv;
gchar *text;
GtkWidget *item, *image, *label;
- GdkPixbuf *icon;
+ GIcon *icon;
g_assert (info != NULL);
/* avoid clashing mnemonics */
if (count <= 10)
- /* This is the label format that is used for the first 10 items
+ /* This is the label format that is used for the first 10 items
* in a recent files menu. The %d is the number of the item,
* the %s is the name of the item. Please keep the _ in front
* of the number to give these menu items a mnemonic.
- *
- * Don't include the prefix "recent menu label|" in the translation.
*/
- text = g_strdup_printf (Q_("recent menu label|_%d. %s"), count, escaped);
+ text = g_strdup_printf (C_("recent menu label", "_%d. %s"), count, escaped);
else
- /* This is the format that is used for items in a recent files menu.
- * The %d is the number of the item, the %s is the name of the item.
- *
- * Don't include the prefix "recent menu label|" in the translation.
+ /* This is the format that is used for items in a recent files menu.
+ * The %d is the number of the item, the %s is the name of the item.
*/
- text = g_strdup_printf (Q_("recent menu label|%d. %s"), count, escaped);
+ text = g_strdup_printf (C_("recent menu label", "%d. %s"), count, escaped);
item = gtk_image_menu_item_new_with_mnemonic (text);
g_free (text);
+ gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item),
+ TRUE);
+
/* ellipsize the menu item label, in case the recent document
* display name is huge.
*/
- label = GTK_BIN (item)->child;
+ label = gtk_bin_get_child (GTK_BIN (item));
if (GTK_IS_LABEL (label))
{
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
if (priv->show_icons)
{
- icon = gtk_recent_info_get_icon (info, priv->icon_size);
-
- image = gtk_image_new_from_pixbuf (icon);
+ icon = gtk_recent_info_get_gicon (info);
+
+ image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item), image);
- g_object_unref (icon);
+ gtk_image_menu_item_set_always_show_image (GTK_IMAGE_MENU_ITEM (item), TRUE);
+ if (icon)
+ g_object_unref (icon);
}
g_signal_connect (item, "activate",
GtkWidget *placeholder;
} MenuPopulateData;
+static MenuPopulateData *
+create_menu_populate_data (GtkRecentChooserMenu *menu)
+{
+ MenuPopulateData *pdata;
+
+ pdata = g_slice_new (MenuPopulateData);
+ pdata->items = NULL;
+ pdata->n_items = 0;
+ pdata->loaded_items = 0;
+ pdata->displayed_items = 0;
+ pdata->menu = menu;
+ pdata->placeholder = g_object_ref (menu->priv->placeholder);
+
+ return pdata;
+}
+
+static void
+free_menu_populate_data (MenuPopulateData *pdata)
+{
+ if (pdata->placeholder)
+ g_object_unref (pdata->placeholder);
+ g_slice_free (MenuPopulateData, pdata);
+}
+
static gboolean
idle_populate_func (gpointer data)
{
return FALSE;
}
+ else
+ gtk_widget_hide (pdata->placeholder);
pdata->n_items = g_list_length (pdata->items);
pdata->loaded_items = 0;
if (pdata->loaded_items == pdata->n_items)
{
- g_list_foreach (pdata->items, (GFunc) gtk_recent_info_unref, NULL);
- g_list_free (pdata->items);
+ g_list_free_full (pdata->items, (GDestroyNotify) gtk_recent_info_unref);
priv->populate_id = 0;
*/
if (!pdata->displayed_items)
gtk_widget_show (pdata->placeholder);
- g_object_unref (pdata->placeholder);
-
- g_slice_free (MenuPopulateData, data);
}
+
+ free_menu_populate_data (pdata);
}
static void
MenuPopulateData *pdata;
GtkRecentChooserMenuPrivate *priv = menu->priv;
- if (menu->priv->populate_id)
+ if (priv->populate_id)
return;
- pdata = g_slice_new (MenuPopulateData);
- pdata->items = NULL;
- pdata->n_items = 0;
- pdata->loaded_items = 0;
- pdata->displayed_items = 0;
- pdata->menu = menu;
- pdata->placeholder = g_object_ref (priv->placeholder);
+ pdata = create_menu_populate_data (menu);
- priv->icon_size = get_icon_size_for_widget (GTK_WIDGET (menu));
-
- /* remove our menu items first and hide the placeholder */
+ /* remove our menu items first */
gtk_recent_chooser_menu_dispose_items (menu);
- gtk_widget_hide (priv->placeholder);
-
+
priv->populate_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
idle_populate_func,
pdata,
menu);
}
-static gint
-get_icon_size_for_widget (GtkWidget *widget)
-{
- GtkSettings *settings;
- gint width, height;
-
- if (gtk_widget_has_screen (widget))
- settings = gtk_settings_get_for_screen (gtk_widget_get_screen (widget));
- else
- settings = gtk_settings_get_default ();
-
- if (gtk_icon_size_lookup_for_settings (settings, GTK_ICON_SIZE_MENU,
- &width, &height))
- return MAX (width, height);
-
- return FALLBACK_ICON_SIZE;
-}
-
static void
foreach_set_shot_tips (GtkWidget *widget,
gpointer user_data)
gtk_container_foreach (GTK_CONTAINER (menu), foreach_set_shot_tips, menu);
}
+static void
+gtk_recent_chooser_update (GtkActivatable *activatable,
+ GtkAction *action,
+ const gchar *property_name)
+{
+ if (strcmp (property_name, "sensitive") == 0)
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+ _gtk_recent_chooser_update (activatable, action, property_name);
+}
+
+static void
+gtk_recent_chooser_sync_action_properties (GtkActivatable *activatable,
+ GtkAction *action)
+{
+ gtk_widget_set_sensitive (GTK_WIDGET (activatable), gtk_action_is_sensitive (action));
+
+ _gtk_recent_chooser_sync_action_properties (activatable, action);
+}
+
+
/*
* Public API
*/
menu->priv->show_numbers = show_numbers;
g_object_notify (G_OBJECT (menu), "show-numbers");
}
-
-#define __GTK_RECENT_CHOOSER_MENU_C__
-#include "gtkaliasdef.c"