1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /* nemo-statusbar.c
3  *
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street - Suite 500,
18  * Boston, MA 02110-1335, USA.
19  */
20 
21 #include "nemo-statusbar.h"
22 
23 #include "nemo-actions.h"
24 
25 #include <config.h>
26 #include <glib/gi18n.h>
27 
28 enum {
29         LAST_SIGNAL
30 };
31 
32 enum {
33     PROP_WINDOW = 1,
34     NUM_PROPERTIES
35 };
36 
37 static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
38 
39 G_DEFINE_TYPE (NemoStatusBar, nemo_status_bar, GTK_TYPE_BOX);
40 
41 static void
nemo_status_bar_init(NemoStatusBar * bar)42 nemo_status_bar_init (NemoStatusBar *bar)
43 {
44     bar->window = NULL;
45 }
46 
47 static void
nemo_status_bar_set_property(GObject * object,guint arg_id,const GValue * value,GParamSpec * pspec)48 nemo_status_bar_set_property (GObject        *object,
49                               guint           arg_id,
50                               const GValue   *value,
51                               GParamSpec     *pspec)
52 {
53     NemoStatusBar *self = NEMO_STATUS_BAR (object);
54 
55     switch (arg_id) {
56         case PROP_WINDOW:
57             self->window = g_value_get_object (value);
58             break;
59         default:
60             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
61             break;
62     }
63 }
64 
65 static void
nemo_status_bar_get_property(GObject * object,guint arg_id,GValue * value,GParamSpec * pspec)66 nemo_status_bar_get_property (GObject      *object,
67                               guint         arg_id,
68                               GValue       *value,
69                               GParamSpec   *pspec)
70 {
71     NemoStatusBar *self = NEMO_STATUS_BAR (object);
72 
73     switch (arg_id) {
74         case PROP_WINDOW:
75             g_value_set_object (value, self->window);
76             break;
77         default:
78             G_OBJECT_WARN_INVALID_PROPERTY_ID (object, arg_id, pspec);
79             break;
80     }
81 }
82 
83 static void
nemo_status_bar_dispose(GObject * object)84 nemo_status_bar_dispose (GObject *object)
85 {
86     NemoStatusBar *bar = NEMO_STATUS_BAR (object);
87 
88     bar->window = NULL;
89 
90     G_OBJECT_CLASS (nemo_status_bar_parent_class)->dispose (object);
91 }
92 
93 static void
action_places_toggle_callback(GtkButton * button,NemoStatusBar * bar)94 action_places_toggle_callback (GtkButton *button, NemoStatusBar *bar)
95 {
96     nemo_window_set_sidebar_id (NEMO_WINDOW (bar->window), NEMO_WINDOW_SIDEBAR_PLACES);
97 
98     nemo_status_bar_sync_button_states (bar);
99 }
100 
101 static void
action_treeview_toggle_callback(GtkButton * button,NemoStatusBar * bar)102 action_treeview_toggle_callback (GtkButton *button, NemoStatusBar *bar)
103 {
104     nemo_window_set_sidebar_id (NEMO_WINDOW (bar->window), NEMO_WINDOW_SIDEBAR_TREE);
105 
106     nemo_status_bar_sync_button_states (bar);
107 }
108 
109 static void
action_show_sidebar_callback(GtkButton * button,NemoStatusBar * bar)110 action_show_sidebar_callback (GtkButton *button, NemoStatusBar *bar)
111 {
112     nemo_window_show_sidebar (bar->window);
113 }
114 
115 static void
action_hide_sidebar_callback(GtkButton * button,NemoStatusBar * bar)116 action_hide_sidebar_callback (GtkButton *button, NemoStatusBar *bar)
117 {
118     nemo_window_hide_sidebar (bar->window);
119 }
120 
121 static void
sidebar_state_changed_cb(gpointer pointer,gboolean state,gpointer user_data)122 sidebar_state_changed_cb (gpointer pointer, gboolean state, gpointer user_data)
123 {
124     nemo_status_bar_sync_button_states (NEMO_STATUS_BAR (user_data));
125 }
126 
127 static void
sidebar_type_changed_cb(gpointer pointer,const gchar * sidebar_id,gpointer user_data)128 sidebar_type_changed_cb (gpointer pointer, const gchar *sidebar_id, gpointer user_data)
129 {
130     nemo_status_bar_sync_button_states (NEMO_STATUS_BAR (user_data));
131 }
132 
133 static void
on_slider_changed_cb(GtkWidget * zoom_slider,gpointer user_data)134 on_slider_changed_cb (GtkWidget *zoom_slider, gpointer user_data)
135 {
136     NemoStatusBar *bar = NEMO_STATUS_BAR (user_data);
137     gdouble val = gtk_range_get_value (GTK_RANGE (zoom_slider));
138 
139     NemoWindowSlot *slot = nemo_window_get_active_slot (bar->window);
140 
141     if (!NEMO_IS_WINDOW_SLOT (slot))
142         return;
143 
144     NemoView *view = slot->content_view;
145 
146     if (!NEMO_IS_VIEW (view))
147         return;
148 
149     nemo_view_zoom_to_level (view, (int) val);
150 }
151 
152 #define SLIDER_WIDTH 100
153 
154 static void
nemo_status_bar_constructed(GObject * object)155 nemo_status_bar_constructed (GObject *object)
156 {
157     NemoStatusBar *bar = NEMO_STATUS_BAR (object);
158     G_OBJECT_CLASS (nemo_status_bar_parent_class)->constructed (object);
159 
160     GtkWidget *statusbar = gtk_statusbar_new ();
161     GtkStyleContext *context;
162 
163     bar->real_statusbar = statusbar;
164 
165     GtkIconSize size = gtk_icon_size_from_name (NEMO_STATUSBAR_ICON_SIZE_NAME);
166 
167     context = gtk_widget_get_style_context (GTK_WIDGET (bar));
168     gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOOLBAR);
169     gtk_container_set_border_width (GTK_CONTAINER (bar), 2);
170 
171     GtkWidget *button, *icon;
172 
173     button = gtk_toggle_button_new ();
174     icon = gtk_image_new_from_icon_name ("sidebar-places-symbolic", size);
175     gtk_button_set_image (GTK_BUTTON (button), icon);
176     gtk_widget_set_tooltip_text (GTK_WIDGET (button), _("Show Places"));
177     bar->places_button = button;
178     gtk_box_pack_start (GTK_BOX (bar), button, FALSE, FALSE, 2);
179     g_signal_connect (GTK_BUTTON (button), "clicked",
180                       G_CALLBACK (action_places_toggle_callback), bar);
181 
182     button = gtk_toggle_button_new ();
183     icon = gtk_image_new_from_icon_name ("sidebar-tree-symbolic", size);
184     gtk_button_set_image (GTK_BUTTON (button), icon);
185     gtk_widget_set_tooltip_text (GTK_WIDGET (button), _("Show Treeview"));
186     bar->tree_button = button;
187     gtk_box_pack_start (GTK_BOX (bar), button, FALSE, FALSE, 2);
188     g_signal_connect (GTK_BUTTON (button), "clicked",
189                       G_CALLBACK (action_treeview_toggle_callback), bar);
190 
191     GtkWidget *sep = gtk_separator_new (GTK_ORIENTATION_VERTICAL);
192     gtk_box_pack_start (GTK_BOX (bar), sep, FALSE, FALSE, 6);
193     gtk_widget_show (sep);
194     bar->separator = sep;
195 
196     button = gtk_button_new ();
197     icon = gtk_image_new_from_icon_name ("sidebar-hide-symbolic", size);
198     gtk_button_set_image (GTK_BUTTON (button), icon);
199     gtk_widget_set_tooltip_text (GTK_WIDGET (button), _("Hide the Sidebar (F9)"));
200     bar->hide_button = button;
201     gtk_box_pack_start (GTK_BOX (bar), button, FALSE, FALSE, 2);
202     g_signal_connect (GTK_BUTTON (button), "clicked",
203                       G_CALLBACK (action_hide_sidebar_callback), bar);
204 
205     button = gtk_button_new ();
206     icon = gtk_image_new_from_icon_name ("sidebar-show-symbolic", size);
207     gtk_button_set_image (GTK_BUTTON (button), icon);
208     gtk_widget_set_tooltip_text (GTK_WIDGET (button), _("Show the Sidebar (F9)"));
209     bar->show_button = button;
210     gtk_box_pack_start (GTK_BOX (bar), button, FALSE, FALSE, 2);
211     g_signal_connect (GTK_BUTTON (button), "clicked",
212                       G_CALLBACK (action_show_sidebar_callback), bar);
213 
214     gtk_box_pack_start (GTK_BOX (bar), statusbar, TRUE, TRUE, 10);
215     gtk_widget_set_margin_top (GTK_WIDGET (statusbar), 0);
216     gtk_widget_set_margin_bottom (GTK_WIDGET (statusbar), 0);
217 
218     GtkWidget *zoom_slider = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL,
219                                                        (gdouble) NEMO_ZOOM_LEVEL_SMALLEST,
220                                                        (gdouble) NEMO_ZOOM_LEVEL_LARGEST,
221                                                        1.0);
222     gtk_widget_set_tooltip_text (GTK_WIDGET (zoom_slider), _("Adjust zoom level"));
223     bar->zoom_slider = zoom_slider;
224 
225     gtk_box_pack_start (GTK_BOX (bar), zoom_slider, FALSE, FALSE, 2);
226 
227     gtk_widget_set_size_request (GTK_WIDGET (zoom_slider), SLIDER_WIDTH, 0);
228     gtk_scale_set_draw_value (GTK_SCALE (zoom_slider), FALSE);
229     gtk_range_set_increments (GTK_RANGE (zoom_slider), 1.0, 1.0);
230     gtk_range_set_round_digits (GTK_RANGE (zoom_slider), 0);
231 
232     gtk_widget_show_all (GTK_WIDGET (bar));
233 
234     g_signal_connect_object (NEMO_WINDOW (bar->window), "notify::show-sidebar",
235                              G_CALLBACK (sidebar_state_changed_cb), bar, G_CONNECT_AFTER);
236 
237     g_signal_connect_object (NEMO_WINDOW (bar->window), "notify::sidebar-view-id",
238                            G_CALLBACK (sidebar_type_changed_cb), bar, G_CONNECT_AFTER);
239 
240     g_signal_connect (GTK_RANGE (zoom_slider), "value-changed",
241                       G_CALLBACK (on_slider_changed_cb), bar);
242 
243     GtkWidget *cont = gtk_statusbar_get_message_area (GTK_STATUSBAR (statusbar));
244 
245     GList *children = gtk_container_get_children (GTK_CONTAINER (cont));
246 
247     gtk_box_set_child_packing (GTK_BOX (cont),
248                                GTK_WIDGET (children->data),
249                                TRUE, FALSE, 10, GTK_PACK_START);
250 
251     g_list_free (children);
252 
253     nemo_status_bar_sync_button_states (bar);
254 }
255 
256 
257 static void
nemo_status_bar_class_init(NemoStatusBarClass * status_bar_class)258 nemo_status_bar_class_init (NemoStatusBarClass *status_bar_class)
259 {
260     GObjectClass *oclass;
261 
262     oclass = G_OBJECT_CLASS (status_bar_class);
263 
264     oclass->set_property = nemo_status_bar_set_property;
265     oclass->get_property = nemo_status_bar_get_property;
266 
267     oclass->dispose = nemo_status_bar_dispose;
268     oclass->constructed = nemo_status_bar_constructed;
269 
270     properties[PROP_WINDOW] = g_param_spec_object ("window",
271                                                    "The NemoWindow",
272                                                    "The parent NemoWindow",
273                                                    NEMO_TYPE_WINDOW,
274                                                    G_PARAM_READWRITE |
275                                                    G_PARAM_CONSTRUCT_ONLY |
276                                                    G_PARAM_STATIC_STRINGS);
277 
278     g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
279 }
280 
281 GtkWidget *
nemo_status_bar_new(NemoWindow * window)282 nemo_status_bar_new (NemoWindow *window)
283 {
284     return g_object_new (NEMO_TYPE_STATUS_BAR,
285                          "orientation", GTK_ORIENTATION_HORIZONTAL,
286                          "spacing", 0,
287                          "window", window,
288                          NULL);
289 }
290 
291 GtkWidget *
nemo_status_bar_get_real_statusbar(NemoStatusBar * bar)292 nemo_status_bar_get_real_statusbar (NemoStatusBar *bar)
293 {
294     return bar->real_statusbar;
295 }
296 
297 void
nemo_status_bar_sync_button_states(NemoStatusBar * bar)298 nemo_status_bar_sync_button_states (NemoStatusBar *bar)
299 {
300     const gchar *sidebar_id = nemo_window_get_sidebar_id (NEMO_WINDOW (bar->window));
301 
302     gboolean sidebar_visible = nemo_window_get_show_sidebar (NEMO_WINDOW (bar->window));
303 
304     if (sidebar_visible) {
305         gtk_widget_show (bar->tree_button);
306         gtk_widget_show (bar->places_button);
307         gtk_widget_show (bar->separator);
308         gtk_widget_show (bar->hide_button);
309         gtk_widget_hide (bar->show_button);
310     } else {
311         gtk_widget_hide (bar->tree_button);
312         gtk_widget_hide (bar->places_button);
313         gtk_widget_hide (bar->hide_button);
314         gtk_widget_hide (bar->separator);
315         gtk_widget_show (bar->show_button);
316     }
317 
318     g_signal_handlers_block_by_func (GTK_BUTTON (bar->tree_button), action_treeview_toggle_callback, bar);
319     if (g_strcmp0 (sidebar_id, NEMO_WINDOW_SIDEBAR_TREE) == 0) {
320         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bar->tree_button), TRUE);
321     } else {
322         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bar->tree_button), FALSE);
323     }
324     g_signal_handlers_unblock_by_func (GTK_BUTTON (bar->tree_button), action_treeview_toggle_callback, bar);
325 
326 
327     g_signal_handlers_block_by_func (GTK_BUTTON (bar->places_button), action_places_toggle_callback, bar);
328 
329     if (g_strcmp0 (sidebar_id, NEMO_WINDOW_SIDEBAR_PLACES) == 0) {
330         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bar->places_button), TRUE);
331     } else {
332         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bar->places_button), FALSE);
333     }
334     g_signal_handlers_unblock_by_func (GTK_BUTTON (bar->places_button), action_places_toggle_callback, bar);
335 }
336 
337 void
nemo_status_bar_sync_zoom_widgets(NemoStatusBar * bar)338 nemo_status_bar_sync_zoom_widgets (NemoStatusBar *bar)
339 {
340 
341     NemoWindowSlot *slot = nemo_window_get_active_slot (bar->window);
342 
343     if (!NEMO_IS_WINDOW_SLOT (slot))
344         return;
345 
346     NemoView *view = slot->content_view;
347 
348     if (!NEMO_IS_VIEW (view))
349         return;
350 
351     NemoZoomLevel zoom_level = nemo_view_get_zoom_level (NEMO_VIEW (view));
352 
353     g_signal_handlers_block_by_func (GTK_RANGE (bar->zoom_slider), on_slider_changed_cb, bar);
354 
355     gtk_range_set_value (GTK_RANGE (bar->zoom_slider), (double) zoom_level);
356 
357     g_signal_handlers_unblock_by_func (GTK_RANGE (bar->zoom_slider), on_slider_changed_cb, bar);
358 }
359