1
/* This file is part of GQ
4
* Sven Herzberg <herzi@gnome-de.org>
6
* Copyright (C) 2006 Sven Herzberg
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.
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.
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
24
#include "gq-comparison.h"
26
#include <glib/gi18n.h>
27
#include "gq-difference.h"
29
struct GqComparisonPrivate {
34
GqDifference * difference;
36
#define P(i) (G_TYPE_INSTANCE_GET_PRIVATE((i), GQ_TYPE_COMPARISON, struct GqComparisonPrivate))
39
gq_comparison_new(GqInputForm* form1,
42
return g_object_new(GQ_TYPE_COMPARISON,
49
gq_comparison_get_difference(GqComparison const* self)
51
g_return_val_if_fail(GQ_IS_COMPARISON(self), NULL);
53
return P(self)->difference;
57
G_DEFINE_TYPE(GqComparison, gq_comparison, GTK_TYPE_DRAWING_AREA);
66
gq_comparison_init(GqComparison* self)
68
P(self)->difference = gq_difference_new();
69
g_signal_connect_swapped(P(self)->difference, "updated",
70
G_CALLBACK(gtk_widget_queue_draw), self);
74
comparison_dispose(GObject* object)
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;
82
if(P(object)->form1) {
83
g_object_unref(P(object)->form1);
84
P(object)->form1 = NULL;
87
if(P(object)->form2) {
88
g_object_unref(P(object)->form2);
89
P(object)->form2 = NULL;
92
G_OBJECT_CLASS(gq_comparison_parent_class)->dispose(object);
96
comparison_get_property(GObject * object,
103
g_value_set_object(value, P(object)->form1);
106
g_value_set_object(value, P(object)->form2);
109
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
115
comparison_update_adj1(GqComparison* self)
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;
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);
131
comparison_update_adj2(GqComparison* self)
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;
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);
147
comparison_set_property(GObject * object,
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);
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);
164
comparison_update_adj1(GQ_COMPARISON(object));
165
g_object_notify(object, "form1");
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);
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);
178
comparison_update_adj2(GQ_COMPARISON(object));
179
g_object_notify(object, "form2");
182
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
188
comparison_render_change(GqFormfill* form1,
193
gpointer* self_and_cr = user_data;
194
GqComparison* self = self_and_cr[0];
195
cairo_t* cr = self_and_cr[1];
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)));
205
cairo_set_line_width(cr, 1.0);
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;
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);
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);
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);
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);
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);
249
comparison_expose_event(GtkWidget * widget,
250
GdkEventExpose* event G_GNUC_UNUSED)
252
gpointer self_and_cr[2];
253
cairo_t* cr = gdk_cairo_create(widget->window);
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);
261
GtkWidget* reference = P(widget)->form1->scwin;
262
/* this area matches the scrolled window */
264
0, reference->allocation.y - widget->allocation.y,
265
widget->allocation.width, reference->allocation.height);
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);
272
cairo_set_source_rgb(cr, 0.68, 0.50, 0.66);
275
cairo_translate(cr, 0.0, reference->allocation.y - widget->allocation.y);
276
self_and_cr[0] = widget;
278
gq_difference_foreach(P(widget)->difference, comparison_render_change, self_and_cr);
285
comparison_size_request(GtkWidget * self G_GNUC_UNUSED,
286
GtkRequisition* requisition)
288
requisition->width = 24;
292
gq_comparison_class_init(GqComparisonClass* self_class G_GNUC_UNUSED)
294
GObjectClass* object_class = G_OBJECT_CLASS(self_class);
295
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(self_class);
298
object_class->dispose = comparison_dispose;
299
object_class->get_property = comparison_get_property;
300
object_class->set_property = comparison_set_property;
302
g_object_class_install_property(object_class, PROP_FORM_1,
303
g_param_spec_object("form1",
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",
310
_("The second form to be compared by this item"),
311
GQ_TYPE_INPUT_FORM, G_PARAM_READWRITE));
314
widget_class->expose_event = comparison_expose_event;
315
widget_class->size_request = comparison_size_request;
317
/* GqComparisonClass */
318
g_type_class_add_private(self_class, sizeof(struct GqComparisonPrivate));