1 /*
2 * overviewprefs.c - This file is part of the Geany Overview plugin
3 *
4 * Copyright (c) 2015 Matthew Brush <mbrush@codebrainz.ca>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 * MA 02110-1301, USA.
20 *
21 */
22
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
26
27 #include "overviewprefs.h"
28 #include "overviewcolor.h"
29 #include "overviewscintilla.h"
30 #include <string.h>
31 #include <stdarg.h>
32
33 enum
34 {
35 PROP_0,
36 PROP_WIDTH,
37 PROP_ZOOM,
38 PROP_SHOW_TOOLTIP,
39 PROP_SHOW_SCROLLBAR,
40 PROP_DOUBLE_BUFFERED,
41 PROP_SCROLL_LINES,
42 PROP_OVERLAY_ENABLED,
43 PROP_OVERLAY_COLOR,
44 PROP_OVERLAY_OUTLINE_COLOR,
45 PROP_OVERLAY_INVERTED,
46 PROP_POSITION,
47 PROP_VISIBLE,
48 N_PROPERTIES
49 };
50
51 struct OverviewPrefs_
52 {
53 GObject parent;
54 guint width;
55 gint zoom;
56 gboolean show_tt;
57 gboolean show_sb;
58 gboolean dbl_buf;
59 gint scr_lines;
60 gboolean ovl_en;
61 OverviewColor ovl_clr;
62 OverviewColor out_clr;
63 gboolean ovl_inv;
64 GtkPositionType position;
65 gboolean visible;
66 };
67
68 struct OverviewPrefsClass_
69 {
70 GObjectClass parent_class;
71 };
72
73 static void overview_prefs_finalize (GObject *object);
74 static void overview_prefs_set_property (GObject *object,
75 guint prop_id,
76 const GValue *value,
77 GParamSpec *pspec);
78 static void overview_prefs_get_property (GObject *object,
79 guint prop_id,
80 GValue *value,
81 GParamSpec *pspec);
82
83
84 static GParamSpec *pspecs[N_PROPERTIES] = { NULL };
85
G_DEFINE_TYPE(OverviewPrefs,overview_prefs,G_TYPE_OBJECT)86 G_DEFINE_TYPE (OverviewPrefs, overview_prefs, G_TYPE_OBJECT)
87
88 static void
89 overview_prefs_class_init (OverviewPrefsClass *klass)
90 {
91 GObjectClass *g_object_class;
92
93 g_object_class = G_OBJECT_CLASS (klass);
94
95 g_object_class->finalize = overview_prefs_finalize;
96 g_object_class->set_property = overview_prefs_set_property;
97 g_object_class->get_property = overview_prefs_get_property;
98
99 pspecs[PROP_WIDTH] = g_param_spec_uint ("width", "Width", "Width of the overview", 16, 512, 120, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
100 pspecs[PROP_ZOOM] = g_param_spec_int ("zoom", "Zoom", "Zoom level of the view", -10, 20, -10, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
101 pspecs[PROP_SHOW_TOOLTIP] = g_param_spec_boolean ("show-tooltip", "ShowTooltip", "Whether to show informational tooltip over the overview", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
102 pspecs[PROP_SHOW_SCROLLBAR] = g_param_spec_boolean ("show-scrollbar", "ShowScrollbar", "Whether to show the normal editor scrollbar", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
103 pspecs[PROP_DOUBLE_BUFFERED] = g_param_spec_boolean ("double-buffered", "DoubleBuffered", "Whether the overview drawing is double-buffered", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
104 pspecs[PROP_SCROLL_LINES] = g_param_spec_uint ("scroll-lines", "ScrollLines", "The number of lines to scroll the overview by", 1, 512, 1, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
105 pspecs[PROP_OVERLAY_ENABLED] = g_param_spec_boolean ("overlay-enabled", "OverlayEnabled", "Whether an overlay is drawn overtop the overview", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
106 pspecs[PROP_OVERLAY_COLOR] = g_param_spec_boxed ("overlay-color", "OverlayColor", "The color of the overlay", OVERVIEW_TYPE_COLOR, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
107 pspecs[PROP_OVERLAY_OUTLINE_COLOR] = g_param_spec_boxed ("overlay-outline-color", "OverlayOutlineColor", "The color of the outlines drawn around the overlay", OVERVIEW_TYPE_COLOR, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
108 pspecs[PROP_OVERLAY_INVERTED] = g_param_spec_boolean ("overlay-inverted", "OverlayInverted", "Whether to invert the drawing of the overlay", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
109 pspecs[PROP_POSITION] = g_param_spec_enum ("position", "Position", "Where to draw the overview", GTK_TYPE_POSITION_TYPE, GTK_POS_RIGHT, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
110 pspecs[PROP_VISIBLE] = g_param_spec_boolean ("visible", "Visible", "Whether the overview is shown", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
111
112 g_object_class_install_properties (g_object_class, N_PROPERTIES, pspecs);
113 }
114
115 static void
overview_prefs_finalize(GObject * object)116 overview_prefs_finalize (GObject *object)
117 {
118 g_return_if_fail (OVERVIEW_IS_PREFS (object));
119 G_OBJECT_CLASS (overview_prefs_parent_class)->finalize (object);
120 }
121
122 static void
overview_prefs_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)123 overview_prefs_set_property (GObject *object,
124 guint prop_id,
125 const GValue *value,
126 GParamSpec *pspec)
127 {
128 OverviewPrefs *self = OVERVIEW_PREFS (object);
129
130 switch (prop_id)
131 {
132 case PROP_WIDTH:
133 self->width = g_value_get_uint (value);
134 g_object_notify (object, "width");
135 break;
136 case PROP_ZOOM:
137 self->zoom = g_value_get_int (value);
138 g_object_notify (object, "zoom");
139 break;
140 case PROP_SHOW_TOOLTIP:
141 self->show_tt = g_value_get_boolean (value);
142 g_object_notify (object, "show-tooltip");
143 break;
144 case PROP_SHOW_SCROLLBAR:
145 self->show_sb = g_value_get_boolean (value);
146 g_object_notify (object, "show-scrollbar");
147 break;
148 case PROP_DOUBLE_BUFFERED:
149 self->dbl_buf = g_value_get_boolean (value);
150 g_object_notify (object, "double-buffered");
151 break;
152 case PROP_SCROLL_LINES:
153 self->scr_lines = g_value_get_uint (value);
154 g_object_notify (object, "scroll-lines");
155 break;
156 case PROP_OVERLAY_ENABLED:
157 self->ovl_en = g_value_get_boolean (value);
158 g_object_notify (object, "overlay-enabled");
159 break;
160 case PROP_OVERLAY_COLOR:
161 {
162 OverviewColor *src = g_value_get_boxed (value);
163 if (src != NULL)
164 memcpy (&self->ovl_clr, src, sizeof (OverviewColor));
165 g_object_notify (object, "overlay-color");
166 break;
167 }
168 case PROP_OVERLAY_OUTLINE_COLOR:
169 {
170 OverviewColor *src = g_value_get_boxed (value);
171 if (src != NULL)
172 memcpy (&self->out_clr, src, sizeof (OverviewColor));
173 g_object_notify (object, "overlay-outline-color");
174 break;
175 }
176 case PROP_OVERLAY_INVERTED:
177 self->ovl_inv = g_value_get_boolean (value);
178 g_object_notify (G_OBJECT (self), "overlay-inverted");
179 break;
180 case PROP_POSITION:
181 self->position = g_value_get_enum (value);
182 g_object_notify (G_OBJECT (self), "position");
183 break;
184 case PROP_VISIBLE:
185 self->visible = g_value_get_boolean (value);
186 g_object_notify (G_OBJECT (self), "visible");
187 break;
188 default:
189 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
190 break;
191 }
192 }
193
194 static void
overview_prefs_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)195 overview_prefs_get_property (GObject *object,
196 guint prop_id,
197 GValue *value,
198 GParamSpec *pspec)
199 {
200 OverviewPrefs *self = OVERVIEW_PREFS (object);
201
202 switch (prop_id)
203 {
204 case PROP_WIDTH:
205 g_value_set_uint (value, self->width);
206 break;
207 case PROP_ZOOM:
208 g_value_set_int (value, self->zoom);
209 break;
210 case PROP_SHOW_TOOLTIP:
211 g_value_set_boolean (value, self->show_tt);
212 break;
213 case PROP_SHOW_SCROLLBAR:
214 g_value_set_boolean (value, self->show_sb);
215 break;
216 case PROP_DOUBLE_BUFFERED:
217 g_value_set_boolean (value, self->dbl_buf);
218 break;
219 case PROP_SCROLL_LINES:
220 g_value_set_uint (value, self->scr_lines);
221 break;
222 case PROP_OVERLAY_ENABLED:
223 g_value_set_boolean (value, self->ovl_en);
224 break;
225 case PROP_OVERLAY_COLOR:
226 g_value_set_boxed (value, &self->ovl_clr);
227 break;
228 case PROP_OVERLAY_OUTLINE_COLOR:
229 g_value_set_boxed (value, &self->out_clr);
230 break;
231 case PROP_OVERLAY_INVERTED:
232 g_value_set_boolean (value, self->ovl_inv);
233 break;
234 case PROP_POSITION:
235 g_value_set_enum (value, self->position);
236 break;
237 case PROP_VISIBLE:
238 g_value_set_boolean (value, self->visible);
239 break;
240 default:
241 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
242 break;
243 }
244 }
245
246 static void
overview_prefs_init(OverviewPrefs * self)247 overview_prefs_init (OverviewPrefs *self)
248 {
249 self->position = GTK_POS_RIGHT;
250 self->visible = TRUE;
251 }
252
253 OverviewPrefs *
overview_prefs_new(void)254 overview_prefs_new (void)
255 {
256 return g_object_new (OVERVIEW_TYPE_PREFS, NULL);
257 }
258
259 gboolean
overview_prefs_load(OverviewPrefs * self,const gchar * filename,GError ** error)260 overview_prefs_load (OverviewPrefs *self,
261 const gchar *filename,
262 GError **error)
263 {
264 gchar *contents = NULL;
265 gsize size = 0;
266 g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE);
267 g_return_val_if_fail (filename != NULL, FALSE);
268 if (! g_file_get_contents (filename, &contents, &size, error))
269 return FALSE;
270 if (! overview_prefs_from_data (self, contents, size, error))
271 {
272 g_free (contents);
273 return FALSE;
274 }
275 g_free (contents);
276 return TRUE;
277 }
278
279 gboolean
overview_prefs_save(OverviewPrefs * self,const gchar * filename,GError ** error)280 overview_prefs_save (OverviewPrefs *self,
281 const gchar *filename,
282 GError **error)
283
284 {
285 gchar *contents = NULL;
286 gsize size = 0;
287 g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE);
288 g_return_val_if_fail (filename != NULL, FALSE);
289 contents = overview_prefs_to_data (self, &size, error);
290 if (contents == NULL)
291 return FALSE;
292 if (! g_file_set_contents (filename, contents, size, error))
293 {
294 g_free (contents);
295 return FALSE;
296 }
297 g_free (contents);
298 return TRUE;
299 }
300
301 #define GET(T, k, v) \
302 do { \
303 if (g_key_file_has_key (kf, "overview", k, NULL)) { \
304 v = g_key_file_get_##T (kf, "overview", k, error); \
305 if (error != NULL && *error != NULL) { \
306 g_key_file_free (kf); \
307 return FALSE; \
308 } else { \
309 g_object_notify (G_OBJECT (self), k); \
310 } \
311 } \
312 } while (0)
313
314 gboolean
overview_prefs_from_data(OverviewPrefs * self,const gchar * contents,gssize size,GError ** error)315 overview_prefs_from_data (OverviewPrefs *self,
316 const gchar *contents,
317 gssize size,
318 GError **error)
319 {
320 GKeyFile *kf;
321 gchar *pos;
322
323 g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE);
324 g_return_val_if_fail (contents != NULL, FALSE);
325
326 kf = g_key_file_new ();
327
328 if (! g_key_file_load_from_data (kf, contents, size,
329 G_KEY_FILE_KEEP_COMMENTS |
330 G_KEY_FILE_KEEP_TRANSLATIONS,
331 error))
332 {
333 g_key_file_free (kf);
334 return FALSE;
335 }
336
337 GET (uint64, "width", self->width);
338 GET (integer, "zoom", self->zoom);
339 GET (boolean, "show-tooltip", self->show_tt);
340 GET (boolean, "show-scrollbar", self->show_sb);
341 GET (boolean, "double-buffered", self->dbl_buf);
342 GET (uint64, "scroll-lines", self->scr_lines);
343 GET (boolean, "overlay-enabled", self->ovl_en);
344 GET (boolean, "overlay-inverted", self->ovl_inv);
345 GET (boolean, "visible", self->visible);
346
347 if (g_key_file_has_key (kf, "overview", "position", NULL))
348 {
349 pos = g_key_file_get_string (kf, "overview", "position", error);
350 if (error != NULL && *error != NULL)
351 return FALSE;
352 if (g_ascii_strcasecmp (pos, "right") == 0)
353 self->position = GTK_POS_RIGHT;
354 else if (g_ascii_strcasecmp (pos, "left") == 0)
355 self->position = GTK_POS_LEFT;
356 else
357 {
358 g_warning ("unknown value '%s' for 'position' key", pos);
359 self->position = GTK_POS_RIGHT;
360 }
361 g_free (pos);
362 }
363
364 if (g_key_file_has_key (kf, "overview", "overlay-color", NULL) &&
365 g_key_file_has_key (kf, "overview", "overlay-alpha", NULL))
366 {
367 if (! overview_color_from_keyfile (&self->ovl_clr, kf, "overview", "overlay", error))
368 {
369 g_key_file_free (kf);
370 return FALSE;
371 }
372 g_object_notify (G_OBJECT (self), "overlay-color");
373 }
374
375 if (g_key_file_has_key (kf, "overview", "overlay-outline-color", NULL) &&
376 g_key_file_has_key (kf, "overview", "overlay-outline-alpha", NULL))
377 {
378 if (! overview_color_from_keyfile (&self->out_clr, kf, "overview", "overlay-outline", error))
379 {
380 g_key_file_free (kf);
381 return FALSE;
382 }
383 g_object_notify (G_OBJECT (self), "overlay-outline-color");
384 }
385
386 g_key_file_free (kf);
387
388 return TRUE;
389 }
390
391 #define SET(T, k, v) g_key_file_set_##T (kf, "overview", k, v)
392
393 gchar *
overview_prefs_to_data(OverviewPrefs * self,gsize * size,GError ** error)394 overview_prefs_to_data (OverviewPrefs *self,
395 gsize *size,
396 GError **error)
397 {
398 GKeyFile *kf;
399 gchar *contents;
400
401 g_return_val_if_fail (OVERVIEW_IS_PREFS (self), NULL);
402
403 kf = g_key_file_new ();
404
405 SET (uint64, "width", self->width);
406 SET (integer, "zoom", self->zoom);
407 SET (boolean, "show-tooltip", self->show_tt);
408 SET (boolean, "show-scrollbar", self->show_sb);
409 SET (boolean, "double-buffered", self->dbl_buf);
410 SET (uint64, "scroll-lines", self->scr_lines);
411 SET (boolean, "overlay-enabled", self->ovl_en);
412 SET (boolean, "overlay-inverted", self->ovl_inv);
413 SET (boolean, "visible", self->visible);
414
415 g_key_file_set_string (kf, "overview", "position",
416 self->position == GTK_POS_LEFT ? "left" : "right");
417
418 overview_color_to_keyfile (&self->ovl_clr, kf, "overview", "overlay");
419 overview_color_to_keyfile (&self->out_clr, kf, "overview", "overlay-outline");
420
421 contents = g_key_file_to_data (kf, size, error);
422 g_key_file_free (kf);
423 return contents;
424 }
425
426 #define BIND(prop) \
427 g_object_bind_property (self, prop, sci, prop, G_BINDING_SYNC_CREATE)
428
429 void
overview_prefs_bind_scintilla(OverviewPrefs * self,GObject * sci)430 overview_prefs_bind_scintilla (OverviewPrefs *self,
431 GObject *sci)
432 {
433 g_return_if_fail (OVERVIEW_IS_PREFS (self));
434 g_return_if_fail (OVERVIEW_IS_SCINTILLA (sci));
435
436 BIND ("width");
437 BIND ("zoom");
438 BIND ("show-tooltip");
439 BIND ("show-scrollbar");
440 BIND ("double-buffered");
441 BIND ("scroll-lines");
442 BIND ("overlay-enabled");
443 BIND ("overlay-color");
444 BIND ("overlay-outline-color");
445 BIND ("overlay-inverted");
446 BIND ("visible");
447 }
448