~ubuntu-branches/debian/stretch/gnome-builder/stretch

« back to all changes in this revision

Viewing changes to contrib/nautilus/nautilus-floating-bar.c

  • Committer: Package Import Robot
  • Author(s): Andreas Henriksson
  • Date: 2015-10-11 12:38:45 UTC
  • Revision ID: package-import@ubuntu.com-20151011123845-a0hvkz01se0p1p5a
Tags: upstream-3.16.3
ImportĀ upstreamĀ versionĀ 3.16.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 
2
 
 
3
/* Nautilus - Floating status bar.
 
4
 *
 
5
 * Copyright (C) 2011 Red Hat Inc.
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Library General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library 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
 * Library General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Library General Public
 
18
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 
19
 *
 
20
 * Authors: Cosimo Cecchi <cosimoc@redhat.com>
 
21
 *
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
 
 
26
#include <string.h>
 
27
 
 
28
#include "nautilus-floating-bar.h"
 
29
 
 
30
struct _NautilusFloatingBar {
 
31
        GtkBox  parent_instance;
 
32
 
 
33
        gchar *primary_label;
 
34
        gchar *details_label;
 
35
 
 
36
        GtkWidget *primary_label_widget;
 
37
        GtkWidget *details_label_widget;
 
38
        GtkWidget *spinner;
 
39
        gboolean show_spinner;
 
40
        gboolean is_interactive;
 
41
};
 
42
 
 
43
enum {
 
44
        PROP_PRIMARY_LABEL = 1,
 
45
        PROP_DETAILS_LABEL,
 
46
        PROP_SHOW_SPINNER,
 
47
        NUM_PROPERTIES
 
48
};
 
49
 
 
50
enum {
 
51
        ACTION,
 
52
        NUM_SIGNALS
 
53
};
 
54
 
 
55
static GParamSpec *properties[NUM_PROPERTIES] = { NULL, };
 
56
static guint signals[NUM_SIGNALS] = { 0, };
 
57
 
 
58
G_DEFINE_TYPE (NautilusFloatingBar, nautilus_floating_bar,
 
59
               GTK_TYPE_BOX);
 
60
 
 
61
static void
 
62
action_button_clicked_cb (GtkButton *button,
 
63
                          NautilusFloatingBar *self)
 
64
{
 
65
        gint action_id;
 
66
 
 
67
        action_id = GPOINTER_TO_INT
 
68
                (g_object_get_data (G_OBJECT (button), "action-id"));
 
69
 
 
70
        g_signal_emit (self, signals[ACTION], 0, action_id);
 
71
}
 
72
 
 
73
static void
 
74
nautilus_floating_bar_finalize (GObject *obj)
 
75
{
 
76
        NautilusFloatingBar *self = NAUTILUS_FLOATING_BAR (obj);
 
77
 
 
78
        g_free (self->primary_label);
 
79
        g_free (self->details_label);
 
80
 
 
81
        G_OBJECT_CLASS (nautilus_floating_bar_parent_class)->finalize (obj);
 
82
}
 
83
 
 
84
static void
 
85
nautilus_floating_bar_get_property (GObject *object,
 
86
                                    guint property_id,
 
87
                                    GValue *value,
 
88
                                    GParamSpec *pspec)
 
89
{
 
90
        NautilusFloatingBar *self = NAUTILUS_FLOATING_BAR (object);
 
91
 
 
92
        switch (property_id) {
 
93
        case PROP_PRIMARY_LABEL:
 
94
                g_value_set_string (value, self->primary_label);
 
95
                break;
 
96
        case PROP_DETAILS_LABEL:
 
97
                g_value_set_string (value, self->details_label);
 
98
                break;
 
99
        case PROP_SHOW_SPINNER:
 
100
                g_value_set_boolean (value, self->show_spinner);
 
101
                break;
 
102
        default:
 
103
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
104
                break;
 
105
        }
 
106
}
 
107
 
 
108
static void
 
109
nautilus_floating_bar_set_property (GObject *object,
 
110
                                    guint property_id,
 
111
                                    const GValue *value,
 
112
                                    GParamSpec *pspec)
 
113
{
 
114
        NautilusFloatingBar *self = NAUTILUS_FLOATING_BAR (object);
 
115
 
 
116
        switch (property_id) {
 
117
        case PROP_PRIMARY_LABEL:
 
118
                nautilus_floating_bar_set_primary_label (self, g_value_get_string (value));
 
119
                break;
 
120
        case PROP_DETAILS_LABEL:
 
121
                nautilus_floating_bar_set_details_label (self, g_value_get_string (value));
 
122
                break;
 
123
        case PROP_SHOW_SPINNER:
 
124
                nautilus_floating_bar_set_show_spinner (self, g_value_get_boolean (value));
 
125
                break;
 
126
        default:
 
127
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
128
                break;
 
129
        }
 
130
}
 
131
 
 
132
static void
 
133
update_labels (NautilusFloatingBar *self)
 
134
{
 
135
        gboolean primary_visible, details_visible;
 
136
 
 
137
        primary_visible = (self->primary_label != NULL) &&
 
138
                (strlen (self->primary_label) > 0);
 
139
        details_visible = (self->details_label != NULL) &&
 
140
                (strlen (self->details_label) > 0);
 
141
 
 
142
        gtk_label_set_text (GTK_LABEL (self->primary_label_widget),
 
143
                            self->primary_label);
 
144
        gtk_widget_set_visible (self->primary_label_widget, primary_visible);
 
145
 
 
146
        gtk_label_set_text (GTK_LABEL (self->details_label_widget),
 
147
                            self->details_label);
 
148
        gtk_widget_set_visible (self->details_label_widget, details_visible);
 
149
}
 
150
 
 
151
static gboolean
 
152
overlay_enter_notify_cb (GtkWidget        *parent,
 
153
                         GdkEventCrossing *event,
 
154
                         gpointer          user_data)
 
155
{
 
156
#if 0
 
157
        GtkWidget *widget = user_data;
 
158
 
 
159
        if (event->window != gtk_widget_get_window (widget)) {
 
160
                return FALSE;
 
161
        }
 
162
 
 
163
        if (NAUTILUS_FLOATING_BAR (widget)->priv->is_interactive) {
 
164
                return FALSE;
 
165
        }
 
166
 
 
167
        if (gtk_widget_get_halign (widget) == GTK_ALIGN_START) {
 
168
                gtk_widget_set_halign (widget, GTK_ALIGN_END);
 
169
        } else {
 
170
                gtk_widget_set_halign (widget, GTK_ALIGN_START);
 
171
        }
 
172
 
 
173
        gtk_widget_queue_resize (widget);
 
174
#endif
 
175
 
 
176
        return FALSE;
 
177
}
 
178
 
 
179
static void
 
180
nautilus_floating_bar_parent_set (GtkWidget *widget,
 
181
                                  GtkWidget *old_parent)
 
182
{
 
183
        GtkWidget *parent;
 
184
 
 
185
        parent = gtk_widget_get_parent (widget);
 
186
 
 
187
        if (old_parent != NULL) {
 
188
                g_signal_handlers_disconnect_by_func (old_parent,
 
189
                                                      overlay_enter_notify_cb, widget);
 
190
        }
 
191
 
 
192
        if (parent != NULL) {
 
193
                g_signal_connect (parent, "enter-notify-event",
 
194
                                  G_CALLBACK (overlay_enter_notify_cb), widget);
 
195
        }
 
196
}
 
197
 
 
198
static void
 
199
nautilus_floating_bar_show (GtkWidget *widget)
 
200
{
 
201
        NautilusFloatingBar *self = NAUTILUS_FLOATING_BAR (widget);
 
202
 
 
203
        GTK_WIDGET_CLASS (nautilus_floating_bar_parent_class)->show (widget);
 
204
 
 
205
        if (self->show_spinner) {
 
206
                gtk_spinner_start (GTK_SPINNER (self->spinner));
 
207
        }
 
208
}
 
209
 
 
210
static void
 
211
nautilus_floating_bar_hide (GtkWidget *widget)
 
212
{
 
213
        NautilusFloatingBar *self = NAUTILUS_FLOATING_BAR (widget);
 
214
 
 
215
        GTK_WIDGET_CLASS (nautilus_floating_bar_parent_class)->hide (widget);
 
216
 
 
217
        gtk_spinner_stop (GTK_SPINNER (self->spinner));
 
218
}
 
219
 
 
220
static void
 
221
get_padding_and_border (GtkWidget *widget,
 
222
                        GtkBorder *border)
 
223
{
 
224
  GtkStyleContext *context;
 
225
  GtkStateFlags state;
 
226
  GtkBorder tmp;
 
227
 
 
228
  context = gtk_widget_get_style_context (widget);
 
229
  state = gtk_widget_get_state_flags (widget);
 
230
 
 
231
  gtk_style_context_get_padding (context, state, border);
 
232
  gtk_style_context_get_border (context, state, &tmp);
 
233
  border->top += tmp.top;
 
234
  border->right += tmp.right;
 
235
  border->bottom += tmp.bottom;
 
236
  border->left += tmp.left;
 
237
}
 
238
 
 
239
static void
 
240
nautilus_floating_bar_get_preferred_width (GtkWidget *widget,
 
241
                                           gint      *minimum_size,
 
242
                                           gint      *natural_size)
 
243
{
 
244
        GtkBorder border;
 
245
 
 
246
        get_padding_and_border (widget, &border);
 
247
 
 
248
        GTK_WIDGET_CLASS (nautilus_floating_bar_parent_class)->get_preferred_width (widget,
 
249
                                                                                    minimum_size,
 
250
                                                                                    natural_size);
 
251
 
 
252
        *minimum_size += border.left + border.right;
 
253
        *natural_size += border.left + border.right;
 
254
}
 
255
 
 
256
static void
 
257
nautilus_floating_bar_get_preferred_width_for_height (GtkWidget *widget,
 
258
                                                      gint       height,
 
259
                                                      gint      *minimum_size,
 
260
                                                      gint      *natural_size)
 
261
{
 
262
        GtkBorder border;
 
263
 
 
264
        get_padding_and_border (widget, &border);
 
265
 
 
266
        GTK_WIDGET_CLASS (nautilus_floating_bar_parent_class)->get_preferred_width_for_height (widget,
 
267
                                                                                               height,
 
268
                                                                                               minimum_size,
 
269
                                                                                               natural_size);
 
270
 
 
271
        *minimum_size += border.left + border.right;
 
272
        *natural_size += border.left + border.right;
 
273
}
 
274
 
 
275
static void
 
276
nautilus_floating_bar_get_preferred_height (GtkWidget *widget,
 
277
                                            gint      *minimum_size,
 
278
                                            gint      *natural_size)
 
279
{
 
280
        GtkBorder border;
 
281
 
 
282
        get_padding_and_border (widget, &border);
 
283
 
 
284
        GTK_WIDGET_CLASS (nautilus_floating_bar_parent_class)->get_preferred_height (widget,
 
285
                                                                                     minimum_size,
 
286
                                                                                     natural_size);
 
287
 
 
288
        *minimum_size += border.top + border.bottom;
 
289
        *natural_size += border.top + border.bottom;
 
290
}
 
291
 
 
292
static void
 
293
nautilus_floating_bar_get_preferred_height_for_width (GtkWidget *widget,
 
294
                                                      gint       width,
 
295
                                                      gint      *minimum_size,
 
296
                                                      gint      *natural_size)
 
297
{
 
298
        GtkBorder border;
 
299
 
 
300
        get_padding_and_border (widget, &border);
 
301
 
 
302
        GTK_WIDGET_CLASS (nautilus_floating_bar_parent_class)->get_preferred_height_for_width (widget,
 
303
                                                                                               width,
 
304
                                                                                               minimum_size,
 
305
                                                                                               natural_size);
 
306
 
 
307
        *minimum_size += border.top + border.bottom;
 
308
        *natural_size += border.top + border.bottom;
 
309
}
 
310
 
 
311
static void
 
312
nautilus_floating_bar_constructed (GObject *obj)
 
313
{
 
314
        NautilusFloatingBar *self = NAUTILUS_FLOATING_BAR (obj);
 
315
        GtkWidget *w, *box, *labels_box;
 
316
 
 
317
        G_OBJECT_CLASS (nautilus_floating_bar_parent_class)->constructed (obj);
 
318
 
 
319
        box = GTK_WIDGET (obj);
 
320
 
 
321
        w = gtk_spinner_new ();
 
322
        gtk_box_pack_start (GTK_BOX (box), w, FALSE, FALSE, 0);
 
323
        gtk_widget_set_visible (w, self->show_spinner);
 
324
        self->spinner = w;
 
325
 
 
326
        gtk_widget_set_size_request (w, 16, 16);
 
327
        gtk_widget_set_margin_start (w, 8);
 
328
 
 
329
        labels_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
 
330
        gtk_box_pack_start (GTK_BOX (box), labels_box, TRUE, TRUE, 0);
 
331
        g_object_set (labels_box,
 
332
                      "margin-top", 2,
 
333
                      "margin-bottom", 2,
 
334
                      "margin-start", 12,
 
335
                      "margin-end", 12,
 
336
                      NULL);
 
337
        gtk_widget_show (labels_box);
 
338
 
 
339
        w = gtk_label_new (NULL);
 
340
        gtk_label_set_ellipsize (GTK_LABEL (w), PANGO_ELLIPSIZE_MIDDLE);
 
341
        gtk_label_set_single_line_mode (GTK_LABEL (w), TRUE);
 
342
        gtk_container_add (GTK_CONTAINER (labels_box), w);
 
343
        self->primary_label_widget = w;
 
344
        gtk_widget_show (w);
 
345
 
 
346
        w = gtk_label_new (NULL);
 
347
        gtk_label_set_single_line_mode (GTK_LABEL (w), TRUE);
 
348
        gtk_container_add (GTK_CONTAINER (labels_box), w);
 
349
        self->details_label_widget = w;
 
350
        gtk_widget_show (w);
 
351
}
 
352
 
 
353
static void
 
354
nautilus_floating_bar_init (NautilusFloatingBar *self)
 
355
{
 
356
        GtkStyleContext *context;
 
357
 
 
358
        context = gtk_widget_get_style_context (GTK_WIDGET (self));
 
359
        gtk_style_context_add_class (context, "floating-bar");
 
360
}
 
361
 
 
362
static void
 
363
nautilus_floating_bar_class_init (NautilusFloatingBarClass *klass)
 
364
{
 
365
        GObjectClass *oclass = G_OBJECT_CLASS (klass);
 
366
        GtkWidgetClass *wclass = GTK_WIDGET_CLASS (klass);
 
367
 
 
368
        oclass->constructed = nautilus_floating_bar_constructed;
 
369
        oclass->set_property = nautilus_floating_bar_set_property;
 
370
        oclass->get_property = nautilus_floating_bar_get_property;
 
371
        oclass->finalize = nautilus_floating_bar_finalize;
 
372
 
 
373
        wclass->get_preferred_width = nautilus_floating_bar_get_preferred_width;
 
374
        wclass->get_preferred_width_for_height = nautilus_floating_bar_get_preferred_width_for_height;
 
375
        wclass->get_preferred_height = nautilus_floating_bar_get_preferred_height;
 
376
        wclass->get_preferred_height_for_width = nautilus_floating_bar_get_preferred_height_for_width;
 
377
        wclass->show = nautilus_floating_bar_show;
 
378
        wclass->hide = nautilus_floating_bar_hide;
 
379
        wclass->parent_set = nautilus_floating_bar_parent_set;
 
380
 
 
381
        properties[PROP_PRIMARY_LABEL] =
 
382
                g_param_spec_string ("primary-label",
 
383
                                     "Bar's primary label",
 
384
                                     "Primary label displayed by the bar",
 
385
                                     NULL,
 
386
                                     G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
 
387
        properties[PROP_DETAILS_LABEL] =
 
388
                g_param_spec_string ("details-label",
 
389
                                     "Bar's details label",
 
390
                                     "Details label displayed by the bar",
 
391
                                     NULL,
 
392
                                     G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
 
393
        properties[PROP_SHOW_SPINNER] =
 
394
                g_param_spec_boolean ("show-spinner",
 
395
                                      "Show spinner",
 
396
                                      "Whether a spinner should be shown in the floating bar",
 
397
                                      FALSE,
 
398
                                      G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
399
 
 
400
        signals[ACTION] =
 
401
                g_signal_new ("action",
 
402
                              G_TYPE_FROM_CLASS (klass),
 
403
                              G_SIGNAL_RUN_LAST,
 
404
                              0, NULL, NULL,
 
405
                              g_cclosure_marshal_VOID__INT,
 
406
                              G_TYPE_NONE, 1,
 
407
                              G_TYPE_INT);
 
408
 
 
409
        g_object_class_install_properties (oclass, NUM_PROPERTIES, properties);
 
410
}
 
411
 
 
412
void
 
413
nautilus_floating_bar_set_primary_label (NautilusFloatingBar *self,
 
414
                                         const gchar *label)
 
415
{
 
416
        if (g_strcmp0 (self->primary_label, label) != 0) {
 
417
                g_free (self->primary_label);
 
418
                self->primary_label = g_strdup (label);
 
419
 
 
420
                g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PRIMARY_LABEL]);
 
421
 
 
422
                update_labels (self);
 
423
        }
 
424
}
 
425
 
 
426
void
 
427
nautilus_floating_bar_set_details_label (NautilusFloatingBar *self,
 
428
                                         const gchar *label)
 
429
{
 
430
        if (g_strcmp0 (self->details_label, label) != 0) {
 
431
                g_free (self->details_label);
 
432
                self->details_label = g_strdup (label);
 
433
 
 
434
                g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_DETAILS_LABEL]);
 
435
 
 
436
                update_labels (self);
 
437
        }
 
438
}
 
439
 
 
440
void
 
441
nautilus_floating_bar_set_labels (NautilusFloatingBar *self,
 
442
                                  const gchar *primary_label,
 
443
                                  const gchar *details_label)
 
444
{
 
445
        nautilus_floating_bar_set_primary_label (self, primary_label);
 
446
        nautilus_floating_bar_set_details_label (self, details_label);
 
447
}
 
448
 
 
449
void
 
450
nautilus_floating_bar_set_show_spinner (NautilusFloatingBar *self,
 
451
                                        gboolean show_spinner)
 
452
{
 
453
        if (self->show_spinner != show_spinner) {
 
454
                self->show_spinner = show_spinner;
 
455
                g_object_set (self->spinner, "active", show_spinner, NULL);
 
456
                gtk_widget_set_visible (self->spinner,
 
457
                                        show_spinner);
 
458
 
 
459
                g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SHOW_SPINNER]);
 
460
        }
 
461
}
 
462
 
 
463
GtkWidget *
 
464
nautilus_floating_bar_new (const gchar *primary_label,
 
465
                           const gchar *details_label,
 
466
                           gboolean show_spinner)
 
467
{
 
468
        return g_object_new (NAUTILUS_TYPE_FLOATING_BAR,
 
469
                             "primary-label", primary_label,
 
470
                             "details-label", details_label,
 
471
                             "show-spinner", show_spinner,
 
472
                             "orientation", GTK_ORIENTATION_HORIZONTAL,
 
473
                             "spacing", 8,
 
474
                             NULL);
 
475
}
 
476
 
 
477
void
 
478
nautilus_floating_bar_add_action (NautilusFloatingBar *self,
 
479
                                  const gchar *icon_name,
 
480
                                  gint action_id)
 
481
{
 
482
        GtkWidget *w, *button;
 
483
 
 
484
        w = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
 
485
        gtk_widget_show (w);
 
486
 
 
487
        button = gtk_button_new ();
 
488
        gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE);
 
489
        gtk_button_set_image (GTK_BUTTON (button), w);
 
490
        gtk_box_pack_end (GTK_BOX (self), button, FALSE, FALSE, 0);
 
491
        gtk_widget_show (button);
 
492
 
 
493
        g_object_set_data (G_OBJECT (button), "action-id",
 
494
                           GINT_TO_POINTER (action_id));
 
495
 
 
496
        g_signal_connect (button, "clicked",
 
497
                          G_CALLBACK (action_button_clicked_cb), self);
 
498
 
 
499
        self->is_interactive = TRUE;
 
500
}
 
501
 
 
502
void
 
503
nautilus_floating_bar_cleanup_actions (NautilusFloatingBar *self)
 
504
{
 
505
        GtkWidget *widget;
 
506
        GList *children, *l;
 
507
        gpointer data;
 
508
 
 
509
        children = gtk_container_get_children (GTK_CONTAINER (self));
 
510
        l = children;
 
511
 
 
512
        while (l != NULL) {
 
513
                widget = l->data;
 
514
                data = g_object_get_data (G_OBJECT (widget), "action-id");
 
515
                l = l->next;
 
516
 
 
517
                if (data != NULL) {
 
518
                        /* destroy this */
 
519
                        gtk_widget_destroy (widget);
 
520
                }
 
521
        }
 
522
 
 
523
        g_list_free (children);
 
524
 
 
525
        self->is_interactive = FALSE;
 
526
}