~ubuntu-branches/ubuntu/dapper/vino/dapper

« back to all changes in this revision

Viewing changes to capplet/vino-url.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2004-10-12 19:36:40 UTC
  • Revision ID: james.westby@ubuntu.com-20041012193640-ybetkwuqt7e04dke
Tags: upstream-2.8.1
ImportĀ upstreamĀ versionĀ 2.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* 
 
2
 * Copyright (C) 2003 Sun Microsystems, Inc.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Library General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library General Public
 
15
 * License along with this library; if not, write to the
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA 02111-1307, USA.
 
18
 *
 
19
 * Authors:
 
20
 *      Mark McLoughlin <mark@skynet.ie>
 
21
 */
 
22
 
 
23
#include <config.h>
 
24
 
 
25
#include "vino-url.h"
 
26
 
 
27
#include <libintl.h>
 
28
#include <gtk/gtktooltips.h>
 
29
#include <libgnomeui/gnome-url.h>
 
30
 
 
31
#define _(x) dgettext (GETTEXT_PACKAGE, x)
 
32
 
 
33
enum
 
34
{
 
35
  PROP_0,
 
36
  PROP_ADDRESS,
 
37
  PROP_TOOLTIP
 
38
};
 
39
 
 
40
struct _VinoURLPrivate
 
41
{
 
42
  char          *address;
 
43
  char          *tooltip;
 
44
 
 
45
  PangoAttrList *attributes;
 
46
  GtkTooltips   *tooltips;
 
47
  GdkWindow     *event_window;
 
48
 
 
49
  guint          button_down : 1;
 
50
  guint          foreground_modified : 1;
 
51
  guint          underline_modified : 1;
 
52
};
 
53
 
 
54
static void vino_url_class_init    (VinoURLClass *klass);
 
55
static void vino_url_instance_init (VinoURL      *url);
 
56
 
 
57
static void vino_url_finalize     (GObject      *object);
 
58
static void vino_url_set_property (GObject      *object,
 
59
                                   guint         prop_id,
 
60
                                   const GValue *value,
 
61
                                   GParamSpec   *pspec);
 
62
static void vino_url_get_property (GObject      *object,
 
63
                                   guint         prop_id,
 
64
                                   GValue       *value,
 
65
                                   GParamSpec   *pspec);
 
66
 
 
67
static void     vino_url_realize        (GtkWidget        *widget);
 
68
static void     vino_url_unrealize      (GtkWidget        *widget);
 
69
static void     vino_url_size_allocate  (GtkWidget        *widget,
 
70
                                         GtkAllocation    *allocation);
 
71
static void     vino_url_size_request   (GtkWidget        *widget,
 
72
                                         GtkRequisition   *requisition);
 
73
static void     vino_url_map            (GtkWidget        *widget);
 
74
static void     vino_url_unmap          (GtkWidget        *widget);
 
75
static gboolean vino_url_expose         (GtkWidget        *widget,
 
76
                                         GdkEventExpose   *event);
 
77
static gboolean vino_url_button_press   (GtkWidget        *widget,
 
78
                                         GdkEventButton   *event);
 
79
static gboolean vino_url_button_release (GtkWidget        *widget,
 
80
                                         GdkEventButton   *event);
 
81
static gboolean vino_url_focus          (GtkWidget        *widget,
 
82
                                         GtkDirectionType  direction);
 
83
static void     vino_url_state_changed  (GtkWidget        *widget,
 
84
                                         GtkStateType      previous_state);
 
85
 
 
86
static void vino_url_activate (VinoURL *url);
 
87
 
 
88
static void vino_url_change_attribute_internal (VinoURL        *url,
 
89
                                                PangoAttribute *attribute,
 
90
                                                gboolean        internal);
 
91
static void vino_url_set_use_underline         (VinoURL        *url,
 
92
                                                gboolean        use_underline);
 
93
static void vino_url_set_use_url_color         (VinoURL        *url,
 
94
                                                gboolean        use_underline);
 
95
 
 
96
static GtkLabelClass *parent_class = NULL;
 
97
 
 
98
GType
 
99
vino_url_get_type (void)
 
100
{
 
101
  static GType url_type = 0;
 
102
  
 
103
  if (!url_type)
 
104
    {
 
105
      static const GTypeInfo url_info =
 
106
      {
 
107
        sizeof (VinoURLClass),
 
108
        NULL,           /* base_init */
 
109
        NULL,           /* base_finalize */
 
110
        (GClassInitFunc) vino_url_class_init,
 
111
        NULL,           /* class_finalize */
 
112
        NULL,           /* class_data */
 
113
        sizeof (VinoURL),
 
114
        0,              /* n_preallocs */
 
115
        (GInstanceInitFunc) vino_url_instance_init,
 
116
      };
 
117
      
 
118
      url_type = g_type_register_static (GTK_TYPE_LABEL,
 
119
                                         "VinoURL",
 
120
                                         &url_info, 0);
 
121
    }
 
122
  
 
123
  return url_type;
 
124
}
 
125
 
 
126
static void
 
127
vino_url_class_init (VinoURLClass *klass)
 
128
{
 
129
  GObjectClass  *gobject_class;
 
130
  GtkWidgetClass *widget_class;
 
131
 
 
132
  parent_class = g_type_class_peek_parent (klass);
 
133
 
 
134
  gobject_class = (GObjectClass *)   klass;
 
135
  widget_class  = (GtkWidgetClass *) klass;
 
136
 
 
137
  gobject_class->finalize     = vino_url_finalize;
 
138
  gobject_class->set_property = vino_url_set_property;
 
139
  gobject_class->get_property = vino_url_get_property;
 
140
 
 
141
  widget_class->realize              = vino_url_realize;
 
142
  widget_class->unrealize            = vino_url_unrealize;
 
143
  widget_class->size_request         = vino_url_size_request;
 
144
  widget_class->size_allocate        = vino_url_size_allocate;
 
145
  widget_class->map                  = vino_url_map;
 
146
  widget_class->unmap                = vino_url_unmap;
 
147
  widget_class->expose_event         = vino_url_expose;
 
148
  widget_class->button_press_event   = vino_url_button_press;
 
149
  widget_class->button_release_event = vino_url_button_release;
 
150
  widget_class->focus                = vino_url_focus;
 
151
  widget_class->state_changed        = vino_url_state_changed;
 
152
 
 
153
  klass->activate = vino_url_activate;
 
154
 
 
155
  g_object_class_install_property (gobject_class,
 
156
                                   PROP_ADDRESS,
 
157
                                   g_param_spec_string ("address",
 
158
                                                        _("Address"),
 
159
                                                        _("The address pointed to by the widget"),
 
160
                                                        NULL,
 
161
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
162
 
 
163
  g_object_class_install_property (gobject_class,
 
164
                                   PROP_TOOLTIP,
 
165
                                   g_param_spec_string ("tooltip",
 
166
                                                        _("Tooltip"),
 
167
                                                        _("A tooltip for this URL"),
 
168
                                                        NULL,
 
169
                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 
170
 
 
171
  gtk_widget_class_install_style_property (widget_class,
 
172
                                           g_param_spec_boxed ("url-color",
 
173
                                                               _("URL color"),
 
174
                                                               _("The color of the URL's label"),
 
175
                                                               GDK_TYPE_COLOR,
 
176
                                                               G_PARAM_READWRITE));
 
177
 
 
178
  widget_class->activate_signal =
 
179
    g_signal_new ("activate",
 
180
                  G_TYPE_FROM_CLASS (gobject_class),
 
181
                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
 
182
                  G_STRUCT_OFFSET (VinoURLClass, activate),
 
183
                  NULL, NULL,
 
184
                  g_cclosure_marshal_VOID__VOID,
 
185
                  G_TYPE_NONE, 0);
 
186
}
 
187
 
 
188
static void
 
189
vino_url_instance_init (VinoURL *url)
 
190
{
 
191
  url->priv = g_new0 (VinoURLPrivate, 1);
 
192
 
 
193
  vino_url_set_use_url_color (url, TRUE);
 
194
  vino_url_set_use_underline (url, TRUE);
 
195
 
 
196
  url->priv->tooltips = gtk_tooltips_new ();
 
197
  g_object_ref (url->priv->tooltips);
 
198
  gtk_object_sink (GTK_OBJECT (url->priv->tooltips));
 
199
 
 
200
  /* Chain up to the label's focus handling code
 
201
   * which is meant for selection, even though
 
202
   * we're not selectable.
 
203
   */
 
204
  GTK_WIDGET_SET_FLAGS (url, GTK_CAN_FOCUS);
 
205
}
 
206
 
 
207
static void
 
208
vino_url_finalize (GObject *object)
 
209
{
 
210
  VinoURL *url = VINO_URL (object);
 
211
 
 
212
  if (url->priv->address)
 
213
    g_free (url->priv->address);
 
214
  url->priv->address = NULL;
 
215
 
 
216
  if (url->priv->attributes)
 
217
    pango_attr_list_unref (url->priv->attributes);
 
218
  url->priv->attributes = NULL;
 
219
 
 
220
  if (url->priv->tooltips)
 
221
    g_object_unref (url->priv->tooltips);
 
222
  url->priv->tooltips = NULL;
 
223
 
 
224
  g_free (url->priv);
 
225
  url->priv = NULL;
 
226
 
 
227
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
228
}
 
229
 
 
230
static void
 
231
vino_url_set_property (GObject      *object,
 
232
                       guint         prop_id,
 
233
                       const GValue *value,
 
234
                       GParamSpec   *pspec)
 
235
{
 
236
  VinoURL *url = VINO_URL (object);
 
237
                                                                                                             
 
238
  switch (prop_id)
 
239
    {
 
240
    case PROP_ADDRESS:
 
241
      vino_url_set_address (url, g_value_get_string (value));
 
242
      break;
 
243
    case PROP_TOOLTIP:
 
244
      vino_url_set_tooltip (url, g_value_get_string (value));
 
245
      break;
 
246
    default:
 
247
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
248
      break;
 
249
    }
 
250
}
 
251
 
 
252
static void
 
253
vino_url_get_property (GObject    *object,
 
254
                       guint       prop_id,
 
255
                       GValue     *value,
 
256
                       GParamSpec *pspec)
 
257
{
 
258
  VinoURL *url = VINO_URL (object);
 
259
 
 
260
  switch (prop_id)
 
261
    {
 
262
    case PROP_ADDRESS:
 
263
      g_value_set_string (value, vino_url_get_address (url));
 
264
      break;
 
265
    case PROP_TOOLTIP:
 
266
      g_value_set_string (value, vino_url_get_tooltip (url));
 
267
      break;
 
268
    default:
 
269
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 
270
      break;
 
271
    }
 
272
}
 
273
 
 
274
static void
 
275
vino_url_realize (GtkWidget *widget)
 
276
{
 
277
  VinoURL       *url = VINO_URL (widget);
 
278
  GdkWindowAttr  attributes;
 
279
  GdkCursor     *cursor = NULL;
 
280
  gint           attributes_mask;
 
281
 
 
282
  GTK_WIDGET_CLASS (parent_class)->realize (widget);
 
283
 
 
284
  attributes.window_type = GDK_WINDOW_CHILD;
 
285
  attributes.x           = widget->allocation.x;
 
286
  attributes.y           = widget->allocation.y;
 
287
  attributes.width       = widget->allocation.width;
 
288
  attributes.height      = widget->allocation.height;
 
289
  attributes.wclass      = GDK_INPUT_ONLY;
 
290
  attributes.event_mask  = gtk_widget_get_events (widget) |
 
291
                                GDK_BUTTON_PRESS_MASK     |
 
292
                                GDK_BUTTON_RELEASE_MASK   |
 
293
                                GDK_ENTER_NOTIFY_MASK     |
 
294
                                GDK_LEAVE_NOTIFY_MASK;
 
295
 
 
296
  attributes_mask = GDK_WA_X | GDK_WA_Y;
 
297
 
 
298
  if (GTK_WIDGET_IS_SENSITIVE (widget))
 
299
    {
 
300
      attributes.cursor = cursor =
 
301
        gdk_cursor_new_for_display (gtk_widget_get_display (widget),
 
302
                                    GDK_HAND2);
 
303
      attributes_mask |= GDK_WA_CURSOR;
 
304
    }
 
305
 
 
306
  url->priv->event_window = gdk_window_new (gtk_widget_get_parent_window (widget),
 
307
                                            &attributes, attributes_mask);
 
308
  gdk_window_set_user_data (url->priv->event_window, widget);
 
309
 
 
310
  if (cursor)
 
311
    gdk_cursor_unref (cursor);
 
312
}
 
313
 
 
314
static void
 
315
vino_url_unrealize (GtkWidget *widget)
 
316
{
 
317
  VinoURL *url = VINO_URL (widget);
 
318
 
 
319
  if (url->priv->event_window)
 
320
    {
 
321
      gdk_window_set_user_data (url->priv->event_window, NULL);
 
322
      gdk_window_destroy (url->priv->event_window);
 
323
      url->priv->event_window = NULL;
 
324
    }
 
325
 
 
326
  GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
 
327
}
 
328
 
 
329
static void
 
330
vino_url_size_request (GtkWidget      *widget,
 
331
                       GtkRequisition *requisition)
 
332
{
 
333
  int focus_width;
 
334
  int focus_pad;
 
335
 
 
336
  gtk_widget_style_get (widget,
 
337
                        "focus-line-width", &focus_width,
 
338
                        "focus-padding", &focus_pad,
 
339
                        NULL);
 
340
 
 
341
  GTK_WIDGET_CLASS (parent_class)->size_request (widget, requisition);
 
342
 
 
343
  requisition->width  += 2 * (focus_width + focus_pad);
 
344
  requisition->height += 2 * (focus_width + focus_pad);
 
345
}
 
346
 
 
347
static void
 
348
vino_url_size_allocate (GtkWidget     *widget,
 
349
                        GtkAllocation *allocation)
 
350
{
 
351
  VinoURL *url = VINO_URL (widget);
 
352
  
 
353
  GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
 
354
 
 
355
  if (GTK_WIDGET_REALIZED (widget))
 
356
    {
 
357
      gdk_window_move_resize (url->priv->event_window,
 
358
                              allocation->x,
 
359
                              allocation->y,
 
360
                              allocation->width,
 
361
                              allocation->height);
 
362
    }
 
363
}
 
364
 
 
365
static void
 
366
vino_url_map (GtkWidget *widget)
 
367
{
 
368
  VinoURL *url = VINO_URL (widget);
 
369
 
 
370
  GTK_WIDGET_CLASS (parent_class)->map (widget);
 
371
 
 
372
  if (url->priv->event_window)
 
373
    gdk_window_show (url->priv->event_window);
 
374
}
 
375
 
 
376
static void
 
377
vino_url_unmap (GtkWidget *widget)
 
378
{
 
379
  VinoURL *url = VINO_URL (widget);
 
380
 
 
381
  if (url->priv->event_window)
 
382
    gdk_window_hide (url->priv->event_window);
 
383
 
 
384
  GTK_WIDGET_CLASS (parent_class)->unmap (widget);
 
385
}
 
386
 
 
387
static gboolean
 
388
vino_url_expose (GtkWidget      *widget,
 
389
                 GdkEventExpose *event)
 
390
{
 
391
  GtkAllocation  real_allocation;
 
392
  PangoLayout   *layout;
 
393
  int            width, height;
 
394
  int            focus_width;
 
395
  int            focus_pad;
 
396
 
 
397
  gtk_widget_style_get (widget,
 
398
                        "focus-line-width", &focus_width,
 
399
                        "focus-padding", &focus_pad,
 
400
                        NULL);
 
401
 
 
402
  /* We need to fool GtkLabel into drawing the label 
 
403
   * in the right place.
 
404
   */
 
405
  real_allocation = widget->allocation;
 
406
 
 
407
  widget->allocation.x      += focus_width + focus_pad;
 
408
  widget->allocation.y      += focus_width + focus_pad;
 
409
  widget->allocation.width  -= 2 * (focus_width + focus_pad);
 
410
  widget->allocation.height -= 2 * (focus_width + focus_pad);
 
411
 
 
412
  GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
 
413
 
 
414
  layout = gtk_label_get_layout (GTK_LABEL (widget));
 
415
 
 
416
  width = height = 0;
 
417
  pango_layout_get_pixel_size (layout, &width, &height);
 
418
 
 
419
  width  += 2 * (focus_pad + focus_width);
 
420
  height += 2 * (focus_pad + focus_width);
 
421
 
 
422
  widget->allocation = real_allocation;
 
423
 
 
424
  if (GTK_WIDGET_HAS_FOCUS (widget))
 
425
    gtk_paint_focus (widget->style,
 
426
                     widget->window,
 
427
                     GTK_WIDGET_STATE (widget),
 
428
                     &event->area,
 
429
                     widget,
 
430
                     "label",
 
431
                     widget->allocation.x,
 
432
                     widget->allocation.y,
 
433
                     width,
 
434
                     height);
 
435
 
 
436
  return FALSE;
 
437
}
 
438
 
 
439
static gboolean
 
440
vino_url_button_press (GtkWidget      *widget,
 
441
                       GdkEventButton *event)
 
442
{
 
443
  VinoURL *url = VINO_URL (widget);
 
444
 
 
445
  if (event->button == 1 && event->window == url->priv->event_window)
 
446
    {
 
447
      url->priv->button_down = TRUE;
 
448
      return TRUE;
 
449
    }
 
450
 
 
451
  return FALSE;
 
452
}
 
453
 
 
454
static gboolean
 
455
vino_url_button_release (GtkWidget      *widget,
 
456
                         GdkEventButton *event)
 
457
{
 
458
  VinoURL *url = VINO_URL (widget);
 
459
 
 
460
  if (event->button == 1 && url->priv->button_down)
 
461
    {
 
462
      gtk_widget_activate (widget);
 
463
      url->priv->button_down = FALSE;
 
464
      return TRUE;
 
465
    }
 
466
 
 
467
  return FALSE;
 
468
}
 
469
 
 
470
static gboolean
 
471
vino_url_focus (GtkWidget        *widget,
 
472
                GtkDirectionType  direction)
 
473
{
 
474
  if (!gtk_widget_is_focus (widget))
 
475
    {
 
476
      gtk_widget_grab_focus (widget);
 
477
      return TRUE;
 
478
    }
 
479
 
 
480
  return FALSE;
 
481
}
 
482
 
 
483
static void
 
484
vino_url_state_changed (GtkWidget    *widget,
 
485
                        GtkStateType  previous_state)
 
486
{
 
487
  if (GTK_WIDGET_REALIZED (widget))
 
488
    {
 
489
      if (GTK_WIDGET_IS_SENSITIVE (widget))
 
490
        {
 
491
          GdkCursor *cursor;
 
492
 
 
493
          cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
 
494
                                               GDK_HAND2);
 
495
          gdk_window_set_cursor (VINO_URL (widget)->priv->event_window, cursor);
 
496
          gdk_cursor_unref (cursor);
 
497
        }
 
498
      else
 
499
        {
 
500
          gdk_window_set_cursor (VINO_URL (widget)->priv->event_window, NULL);
 
501
        }
 
502
    }
 
503
 
 
504
  vino_url_set_use_url_color (VINO_URL (widget), GTK_WIDGET_IS_SENSITIVE (widget));
 
505
}
 
506
 
 
507
static void
 
508
vino_url_activate (VinoURL *url)
 
509
{
 
510
  GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (url));
 
511
  GError    *error = NULL;
 
512
 
 
513
  if (!url->priv->address)
 
514
    return;
 
515
 
 
516
  if (!gnome_url_show_on_screen (url->priv->address, screen, &error))
 
517
    {
 
518
      /* FIXME better error handling!
 
519
       *       What best to do? For the specific case
 
520
       *       in this preferences dialog we want to be
 
521
       *       able to pop up a dialog with the error
 
522
       *       but also the vino URL as a selectable
 
523
       *       label.
 
524
       *
 
525
       *       Maybe chain this up to the caller?
 
526
       */
 
527
 
 
528
      g_warning ("Failed to show URL '%s': %s\n",
 
529
                 url->priv->address, error->message);
 
530
      g_error_free (error);
 
531
    }
 
532
}
 
533
 
 
534
GtkWidget *
 
535
vino_url_new (const char *address,
 
536
              const char *label,
 
537
              const char *tooltip)
 
538
{
 
539
  g_return_val_if_fail (address != NULL, NULL);
 
540
 
 
541
  return g_object_new (VINO_TYPE_URL,
 
542
                       "address", address,
 
543
                       "label",   label,
 
544
                       "tooltip", tooltip,
 
545
                       NULL);
 
546
}
 
547
 
 
548
static void
 
549
vino_url_set_use_underline (VinoURL  *url,
 
550
                            gboolean  use_underline)
 
551
{
 
552
  if (!url->priv->underline_modified)
 
553
    {
 
554
      if (use_underline)
 
555
        {
 
556
          vino_url_change_attribute_internal (url,
 
557
                                              pango_attr_underline_new (PANGO_UNDERLINE_SINGLE),
 
558
                                              TRUE);
 
559
        }
 
560
      else
 
561
        {
 
562
          vino_url_unset_attribute_type (url, PANGO_ATTR_UNDERLINE);
 
563
        }
 
564
    }
 
565
}
 
566
 
 
567
static void
 
568
vino_url_set_use_url_color (VinoURL  *url,
 
569
                            gboolean  use_url_color)
 
570
{
 
571
  if (!url->priv->foreground_modified)
 
572
    {
 
573
      if (use_url_color)
 
574
        {
 
575
          GdkColor        blue = { 0, 0x0000, 0x0000, 0xffff };
 
576
          GdkColor       *url_color;
 
577
          PangoAttribute *foreground;
 
578
 
 
579
          gtk_widget_style_get (GTK_WIDGET (url),
 
580
                                "url-color", &url_color,
 
581
                                NULL);
 
582
          if (!url_color)
 
583
            url_color = &blue;
 
584
 
 
585
          foreground = pango_attr_foreground_new (url_color->red,
 
586
                                                  url_color->green,
 
587
                                                  url_color->blue);
 
588
 
 
589
          vino_url_change_attribute_internal (url, foreground, TRUE);
 
590
 
 
591
          if (url_color != &blue)
 
592
            gdk_color_free (url_color);
 
593
        }
 
594
      else
 
595
        {
 
596
          vino_url_unset_attribute_type (url, PANGO_ATTR_FOREGROUND);
 
597
        }
 
598
    }
 
599
}
 
600
 
 
601
void
 
602
vino_url_set_address (VinoURL    *url,
 
603
                      const char *address)
 
604
{
 
605
  g_return_if_fail (VINO_IS_URL (url));
 
606
 
 
607
  g_free (url->priv->address);
 
608
  url->priv->address = g_strdup (address);
 
609
 
 
610
  g_object_notify (G_OBJECT (url), "address");
 
611
}
 
612
 
 
613
G_CONST_RETURN char *
 
614
vino_url_get_address (VinoURL *url)
 
615
{
 
616
  g_return_val_if_fail (VINO_IS_URL (url), NULL);
 
617
 
 
618
  return url->priv->address;
 
619
}
 
620
 
 
621
void
 
622
vino_url_set_tooltip (VinoURL    *url,
 
623
                      const char *tooltip)
 
624
{
 
625
  g_return_if_fail (VINO_IS_URL (url));
 
626
 
 
627
  g_free (url->priv->tooltip);
 
628
  url->priv->tooltip = g_strdup (tooltip);
 
629
 
 
630
  gtk_tooltips_set_tip (url->priv->tooltips,
 
631
                        GTK_WIDGET (url),
 
632
                        url->priv->tooltip,
 
633
                        NULL);
 
634
 
 
635
  g_object_notify (G_OBJECT (url), "tooltip");
 
636
}
 
637
 
 
638
G_CONST_RETURN char *
 
639
vino_url_get_tooltip (VinoURL *url)
 
640
{
 
641
  g_return_val_if_fail (VINO_IS_URL (url), NULL);
 
642
 
 
643
  return url->priv->tooltip;
 
644
}
 
645
 
 
646
/* Debugging; There should probably be a nicer API
 
647
 * for fiddling with the attributes on a label;
 
648
 * Either that or I'm being dumb again;
 
649
 */
 
650
#define SANITY_CHECK_ATTRIBUTES
 
651
 
 
652
static void
 
653
sanity_check_attributes_notify (VinoURL *url)
 
654
{
 
655
  PangoAttrList *attrs;
 
656
 
 
657
  attrs = gtk_label_get_attributes (GTK_LABEL (url));
 
658
  if (attrs != url->priv->attributes)
 
659
    {
 
660
      g_warning ("Label attributes changed, resetting");
 
661
      gtk_label_set_attributes (GTK_LABEL (url),
 
662
                                url->priv->attributes);
 
663
    }
 
664
}
 
665
 
 
666
static void
 
667
sanity_check_attributes (VinoURL *url)
 
668
{
 
669
#ifdef SANITY_CHECK_ATTRIBUTES
 
670
  g_signal_connect (url, "notify::attributes",
 
671
                    G_CALLBACK (sanity_check_attributes_notify), NULL);
 
672
#endif /* SANITY_CHECK_ATTRIBUTES */
 
673
}
 
674
 
 
675
static void
 
676
vino_url_change_attribute_internal (VinoURL        *url,
 
677
                                    PangoAttribute *attribute,
 
678
                                    gboolean        internal)
 
679
{
 
680
  if (!url->priv->attributes)
 
681
    {
 
682
      url->priv->attributes = pango_attr_list_new ();
 
683
      gtk_label_set_attributes (GTK_LABEL (url), url->priv->attributes);
 
684
      sanity_check_attributes (url);
 
685
    }
 
686
 
 
687
  attribute->start_index = 0;
 
688
  attribute->end_index = G_MAXINT;
 
689
 
 
690
  if (!internal)
 
691
    {
 
692
      if (attribute->klass->type == PANGO_ATTR_FOREGROUND)
 
693
        url->priv->foreground_modified = TRUE;
 
694
 
 
695
      if (attribute->klass->type == PANGO_ATTR_UNDERLINE)
 
696
        url->priv->underline_modified = TRUE;
 
697
    }
 
698
 
 
699
  pango_attr_list_change (url->priv->attributes, attribute);
 
700
}
 
701
 
 
702
void
 
703
vino_url_change_attribute (VinoURL        *url,
 
704
                           PangoAttribute *attribute)
 
705
{
 
706
  g_return_if_fail (VINO_IS_URL (url));
 
707
 
 
708
  vino_url_change_attribute_internal (url, attribute, FALSE);
 
709
}
 
710
 
 
711
static gboolean
 
712
filter_out_attr_type (PangoAttribute *attribute,
 
713
                      gpointer        data)
 
714
{
 
715
  PangoAttrType attr_type = GPOINTER_TO_INT (data);
 
716
 
 
717
  return attribute->klass->type == attr_type;
 
718
}
 
719
 
 
720
void
 
721
vino_url_unset_attribute_type (VinoURL       *url,
 
722
                               PangoAttrType  attr_type)
 
723
{
 
724
  g_return_if_fail (VINO_IS_URL (url));
 
725
 
 
726
  if (url->priv->attributes)
 
727
    {
 
728
      PangoAttrList *filtered;
 
729
 
 
730
      filtered =
 
731
        pango_attr_list_filter (url->priv->attributes,
 
732
                                (PangoAttrFilterFunc) filter_out_attr_type,
 
733
                                GINT_TO_POINTER (attr_type));
 
734
      if (filtered)
 
735
        pango_attr_list_unref (filtered);
 
736
    }
 
737
}