~ubuntu-branches/ubuntu/precise/gnome-control-center/precise-updates

« back to all changes in this revision

Viewing changes to shell/shell-search-renderer.c

Tags: upstream-3.0.1.1
ImportĀ upstreamĀ versionĀ 3.0.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2010 Intel, Inc.
 
3
 *
 
4
 * The Control Center is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by the
 
6
 * Free Software Foundation; either version 2 of the License, or (at your
 
7
 * option) any later version.
 
8
 *
 
9
 * The Control Center is distributed in the hope that it will be useful, but
 
10
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
11
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
12
 * for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along
 
15
 * with the Control Center; if not, write to the Free Software Foundation,
 
16
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 *
 
18
 * Author: Thomas Wood <thos@gnome.org>
 
19
 */
 
20
 
 
21
#include "shell-search-renderer.h"
 
22
#include <string.h>
 
23
 
 
24
G_DEFINE_TYPE (ShellSearchRenderer, shell_search_renderer, GTK_TYPE_CELL_RENDERER)
 
25
 
 
26
#define SEARCH_RENDERER_PRIVATE(o) \
 
27
  (G_TYPE_INSTANCE_GET_PRIVATE ((o), SHELL_TYPE_SEARCH_RENDERER, ShellSearchRendererPrivate))
 
28
 
 
29
struct _ShellSearchRendererPrivate
 
30
{
 
31
  gchar *title;
 
32
  gchar *search_target;
 
33
  gchar *search_string;
 
34
 
 
35
  PangoLayout *layout;
 
36
};
 
37
 
 
38
enum
 
39
{
 
40
  PROP_TITLE = 1,
 
41
  PROP_SEARCH_TARGET,
 
42
  PROP_SEARCH_STRING
 
43
};
 
44
 
 
45
 
 
46
static void
 
47
shell_search_renderer_get_property (GObject    *object,
 
48
                                    guint       property_id,
 
49
                                    GValue     *value,
 
50
                                    GParamSpec *pspec)
 
51
{
 
52
  switch (property_id)
 
53
    {
 
54
  case PROP_TITLE:
 
55
  case PROP_SEARCH_TARGET:
 
56
  case PROP_SEARCH_STRING:
 
57
    break;
 
58
 
 
59
 
 
60
    default:
 
61
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
62
    }
 
63
}
 
64
 
 
65
static void
 
66
shell_search_renderer_set_property (GObject      *object,
 
67
                                    guint         property_id,
 
68
                                    const GValue *value,
 
69
                                    GParamSpec   *pspec)
 
70
{
 
71
  ShellSearchRendererPrivate *priv = SHELL_SEARCH_RENDERER (object)->priv;
 
72
 
 
73
  switch (property_id)
 
74
    {
 
75
  case PROP_TITLE:
 
76
    g_free (priv->title);
 
77
    priv->title = g_value_dup_string (value);
 
78
    break;
 
79
 
 
80
  case PROP_SEARCH_TARGET:
 
81
    g_free (priv->search_target);
 
82
    priv->search_target = g_value_dup_string (value);
 
83
    break;
 
84
 
 
85
  case PROP_SEARCH_STRING:
 
86
    g_free (priv->search_string);
 
87
    priv->search_string = g_value_dup_string (value);
 
88
    break;
 
89
 
 
90
    default:
 
91
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
92
    }
 
93
}
 
94
 
 
95
static void
 
96
shell_search_renderer_dispose (GObject *object)
 
97
{
 
98
  ShellSearchRendererPrivate *priv = SHELL_SEARCH_RENDERER (object)->priv;
 
99
 
 
100
  if (priv->layout)
 
101
    {
 
102
      g_object_unref (priv->layout);
 
103
      priv->layout = NULL;
 
104
    }
 
105
 
 
106
  G_OBJECT_CLASS (shell_search_renderer_parent_class)->dispose (object);
 
107
}
 
108
 
 
109
static void
 
110
shell_search_renderer_finalize (GObject *object)
 
111
{
 
112
  ShellSearchRendererPrivate *priv = SHELL_SEARCH_RENDERER (object)->priv;
 
113
 
 
114
  if (priv->title)
 
115
    {
 
116
      g_free (priv->title);
 
117
      priv->title = NULL;
 
118
    }
 
119
 
 
120
  if (priv->search_target)
 
121
    {
 
122
      g_free (priv->search_target);
 
123
      priv->search_target = NULL;
 
124
    }
 
125
 
 
126
  if (priv->search_string)
 
127
    {
 
128
      g_free (priv->search_string);
 
129
      priv->search_string = NULL;
 
130
    }
 
131
 
 
132
  G_OBJECT_CLASS (shell_search_renderer_parent_class)->finalize (object);
 
133
}
 
134
 
 
135
static void
 
136
shell_search_renderer_set_layout (ShellSearchRenderer *cell, GtkWidget *widget)
 
137
{
 
138
  gchar *display_string;
 
139
  ShellSearchRendererPrivate *priv = cell->priv;
 
140
  gchar *needle, *haystack;
 
141
  gchar *full_string;
 
142
 
 
143
  if (!priv->layout)
 
144
    {
 
145
      priv->layout = pango_layout_new (gtk_widget_get_pango_context (widget));
 
146
      pango_layout_set_ellipsize (priv->layout, PANGO_ELLIPSIZE_END);
 
147
    }
 
148
 
 
149
  full_string = priv->search_target;
 
150
 
 
151
  if (priv->search_string != NULL)
 
152
    needle = g_utf8_casefold (priv->search_string, -1);
 
153
  else
 
154
    needle = NULL;
 
155
  haystack = g_utf8_casefold (full_string, -1);
 
156
 
 
157
  /* clear any previous attributes */
 
158
  pango_layout_set_attributes (priv->layout, NULL);
 
159
 
 
160
  if (priv->search_string && priv->title
 
161
      && (strstr (haystack, needle)))
 
162
    {
 
163
      gchar *start;
 
164
      gchar *lead, *trail, *leaddot;
 
165
      gchar *match;
 
166
      gint count;
 
167
 
 
168
#define CONTEXT 10
 
169
 
 
170
      count = strlen (needle);
 
171
      start = full_string + (strstr (haystack, needle) - haystack);
 
172
 
 
173
      lead = MAX (start - CONTEXT, full_string);
 
174
      trail = start + count;
 
175
 
 
176
      if (lead == full_string)
 
177
        leaddot = "";
 
178
      else
 
179
        leaddot = "...";
 
180
 
 
181
      match = g_strndup (start, count);
 
182
      lead = g_strndup (lead, start - lead);
 
183
 
 
184
      display_string = g_markup_printf_escaped ("%s\n"
 
185
                                                "<small>%s%s<b>%s</b>%s</small>",
 
186
                                                priv->title, leaddot, lead,
 
187
                                                match, trail);
 
188
 
 
189
      g_free (match);
 
190
      g_free (lead);
 
191
    }
 
192
  else
 
193
    display_string = g_markup_escape_text (priv->title, -1);
 
194
 
 
195
 
 
196
  pango_layout_set_markup (priv->layout, display_string, -1);
 
197
  g_free (display_string);
 
198
  g_free (needle);
 
199
  g_free (haystack);
 
200
}
 
201
 
 
202
static void
 
203
shell_search_renderer_get_size (GtkCellRenderer    *cell,
 
204
                                GtkWidget          *widget,
 
205
                                const GdkRectangle *cell_area,
 
206
                                gint               *x_offset,
 
207
                                gint               *y_offset,
 
208
                                gint               *width,
 
209
                                gint               *height)
 
210
{
 
211
  ShellSearchRendererPrivate *priv = SHELL_SEARCH_RENDERER (cell)->priv;
 
212
  PangoRectangle rect;
 
213
 
 
214
  shell_search_renderer_set_layout (SHELL_SEARCH_RENDERER (cell), widget);
 
215
 
 
216
  pango_layout_set_width (priv->layout, PANGO_SCALE * 180);
 
217
  pango_layout_get_pixel_extents (priv->layout, NULL, &rect);
 
218
 
 
219
  if (width) *width = rect.width;
 
220
  if (height) *height = rect.height;
 
221
 
 
222
  if (x_offset) *x_offset = 0;
 
223
  if (y_offset) *y_offset = 0;
 
224
 
 
225
}
 
226
 
 
227
static void
 
228
shell_search_renderer_render (GtkCellRenderer      *cell,
 
229
                              cairo_t              *cr,
 
230
                              GtkWidget            *widget,
 
231
                              const GdkRectangle   *background_area,
 
232
                              const GdkRectangle   *cell_area,
 
233
                              GtkCellRendererState  flags)
 
234
{
 
235
  ShellSearchRendererPrivate *priv = SHELL_SEARCH_RENDERER (cell)->priv;
 
236
  PangoRectangle rect;
 
237
 
 
238
  shell_search_renderer_set_layout (SHELL_SEARCH_RENDERER (cell), widget);
 
239
 
 
240
  pango_layout_get_pixel_extents (priv->layout, NULL, &rect);
 
241
 
 
242
  cairo_move_to (cr, cell_area->x, cell_area->y);
 
243
 
 
244
  /* FIXME: get the correct colour from the theme */
 
245
  cairo_set_source_rgb (cr, 0, 0, 0);
 
246
  if (priv->layout)
 
247
    pango_cairo_layout_path (cr, priv->layout);
 
248
  cairo_fill (cr);
 
249
}
 
250
 
 
251
static void
 
252
shell_search_renderer_class_init (ShellSearchRendererClass *klass)
 
253
{
 
254
  GParamSpec *pspec;
 
255
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
256
  GtkCellRendererClass *cell_renderer = GTK_CELL_RENDERER_CLASS (klass);
 
257
 
 
258
  g_type_class_add_private (klass, sizeof (ShellSearchRendererPrivate));
 
259
 
 
260
  object_class->get_property = shell_search_renderer_get_property;
 
261
  object_class->set_property = shell_search_renderer_set_property;
 
262
  object_class->dispose = shell_search_renderer_dispose;
 
263
  object_class->finalize = shell_search_renderer_finalize;
 
264
 
 
265
  cell_renderer->get_size = shell_search_renderer_get_size;
 
266
  cell_renderer->render = shell_search_renderer_render;
 
267
 
 
268
  pspec = g_param_spec_string ("title",
 
269
                               "Title",
 
270
                               "Item title",
 
271
                               "",
 
272
                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
273
  g_object_class_install_property (object_class, PROP_TITLE, pspec);
 
274
 
 
275
  pspec = g_param_spec_string ("search-target",
 
276
                               "Search Target",
 
277
                               "The string that will be searched",
 
278
                               "",
 
279
                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
280
  g_object_class_install_property (object_class, PROP_SEARCH_TARGET, pspec);
 
281
 
 
282
  pspec = g_param_spec_string ("search-string",
 
283
                               "Search String",
 
284
                               "Current search string",
 
285
                               "",
 
286
                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
287
  g_object_class_install_property (object_class, PROP_SEARCH_STRING, pspec);
 
288
}
 
289
 
 
290
static void
 
291
shell_search_renderer_init (ShellSearchRenderer *self)
 
292
{
 
293
  self->priv = SEARCH_RENDERER_PRIVATE (self);
 
294
}
 
295
 
 
296
ShellSearchRenderer *
 
297
shell_search_renderer_new (void)
 
298
{
 
299
  return g_object_new (SHELL_TYPE_SEARCH_RENDERER, NULL);
 
300
}