Replace hildon pannable area with modest scrollable in msg view window
[modest] / src / widgets / modest-scrollable.c
1 /* Copyright (c) 2009, Igalia
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <config.h>
31
32 #include <modest-scrollable.h>
33
34 /**
35  * modest_scrollable_add_with_viewport:
36  * @scrollable: a #ModestScrollable instance
37  * @widget: a #GtkWidget
38  *
39  * adds a widget to the @scrollable, wrapping it into a viewport.
40  * This is useful if @widget does not implement scroll_adjustments
41  * interface.
42  */
43 void            
44 modest_scrollable_add_with_viewport (ModestScrollable *scrollable,
45                                      GtkWidget *widget)
46 {
47         if (MODEST_SCROLLABLE_GET_IFACE (scrollable)->add_with_viewport) {
48                 MODEST_SCROLLABLE_GET_IFACE (scrollable)->add_with_viewport (scrollable, widget);
49         }
50 }
51
52 /**
53  * modest_scrollable_get_vadjustment:
54  * @self: a #ModestScrollable
55  *
56  * obtains the vertical adjustment for @self
57  *
58  * Returns: a #GtkAdjustment
59  */
60 GtkAdjustment *
61 modest_scrollable_get_vadjustment (ModestScrollable *self)
62 {
63         if (MODEST_SCROLLABLE_GET_IFACE (self)->get_vadjustment) {
64                 return MODEST_SCROLLABLE_GET_IFACE (self)->get_vadjustment (self);
65         } else {
66                 return NULL;
67         }
68 }
69
70 /**
71  * modest_scrollable_get_hadjustment:
72  * @self: a #ModestScrollable
73  *
74  * obtains the horizontal adjustment for @self
75  *
76  * Returns: a #GtkAdjustment
77  */
78 GtkAdjustment *
79 modest_scrollable_get_hadjustment (ModestScrollable *self)
80 {
81         if (MODEST_SCROLLABLE_GET_IFACE (self)->get_hadjustment) {
82                 return MODEST_SCROLLABLE_GET_IFACE (self)->get_hadjustment (self);
83         } else {
84                 return NULL;
85         }
86 }
87
88 /**
89  * modest_scrollable_scroll_to:
90  * @scrollable: a #ModestScrollable instance
91  * @x: the X coordinate to scroll to
92  * @y: the Y coordinate to scroll to
93  *
94  * scrolls softly visible area of @scrollable, to show the coordinates
95  * (@x, @y).
96  */
97 void            
98 modest_scrollable_scroll_to (ModestScrollable *scrollable,
99                              const gint x, const gint y)
100 {
101         if (MODEST_SCROLLABLE_GET_IFACE (scrollable)->scroll_to) {
102                 MODEST_SCROLLABLE_GET_IFACE (scrollable)->scroll_to (scrollable, x, y);
103         }
104 }
105
106 /**
107  * modest_scrollable_jump_to:
108  * @scrollable: a #ModestScrollable instance
109  * @x: the X coordinate to jump to
110  * @y: the Y coordinate to jump to
111  *
112  * scrolls visible area of @scrollable, to show the coordinates
113  * (@x, @y). Movement is immediate.
114  */
115 void            
116 modest_scrollable_jump_to (ModestScrollable *scrollable,
117                              const gint x, const gint y)
118 {
119         if (MODEST_SCROLLABLE_GET_IFACE (scrollable)->jump_to) {
120                 MODEST_SCROLLABLE_GET_IFACE (scrollable)->jump_to (scrollable, x, y);
121         }
122 }
123
124 /**
125  * modest_scrollable_get_vertical_policy:
126  * @scrollable: a #ModestScrollable instance
127  *
128  * returns the vertical scroll policy
129  *
130  * Returns: a #GtkPolicyType
131  */
132 GtkPolicyType            
133 modest_scrollable_get_vertical_policy (ModestScrollable *scrollable)
134 {
135         if (MODEST_SCROLLABLE_GET_IFACE (scrollable)->get_vertical_policy) {
136                 return MODEST_SCROLLABLE_GET_IFACE (scrollable)->get_vertical_policy (scrollable);
137         } else {
138                 return GTK_POLICY_NEVER;
139         }
140 }
141
142 /**
143  * modest_scrollable_get_horizontal_policy:
144  * @scrollable: a #ModestScrollable instance
145  *
146  * returns the horizontal scroll policy
147  *
148  * Returns: a #GtkPolicyType
149  */
150 GtkPolicyType            
151 modest_scrollable_get_horizontal_policy (ModestScrollable *scrollable)
152 {
153         if (MODEST_SCROLLABLE_GET_IFACE (scrollable)->get_horizontal_policy) {
154                 return MODEST_SCROLLABLE_GET_IFACE (scrollable)->get_horizontal_policy (scrollable);
155         } else {
156                 return GTK_POLICY_NEVER;
157         }
158 }
159
160 /**
161  * modest_scrollable_set_vertical_policy:
162  * @scrollable: a #ModestScrollable instance
163  * @policy: a #GtkPolicyType
164  *
165  * sets the vertical scroll policy
166  */
167 void
168 modest_scrollable_set_vertical_policy (ModestScrollable *scrollable,
169                                        GtkPolicyType policy)
170 {
171         if (MODEST_SCROLLABLE_GET_IFACE (scrollable)->set_vertical_policy) {
172                 MODEST_SCROLLABLE_GET_IFACE (scrollable)->set_vertical_policy (scrollable, policy);
173         }
174 }
175
176 /**
177  * modest_scrollable_set_horizontal_policy:
178  * @scrollable: a #ModestScrollable instance
179  * @policy: a #GtkPolicyType
180  *
181  * sets the horizontal scroll policy
182  */
183 void
184 modest_scrollable_set_horizontal_policy (ModestScrollable *scrollable,
185                                          GtkPolicyType policy)
186 {
187         if (MODEST_SCROLLABLE_GET_IFACE (scrollable)->set_horizontal_policy) {
188                 MODEST_SCROLLABLE_GET_IFACE (scrollable)->set_horizontal_policy (scrollable, policy);
189         }
190 }
191
192 static void
193 modest_scrollable_base_init (gpointer g_iface)
194 {
195         static gboolean initialized = FALSE;
196
197         if (!initialized) {
198                 /* create interface signals here. */
199                 initialized = TRUE;
200
201                 g_object_interface_install_property (g_iface,
202                                                      g_param_spec_enum ("vertical_policy",
203                                                                         "Vertical scroll policy",
204                                                                         "Visual policy of the vertical scroll",
205                                                                         GTK_TYPE_POLICY_TYPE,
206                                                                         GTK_POLICY_AUTOMATIC,
207                                                                         G_PARAM_READWRITE |
208                                                                         G_PARAM_CONSTRUCT));
209
210                 g_object_interface_install_property (g_iface,
211                                                      g_param_spec_enum ("horizontal_policy",
212                                                                         "Horizontal scroll policy",
213                                                                         "Visual policy of the horizontal scroll",
214                                                                         GTK_TYPE_POLICY_TYPE,
215                                                                         GTK_POLICY_AUTOMATIC,
216                                                                         G_PARAM_READWRITE |
217                                                                         G_PARAM_CONSTRUCT));
218
219                 g_object_interface_install_property (g_iface,
220                                                      g_param_spec_enum ("movement_mode",
221                                                                         "Directions scroll is allowed",
222                                                                         "Movements allowed in the scrollable",
223                                                                         MODEST_TYPE_MOVEMENT_MODE,
224                                                                         MODEST_MOVEMENT_MODE_VERTICAL,
225                                                                         G_PARAM_READWRITE |
226                                                                         G_PARAM_CONSTRUCT));
227
228                 g_object_interface_install_property (g_iface,
229                                                      g_param_spec_int ("horizontal-max-overshoot",
230                                                                        "Horizontal max overshoot",
231                                                                        "Horizontal maximum overshoot (0 disables)",
232                                                                        0, G_MAXINT, 150,
233                                                                        G_PARAM_READWRITE |G_PARAM_CONSTRUCT));
234
235                 g_object_interface_install_property (g_iface,
236                                                      g_param_spec_int ("vertical-max-overshoot",
237                                                                        "Vertical max overshoot",
238                                                                        "Vertical maximum overshoot (0 disables)",
239                                                                        0, G_MAXINT, 150,
240                                                                        G_PARAM_READWRITE |G_PARAM_CONSTRUCT));
241
242
243         }
244 }
245
246 GType
247 modest_scrollable_get_type (void)
248 {
249         static GType type = 0;
250
251         if (G_UNLIKELY(type == 0)) 
252         {
253                 static const GTypeInfo info = 
254                 {
255                   sizeof (ModestScrollableIface),
256                   modest_scrollable_base_init,   /* base_init */
257                   NULL,   /* base_finalize */
258                   NULL,   /* class_init */
259                   NULL,   /* class_finalize */
260                   NULL,   /* class_data */
261                   0,
262                   0,      /* n_preallocs */
263                   NULL,   /* instance_init */
264                   NULL
265                 };
266
267                 type = g_type_register_static (G_TYPE_INTERFACE,
268                         "ModestScrollable", &info, 0);
269
270         }
271
272         return type;
273 }
274
275 void
276 modest_scrollable_scroll (ModestScrollable *scrollable, 
277                           gint horizontal, gint vertical)
278 {
279         g_return_if_fail (MODEST_IS_SCROLLABLE (scrollable));
280         gint h_pos = -1;
281         gint v_pos = -1;
282
283         g_assert (scrollable);
284         /* at atleast one of values have to be valid */
285         g_return_if_fail (h_pos == -1 && v_pos == -1);
286
287         if (horizontal != 0) {
288                 GtkAdjustment *h_adj;
289
290                 h_adj = modest_scrollable_get_hadjustment (scrollable);
291                 g_return_if_fail (h_adj);
292
293                 h_pos = h_adj->value + h_adj->step_increment * horizontal;
294                 if (horizontal > 0) {
295                         h_pos += h_adj->page_size;
296                 }
297         }
298
299         if (vertical != 0) {
300                 GtkAdjustment *v_adj;
301
302                 v_adj = modest_scrollable_get_vadjustment (scrollable);
303                 g_return_if_fail (v_adj);
304
305                 v_pos = v_adj->value + v_adj->step_increment * vertical;
306                 if (vertical > 0) {
307                         v_pos += v_adj->page_size;
308                 }
309         }
310
311         modest_scrollable_scroll_to (scrollable, h_pos, v_pos);
312 }
313
314 GType
315 modest_movement_mode_get_type (void)
316 {
317   static GType etype = 0;
318   if (etype == 0) {
319     static const GFlagsValue values[] = {
320             { MODEST_MOVEMENT_MODE_HORIZONTAL, "HILDON_MOVEMENT_MODE_HORIZONTAL", "horizontal" },
321             { MODEST_MOVEMENT_MODE_VERTICAL, "MODEST_MOVEMENT_MODE_VERTICAL", "vertical" },
322             { MODEST_MOVEMENT_MODE_BOTH, "MODEST_MOVEMENT_MODE_BOTH", "both" },
323             { 0, NULL, NULL }
324     };
325     etype = g_flags_register_static ("ModestMovementMode", values);
326   }
327   return etype;
328 }