*** empty log message ***
[anjuta-git-plugin.git] / libegg / egg-recent-action.c
blob0d4a1b02a4f63d25a7f0a8597930523defa9a015
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
3 /* egg-recent-action widget
5 * Copyright (C) Naba Kumar <naba@gnome.org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * You should have received a copy of the GNU General Public
18 * License along with this program; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
22 #include <stdio.h>
23 #include <gtk/gtkwidget.h>
24 #include <gtk/gtktoggletoolbutton.h>
25 #include <libegg/recent-files/egg-recent-view.h>
26 #include <libegg/recent-files/egg-recent-view-gtk.h>
27 #include "egg-recent-action.h"
29 #ifndef _
30 # define _(s) (s)
31 #endif
33 struct _EggRecentActionPriv
35 GList *recent_models;
36 gint size;
37 gchar *selected_uri;
40 static void egg_recent_action_init (EggRecentAction *action);
41 static void egg_recent_action_class_init (EggRecentActionClass *class);
43 static GtkWidget * create_tool_item (GtkAction *action);
44 static GtkWidget * create_menu_item (GtkAction *action);
45 static void connect_proxy (GtkAction *action,
46 GtkWidget *proxy);
47 static void disconnect_proxy (GtkAction *action,
48 GtkWidget *proxy);
49 static void egg_recent_action_finalize (GObject *object);
50 static void egg_recent_action_dispose (GObject *object);
51 static gboolean on_recent_select (EggRecentView *recent, EggRecentItem *item,
52 EggRecentAction *plugin);
54 static GObjectClass *parent_class = NULL;
56 GType
57 egg_recent_action_get_type (void)
59 static GtkType type = 0;
61 if (!type)
63 static const GTypeInfo type_info =
65 sizeof (EggRecentActionClass),
66 (GBaseInitFunc) NULL,
67 (GBaseFinalizeFunc) NULL,
68 (GClassInitFunc) egg_recent_action_class_init,
69 (GClassFinalizeFunc) NULL,
70 NULL,
72 sizeof (EggRecentAction),
73 0, /* n_preallocs */
74 (GInstanceInitFunc) egg_recent_action_init,
77 type = g_type_register_static (GTK_TYPE_ACTION,
78 "EggRecentAction",
79 &type_info, 0);
81 return type;
84 static void
85 egg_recent_action_class_init (EggRecentActionClass *class)
87 GtkActionClass *action_class;
88 GObjectClass *object_class;
90 parent_class = g_type_class_peek_parent (class);
91 action_class = GTK_ACTION_CLASS (class);
92 object_class = G_OBJECT_CLASS (class);
94 object_class->finalize = egg_recent_action_finalize;
95 object_class->dispose = egg_recent_action_dispose;
97 action_class->connect_proxy = connect_proxy;
98 action_class->disconnect_proxy = disconnect_proxy;
99 action_class->menu_item_type = GTK_TYPE_MENU_ITEM;
100 action_class->toolbar_item_type = GTK_TYPE_TOOL_ITEM;
101 action_class->create_tool_item = create_tool_item;
102 action_class->create_menu_item = create_menu_item;
105 static void
106 egg_recent_action_init (EggRecentAction *action)
108 action->priv = g_new0 (EggRecentActionPriv, 1);
109 action->priv->recent_models = NULL;
110 action->priv->selected_uri = NULL;
113 static void
114 egg_recent_action_dispose (GObject *object)
116 EggRecentActionPriv *priv;
118 priv = EGG_RECENT_ACTION (object)->priv;
119 if (priv->recent_models)
121 GList *node;
122 node = priv->recent_models;
123 while (node)
125 g_object_unref (node->data);
126 node = g_list_next (node);
128 g_list_free (priv->recent_models);
129 priv->recent_models = NULL;
131 if (parent_class->dispose)
132 parent_class->dispose (object);
135 static void
136 egg_recent_action_finalize (GObject *object)
138 g_free (EGG_RECENT_ACTION (object)->priv->selected_uri);
139 g_free (EGG_RECENT_ACTION (object)->priv);
140 if (parent_class->finalize)
141 parent_class->finalize (object);
144 static gboolean
145 on_recent_select (EggRecentView *view, EggRecentItem *item,
146 EggRecentAction *action)
148 gchar *uri;
149 gboolean ret = TRUE;
151 uri = egg_recent_item_get_uri (item);
152 if (uri)
154 g_free (action->priv->selected_uri);
155 action->priv->selected_uri = g_strdup (uri);
156 g_free (uri);
157 gtk_action_activate (GTK_ACTION (action));
159 return ret;
162 static void
163 on_recent_files_tooltip (GtkTooltips *tooltips, GtkWidget *menu_item,
164 EggRecentItem *item, gpointer user_data)
166 char *uri, *tip;
168 uri = egg_recent_item_get_uri_for_display (item);
169 tip = g_strdup_printf ("Open '%s'", uri);
171 gtk_tooltips_set_tip (tooltips, menu_item, tip, NULL);
173 g_free (uri);
176 static void
177 update_recent_submenu (EggRecentAction *action, GtkWidget *submenu,
178 EggRecentModel *model, gint id)
180 EggRecentViewGtk *recent_view;
181 GtkWidget *sep = NULL;
182 gchar buff[64];
184 if (id != 0)
186 sep = gtk_menu_item_new ();
187 gtk_widget_show (sep);
188 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), sep);
190 recent_view = egg_recent_view_gtk_new (submenu, sep);
191 egg_recent_view_gtk_set_tooltip_func (recent_view,
192 on_recent_files_tooltip, NULL);
193 egg_recent_view_set_model (EGG_RECENT_VIEW (recent_view),
194 model);
195 snprintf (buff, 64, "recent-view-%d", id);
196 g_object_set_data_full (G_OBJECT (submenu), buff, recent_view,
197 g_object_unref);
198 g_signal_connect (G_OBJECT (recent_view), "activate",
199 G_CALLBACK (on_recent_select), action);
202 static GtkWidget*
203 create_recent_submenu (EggRecentAction *action)
205 GtkWidget *submenu;
206 GList *node;
207 gint id;
209 submenu = gtk_menu_new ();
210 node = action->priv->recent_models;
211 id = 0;
212 while (node)
214 update_recent_submenu (action, submenu, node->data, id);
215 id++;
216 node = g_list_next (node);
218 return submenu;
221 static void
222 on_reposition_menu (GtkMenu *menu, gint *x, gint *y, gboolean *push_in,
223 gpointer data)
225 gint x1, y1, w, h, d;
226 GtkWidget *button = GTK_WIDGET (data);
227 gdk_window_get_origin (button->window, x, y);
228 gdk_window_get_geometry (button->window, &x1, &y1, &w, &h, &d);
229 *y += button->allocation.height;
230 if (GTK_WIDGET_NO_WINDOW (button))
232 *x += button->allocation.x;
233 *y += button->allocation.y;
237 static void
238 on_selection_done_menu (GtkMenu *menu, GtkWidget *button)
240 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
243 static void
244 on_button_pressed (GtkToggleToolButton *button, EggRecentAction *action)
246 GtkWidget *submenu;
248 /* g_message ("Recent toolitem toggled"); */
249 submenu = g_object_get_data (G_OBJECT (button), "submenu");
250 if (!submenu)
252 submenu = create_recent_submenu (action);
253 g_object_set_data_full (G_OBJECT (button), "submenu", submenu,
254 (GDestroyNotify)gtk_widget_destroy);
255 g_object_set_data (G_OBJECT (submenu), "thebutton", button);
256 g_signal_connect (G_OBJECT (submenu), "selection-done",
257 G_CALLBACK (on_selection_done_menu), button);
258 gtk_widget_show (submenu);
260 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
262 gtk_menu_popup (GTK_MENU (submenu), NULL, NULL, on_reposition_menu,
263 button, 0, gtk_get_current_event_time ());
264 gtk_menu_reposition (GTK_MENU (submenu));
266 else
268 gtk_menu_popdown (GTK_MENU (submenu));
272 static GtkWidget *
273 create_tool_item (GtkAction *action)
275 GtkWidget *arrow;
276 GtkWidget *button;
277 GtkToolItem *item;
279 g_return_val_if_fail (EGG_IS_RECENT_ACTION (action), NULL);
280 /* g_message ("Creating recent toolitem"); */
282 item = gtk_tool_item_new ();
283 gtk_widget_show(GTK_WIDGET (item));
284 button = gtk_toggle_button_new ();
285 gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
286 gtk_container_add (GTK_CONTAINER (item), button);
287 gtk_widget_show(GTK_WIDGET (button));
288 arrow = gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_NONE);
289 gtk_widget_show (arrow);
290 gtk_container_add (GTK_CONTAINER (button), arrow);
291 return GTK_WIDGET (item);
294 static GtkWidget *
295 create_menu_item (GtkAction *action)
297 GtkWidget *menuitem, *submenu;
298 menuitem = (* GTK_ACTION_CLASS (parent_class)->create_menu_item) (action);
299 submenu = create_recent_submenu (EGG_RECENT_ACTION (action));
300 gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
301 return menuitem;
304 static void
305 connect_proxy (GtkAction *action, GtkWidget *proxy)
307 EggRecentAction *recent_action;
309 recent_action = EGG_RECENT_ACTION (action);
311 /* do this before hand, so that we don't call the "activate" handler */
312 if (GTK_IS_TOOL_ITEM (proxy))
314 g_signal_connect (G_OBJECT (gtk_bin_get_child(GTK_BIN (proxy))), "toggled",
315 G_CALLBACK (on_button_pressed), action);
317 (* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
320 static void
321 disconnect_proxy (GtkAction *action, GtkWidget *proxy)
323 EggRecentAction *recent_action;
325 recent_action = EGG_RECENT_ACTION (action);
327 /* do this before hand, so that we don't call the "activate" handler */
328 if (GTK_IS_TOOL_ITEM (proxy))
330 g_signal_handlers_disconnect_by_func (G_OBJECT (gtk_bin_get_child(GTK_BIN (proxy))),
331 G_CALLBACK (on_button_pressed), action);
333 (* GTK_ACTION_CLASS (parent_class)->connect_proxy) (action, proxy);
337 * egg_recent_action_set_model:
338 * @action: the action object
339 * @model: a GtkTreeModel
341 * Sets a model in the action.
343 void
344 egg_recent_action_add_model (EggRecentAction *action, EggRecentModel *model)
346 GSList *slist;
348 g_return_if_fail (EGG_IS_RECENT_ACTION (action));
349 g_return_if_fail (EGG_IS_RECENT_MODEL (model));
351 g_object_ref (model);
352 action->priv->recent_models =
353 g_list_append (action->priv->recent_models, model);
355 for (slist = gtk_action_get_proxies (GTK_ACTION(action));
356 slist; slist = slist->next)
358 GtkWidget *proxy = slist->data;
360 gtk_action_block_activate_from (GTK_ACTION (action), proxy);
362 if (GTK_IS_MENU_ITEM (proxy))
364 GtkWidget *submenu;
366 submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM(proxy));
367 update_recent_submenu (action, submenu, model,
368 g_list_length (action->priv->recent_models)-1);
370 else if (GTK_IS_TOOL_ITEM (proxy))
372 GtkWidget *submenu;
374 submenu = g_object_get_data (G_OBJECT (gtk_bin_get_child(GTK_BIN(proxy))), "submenu");
375 update_recent_submenu (action, submenu, model,
376 g_list_length (action->priv->recent_models)-1);
378 else
380 g_warning ("Don't know how to set popdown for `%s' widgets",
381 G_OBJECT_TYPE_NAME (proxy));
383 gtk_action_unblock_activate_from (GTK_ACTION (action), proxy);
387 const gchar*
388 egg_recent_action_get_selected_uri (EggRecentAction *action)
390 return action->priv->selected_uri;