1 /*
2 *
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU Lesser General Public License as published by
5 * the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
10 * for more details.
11 *
12 * You should have received a copy of the GNU Lesser General Public License
13 * along with this program; if not, see <http://www.gnu.org/licenses/>.
14 *
15 *
16 * Authors:
17 * Chris Lahey <clahey@ximian.com>
18 *
19 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
20 *
21 */
22
23 #include "evolution-config.h"
24
25 #include <libedataserver/libedataserver.h>
26 #include "e-canvas-utils.h"
27
28 void
e_canvas_item_move_absolute(GnomeCanvasItem * item,gdouble dx,gdouble dy)29 e_canvas_item_move_absolute (GnomeCanvasItem *item,
30 gdouble dx,
31 gdouble dy)
32 {
33 cairo_matrix_t translate;
34
35 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
36
37 cairo_matrix_init_translate (&translate, dx, dy);
38
39 gnome_canvas_item_set_matrix (item, &translate);
40 }
41
42 static double
compute_offset(gint top,gint bottom,gint page_top,gint page_bottom)43 compute_offset (gint top,
44 gint bottom,
45 gint page_top,
46 gint page_bottom)
47 {
48 gint size = bottom - top;
49 gint offset = 0;
50
51 if (top <= page_top && bottom >= page_bottom)
52 return 0;
53
54 if (bottom > page_bottom)
55 offset = (bottom - page_bottom);
56 if (top < page_top + offset)
57 offset = (top - page_top);
58
59 if (top <= page_top + offset && bottom >= page_bottom + offset)
60 return offset;
61
62 if (top < page_top + size * 3 / 2 + offset)
63 offset = top - (page_top + size * 3 / 2);
64 if (bottom > page_bottom - size * 3 / 2 + offset)
65 offset = bottom - (page_bottom - size * 3 / 2);
66 if (top < page_top + size * 3 / 2 + offset)
67 offset = top - ((page_top + page_bottom - (bottom - top)) / 2);
68
69 return offset;
70 }
71
72 static void
e_canvas_show_area(GnomeCanvas * canvas,gdouble x1,gdouble y1,gdouble x2,gdouble y2)73 e_canvas_show_area (GnomeCanvas *canvas,
74 gdouble x1,
75 gdouble y1,
76 gdouble x2,
77 gdouble y2)
78 {
79 GtkAdjustment *h, *v;
80 gint dx = 0, dy = 0;
81 gdouble page_size;
82 gdouble lower;
83 gdouble upper;
84 gdouble value;
85
86 g_return_if_fail (canvas != NULL);
87 g_return_if_fail (GNOME_IS_CANVAS (canvas));
88
89 h = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas));
90 page_size = gtk_adjustment_get_page_size (h);
91 lower = gtk_adjustment_get_lower (h);
92 upper = gtk_adjustment_get_upper (h);
93 value = gtk_adjustment_get_value (h);
94 dx = compute_offset (x1, x2, value, value + page_size);
95 if (dx)
96 gtk_adjustment_set_value (h, CLAMP (value + dx, lower, upper - page_size));
97
98 v = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas));
99 page_size = gtk_adjustment_get_page_size (v);
100 lower = gtk_adjustment_get_lower (v);
101 upper = gtk_adjustment_get_upper (v);
102 value = gtk_adjustment_get_value (v);
103 dy = compute_offset (y1, y2, value, value + page_size);
104 if (dy)
105 gtk_adjustment_set_value (v, CLAMP (value + dy, lower, upper - page_size));
106 }
107
108 void
e_canvas_item_show_area(GnomeCanvasItem * item,gdouble x1,gdouble y1,gdouble x2,gdouble y2)109 e_canvas_item_show_area (GnomeCanvasItem *item,
110 gdouble x1,
111 gdouble y1,
112 gdouble x2,
113 gdouble y2)
114 {
115 g_return_if_fail (item != NULL);
116 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
117
118 gnome_canvas_item_i2w (item, &x1, &y1);
119 gnome_canvas_item_i2w (item, &x2, &y2);
120
121 e_canvas_show_area (item->canvas, x1, y1, x2, y2);
122 }
123
124 static gboolean
e_canvas_area_shown(GnomeCanvas * canvas,gdouble x1,gdouble y1,gdouble x2,gdouble y2)125 e_canvas_area_shown (GnomeCanvas *canvas,
126 gdouble x1,
127 gdouble y1,
128 gdouble x2,
129 gdouble y2)
130 {
131 GtkAdjustment *h, *v;
132 gint dx = 0, dy = 0;
133 gdouble page_size;
134 gdouble lower;
135 gdouble upper;
136 gdouble value;
137
138 g_return_val_if_fail (canvas != NULL, FALSE);
139 g_return_val_if_fail (GNOME_IS_CANVAS (canvas), FALSE);
140
141 h = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas));
142 page_size = gtk_adjustment_get_page_size (h);
143 lower = gtk_adjustment_get_lower (h);
144 upper = gtk_adjustment_get_upper (h);
145 value = gtk_adjustment_get_value (h);
146 dx = compute_offset (x1, x2, value, value + page_size);
147 if (CLAMP (value + dx, lower, upper - page_size) - value != 0)
148 return FALSE;
149
150 v = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas));
151 page_size = gtk_adjustment_get_page_size (v);
152 lower = gtk_adjustment_get_lower (v);
153 upper = gtk_adjustment_get_upper (v);
154 value = gtk_adjustment_get_value (v);
155 dy = compute_offset (y1, y2, value, value + page_size);
156 if (CLAMP (value + dy, lower, upper - page_size) - value != 0)
157 return FALSE;
158 return TRUE;
159 }
160
161 gboolean
e_canvas_item_area_shown(GnomeCanvasItem * item,gdouble x1,gdouble y1,gdouble x2,gdouble y2)162 e_canvas_item_area_shown (GnomeCanvasItem *item,
163 gdouble x1,
164 gdouble y1,
165 gdouble x2,
166 gdouble y2)
167 {
168 g_return_val_if_fail (item != NULL, FALSE);
169 g_return_val_if_fail (GNOME_IS_CANVAS_ITEM (item), FALSE);
170
171 gnome_canvas_item_i2w (item, &x1, &y1);
172 gnome_canvas_item_i2w (item, &x2, &y2);
173
174 return e_canvas_area_shown (item->canvas, x1, y1, x2, y2);
175 }
176
177 typedef struct {
178 gdouble x1;
179 gdouble y1;
180 gdouble x2;
181 gdouble y2;
182 GnomeCanvas *canvas;
183 } DoubsAndCanvas;
184
185 static void
doubs_and_canvas_free(gpointer ptr)186 doubs_and_canvas_free (gpointer ptr)
187 {
188 DoubsAndCanvas *dac = ptr;
189
190 if (dac) {
191 g_object_unref (dac->canvas);
192 g_free (dac);
193 }
194 }
195
196 static gboolean
show_area_timeout(gpointer data)197 show_area_timeout (gpointer data)
198 {
199 DoubsAndCanvas *dac = data;
200
201 e_canvas_show_area (dac->canvas, dac->x1, dac->y1, dac->x2, dac->y2);
202
203 return FALSE;
204 }
205
206 void
e_canvas_item_show_area_delayed(GnomeCanvasItem * item,gdouble x1,gdouble y1,gdouble x2,gdouble y2,gint delay)207 e_canvas_item_show_area_delayed (GnomeCanvasItem *item,
208 gdouble x1,
209 gdouble y1,
210 gdouble x2,
211 gdouble y2,
212 gint delay)
213 {
214 GSource *source;
215
216 source = e_canvas_item_show_area_delayed_ex (item, x1, y1, x2, y2, delay);
217 if (source)
218 g_source_unref (source);
219 }
220
221 /* Use g_source_unref() when done with the returned pointer. */
222 GSource *
e_canvas_item_show_area_delayed_ex(GnomeCanvasItem * item,gdouble x1,gdouble y1,gdouble x2,gdouble y2,gint delay)223 e_canvas_item_show_area_delayed_ex (GnomeCanvasItem *item,
224 gdouble x1,
225 gdouble y1,
226 gdouble x2,
227 gdouble y2,
228 gint delay)
229 {
230 GSource *source;
231 DoubsAndCanvas *dac;
232
233 g_return_val_if_fail (item != NULL, NULL);
234 g_return_val_if_fail (GNOME_IS_CANVAS_ITEM (item), NULL);
235
236 gnome_canvas_item_i2w (item, &x1, &y1);
237 gnome_canvas_item_i2w (item, &x2, &y2);
238
239 dac = g_new (DoubsAndCanvas, 1);
240 dac->x1 = x1;
241 dac->y1 = y1;
242 dac->x2 = x2;
243 dac->y2 = y2;
244 dac->canvas = g_object_ref (item->canvas);
245
246 source = g_timeout_source_new (delay);
247 g_source_set_callback (source, show_area_timeout, dac, doubs_and_canvas_free);
248 g_source_set_name (source, G_STRFUNC);
249 g_source_attach (source, NULL);
250
251 return source;
252 }
253