1 /*
2  * xed-tab-label.c
3  * This file is part of xed
4  *
5  * Copyright (C) 2010 - Paolo Borelli
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
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
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 #include <config.h>
24 #include <glib/gi18n.h>
25 #include <gtk/gtk.h>
26 
27 #include "xed-tab-label.h"
28 #include "xed-close-button.h"
29 
30 /* Signals */
31 enum
32 {
33     CLOSE_CLICKED,
34     LAST_SIGNAL
35 };
36 
37 enum
38 {
39     PROP_0,
40     PROP_TAB
41 };
42 
43 struct _XedTabLabelPrivate
44 {
45     XedTab *tab;
46 
47     GtkWidget *label_box;
48     GtkWidget *close_button;
49     GtkWidget *spinner;
50     GtkWidget *icon;
51     GtkWidget *label;
52 
53     gboolean close_button_sensitive;
54 };
55 
56 static guint signals[LAST_SIGNAL] = { 0 };
57 
G_DEFINE_TYPE_WITH_PRIVATE(XedTabLabel,xed_tab_label,GTK_TYPE_BOX)58 G_DEFINE_TYPE_WITH_PRIVATE (XedTabLabel, xed_tab_label, GTK_TYPE_BOX)
59 
60 static void
61 xed_tab_label_finalize (GObject *object)
62 {
63     G_OBJECT_CLASS (xed_tab_label_parent_class)->finalize (object);
64 }
65 
66 static void
xed_tab_label_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)67 xed_tab_label_set_property (GObject      *object,
68                             guint         prop_id,
69                             const GValue *value,
70                             GParamSpec   *pspec)
71 {
72     XedTabLabel *tab_label = XED_TAB_LABEL (object);
73 
74     switch (prop_id)
75     {
76         case PROP_TAB:
77             tab_label->priv->tab = XED_TAB (g_value_get_object (value));
78             break;
79 
80         default:
81             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
82             break;
83     }
84 }
85 
86 static void
xed_tab_label_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)87 xed_tab_label_get_property (GObject    *object,
88                             guint       prop_id,
89                             GValue     *value,
90                             GParamSpec *pspec)
91 {
92     XedTabLabel *tab_label = XED_TAB_LABEL (object);
93 
94     switch (prop_id)
95     {
96         case PROP_TAB:
97             g_value_set_object (value, tab_label->priv->tab);
98             break;
99 
100         default:
101             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
102             break;
103     }
104 }
105 
106 static void
close_button_clicked_cb(GtkWidget * widget,XedTabLabel * tab_label)107 close_button_clicked_cb (GtkWidget   *widget,
108                          XedTabLabel *tab_label)
109 {
110     g_signal_emit (tab_label, signals[CLOSE_CLICKED], 0, NULL);
111 }
112 
113 static void
sync_tip(XedTab * tab,XedTabLabel * tab_label)114 sync_tip (XedTab      *tab,
115           XedTabLabel *tab_label)
116 {
117     gchar *str;
118 
119     str = _xed_tab_get_tooltips (tab);
120     g_return_if_fail (str != NULL);
121 
122     gtk_widget_set_tooltip_markup (tab_label->priv->label_box, str);
123     g_free (str);
124 }
125 
126 static void
sync_name(XedTab * tab,GParamSpec * pspec,XedTabLabel * tab_label)127 sync_name (XedTab      *tab,
128            GParamSpec  *pspec,
129            XedTabLabel *tab_label)
130 {
131     gchar *str;
132 
133     g_return_if_fail (tab == tab_label->priv->tab);
134 
135     str = _xed_tab_get_name (tab);
136     g_return_if_fail (str != NULL);
137 
138     gtk_label_set_text (GTK_LABEL (tab_label->priv->label), str);
139     g_free (str);
140 
141     sync_tip (tab, tab_label);
142 }
143 
144 static void
sync_state(XedTab * tab,GParamSpec * pspec,XedTabLabel * tab_label)145 sync_state (XedTab      *tab,
146             GParamSpec  *pspec,
147             XedTabLabel *tab_label)
148 {
149     XedTabState  state;
150 
151     g_return_if_fail (tab == tab_label->priv->tab);
152 
153     state = xed_tab_get_state (tab);
154 
155     gtk_widget_set_sensitive (tab_label->priv->close_button,
156                               tab_label->priv->close_button_sensitive &&
157                               (state != XED_TAB_STATE_CLOSING) &&
158                               (state != XED_TAB_STATE_SAVING)  &&
159                               (state != XED_TAB_STATE_SHOWING_PRINT_PREVIEW) &&
160                               (state != XED_TAB_STATE_SAVING_ERROR));
161 
162     if ((state == XED_TAB_STATE_LOADING) ||
163         (state == XED_TAB_STATE_SAVING) ||
164         (state == XED_TAB_STATE_REVERTING))
165     {
166         gtk_widget_hide (tab_label->priv->icon);
167 
168         gtk_widget_show (tab_label->priv->spinner);
169         gtk_spinner_start (GTK_SPINNER (tab_label->priv->spinner));
170     }
171     else
172     {
173         GdkPixbuf *pixbuf;
174 
175         pixbuf = _xed_tab_get_icon (tab);
176 
177         if (pixbuf != NULL)
178         {
179             gtk_image_set_from_pixbuf (GTK_IMAGE (tab_label->priv->icon), pixbuf);
180             g_clear_object (&pixbuf);
181             gtk_widget_show (tab_label->priv->icon);
182         }
183         else
184         {
185             gtk_widget_hide (tab_label->priv->icon);
186         }
187 
188         gtk_widget_hide (tab_label->priv->spinner);
189         gtk_spinner_stop (GTK_SPINNER (tab_label->priv->spinner));
190     }
191 
192     /* sync tip since encoding is known only after load/save end */
193     sync_tip (tab, tab_label);
194 }
195 
196 static void
xed_tab_label_constructed(GObject * object)197 xed_tab_label_constructed (GObject *object)
198 {
199     XedTabLabel *tab_label = XED_TAB_LABEL (object);
200 
201     if (!tab_label->priv->tab)
202     {
203         g_critical ("The tab label was not properly constructed");
204         return;
205     }
206 
207     sync_name (tab_label->priv->tab, NULL, tab_label);
208     sync_state (tab_label->priv->tab, NULL, tab_label);
209 
210     g_signal_connect_object (tab_label->priv->tab, "notify::name",
211                              G_CALLBACK (sync_name), tab_label, 0);
212 
213     g_signal_connect_object (tab_label->priv->tab, "notify::state",
214                              G_CALLBACK (sync_state), tab_label, 0);
215 }
216 
217 static void
xed_tab_label_class_init(XedTabLabelClass * klass)218 xed_tab_label_class_init (XedTabLabelClass *klass)
219 {
220     GObjectClass *object_class = G_OBJECT_CLASS (klass);
221 
222     object_class->finalize = xed_tab_label_finalize;
223     object_class->set_property = xed_tab_label_set_property;
224     object_class->get_property = xed_tab_label_get_property;
225     object_class->constructed = xed_tab_label_constructed;
226 
227     signals[CLOSE_CLICKED] =
228         g_signal_new ("close-clicked",
229                       G_OBJECT_CLASS_TYPE (object_class),
230                       G_SIGNAL_RUN_LAST,
231                       G_STRUCT_OFFSET (XedTabLabelClass, close_clicked),
232                       NULL, NULL,
233                       g_cclosure_marshal_VOID__VOID,
234                       G_TYPE_NONE,
235                       0);
236 
237     g_object_class_install_property (object_class,
238                                      PROP_TAB,
239                                      g_param_spec_object ("tab",
240                                                           "Tab",
241                                                           "The XedTab",
242                                                           XED_TYPE_TAB,
243                                                           G_PARAM_READWRITE |
244                                                           G_PARAM_CONSTRUCT_ONLY));
245 }
246 
247 static void
xed_tab_label_init(XedTabLabel * tab_label)248 xed_tab_label_init (XedTabLabel *tab_label)
249 {
250     GtkWidget *hbox;
251     GtkWidget *close_button;
252     GtkWidget *spinner;
253     GtkWidget *icon;
254     GtkWidget *label;
255     GtkWidget *dummy_label;
256 
257     tab_label->priv = xed_tab_label_get_instance_private (tab_label);
258 
259     tab_label->priv->close_button_sensitive = TRUE;
260 
261     gtk_orientable_set_orientation (GTK_ORIENTABLE (tab_label), GTK_ORIENTATION_HORIZONTAL);
262 
263     hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
264     gtk_box_pack_start (GTK_BOX (tab_label), hbox, TRUE, TRUE, 0);
265 
266     close_button = xed_close_button_new ();
267     gtk_widget_set_tooltip_text (close_button, _("Close document"));
268     gtk_box_pack_start (GTK_BOX (tab_label), close_button, FALSE, FALSE, 0);
269     tab_label->priv->close_button = close_button;
270 
271     g_signal_connect (close_button, "clicked",
272                       G_CALLBACK (close_button_clicked_cb), tab_label);
273 
274     spinner = gtk_spinner_new ();
275     gtk_box_pack_start (GTK_BOX (hbox), spinner, FALSE, FALSE, 0);
276     tab_label->priv->spinner = spinner;
277 
278     /* setup icon, empty by default */
279     icon = gtk_image_new ();
280     gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
281     tab_label->priv->icon = icon;
282 
283     label = gtk_label_new ("");
284 
285     tab_label->priv->label_box = hbox;
286 
287     gtk_widget_set_halign (label, GTK_ALIGN_START);
288     gtk_widget_set_margin_start (label, 0);
289     gtk_widget_set_margin_end (label, 0);
290     gtk_widget_set_margin_top (label, 0);
291     gtk_widget_set_margin_bottom (label, 0);
292 
293     gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
294     tab_label->priv->label = label;
295 
296     dummy_label = gtk_label_new ("");
297     gtk_box_pack_start (GTK_BOX (hbox), dummy_label, TRUE, TRUE, 0);
298 
299     gtk_widget_show (hbox);
300     gtk_widget_show (close_button);
301     gtk_widget_show (icon);
302     gtk_widget_show (label);
303     gtk_widget_show (dummy_label);
304 }
305 
306 void
xed_tab_label_set_close_button_sensitive(XedTabLabel * tab_label,gboolean sensitive)307 xed_tab_label_set_close_button_sensitive (XedTabLabel *tab_label,
308                                           gboolean     sensitive)
309 {
310     XedTabState state;
311 
312     g_return_if_fail (XED_IS_TAB_LABEL (tab_label));
313 
314     sensitive = (sensitive != FALSE);
315 
316     if (sensitive == tab_label->priv->close_button_sensitive)
317     {
318         return;
319     }
320 
321     tab_label->priv->close_button_sensitive = sensitive;
322 
323     state = xed_tab_get_state (tab_label->priv->tab);
324 
325     gtk_widget_set_sensitive (tab_label->priv->close_button,
326                               tab_label->priv->close_button_sensitive &&
327                               (state != XED_TAB_STATE_CLOSING) &&
328                               (state != XED_TAB_STATE_SAVING)  &&
329                               (state != XED_TAB_STATE_SHOWING_PRINT_PREVIEW) &&
330                               (state != XED_TAB_STATE_PRINTING) &&
331                               (state != XED_TAB_STATE_PRINT_PREVIEWING) &&
332                               (state != XED_TAB_STATE_SAVING_ERROR));
333 }
334 
335 XedTab *
xed_tab_label_get_tab(XedTabLabel * tab_label)336 xed_tab_label_get_tab (XedTabLabel *tab_label)
337 {
338     g_return_val_if_fail (XED_IS_TAB_LABEL (tab_label), NULL);
339 
340     return tab_label->priv->tab;
341 }
342 
343 GtkWidget *
xed_tab_label_new(XedTab * tab)344 xed_tab_label_new (XedTab *tab)
345 {
346     XedTabLabel *tab_label;
347 
348     tab_label = g_object_new (XED_TYPE_TAB_LABEL,
349                               "homogeneous", FALSE,
350                               "tab", tab,
351                               NULL);
352 
353     return GTK_WIDGET (tab_label);
354 }
355