~ubuntu-branches/ubuntu/trusty/gq/trusty

« back to all changes in this revision

Viewing changes to src/gq-comparison.c

  • Committer: Bazaar Package Importer
  • Author(s): Barry deFreese
  • Date: 2009-10-25 23:34:56 UTC
  • mfrom: (1.1.4 upstream) (3.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20091025233456-i794n3yg2cff930j
Tags: 1.3.4-1
* QA upload.
  + Set maintainer to Debian QA Group <packages@qa.debian.org>.
* New upstream release. (Closes: #534705).
  + Does not segfault on amd64. (Closes: #444312).
  + Remove all existing patches and change patch system to quilt.
  + Replace dpatch build-dep with quilt.
* 01_desktop_file.diff - Remove encoding and bogus categories 
  from desktop file.
* Copy in config.{sub,guess} on configure, rm them on clean.
  + Add build-dep on autotools-dev.
* Make clean not ignore errors.
* Add copyright holders and version path to GPL (GPL-2).
* Update watch file to use SF redirector. (Closes: #449749).
* Bump debhelper build-dep and compat to 5.
* Bump Standards Version to 3.8.3.
  + Menu policy transition.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of GQ
 
2
 *
 
3
 * AUTHORS
 
4
 *     Sven Herzberg  <herzi@gnome-de.org>
 
5
 *
 
6
 * Copyright (C) 2006  Sven Herzberg
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU Lesser General Public License as
 
10
 * published by the Free Software Foundation; either version 2.1 of the
 
11
 * License, or (at your option) any later version.
 
12
 *
 
13
 * This program is distributed in the hope that it will be useful,
 
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
 * GNU Lesser General Public License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Lesser General Public License
 
19
 * along with this program; if not, write to the Free Software
 
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
21
 * USA
 
22
 */
 
23
 
 
24
#include "gq-comparison.h"
 
25
 
 
26
#include <glib/gi18n.h>
 
27
#include "gq-difference.h"
 
28
 
 
29
struct GqComparisonPrivate {
 
30
        GqInputForm  * form1;
 
31
        GqInputForm  * form2;
 
32
        GtkAdjustment* adj1;
 
33
        GtkAdjustment* adj2;
 
34
        GqDifference * difference;
 
35
};
 
36
#define P(i) (G_TYPE_INSTANCE_GET_PRIVATE((i), GQ_TYPE_COMPARISON, struct GqComparisonPrivate))
 
37
 
 
38
GtkWidget*
 
39
gq_comparison_new(GqInputForm* form1,
 
40
                  GqInputForm* form2)
 
41
{
 
42
        return g_object_new(GQ_TYPE_COMPARISON,
 
43
                            "form1", form1,
 
44
                            "form2", form2,
 
45
                            NULL);
 
46
}
 
47
 
 
48
GqDifference*
 
49
gq_comparison_get_difference(GqComparison const* self)
 
50
{
 
51
        g_return_val_if_fail(GQ_IS_COMPARISON(self), NULL);
 
52
 
 
53
        return P(self)->difference;
 
54
}
 
55
 
 
56
/* GType */
 
57
G_DEFINE_TYPE(GqComparison, gq_comparison, GTK_TYPE_DRAWING_AREA);
 
58
 
 
59
enum {
 
60
        PROP_0,
 
61
        PROP_FORM_1,
 
62
        PROP_FORM_2
 
63
};
 
64
 
 
65
static void
 
66
gq_comparison_init(GqComparison* self)
 
67
{
 
68
        P(self)->difference = gq_difference_new();
 
69
        g_signal_connect_swapped(P(self)->difference, "updated",
 
70
                                 G_CALLBACK(gtk_widget_queue_draw), self);
 
71
}
 
72
 
 
73
static void
 
74
comparison_dispose(GObject* object)
 
75
{
 
76
        if(P(object)->difference) {
 
77
                g_signal_handlers_disconnect_by_func(P(object)->difference, gtk_widget_queue_draw, object);
 
78
                g_object_unref(P(object)->difference);
 
79
                P(object)->difference = NULL;
 
80
        }
 
81
 
 
82
        if(P(object)->form1) {
 
83
                g_object_unref(P(object)->form1);
 
84
                P(object)->form1 = NULL;
 
85
        }
 
86
 
 
87
        if(P(object)->form2) {
 
88
                g_object_unref(P(object)->form2);
 
89
                P(object)->form2 = NULL;
 
90
        }
 
91
 
 
92
        G_OBJECT_CLASS(gq_comparison_parent_class)->dispose(object);
 
93
}
 
94
 
 
95
static void
 
96
comparison_get_property(GObject   * object,
 
97
                        guint       prop_id,
 
98
                        GValue    * value,
 
99
                        GParamSpec* pspec)
 
100
{
 
101
        switch(prop_id) {
 
102
        case PROP_FORM_1:
 
103
                g_value_set_object(value, P(object)->form1);
 
104
                break;
 
105
        case PROP_FORM_2:
 
106
                g_value_set_object(value, P(object)->form2);
 
107
                break;
 
108
        default:
 
109
                G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 
110
                break;
 
111
        }
 
112
}
 
113
 
 
114
static void
 
115
comparison_update_adj1(GqComparison* self)
 
116
{
 
117
        if(P(self)->adj1) {
 
118
                g_signal_handlers_disconnect_by_func(P(self)->adj1, gtk_widget_queue_draw, self);
 
119
                g_object_unref(P(self)->adj1);
 
120
                P(self)->adj1 = NULL;
 
121
        }
 
122
 
 
123
        if(P(self)->form1) {
 
124
                P(self)->adj1 = g_object_ref(gtk_range_get_adjustment(GTK_RANGE(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(P(self)->form1))->vscrollbar)));
 
125
                g_signal_connect_swapped(P(self)->adj1, "value-changed",
 
126
                                         G_CALLBACK(gtk_widget_queue_draw), self);
 
127
        }
 
128
}
 
129
 
 
130
static void
 
131
comparison_update_adj2(GqComparison* self)
 
132
{
 
133
        if(P(self)->adj2) {
 
134
                g_signal_handlers_disconnect_by_func(P(self)->adj2, gtk_widget_queue_draw, self);
 
135
                g_object_unref(P(self)->adj2);
 
136
                P(self)->adj2 = NULL;
 
137
        }
 
138
 
 
139
        if(P(self)->form2) {
 
140
                P(self)->adj2 = g_object_ref(gtk_range_get_adjustment(GTK_RANGE(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(P(self)->form2))->vscrollbar)));
 
141
                g_signal_connect_swapped(P(self)->adj2, "value-changed",
 
142
                                         G_CALLBACK(gtk_widget_queue_draw), self);
 
143
        }
 
144
}
 
145
 
 
146
static void
 
147
comparison_set_property(GObject     * object,
 
148
                        guint         prop_id,
 
149
                        GValue const* value,
 
150
                        GParamSpec  * pspec)
 
151
{
 
152
        switch(prop_id) {
 
153
        case PROP_FORM_1:
 
154
                if(P(object)->form1) {
 
155
                        g_signal_handlers_disconnect_by_func(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(P(object)->form1))->vscrollbar, comparison_update_adj1, object);
 
156
                        g_object_unref(P(object)->form1);
 
157
                }
 
158
                P(object)->form1 = (GqInputForm*)g_value_dup_object(value);
 
159
                gq_difference_set_form1(P(object)->difference, P(object)->form1);
 
160
                if(P(object)->form1) {
 
161
                        g_signal_connect_swapped(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(P(object)->form1))->vscrollbar, "notify::adjustment",
 
162
                                                 G_CALLBACK(comparison_update_adj1), object);
 
163
                }
 
164
                comparison_update_adj1(GQ_COMPARISON(object));
 
165
                g_object_notify(object, "form1");
 
166
                break;
 
167
        case PROP_FORM_2:
 
168
                if(P(object)->form2) {
 
169
                        g_signal_handlers_disconnect_by_func(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(P(object)->form2))->vscrollbar, comparison_update_adj2, object);
 
170
                        g_object_unref(P(object)->form2);
 
171
                }
 
172
                P(object)->form2 = (GqInputForm*)g_value_dup_object(value);
 
173
                gq_difference_set_form2(P(object)->difference, P(object)->form2);
 
174
                if(P(object)->form2) {
 
175
                        g_signal_connect_swapped(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(P(object)->form2))->vscrollbar, "notify::adjustment",
 
176
                                                 G_CALLBACK(comparison_update_adj2), object);
 
177
                }
 
178
                comparison_update_adj2(GQ_COMPARISON(object));
 
179
                g_object_notify(object, "form2");
 
180
                break;
 
181
        default:
 
182
                G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
 
183
                break;
 
184
        }
 
185
}
 
186
 
 
187
static void
 
188
comparison_render_change(GqFormfill* form1,
 
189
                         GqFormfill* form2,
 
190
                         gboolean    equal,
 
191
                         gpointer    user_data)
 
192
{
 
193
        gpointer* self_and_cr = user_data;
 
194
        GqComparison* self = self_and_cr[0];
 
195
        cairo_t* cr = self_and_cr[1];
 
196
        gdouble offsets[2];
 
197
 
 
198
        if(equal) {
 
199
                return;
 
200
        }
 
201
 
 
202
        offsets[0] = gtk_adjustment_get_value(gtk_range_get_adjustment(GTK_RANGE(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(GQ_INPUT_FORM(P(self)->form1)))->vscrollbar)));
 
203
        offsets[1] = gtk_adjustment_get_value(gtk_range_get_adjustment(GTK_RANGE(GTK_SCROLLED_WINDOW(gq_input_form_get_scrolled_window(GQ_INPUT_FORM(P(self)->form1)))->vscrollbar)));
 
204
 
 
205
        cairo_set_line_width(cr, 1.0);
 
206
        if(form1 && form2) {
 
207
                // render difference
 
208
                GtkWidget* label = gq_formfill_get_event_box(form1);
 
209
                gdouble old = (int)(label->allocation.y - offsets[0] + 0.5*label->allocation.height)+0.5;
 
210
                cairo_save(cr);
 
211
                        cairo_rectangle(cr, 0.5, ((int)(label->allocation.y - offsets[0]))+0.5,
 
212
                                        10.0, label->allocation.height - 1);
 
213
                        cairo_set_source_rgb(cr, 0.45, 0.62, 0.81);
 
214
                        cairo_fill_preserve(cr);
 
215
                        cairo_set_source_rgb(cr, 0.13, 0.29, 0.53);
 
216
                        cairo_stroke(cr);
 
217
                cairo_restore(cr);
 
218
                label = gq_formfill_get_event_box(form2);
 
219
                cairo_rectangle(cr, 13.5, ((int)(label->allocation.y - offsets[1]))+0.5, 10.0, label->allocation.height - 1);
 
220
                cairo_set_source_rgb(cr, 0.45, 0.62, 0.81);
 
221
                cairo_fill_preserve(cr);
 
222
                cairo_set_source_rgb(cr, 0.13, 0.29, 0.53);
 
223
                cairo_stroke(cr);
 
224
                cairo_move_to(cr, 5.0, old);
 
225
                cairo_line_to(cr, 19.0, (int)(label->allocation.y - offsets[0] + 0.5*label->allocation.height)-0.5);
 
226
                cairo_stroke(cr);
 
227
        }
 
228
        else if(form1) {
 
229
                // render only in one
 
230
                GtkWidget* label = gq_formfill_get_event_box(form1);
 
231
                cairo_rectangle(cr, 0.5, ((int)(label->allocation.y - offsets[0]))+0.5, 10.0, label->allocation.height - 1);
 
232
                cairo_set_source_rgb(cr, 0.54, 0.88, 0.2);
 
233
                cairo_fill_preserve(cr);
 
234
                cairo_set_source_rgb(cr, 0.3, 0.6, 0.02);
 
235
                cairo_stroke(cr);
 
236
        }
 
237
        else if(form2) {
 
238
                // render only in two
 
239
                GtkWidget* label = gq_formfill_get_event_box(form2);
 
240
                cairo_rectangle(cr, 13.5, ((int)(label->allocation.y - offsets[1]))+0.5, 10.0, label->allocation.height - 1);
 
241
                cairo_set_source_rgb(cr, 0.54, 0.88, 0.2);
 
242
                cairo_fill_preserve(cr);
 
243
                cairo_set_source_rgb(cr, 0.3, 0.6, 0.02);
 
244
                cairo_stroke(cr);
 
245
        }
 
246
}
 
247
 
 
248
static gboolean
 
249
comparison_expose_event(GtkWidget     * widget,
 
250
                        GdkEventExpose* event  G_GNUC_UNUSED)
 
251
{
 
252
        gpointer self_and_cr[2];
 
253
        cairo_t* cr = gdk_cairo_create(widget->window);
 
254
#if 0
 
255
        GtkWidget* reference = widget;
 
256
        /* this area matches the whole widget */
 
257
        cairo_rectangle(cr, 0, 0,
 
258
                        reference->allocation.width,
 
259
                        reference->allocation.height);
 
260
#elsif 0
 
261
        GtkWidget* reference = P(widget)->form1->scwin;
 
262
        /* this area matches the scrolled window */
 
263
        cairo_rectangle(cr,
 
264
                        0, reference->allocation.y - widget->allocation.y,
 
265
                        widget->allocation.width, reference->allocation.height);
 
266
#else
 
267
        GtkWidget* reference = gtk_bin_get_child(GTK_BIN(gq_input_form_get_scrolled_window(GQ_INPUT_FORM(P(widget)->form1))));
 
268
        //cairo_rectangle(cr, 0, reference->allocation.y - widget->allocation.y,
 
269
        //              widget->allocation.width, reference->allocation.height);
 
270
#endif
 
271
#if 0
 
272
        cairo_set_source_rgb(cr, 0.68, 0.50, 0.66);
 
273
        cairo_fill(cr);
 
274
#endif
 
275
        cairo_translate(cr, 0.0, reference->allocation.y - widget->allocation.y);
 
276
        self_and_cr[0] = widget;
 
277
        self_and_cr[1] = cr;
 
278
        gq_difference_foreach(P(widget)->difference, comparison_render_change, self_and_cr);
 
279
 
 
280
        cairo_destroy(cr);
 
281
        return TRUE;
 
282
}
 
283
 
 
284
static void
 
285
comparison_size_request(GtkWidget     * self G_GNUC_UNUSED,
 
286
                        GtkRequisition* requisition)
 
287
{
 
288
        requisition->width = 24;
 
289
}
 
290
 
 
291
static void
 
292
gq_comparison_class_init(GqComparisonClass* self_class G_GNUC_UNUSED)
 
293
{
 
294
        GObjectClass*   object_class = G_OBJECT_CLASS(self_class);
 
295
        GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(self_class);
 
296
 
 
297
        /* GObjectClass */
 
298
        object_class->dispose      = comparison_dispose;
 
299
        object_class->get_property = comparison_get_property;
 
300
        object_class->set_property = comparison_set_property;
 
301
 
 
302
        g_object_class_install_property(object_class, PROP_FORM_1,
 
303
                                        g_param_spec_object("form1",
 
304
                                                            _("Form 1"),
 
305
                                                            _("The first form to be compared by this item"),
 
306
                                                            GQ_TYPE_INPUT_FORM, G_PARAM_READWRITE));
 
307
        g_object_class_install_property(object_class, PROP_FORM_2,
 
308
                                        g_param_spec_object("form2",
 
309
                                                            _("Form 2"),
 
310
                                                            _("The second form to be compared by this item"),
 
311
                                                            GQ_TYPE_INPUT_FORM, G_PARAM_READWRITE));
 
312
 
 
313
        /* GtkWidgetClass */
 
314
        widget_class->expose_event = comparison_expose_event;
 
315
        widget_class->size_request = comparison_size_request;
 
316
 
 
317
        /* GqComparisonClass */
 
318
        g_type_class_add_private(self_class, sizeof(struct GqComparisonPrivate));
 
319
}
 
320