]> Pileus Git - ~andy/gtk/blob - gtk/gtkrecentchooserdialog.c
474a1b04668222ec5df3f8f9574d39624f318979
[~andy/gtk] / gtk / gtkrecentchooserdialog.c
1 /* GTK - The GIMP Toolkit
2  * gtkrecentchooserdialog.c: Recent files selector dialog
3  * Copyright (C) 2006 Emmanuele Bassi
4  * 
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22
23 #include "gtkrecentchooserdialog.h"
24 #include "gtkrecentchooserwidget.h"
25 #include "gtkrecentchooserutils.h"
26 #include "gtkrecentmanager.h"
27 #include "gtktypebuiltins.h"
28 #include "gtkalias.h"
29
30 #include <stdarg.h>
31
32 struct _GtkRecentChooserDialogPrivate
33 {
34   GtkRecentManager *manager;
35   
36   GtkWidget *chooser;
37 };
38
39 #define GTK_RECENT_CHOOSER_DIALOG_GET_PRIVATE(obj)      (GTK_RECENT_CHOOSER_DIALOG (obj)->priv)
40
41 static void gtk_recent_chooser_dialog_class_init (GtkRecentChooserDialogClass *klass);
42 static void gtk_recent_chooser_dialog_init       (GtkRecentChooserDialog      *dialog);
43 static void gtk_recent_chooser_dialog_finalize   (GObject                     *object);
44
45 static GObject *gtk_recent_chooser_dialog_constructor (GType                  type,
46                                                        guint                  n_construct_properties,
47                                                        GObjectConstructParam *construct_params);
48
49 static void gtk_recent_chooser_dialog_set_property (GObject      *object,
50                                                     guint         prop_id,
51                                                     const GValue *value,
52                                                     GParamSpec   *pspec);
53 static void gtk_recent_chooser_dialog_get_property (GObject      *object,
54                                                     guint         prop_id,
55                                                     GValue       *value,
56                                                     GParamSpec   *pspec);
57
58 static void gtk_recent_chooser_dialog_map       (GtkWidget *widget);
59 static void gtk_recent_chooser_dialog_unmap     (GtkWidget *widget);
60 static void gtk_recent_chooser_dialog_style_set (GtkWidget *widget,
61                                                  GtkStyle  *old_style);
62
63
64 G_DEFINE_TYPE_WITH_CODE (GtkRecentChooserDialog,
65                          gtk_recent_chooser_dialog,
66                          GTK_TYPE_DIALOG,
67                          G_IMPLEMENT_INTERFACE (GTK_TYPE_RECENT_CHOOSER,
68                                                 _gtk_recent_chooser_delegate_iface_init))
69
70 static void
71 gtk_recent_chooser_dialog_class_init (GtkRecentChooserDialogClass *klass)
72 {
73   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
74   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
75   
76   gobject_class->set_property = gtk_recent_chooser_dialog_set_property;
77   gobject_class->get_property = gtk_recent_chooser_dialog_get_property;
78   gobject_class->constructor = gtk_recent_chooser_dialog_constructor;
79   gobject_class->finalize = gtk_recent_chooser_dialog_finalize;
80   
81   widget_class->map = gtk_recent_chooser_dialog_map;
82   widget_class->unmap = gtk_recent_chooser_dialog_unmap;
83   widget_class->style_set = gtk_recent_chooser_dialog_style_set;
84   
85   _gtk_recent_chooser_install_properties (gobject_class);
86   
87   g_type_class_add_private (klass, sizeof (GtkRecentChooserDialogPrivate));
88 }
89
90 static void
91 gtk_recent_chooser_dialog_init (GtkRecentChooserDialog *dialog)
92 {
93   GtkRecentChooserDialogPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
94                                                                      GTK_TYPE_RECENT_CHOOSER_DIALOG,
95                                                                      GtkRecentChooserDialogPrivate);
96   
97   dialog->priv = priv;
98   
99   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
100 }
101
102 /* we intercept the GtkRecentChooser::item_activated signal and try to
103  * make the dialog emit a valid response signal
104  */
105 static void
106 gtk_recent_chooser_item_activated_cb (GtkRecentChooser *chooser,
107                                       gpointer          user_data)
108 {
109   GtkRecentChooserDialog *dialog;
110   GList *children, *l;
111
112   dialog = GTK_RECENT_CHOOSER_DIALOG (user_data);
113
114   if (gtk_window_activate_default (GTK_WINDOW (dialog)))
115     return;
116   
117   children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
118   
119   for (l = children; l; l = l->next)
120     {
121       GtkWidget *widget;
122       gint response_id;
123       
124       widget = GTK_WIDGET (l->data);
125       response_id = gtk_dialog_get_response_for_widget (GTK_DIALOG (dialog), widget);
126       
127       if (response_id == GTK_RESPONSE_ACCEPT ||
128           response_id == GTK_RESPONSE_OK     ||
129           response_id == GTK_RESPONSE_YES    ||
130           response_id == GTK_RESPONSE_APPLY)
131         {
132           g_list_free (children);
133           
134           gtk_dialog_response (GTK_DIALOG (dialog), response_id);
135
136           return;
137         }
138     }
139   
140   g_list_free (children);
141 }
142
143 static GObject *
144 gtk_recent_chooser_dialog_constructor (GType                  type,
145                                        guint                  n_construct_properties,
146                                        GObjectConstructParam *construct_params)
147 {
148   GObject *object;
149   GtkRecentChooserDialogPrivate *priv;
150   
151   object = G_OBJECT_CLASS (gtk_recent_chooser_dialog_parent_class)->constructor (type,
152                                                                                  n_construct_properties,
153                                                                                  construct_params);
154   priv = GTK_RECENT_CHOOSER_DIALOG_GET_PRIVATE (object);
155   
156   gtk_widget_push_composite_child ();
157   
158   if (priv->manager)
159     priv->chooser = g_object_new (GTK_TYPE_RECENT_CHOOSER_WIDGET,
160                                   "recent-manager", priv->manager,
161                                   NULL);
162   else
163     priv->chooser = g_object_new (GTK_TYPE_RECENT_CHOOSER_WIDGET, NULL);
164   
165   g_signal_connect (priv->chooser, "item_activated",
166                     G_CALLBACK (gtk_recent_chooser_item_activated_cb),
167                     object);
168   
169   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox),
170                       priv->chooser, TRUE, TRUE, 0);
171   gtk_widget_show (priv->chooser);
172   
173   _gtk_recent_chooser_set_delegate (GTK_RECENT_CHOOSER (object),
174                                     GTK_RECENT_CHOOSER (priv->chooser));
175   
176   gtk_widget_pop_composite_child ();
177   
178   return object;
179 }
180
181 static void
182 gtk_recent_chooser_dialog_set_property (GObject      *object,
183                                         guint         prop_id,
184                                         const GValue *value,
185                                         GParamSpec   *pspec)
186 {
187   GtkRecentChooserDialogPrivate *priv;
188   
189   priv = GTK_RECENT_CHOOSER_DIALOG_GET_PRIVATE (object);
190   
191   switch (prop_id)
192     {
193     case GTK_RECENT_CHOOSER_PROP_RECENT_MANAGER:
194       priv->manager = g_value_get_object (value);
195       break;
196     default:
197       g_object_set_property (G_OBJECT (priv->chooser), pspec->name, value);
198       break;
199     }
200 }
201
202 static void
203 gtk_recent_chooser_dialog_get_property (GObject      *object,
204                                         guint         prop_id,
205                                         GValue       *value,
206                                         GParamSpec   *pspec)
207 {
208   GtkRecentChooserDialogPrivate *priv;
209   
210   priv = GTK_RECENT_CHOOSER_DIALOG_GET_PRIVATE (object);
211   
212   g_object_get_property (G_OBJECT (priv->chooser), pspec->name, value);
213 }
214
215 static void
216 gtk_recent_chooser_dialog_finalize (GObject *object)
217 {
218   GtkRecentChooserDialog *dialog = GTK_RECENT_CHOOSER_DIALOG (object);
219  
220   dialog->priv->manager = NULL;
221   
222   G_OBJECT_CLASS (gtk_recent_chooser_dialog_parent_class)->finalize (object);
223 }
224
225 static void
226 gtk_recent_chooser_dialog_map (GtkWidget *widget)
227 {
228   GtkRecentChooserDialog *dialog = GTK_RECENT_CHOOSER_DIALOG (widget);
229   GtkRecentChooserDialogPrivate *priv = dialog->priv;
230   
231   if (!GTK_WIDGET_MAPPED (priv->chooser))
232     gtk_widget_map (priv->chooser);
233
234   GTK_WIDGET_CLASS (gtk_recent_chooser_dialog_parent_class)->map (widget);
235 }
236
237 static void
238 gtk_recent_chooser_dialog_unmap (GtkWidget *widget)
239 {
240   GtkRecentChooserDialog *dialog = GTK_RECENT_CHOOSER_DIALOG (widget);
241   GtkRecentChooserDialogPrivate *priv = dialog->priv;
242   
243   GTK_WIDGET_CLASS (gtk_recent_chooser_dialog_parent_class)->unmap (widget);
244   
245   gtk_widget_unmap (priv->chooser);
246 }
247
248 /* taken from gtkfilechooserdialog.c */
249 static void
250 gtk_recent_chooser_dialog_style_set (GtkWidget *widget,
251                                      GtkStyle  *old_style)
252 {
253   GtkDialog *dialog;
254
255   dialog = GTK_DIALOG (widget);
256
257   /* Override the style properties with HIG-compliant spacings.  Ugh.
258    * http://developer.gnome.org/projects/gup/hig/1.0/layout.html#layout-dialogs
259    * http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing
260    */
261
262   gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
263   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 24);
264
265   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
266   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
267   
268   if (GTK_WIDGET_CLASS (gtk_recent_chooser_dialog_parent_class)->style_set)
269     GTK_WIDGET_CLASS (gtk_recent_chooser_dialog_parent_class)->style_set (widget, old_style);
270 }
271
272 static GtkWidget *
273 gtk_recent_chooser_dialog_new_valist (const gchar      *title,
274                                       GtkWindow        *parent,
275                                       GtkRecentManager *manager,
276                                       const gchar      *first_button_text,
277                                       va_list           varargs)
278 {
279   GtkWidget *result;
280   const char *button_text = first_button_text;
281   gint response_id;
282   
283   result = g_object_new (GTK_TYPE_RECENT_CHOOSER_DIALOG,
284                          "title", title,
285                          "recent-manager", manager,
286                          NULL);
287   
288   if (parent)
289     gtk_window_set_transient_for (GTK_WINDOW (result), parent);
290   
291   while (button_text)
292     {
293       response_id = va_arg (varargs, gint);
294       gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
295       button_text = va_arg (varargs, const gchar *);
296     }
297   
298   return result;
299 }
300
301 /**
302  * gtk_recent_chooser_dialog_new:
303  * @title: Title of the dialog, or %NULL
304  * @parent: Transient parent of the dialog, or %NULL,
305  * @first_button_text: stock ID or text to go in the first button, or %NULL
306  * @Varargs: response ID for the first button, then additional (button, id)
307  *   pairs, ending with %NULL
308  *
309  * Creates a new #GtkRecentChooserDialog.  This function is analogous to
310  * gtk_dialog_new_with_buttons().
311  *
312  * Return value: a new #GtkRecentChooserDialog
313  *
314  * Since: 2.10
315  */
316 GtkWidget *
317 gtk_recent_chooser_dialog_new (const gchar *title,
318                                GtkWindow   *parent,
319                                const gchar *first_button_text,
320                                ...)
321 {
322   GtkWidget *result;
323   va_list varargs;
324   
325   va_start (varargs, first_button_text);
326   result = gtk_recent_chooser_dialog_new_valist (title,
327                                                  parent,
328                                                  NULL,
329                                                  first_button_text,
330                                                  varargs);
331   va_end (varargs);
332   
333   return result;
334 }
335
336 /**
337  * gtk_recent_chooser_dialog_new_for_manager:
338  * @title: Title of the dialog, or %NULL
339  * @parent: Transient parent of the dialog, or %NULL,
340  * @manager: a #GtkRecentManager
341  * @first_button_text: stock ID or text to go in the first button, or %NULL
342  * @Varargs: response ID for the first button, then additional (button, id)
343  *   pairs, ending with %NULL
344  *
345  * Creates a new #GtkRecentChooserDialog with a specified recent manager.
346  *
347  * This is useful if you have implemented your own recent manager, or if you
348  * have a customized instance of a #GtkRecentManager object.
349  *
350  * Return value: a new #GtkRecentChooserDialog
351  *
352  * Since: 2.10
353  */
354 GtkWidget *
355 gtk_recent_chooser_dialog_new_for_manager (const gchar      *title,
356                                            GtkWindow        *parent,
357                                            GtkRecentManager *manager,
358                                            const gchar      *first_button_text,
359                                            ...)
360 {
361   GtkWidget *result;
362   va_list varargs;
363   
364   va_start (varargs, first_button_text);
365   result = gtk_recent_chooser_dialog_new_valist (title,
366                                                  parent,
367                                                  manager,
368                                                  first_button_text,
369                                                  varargs);
370   va_end (varargs);
371   
372   return result;
373 }
374
375 #define __GTK_RECENT_CHOOSER_DIALOG_C__
376 #include "gtkaliasdef.c"