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