source: branches/joshe/gtk/trcellrenderertorrent.c @ 77

Last change on this file since 77 was 73, checked in by joshe, 16 years ago

Merge rev 68:72 from trunk.

File size: 9.9 KB
Line 
1/* trcellrenderertorrent.c
2 * Copyright (C) 2002 Naba Kumar <kh_naba@users.sourceforge.net>
3 * heavily modified by Jörgen Scheibengruber <mfcn@gmx.de>
4 * heavily modified by Marco Pesenti Gritti <marco@gnome.org>
5 * heavily modified by Josh Elsasser <josh@elsasser.org> for transmission
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, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 */
22/*
23 * Modified by the GTK+ Team and others 1997-2004.  See the AUTHORS
24 * file for a list of people on the GTK+ Team.  See the ChangeLog
25 * files for a list of changes.  These files are distributed with
26 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 */
28
29#include <gtk/gtk.h>
30
31#include "trcellrenderertorrent.h"
32#include "util.h"
33
34enum { PROP_0, PROP_VALUE, PROP_TEXT, PROP_LABEL }; 
35
36struct _TrCellRendererTorrentPrivate {
37  gfloat value;
38  gchar *text;
39  PangoAttrList *text_attrs;
40  gchar *label;
41  PangoAttrList *label_attrs;
42  GtkStyle *style;
43};
44
45static void
46finalize(GObject *object);
47static void
48get_property(GObject *obj, guint id, GValue *value, GParamSpec *spec);
49static void
50set_property(GObject *obj, guint id, const GValue *value, GParamSpec *spec);
51static void
52get_size(GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *area,
53         gint *xoff, gint *yoff, gint *width, gint *height);
54static void
55render(GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget,
56       GdkRectangle *bg, GdkRectangle *area, GdkRectangle *exp, guint flags);
57
58     
59G_DEFINE_TYPE(TrCellRendererTorrent, tr_cell_renderer_torrent, GTK_TYPE_CELL_RENDERER);
60
61static void
62tr_cell_renderer_torrent_class_init (TrCellRendererTorrentClass *klass) {
63  GObjectClass *object_class = G_OBJECT_CLASS (klass);
64  GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
65 
66  object_class->finalize = finalize;
67  object_class->get_property = get_property;
68  object_class->set_property = set_property;
69 
70  cell_class->get_size = get_size;
71  cell_class->render = render;
72 
73  g_object_class_install_property(
74    object_class, PROP_VALUE,
75    g_param_spec_float("value", "Value", "Value of the torrent bar",
76                       0.0, 1.0, 0.0, G_PARAM_READWRITE));
77
78  g_object_class_install_property(
79    object_class, PROP_TEXT,
80    g_param_spec_string ("text", "Text", "Text under the torrent bar",
81  /* XXX should I have NULL or "" here, and is initial strdup needed? */
82                         NULL, G_PARAM_READWRITE));
83
84  g_object_class_install_property(
85    object_class, PROP_LABEL,
86    g_param_spec_string ("label", "Label", "Text on the torrent bar",
87                         NULL, G_PARAM_READWRITE));
88
89  g_type_class_add_private (object_class, 
90                            sizeof (TrCellRendererTorrentPrivate));
91}
92
93static void
94tr_cell_renderer_torrent_init(TrCellRendererTorrent *tcell) {
95  tcell->priv = G_TYPE_INSTANCE_GET_PRIVATE(
96    tcell, GTK_TYPE_CELL_RENDERER_TORRENT, TrCellRendererTorrentPrivate);
97  tcell->priv->value = 0.0;
98  tcell->priv->text = g_strdup("");
99  tcell->priv->text_attrs = NULL;
100  tcell->priv->label = g_strdup("");
101  tcell->priv->text_attrs = NULL;
102  tcell->priv->style = NULL;
103}
104
105GtkCellRenderer*
106tr_cell_renderer_torrent_new(void) {
107  return g_object_new (GTK_TYPE_CELL_RENDERER_TORRENT, NULL);
108}
109
110/* XXX need to do this better somehow */
111void
112tr_cell_renderer_torrent_reset_style(TrCellRendererTorrent *tor) {
113  if(NULL != tor->priv->style) {
114    gtk_style_detach(tor->priv->style);
115    gtk_style_unref(tor->priv->style);
116    tor->priv->style = NULL;
117  }
118}
119
120static void
121finalize(GObject *object) {
122  TrCellRendererTorrent *tcell = TR_CELL_RENDERER_TORRENT(object);
123
124  g_free(tcell->priv->text);
125  g_free(tcell->priv->label);
126
127  if(NULL != tcell->priv->text_attrs)
128    pango_attr_list_unref(tcell->priv->text_attrs);
129  if(NULL != tcell->priv->label_attrs)
130    pango_attr_list_unref(tcell->priv->label_attrs);
131  if(NULL != tcell->priv->style) {
132    gtk_style_detach(tcell->priv->style);
133    gtk_style_unref(tcell->priv->style);
134  }
135
136  G_OBJECT_CLASS (tr_cell_renderer_torrent_parent_class)->finalize(object);
137}
138
139static void
140get_property(GObject *object, guint id, GValue *value, GParamSpec *pspec) {
141  TrCellRendererTorrent *tcell = TR_CELL_RENDERER_TORRENT (object);
142 
143  switch (id) {
144    case PROP_VALUE:
145      g_value_set_float (value, tcell->priv->value);
146      break;
147    case PROP_TEXT:
148      g_value_set_string (value, tcell->priv->text);
149      break;
150    case PROP_LABEL:
151      g_value_set_string (value, tcell->priv->label);
152      break;
153    default:
154      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, id, pspec);
155  }
156}
157
158static void
159set_property(GObject *obj, guint id, const GValue *value, GParamSpec *spec) {
160  TrCellRendererTorrent *tcell = TR_CELL_RENDERER_TORRENT(obj);
161  gchar **prop = NULL; 
162  PangoAttrList **attrs = NULL;
163  /*GError *err = NULL;*/
164  const gchar *markup;
165 
166  switch(id) {
167    case PROP_VALUE:
168      tcell->priv->value = g_value_get_float(value);
169      break;
170
171    case PROP_TEXT:
172      prop = &tcell->priv->text;
173      attrs = &tcell->priv->text_attrs;
174      /* fallthrough */
175
176    case PROP_LABEL:
177      if(PROP_LABEL == id) {
178        prop = &tcell->priv->label;
179        attrs = &tcell->priv->label_attrs;
180      }
181
182      if(NULL == (markup = g_value_get_string(value)))
183        markup = "";
184
185      g_free(*prop);
186      if(NULL != *attrs)
187        pango_attr_list_unref(*attrs);
188
189      *prop = g_strdup(markup);
190
191      /*
192      if(pango_parse_markup(markup, -1, 0, attrs, prop, NULL, &err))
193        break;
194       
195      g_warning ("Failed to parse markup: %s", err->message);
196      g_error_free(err);
197      */
198      break;
199
200    default:
201      G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, id, spec);
202  }
203}
204
205static void
206get_size(GtkCellRenderer *cell, GtkWidget *widget, GdkRectangle *area,
207         gint *xoff, gint *yoff, gint *width, gint *height) {
208  TrCellRendererTorrent *tcell = TR_CELL_RENDERER_TORRENT(cell);
209  /* XXX do I have to unref the context? */
210  PangoLayout *layout = pango_layout_new(gtk_widget_get_pango_context(widget));
211  PangoRectangle rect;
212  gint h = cell->ypad * 2;
213  gint w1, w2;
214
215  pango_layout_set_markup(layout, tcell->priv->label, -1);
216  pango_layout_get_pixel_extents(layout, NULL, &rect);
217  w1 = rect.width;
218  h += rect.height;
219
220  pango_layout_set_markup(layout, tcell->priv->text, -1);
221  pango_layout_get_pixel_extents(layout, NULL, &rect);
222  w2 = rect.width;
223  h += rect.height;
224
225  if(NULL != xoff)
226    *xoff = 0;
227  if(NULL != yoff)
228    *yoff = (area->height - h) / 2;
229  if(NULL != width)
230    *width = MAX(w1, w2) + cell->xpad * 2;
231  if(NULL != height)
232    *height = h;
233
234  g_object_unref(layout);
235}
236
237#define RECTARGS(rect)          (rect).x, (rect).y, (rect).width, (rect).height
238
239static void
240render(GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget,
241       GdkRectangle *bg SHUTUP, GdkRectangle *area, GdkRectangle *exp SHUTUP,
242       guint flags) {
243  TrCellRendererTorrent *tcell = TR_CELL_RENDERER_TORRENT(cell);
244  PangoContext *ctx = gtk_widget_get_pango_context(widget);
245  PangoLayout *llayout, *tlayout;
246  PangoRectangle lrect, trect;
247  GdkRectangle bar, complete, text;
248  gboolean rtl;
249  GtkStyle *style;
250
251  /* try to use the style for GtkProgressBar */
252  if(NULL == tcell->priv->style)
253    if(NULL != (tcell->priv->style = gtk_rc_get_style_by_paths(
254                  gtk_widget_get_settings(widget), NULL, NULL,
255                  gtk_progress_bar_get_type())))
256      tcell->priv->style = gtk_style_attach(gtk_style_ref(tcell->priv->style),
257                                            window);
258  style = (NULL == tcell->priv->style ? widget->style : tcell->priv->style);
259
260  rtl = gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
261
262  /* get the text layouts */
263  llayout = pango_layout_new(ctx);
264  /* XXX cache parsed markup? */
265  pango_layout_set_markup(llayout, tcell->priv->label, -1);
266  pango_layout_get_pixel_extents(llayout, NULL, &lrect);
267  tlayout = pango_layout_new(ctx);
268  pango_layout_set_markup(tlayout, tcell->priv->text, -1);
269  pango_layout_get_pixel_extents (tlayout, NULL, &trect);
270
271  /* set up the dimensions for the bar */
272  bar.x = area->x + cell->xpad;
273  bar.y = area->y + cell->ypad +
274    (area->height - lrect.height - trect.height) / 2;
275  bar.width = area->width - cell->xpad * 2;
276  bar.height = lrect.height;
277
278  /* set up the dimensions for the complete portion of the bar */
279  complete.x = bar.x + style->xthickness;
280  complete.y = bar.y + style->ythickness;
281  complete.width = (bar.width - style->xthickness * 2) * tcell->priv->value;
282  complete.height = bar.height - style->ythickness * 2;
283  if(rtl)
284    complete.x += bar.width - complete.width;
285
286  /* set up the dimensions for the text under the bar */
287  text.x = bar.x;
288  text.y = bar.y + bar.height;
289  text.width = bar.width;
290  text.height = area->height - bar.height;
291
292  /* draw the background of the bar */
293  if(complete.width < bar.width)
294    gtk_paint_box(style, window, GTK_STATE_NORMAL, GTK_SHADOW_IN, 
295                  NULL, widget, "trough", RECTARGS(bar));
296
297  /* draw the complete portion of the bar */
298  if(0 < complete.width)
299    gtk_paint_box(style, window, GTK_STATE_PRELIGHT, GTK_SHADOW_OUT,
300                  NULL, widget, "bar", RECTARGS(complete));
301
302  /* draw the text under the bar */
303  gtk_paint_layout(style, window, (GTK_CELL_RENDERER_SELECTED & flags ?
304                   GTK_STATE_SELECTED : GTK_STATE_NORMAL), FALSE, &text,
305                   widget, "cellrenderertext", text.x, text.y, tlayout);
306
307  /* free memory */
308  g_object_unref(llayout);
309  g_object_unref(tlayout);
310}
Note: See TracBrowser for help on using the repository browser.