[geany/geany-plugins] a1505b: Add new "Overview" plugin

Matthew Brush git-noreply at xxxxx
Sun Apr 12 00:32:48 UTC 2015


Branch:      refs/heads/master
Author:      Matthew Brush <matt at geany.org>
Committer:   Matthew Brush <matt at geany.org>
Date:        Sun, 12 Apr 2015 00:32:48 UTC
Commit:      a1505b9622d5e794471893a2e405847d9f9b3217
             https://github.com/geany/geany-plugins/commit/a1505b9622d5e794471893a2e405847d9f9b3217

Log Message:
-----------
Add new "Overview" plugin


Modified Paths:
--------------
    Makefile.am
    build/overview.m4
    configure.ac
    overview/AUTHORS
    overview/COPYING
    overview/ChangeLog
    overview/Makefile.am
    overview/NEWS
    overview/README
    overview/data/Makefile.am
    overview/data/prefs.ui
    overview/overview/Makefile.am
    overview/overview/overviewcolor.c
    overview/overview/overviewcolor.h
    overview/overview/overviewplugin.c
    overview/overview/overviewplugin.h
    overview/overview/overviewprefs.c
    overview/overview/overviewprefs.h
    overview/overview/overviewprefspanel.c
    overview/overview/overviewprefspanel.h
    overview/overview/overviewscintilla.c
    overview/overview/overviewscintilla.h
    overview/overview/overviewui.c
    overview/overview/overviewui.h
    overview/wscript_build

Modified: Makefile.am
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -115,6 +115,10 @@ if ENABLE_MULTITERM
 SUBDIRS += multiterm
 endif
 
+if ENABLE_OVERVIEW
+SUBDIRS += overview
+endif
+
 if ENABLE_PAIRTAGHIGHLIGHTER
 SUBDIRS += pairtaghighlighter
 endif


Modified: build/overview.m4
12 lines changed, 12 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,12 @@
+AC_DEFUN([GP_CHECK_OVERVIEW],
+[
+    GP_ARG_DISABLE([overview], [auto])
+
+    GP_COMMIT_PLUGIN_STATUS([Overview])
+
+    AC_CONFIG_FILES([
+        overview/Makefile
+        overview/data/Makefile
+        overview/overview/Makefile
+    ])
+])


Modified: configure.ac
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -55,6 +55,7 @@ GP_CHECK_GENIUSPASTE
 GP_CHECK_GITCHANGEBAR
 GP_CHECK_MARKDOWN
 GP_CHECK_MULTITERM
+GP_CHECK_OVERVIEW
 GP_CHECK_PAIRTAGHIGHLIGHTER
 GP_CHECK_POHELPER
 GP_CHECK_PRETTYPRINTER


Modified: overview/AUTHORS
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: overview/COPYING
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: overview/ChangeLog
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: overview/Makefile.am
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,3 @@
+include $(top_srcdir)/build/vars.auxfiles.mk
+SUBDIRS = overview data
+plugin = overview


Modified: overview/NEWS
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: overview/README
0 lines changed, 0 insertions(+), 0 deletions(-)
===================================================================
No diff available, check online


Modified: overview/data/Makefile.am
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,2 @@
+overviewdatadir = $(pkgdatadir)/overview
+overviewdata_DATA = prefs.ui


Modified: overview/data/prefs.ui
356 lines changed, 356 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="2.24"/>
+  <!-- interface-naming-policy project-wide -->
+  <object class="GtkAdjustment" id="overview-scroll-lines-adjustment">
+    <property name="upper">100</property>
+    <property name="value">1</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="overview-width-adjustment">
+    <property name="lower">16</property>
+    <property name="upper">512</property>
+    <property name="value">120</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkAdjustment" id="overview-zoom-adjustment">
+    <property name="lower">-10</property>
+    <property name="upper">20</property>
+    <property name="value">-10</property>
+    <property name="step_increment">1</property>
+    <property name="page_increment">10</property>
+  </object>
+  <object class="GtkTable" id="overview-prefs-table">
+    <property name="visible">True</property>
+    <property name="can_focus">False</property>
+    <property name="border_width">12</property>
+    <property name="n_rows">5</property>
+    <property name="n_columns">2</property>
+    <property name="column_spacing">4</property>
+    <property name="row_spacing">2</property>
+    <child>
+      <object class="GtkLabel" id="overview-zoom-label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="tooltip_text" translatable="yes">The amount to zoom the overview sidebar. This should probably negative if you want the sidebar zoomed out.</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">Zoom Level:</property>
+      </object>
+      <packing>
+        <property name="top_attach">1</property>
+        <property name="bottom_attach">2</property>
+        <property name="x_options">GTK_FILL</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkSpinButton" id="overview-zoom-spin">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="tooltip_text" translatable="yes">The amount to zoom the overview sidebar. This should probably negative if you want the sidebar zoomed out.</property>
+        <property name="invisible_char">•</property>
+        <property name="primary_icon_activatable">False</property>
+        <property name="secondary_icon_activatable">False</property>
+        <property name="primary_icon_sensitive">True</property>
+        <property name="secondary_icon_sensitive">True</property>
+        <property name="adjustment">overview-zoom-adjustment</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="right_attach">2</property>
+        <property name="top_attach">1</property>
+        <property name="bottom_attach">2</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="overview-width-label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="tooltip_text" translatable="yes">The width of the overview sidebar.</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">Width:</property>
+      </object>
+      <packing>
+        <property name="x_options">GTK_FILL</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkSpinButton" id="overview-width-spin">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="tooltip_text" translatable="yes">The width of the overview sidebar.</property>
+        <property name="invisible_char">•</property>
+        <property name="primary_icon_activatable">False</property>
+        <property name="secondary_icon_activatable">False</property>
+        <property name="primary_icon_sensitive">True</property>
+        <property name="secondary_icon_sensitive">True</property>
+        <property name="adjustment">overview-width-adjustment</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="right_attach">2</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkSpinButton" id="overview-scroll-lines-spin">
+        <property name="visible">True</property>
+        <property name="can_focus">True</property>
+        <property name="tooltip_text" translatable="yes">The number of lines to scroll at a time when scrolling the overview sidebar.</property>
+        <property name="invisible_char">•</property>
+        <property name="primary_icon_activatable">False</property>
+        <property name="secondary_icon_activatable">False</property>
+        <property name="primary_icon_sensitive">True</property>
+        <property name="secondary_icon_sensitive">True</property>
+        <property name="adjustment">overview-scroll-lines-adjustment</property>
+      </object>
+      <packing>
+        <property name="left_attach">1</property>
+        <property name="right_attach">2</property>
+        <property name="top_attach">2</property>
+        <property name="bottom_attach">3</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkLabel" id="overview-scroll-lines-label">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="tooltip_text" translatable="yes">The number of lines to scroll at a time when scrolling the overview sidebar.</property>
+        <property name="xalign">0</property>
+        <property name="label" translatable="yes">Scroll Lines:</property>
+      </object>
+      <packing>
+        <property name="top_attach">2</property>
+        <property name="bottom_attach">3</property>
+        <property name="x_options">GTK_FILL</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkFrame" id="overview-options-frame">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label_xalign">0</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkAlignment" id="overview-options-alignment">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="top_padding">6</property>
+            <property name="bottom_padding">6</property>
+            <property name="left_padding">6</property>
+            <property name="right_padding">6</property>
+            <child>
+              <object class="GtkVBox" id="overview-options-vbox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">2</property>
+                <child>
+                  <object class="GtkCheckButton" id="overview-position-left-check">
+                    <property name="label" translatable="yes">Position on left</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="tooltip_text" translatable="yes">Position the overview bar on the left rather than the right (requires Geany 1.25 or greater).</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="overview-hide-tooltip-check">
+                    <property name="label" translatable="yes">Hide tooltip</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="tooltip_text" translatable="yes">Hide the tooltip that is displayed when mousing over the overview that shows line, column and position information.</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="overview-hide-scrollbar-check">
+                    <property name="label" translatable="yes">Hide editor scrollbar</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="tooltip_text" translatable="yes">Whether to hide Geany's regular editor scrollbar while the overview bar is visible.</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="overview-overlay-disable-check">
+                    <property name="label" translatable="yes">Disable overlay</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="tooltip_text" translatable="yes">Turn off drawing overlay, which shows the region of the main editor view that is currently in view, ontop of the overview bar.</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="overview-options-frame-label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Options</property>
+            <property name="use_markup">True</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="right_attach">2</property>
+        <property name="top_attach">3</property>
+        <property name="bottom_attach">4</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+    <child>
+      <object class="GtkFrame" id="overview-overlay-frame">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="label_xalign">0</property>
+        <property name="shadow_type">in</property>
+        <child>
+          <object class="GtkAlignment" id="overview-overlay-frame-align">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="top_padding">6</property>
+            <property name="bottom_padding">6</property>
+            <property name="left_padding">6</property>
+            <property name="right_padding">6</property>
+            <child>
+              <object class="GtkTable" id="overview-overlay-table">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="n_rows">3</property>
+                <property name="n_columns">2</property>
+                <property name="column_spacing">4</property>
+                <property name="row_spacing">2</property>
+                <child>
+                  <object class="GtkLabel" id="overview-overlay-color-label">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="tooltip_text" translatable="yes">The color and opacity of the overlay drawn ontop of the overlay sidebar.</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Color:</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkLabel" id="overview-overlay-outline-label">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="tooltip_text" translatable="yes">The color and opacity of the border drawn around the revealed area in the overview sidebar. Set to the same as Overlay Color to disable.</property>
+                    <property name="xalign">0</property>
+                    <property name="label" translatable="yes">Outline Color:</property>
+                  </object>
+                  <packing>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkColorButton" id="overview-overlay-outline-color">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">The color and opacity of the border drawn around the revealed area in the overview sidebar. Set to the same as Overlay Color to disable.</property>
+                    <property name="use_alpha">True</property>
+                    <property name="color">#000000000000</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">2</property>
+                    <property name="bottom_attach">3</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkColorButton" id="overview-overlay-color">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">The color and opacity of the overlay drawn ontop of the overlay sidebar.</property>
+                    <property name="use_alpha">True</property>
+                    <property name="color">#000000000000</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">1</property>
+                    <property name="right_attach">2</property>
+                    <property name="top_attach">1</property>
+                    <property name="bottom_attach">2</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkCheckButton" id="overview-overlay-inverted-check">
+                    <property name="label" translatable="yes">Draw over visible area</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">False</property>
+                    <property name="tooltip_text" translatable="yes">When checked it will draw the overlay ontop of the area that is visible in the main editor view, when unckecked, it will do the opposite and draw the overlay everywhere but the visible area, "revealing" the visible part.</property>
+                    <property name="active">True</property>
+                    <property name="draw_indicator">True</property>
+                  </object>
+                  <packing>
+                    <property name="right_attach">2</property>
+                    <property name="x_options">GTK_FILL</property>
+                    <property name="y_options">GTK_FILL</property>
+                  </packing>
+                </child>
+              </object>
+            </child>
+          </object>
+        </child>
+        <child type="label">
+          <object class="GtkLabel" id="oveview-overlay-frame-label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Overlay</property>
+            <property name="use_markup">True</property>
+          </object>
+        </child>
+      </object>
+      <packing>
+        <property name="right_attach">2</property>
+        <property name="top_attach">4</property>
+        <property name="bottom_attach">5</property>
+        <property name="y_options">GTK_FILL</property>
+      </packing>
+    </child>
+  </object>
+</interface>


Modified: overview/overview/Makefile.am
29 lines changed, 29 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,29 @@
+include $(top_srcdir)/build/vars.build.mk
+
+plugin = overview
+
+geanyplugins_LTLIBRARIES = overview.la
+
+overview_la_SOURCES = \
+	overviewcolor.c \
+	overviewcolor.h \
+	overviewplugin.c \
+	overviewplugin.h \
+	overviewprefs.c \
+	overviewprefs.h \
+	overviewprefspanel.c \
+	overviewprefspanel.h \
+	overviewscintilla.c \
+	overviewscintilla.h \
+	overviewui.c \
+	overviewui.h
+
+overview_la_CFLAGS = \
+	$(AM_CFLAGS) \
+	-I$(srcdir)/.. \
+	-DOVERVIEW_PREFS_UI_FILE=\""$(pkgdatadir)/overview/prefs.ui"\"
+
+overview_la_LIBADD = \
+	$(COMMONLIBS)
+
+include $(top_srcdir)/build/cppcheck.mk


Modified: overview/overview/overviewcolor.c
305 lines changed, 305 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,305 @@
+/*
+ * overviewcolor.c - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "overviewcolor.h"
+#include <string.h>
+
+OverviewColor *
+overview_color_copy (OverviewColor *color)
+{
+  OverviewColor *new_color = g_slice_new0 (OverviewColor);
+  memcpy (new_color, color, sizeof (OverviewColor));
+  return new_color;
+}
+
+void
+overview_color_free (OverviewColor *color)
+{
+  if (color != NULL)
+    g_slice_free (OverviewColor, color);
+}
+
+gboolean
+overview_color_equal (const OverviewColor *color1,
+                      const OverviewColor *color2)
+{
+  return (color1->red   == color2->red &&
+          color1->green == color2->green &&
+          color1->blue  == color2->blue &&
+          color1->alpha == color2->alpha);
+}
+
+gboolean
+overview_color_parse (OverviewColor *color,
+                      const gchar   *color_str)
+{
+  g_return_val_if_fail (color != NULL, FALSE);
+  g_return_val_if_fail (color_str != NULL, FALSE);
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+  GdkRGBA gcolor;
+  if (gdk_rgba_parse (&gcolor, color_str))
+    {
+      overview_color_from_rgba (color, &gcolor);
+      return TRUE;
+    }
+#else
+  GdkColor gcolor;
+  if (gdk_color_parse (color_str, &gcolor))
+    {
+      overview_color_from_gdk_color (color, &gcolor, 1.0);
+      return TRUE;
+    }
+#endif
+
+  return FALSE;
+}
+
+gchar *
+overview_color_to_string (const OverviewColor *color)
+{
+  g_return_val_if_fail (color != NULL, NULL);
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+  GdkRGBA gcolor;
+  overview_color_to_rgba (color, &gcolor);
+  return gdk_rgba_to_string (&gcolor);
+#else
+  GdkColor gcolor;
+  overview_color_to_gdk_color (color, &gcolor);
+  return gdk_color_to_string (&gcolor);
+#endif
+}
+
+void
+overview_color_from_gdk_color (OverviewColor  *color,
+                               const GdkColor *gcolor,
+                               gdouble         alpha)
+{
+  g_return_if_fail (color != NULL);
+  g_return_if_fail (gcolor != NULL);
+
+  color->red   = (gdouble) gcolor->red / G_MAXUINT16;
+  color->green = (gdouble) gcolor->green / G_MAXUINT16;
+  color->blue  = (gdouble) gcolor->blue / G_MAXUINT16;
+  color->alpha = alpha;
+}
+
+void
+overview_color_to_gdk_color (const OverviewColor *color,
+                             GdkColor            *gcolor)
+{
+  g_return_if_fail (color != NULL);
+  g_return_if_fail (gcolor != NULL);
+
+  gcolor->red   = (guint16)(color->red * G_MAXUINT16);
+  gcolor->green = (guint16)(color->green * G_MAXUINT16);
+  gcolor->blue  = (guint16)(color->blue * G_MAXUINT16);
+}
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+void
+overview_color_from_rgba (OverviewColor *color,
+                          const GdkRGBA *rgba)
+{
+  g_return_if_fail (color != NULL);
+  g_return_if_fail (rgba != NULL);
+
+  color->red   = rgba->red;
+  color->green = rgba->green;
+  color->blue  = rgba->blue;
+  color->alpha = rgba->alpha;
+}
+
+void
+overview_color_to_rgba (const OverviewColor *color,
+                        GdkRGBA             *rgba)
+{
+  g_return_if_fail (color != NULL);
+  g_return_if_fail (rgba != NULL);
+
+  rgba->red   = color->red;
+  rgba->green = color->green;
+  rgba->blue  = color->blue;
+  rgba->alpha = color->alpha;
+}
+#endif
+
+void
+overview_color_from_int (OverviewColor *color,
+                         guint32        abgr,
+                         gboolean       with_alpha)
+{
+  g_return_if_fail (color != NULL);
+  guint8 r = abgr & 0xFF;
+  guint8 g = (abgr>>8) & 0xFF;
+  guint8 b = (abgr>>16) & 0xFF;
+  guint8 a = 255;
+
+  if (with_alpha)
+    a = (abgr>>24) & 0xFF;
+
+  color->red   = (gdouble)r / G_MAXUINT8;
+  color->green = (gdouble)g / G_MAXUINT8;
+  color->blue  = (gdouble)b / G_MAXUINT8;
+  color->alpha = (gdouble)a / G_MAXUINT8;
+}
+
+guint32
+overview_color_to_int (const OverviewColor *color,
+                       gboolean             with_alpha)
+{
+  g_return_val_if_fail (color != NULL, 0);
+
+  guint32 r = (guint8)(color->red * 255.0);
+  guint32 g = (guint8)(color->green * 255.0);
+  guint32 b = (guint8)(color->blue * 255.0);
+  guint32 a = 0;
+
+  if (with_alpha)
+    a = (guint8)(color->alpha * 255.0);
+
+  return (a<<24) | (b<<16) | (g<<8) | r;
+}
+
+gboolean
+overview_color_from_keyfile   (OverviewColor *color,
+                               GKeyFile      *keyfile,
+                               const gchar   *section,
+                               const gchar   *option,
+                               GError       **error)
+{
+  gchar  *color_key;
+  gchar  *alpha_key;
+  gchar  *clr_str;
+  gdouble alpha;
+
+  g_return_val_if_fail (color != NULL, FALSE);
+  g_return_val_if_fail (keyfile != NULL, FALSE);
+  g_return_val_if_fail (section != NULL, FALSE);
+  g_return_val_if_fail (option != NULL, FALSE);
+
+  color_key = g_strdup_printf ("%s-color", option);
+  alpha_key = g_strdup_printf ("%s-alpha", option);
+
+  clr_str = g_key_file_get_string (keyfile, section, color_key, error);
+  if (*error != NULL)
+    {
+      g_free (color_key);
+      g_free (alpha_key);
+      return FALSE;
+    }
+
+  g_free (color_key);
+
+  alpha = g_key_file_get_double (keyfile, section, alpha_key, error);
+  if (*error != NULL)
+    {
+      g_free (alpha_key);
+      g_free (clr_str);
+      return FALSE;
+    }
+
+  g_free (alpha_key);
+
+  if (alpha < 0.0 || alpha > 1.0)
+    g_warning ("alpha value '%g' from keyfile out of 0-1 range", alpha);
+
+  overview_color_parse (color, clr_str);
+  color->alpha = alpha;
+
+  g_free (clr_str);
+
+  return TRUE;
+}
+
+gboolean
+overview_color_to_keyfile (const OverviewColor *color,
+                           GKeyFile            *keyfile,
+                           const gchar         *section,
+                           const gchar         *option)
+{
+  gchar *color_key;
+  gchar *alpha_key;
+  gchar *clr_str;
+
+  g_return_val_if_fail (color != NULL, FALSE);
+  g_return_val_if_fail (keyfile != NULL, FALSE);
+  g_return_val_if_fail (section != NULL, FALSE);
+  g_return_val_if_fail (option != NULL, FALSE);
+
+  color_key = g_strdup_printf ("%s-color", option);
+  alpha_key = g_strdup_printf ("%s-alpha", option);
+
+  clr_str = overview_color_to_string (color);
+  g_key_file_set_string (keyfile, section, color_key, clr_str);
+  g_free (color_key);
+  g_free (clr_str);
+
+  g_key_file_set_double (keyfile, section, alpha_key, color->alpha);
+  g_free (alpha_key);
+
+  return TRUE;
+}
+
+void
+overview_color_from_color_button (OverviewColor  *color,
+                                  GtkColorButton *button)
+{
+  GdkColor gcolor;
+  guint16  alpha;
+  gdouble  falpha;
+  gtk_color_button_get_color (button, &gcolor);
+  alpha = gtk_color_button_get_alpha (button);
+  falpha = (gdouble) alpha / (gdouble) G_MAXUINT16;
+  overview_color_from_gdk_color (color, &gcolor, falpha);
+}
+
+void
+overview_color_to_color_button (const OverviewColor *color,
+                                GtkColorButton      *button)
+{
+  GdkColor gcolor;
+  guint16  alpha;
+  overview_color_to_gdk_color (color, &gcolor);
+  gtk_color_button_set_color (button, &gcolor);
+  alpha = (guint16)(color->alpha * (gdouble) G_MAXUINT16);
+  gtk_color_button_set_alpha (button, alpha);
+}
+
+GType
+overview_color_get_type (void)
+{
+  static GType type = 0;
+  if (type == 0)
+    {
+      type =
+        g_boxed_type_register_static ("OverviewColor",
+                                      (GBoxedCopyFunc) overview_color_copy,
+                                      (GBoxedFreeFunc) overview_color_free);
+    }
+  return type;
+}


Modified: overview/overview/overviewcolor.h
79 lines changed, 79 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,79 @@
+/*
+ * overviewcolor.h - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef OVERVIEW_COLOR_H_
+#define OVERVIEW_COLOR_H_
+
+#include <gtk/gtk.h>
+
+#define OVERVIEW_TYPE_COLOR (overview_color_get_type ())
+#define OVERVIEW_COLOR_INIT { 0.0, 0.0, 0.0, 1.0 }
+
+typedef struct
+{
+  gdouble red;
+  gdouble green;
+  gdouble blue;
+  gdouble alpha;
+}
+OverviewColor;
+
+GType          overview_color_get_type       (void);
+OverviewColor *overview_color_copy           (OverviewColor       *color);
+void           overview_color_free           (OverviewColor       *color);
+gboolean       overview_color_equal          (const OverviewColor *color1,
+                                              const OverviewColor *color2);
+gboolean       overview_color_parse          (OverviewColor       *color,
+                                              const gchar         *color_str);
+gchar         *overview_color_to_string      (const OverviewColor *color);
+void           overview_color_from_gdk_color (OverviewColor       *color,
+                                              const GdkColor      *gcolor,
+                                              gdouble              alpha);
+void           overview_color_to_gdk_color   (const OverviewColor *color,
+                                              GdkColor            *gcolor);
+#if GTK_CHECK_VERSION (3, 0, 0)
+void           overview_color_from_rgba      (OverviewColor       *color,
+                                              const GdkRGBA       *rgba);
+void           overview_color_to_rgba        (const OverviewColor *color,
+                                              GdkRGBA             *rgba);
+#endif
+void           overview_color_from_int       (OverviewColor       *color,
+                                              guint32              abgr,
+                                              gboolean             with_alpha);
+guint32        overview_color_to_int         (const OverviewColor *color,
+                                              gboolean             with_alpha);
+gboolean       overview_color_from_keyfile   (OverviewColor       *color,
+                                              GKeyFile            *keyfile,
+                                              const gchar         *section,
+                                              const gchar         *option,
+                                              GError             **error);
+gboolean       overview_color_to_keyfile     (const OverviewColor *color,
+                                              GKeyFile            *keyfile,
+                                              const gchar         *section,
+                                              const gchar         *option);
+
+void           overview_color_from_color_button (OverviewColor       *color,
+                                                 GtkColorButton      *button);
+void           overview_color_to_color_button   (const OverviewColor *color,
+                                                 GtkColorButton      *button);
+
+#endif /* OVERVIEW_COLOR_H_ */


Modified: overview/overview/overviewplugin.c
232 lines changed, 232 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,232 @@
+/*
+ * overviewplugin.c - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "overviewplugin.h"
+#include "overviewscintilla.h"
+#include "overviewprefs.h"
+#include "overviewprefspanel.h"
+#include "overviewui.h"
+#include <errno.h>
+
+GeanyPlugin    *geany_plugin;
+GeanyData      *geany_data;
+GeanyFunctions *geany_functions;
+
+PLUGIN_VERSION_CHECK (224)
+
+PLUGIN_SET_INFO (
+  "Overview",
+  _("Provides an overview of the active document"),
+  "0.01",
+  "Matthew Brush <matt at geany.org>")
+
+static OverviewPrefs   *overview_prefs     = NULL;
+
+static void write_config (void);
+
+static void
+on_visible_pref_notify (OverviewPrefs *prefs,
+                        GParamSpec    *pspec,
+                        gpointer       user_data)
+{
+  write_config ();
+}
+
+static void
+toggle_visibility (void)
+{
+  gboolean visible = TRUE;
+  g_object_get (overview_prefs, "visible", &visible, NULL);
+  g_object_set (overview_prefs, "visible", !visible, NULL);
+}
+
+enum
+{
+  KB_TOGGLE_VISIBLE,
+  KB_TOGGLE_POSITION,
+  KB_TOGGLE_INVERTED,
+  NUM_KB
+};
+
+static gboolean
+on_kb_activate (guint keybinding_id)
+{
+  switch (keybinding_id)
+    {
+    case KB_TOGGLE_VISIBLE:
+      toggle_visibility ();
+      break;
+    case KB_TOGGLE_POSITION:
+      {
+        GtkPositionType pos;
+        g_object_get (overview_prefs, "position", &pos, NULL);
+        pos = (pos == GTK_POS_LEFT) ? GTK_POS_RIGHT : GTK_POS_LEFT;
+        g_object_set (overview_prefs, "position", pos, NULL);
+        break;
+      }
+    case KB_TOGGLE_INVERTED:
+      {
+        gboolean inv = FALSE;
+        g_object_get (overview_prefs, "overlay-inverted", &inv, NULL);
+        g_object_set (overview_prefs, "overlay-inverted", !inv, NULL);
+        break;
+      }
+    default:
+      break;
+    }
+  return TRUE;
+}
+
+static gchar *
+get_config_file (void)
+{
+  gchar              *dir;
+  gchar              *fn;
+  static const gchar *def_config = OVERVIEW_PREFS_DEFAULT_CONFIG;
+
+  dir = g_build_filename (geany_data->app->configdir, "plugins", "overview", NULL);
+  fn = g_build_filename (dir, "prefs.conf", NULL);
+
+  if (! g_file_test (fn, G_FILE_TEST_IS_DIR))
+    {
+      if (g_mkdir_with_parents (dir, 0755) != 0)
+        {
+          g_critical ("failed to create config dir '%s': %s", dir, g_strerror (errno));
+          g_free (dir);
+          g_free (fn);
+          return NULL;
+        }
+    }
+
+  g_free (dir);
+
+  if (! g_file_test (fn, G_FILE_TEST_EXISTS))
+    {
+      GError *error = NULL;
+      if (!g_file_set_contents (fn, def_config, -1, &error))
+        {
+          g_critical ("failed to save default config to file '%s': %s",
+                      fn, error->message);
+          g_error_free (error);
+          g_free (fn);
+          return NULL;
+        }
+    }
+
+  return fn;
+}
+
+static void
+write_config (void)
+{
+  gchar  *conf_file;
+  GError *error = NULL;
+  conf_file = get_config_file ();
+  if (! overview_prefs_save (overview_prefs, conf_file, &error))
+    {
+      g_critical ("failed to save preferences to file '%s': %s", conf_file, error->message);
+      g_error_free (error);
+    }
+  g_free (conf_file);
+}
+
+void
+plugin_init (G_GNUC_UNUSED GeanyData *data)
+{
+  gchar          *conf_file;
+  GError         *error = NULL;
+  GeanyKeyGroup  *key_group;
+
+  plugin_module_make_resident (geany_plugin);
+
+  overview_prefs = overview_prefs_new ();
+  conf_file = get_config_file ();
+  if (! overview_prefs_load (overview_prefs, conf_file, &error))
+    {
+      g_critical ("failed to load preferences file '%s': %s", conf_file, error->message);
+      g_error_free (error);
+    }
+  g_free (conf_file);
+
+  overview_ui_init (overview_prefs);
+
+  key_group = plugin_set_key_group (geany_plugin,
+                                    "overview",
+                                    NUM_KB,
+                                    on_kb_activate);
+
+  keybindings_set_item (key_group,
+                        KB_TOGGLE_VISIBLE,
+                        NULL, 0, 0,
+                        "toggle-visibility",
+                        "Toggle Visibility",
+                        overview_ui_get_menu_item ());
+
+  keybindings_set_item (key_group,
+                        KB_TOGGLE_POSITION,
+                        NULL, 0, 0,
+                        "toggle-position",
+                        "Toggle Left/Right Position",
+                        NULL);
+
+  keybindings_set_item (key_group,
+                        KB_TOGGLE_INVERTED,
+                        NULL, 0, 0,
+                        "toggle-inverted",
+                        "Toggle Overlay Inversion",
+                        NULL);
+
+  g_signal_connect (overview_prefs, "notify::visible", G_CALLBACK (on_visible_pref_notify), NULL);
+}
+
+void
+plugin_cleanup (void)
+{
+  write_config ();
+  overview_ui_deinit ();
+
+  if (OVERVIEW_IS_PREFS (overview_prefs))
+    g_object_unref (overview_prefs);
+  overview_prefs = NULL;
+}
+
+static void
+on_prefs_stored (OverviewPrefsPanel *panel,
+                 OverviewPrefs      *prefs,
+                 gpointer            user_data)
+{
+  write_config ();
+  overview_ui_queue_update ();
+}
+
+GtkWidget *
+plugin_configure (GtkDialog *dialog)
+{
+  GtkWidget *panel;
+  panel = overview_prefs_panel_new (overview_prefs, dialog);
+  g_signal_connect (panel, "prefs-stored", G_CALLBACK (on_prefs_stored), NULL);
+  return panel;
+}


Modified: overview/overview/overviewplugin.h
37 lines changed, 37 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,37 @@
+/*
+ * overviewplugin.h - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef OVERVIEW_PLUGIN_H
+#define OVERVIEW_PLUGIN_H
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <geanyplugin.h>
+
+extern GeanyData      *geany_data;
+extern GeanyPlugin    *geany_plugin;
+extern GeanyFunctions *geany_functions;
+
+void     overview_plugin_queue_update (void);
+gboolean overview_geany_supports_left_position (void);
+
+#endif // OVERVIEW_PLUGIN_H


Modified: overview/overview/overviewprefs.c
447 lines changed, 447 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,447 @@
+/*
+ * overviewprefs.c - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "overviewprefs.h"
+#include "overviewcolor.h"
+#include "overviewscintilla.h"
+#include <string.h>
+#include <stdarg.h>
+
+enum
+{
+  PROP_0,
+  PROP_WIDTH,
+  PROP_ZOOM,
+  PROP_SHOW_TOOLTIP,
+  PROP_SHOW_SCROLLBAR,
+  PROP_DOUBLE_BUFFERED,
+  PROP_SCROLL_LINES,
+  PROP_OVERLAY_ENABLED,
+  PROP_OVERLAY_COLOR,
+  PROP_OVERLAY_OUTLINE_COLOR,
+  PROP_OVERLAY_INVERTED,
+  PROP_POSITION,
+  PROP_VISIBLE,
+  N_PROPERTIES
+};
+
+struct OverviewPrefs_
+{
+  GObject         parent;
+  guint           width;
+  gint            zoom;
+  gboolean        show_tt;
+  gboolean        show_sb;
+  gboolean        dbl_buf;
+  gint            scr_lines;
+  gboolean        ovl_en;
+  OverviewColor   ovl_clr;
+  OverviewColor   out_clr;
+  gboolean        ovl_inv;
+  GtkPositionType position;
+  gboolean        visible;
+};
+
+struct OverviewPrefsClass_
+{
+  GObjectClass parent_class;
+};
+
+static void overview_prefs_finalize     (GObject      *object);
+static void overview_prefs_set_property (GObject      *object,
+                                         guint         prop_id,
+                                         const GValue *value,
+                                         GParamSpec   *pspec);
+static void overview_prefs_get_property (GObject      *object,
+                                         guint         prop_id,
+                                         GValue       *value,
+                                         GParamSpec   *pspec);
+
+
+static GParamSpec *pspecs[N_PROPERTIES] = { NULL };
+
+G_DEFINE_TYPE (OverviewPrefs, overview_prefs, G_TYPE_OBJECT)
+
+static void
+overview_prefs_class_init (OverviewPrefsClass *klass)
+{
+  GObjectClass *g_object_class;
+
+  g_object_class = G_OBJECT_CLASS (klass);
+
+  g_object_class->finalize     = overview_prefs_finalize;
+  g_object_class->set_property = overview_prefs_set_property;
+  g_object_class->get_property = overview_prefs_get_property;
+
+  pspecs[PROP_WIDTH] = g_param_spec_uint ("width", "Width", "Width of the overview", 16, 512, 120, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+  pspecs[PROP_ZOOM] = g_param_spec_int ("zoom", "Zoom", "Zoom level of the view", -10, 20, -10, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+  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);
+  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);
+  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);
+  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);
+  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);
+  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);
+  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);
+  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);
+  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);
+  pspecs[PROP_VISIBLE] = g_param_spec_boolean ("visible", "Visible", "Whether the overview is shown", TRUE, G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  g_object_class_install_properties (g_object_class, N_PROPERTIES, pspecs);
+}
+
+static void
+overview_prefs_finalize (GObject *object)
+{
+  g_return_if_fail (OVERVIEW_IS_PREFS (object));
+  G_OBJECT_CLASS (overview_prefs_parent_class)->finalize (object);
+}
+
+static void
+overview_prefs_set_property (GObject      *object,
+                             guint         prop_id,
+                             const GValue *value,
+                             GParamSpec   *pspec)
+{
+  OverviewPrefs *self = OVERVIEW_PREFS (object);
+
+  switch (prop_id)
+    {
+    case PROP_WIDTH:
+      self->width = g_value_get_uint (value);
+      g_object_notify (object, "width");
+      break;
+    case PROP_ZOOM:
+      self->zoom = g_value_get_int (value);
+      g_object_notify (object, "zoom");
+      break;
+    case PROP_SHOW_TOOLTIP:
+      self->show_tt = g_value_get_boolean (value);
+      g_object_notify (object, "show-tooltip");
+      break;
+    case PROP_SHOW_SCROLLBAR:
+      self->show_sb = g_value_get_boolean (value);
+      g_object_notify (object, "show-scrollbar");
+      break;
+    case PROP_DOUBLE_BUFFERED:
+      self->dbl_buf = g_value_get_boolean (value);
+      g_object_notify (object, "double-buffered");
+      break;
+    case PROP_SCROLL_LINES:
+      self->scr_lines = g_value_get_uint (value);
+      g_object_notify (object, "scroll-lines");
+      break;
+    case PROP_OVERLAY_ENABLED:
+      self->ovl_en = g_value_get_boolean (value);
+      g_object_notify (object, "overlay-enabled");
+      break;
+    case PROP_OVERLAY_COLOR:
+      {
+        OverviewColor *src = g_value_get_boxed (value);
+        if (src != NULL)
+          memcpy (&self->ovl_clr, src, sizeof (OverviewColor));
+        g_object_notify (object, "overlay-color");
+        break;
+      }
+    case PROP_OVERLAY_OUTLINE_COLOR:
+      {
+        OverviewColor *src = g_value_get_boxed (value);
+        if (src != NULL)
+          memcpy (&self->out_clr, src, sizeof (OverviewColor));
+        g_object_notify (object, "overlay-outline-color");
+        break;
+      }
+    case PROP_OVERLAY_INVERTED:
+      self->ovl_inv = g_value_get_boolean (value);
+      g_object_notify (G_OBJECT (self), "overlay-inverted");
+      break;
+    case PROP_POSITION:
+      self->position = g_value_get_enum (value);
+      g_object_notify (G_OBJECT (self), "position");
+      break;
+    case PROP_VISIBLE:
+      self->visible = g_value_get_boolean (value);
+      g_object_notify (G_OBJECT (self), "visible");
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+overview_prefs_get_property (GObject      *object,
+                             guint         prop_id,
+                             GValue       *value,
+                             GParamSpec   *pspec)
+{
+  OverviewPrefs *self = OVERVIEW_PREFS (object);
+
+  switch (prop_id)
+    {
+    case PROP_WIDTH:
+      g_value_set_uint (value, self->width);
+      break;
+    case PROP_ZOOM:
+      g_value_set_int (value, self->zoom);
+      break;
+    case PROP_SHOW_TOOLTIP:
+      g_value_set_boolean (value, self->show_tt);
+      break;
+    case PROP_SHOW_SCROLLBAR:
+      g_value_set_boolean (value, self->show_sb);
+      break;
+    case PROP_DOUBLE_BUFFERED:
+      g_value_set_boolean (value, self->dbl_buf);
+      break;
+    case PROP_SCROLL_LINES:
+      g_value_set_uint (value, self->scr_lines);
+      break;
+    case PROP_OVERLAY_ENABLED:
+      g_value_set_boolean (value, self->ovl_en);
+      break;
+    case PROP_OVERLAY_COLOR:
+      g_value_set_boxed (value, &self->ovl_clr);
+      break;
+    case PROP_OVERLAY_OUTLINE_COLOR:
+      g_value_set_boxed (value, &self->out_clr);
+      break;
+    case PROP_OVERLAY_INVERTED:
+      g_value_set_boolean (value, self->ovl_inv);
+      break;
+    case PROP_POSITION:
+      g_value_set_enum (value, self->position);
+      break;
+    case PROP_VISIBLE:
+      g_value_set_boolean (value, self->visible);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+overview_prefs_init (OverviewPrefs *self)
+{
+  self->position = GTK_POS_RIGHT;
+  self->visible  = TRUE;
+}
+
+OverviewPrefs *
+overview_prefs_new (void)
+{
+  return g_object_new (OVERVIEW_TYPE_PREFS, NULL);
+}
+
+gboolean
+overview_prefs_load (OverviewPrefs *self,
+                     const gchar   *filename,
+                     GError       **error)
+{
+  gchar  *contents = NULL;
+  gsize   size = 0;
+  g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE);
+  g_return_val_if_fail (filename != NULL, FALSE);
+  if (! g_file_get_contents (filename, &contents, &size, error))
+    return FALSE;
+  if (! overview_prefs_from_data (self, contents, size, error))
+    {
+      g_free (contents);
+      return FALSE;
+    }
+  g_free (contents);
+  return TRUE;
+}
+
+gboolean
+overview_prefs_save (OverviewPrefs *self,
+                     const gchar   *filename,
+                     GError       **error)
+
+{
+  gchar *contents = NULL;
+  gsize  size = 0;
+  g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE);
+  g_return_val_if_fail (filename != NULL, FALSE);
+  contents = overview_prefs_to_data (self, &size, error);
+  if (contents == NULL)
+    return FALSE;
+  if (! g_file_set_contents (filename, contents, size, error))
+    {
+      g_free (contents);
+      return FALSE;
+    }
+  g_free (contents);
+  return TRUE;
+}
+
+#define GET(T, k, v)                                     \
+  do {                                                   \
+    if (g_key_file_has_key (kf, "overview", k, NULL)) {  \
+      v = g_key_file_get_##T (kf, "overview", k, error); \
+      if (error != NULL && *error != NULL) {             \
+        g_key_file_free (kf);                            \
+        return FALSE;                                    \
+      } else {                                           \
+        g_object_notify (G_OBJECT (self), k);            \
+      }                                                  \
+    }                                                    \
+  } while (0)
+
+gboolean
+overview_prefs_from_data (OverviewPrefs *self,
+                          const gchar   *contents,
+                          gssize         size,
+                          GError       **error)
+{
+  GKeyFile *kf;
+  gchar    *pos;
+
+  g_return_val_if_fail (OVERVIEW_IS_PREFS (self), FALSE);
+  g_return_val_if_fail (contents != NULL, FALSE);
+
+  kf = g_key_file_new ();
+
+  if (! g_key_file_load_from_data (kf, contents, size,
+                                   G_KEY_FILE_KEEP_COMMENTS |
+                                     G_KEY_FILE_KEEP_TRANSLATIONS,
+                                  error))
+    {
+      g_key_file_free (kf);
+      return FALSE;
+    }
+
+  GET (uint64,  "width",            self->width);
+  GET (integer, "zoom",             self->zoom);
+  GET (boolean, "show-tooltip",     self->show_tt);
+  GET (boolean, "show-scrollbar",   self->show_sb);
+  GET (boolean, "double-buffered",  self->dbl_buf);
+  GET (uint64,  "scroll-lines",     self->scr_lines);
+  GET (boolean, "overlay-enabled",  self->ovl_en);
+  GET (boolean, "overlay-inverted", self->ovl_inv);
+  GET (boolean, "visible",          self->visible);
+
+  if (g_key_file_has_key (kf, "overview", "position", NULL))
+    {
+      pos = g_key_file_get_string (kf, "overview", "position", error);
+      if (error != NULL && *error != NULL)
+        return FALSE;
+      if (g_ascii_strcasecmp (pos, "right") == 0)
+        self->position = GTK_POS_RIGHT;
+      else if (g_ascii_strcasecmp (pos, "left") == 0)
+        self->position = GTK_POS_LEFT;
+      else
+        {
+          g_warning ("unknown value '%s' for 'position' key", pos);
+          self->position = GTK_POS_RIGHT;
+        }
+      g_free (pos);
+    }
+
+  if (g_key_file_has_key (kf, "overview", "overlay-color", NULL) &&
+      g_key_file_has_key (kf, "overview", "overlay-alpha", NULL))
+    {
+      if (! overview_color_from_keyfile (&self->ovl_clr, kf, "overview", "overlay", error))
+        {
+          g_key_file_free (kf);
+          return FALSE;
+        }
+      g_object_notify (G_OBJECT (self), "overlay-color");
+    }
+
+  if (g_key_file_has_key (kf, "overview", "overlay-outline-color", NULL) &&
+      g_key_file_has_key (kf, "overview", "overlay-outline-alpha", NULL))
+    {
+      if (! overview_color_from_keyfile (&self->out_clr, kf, "overview", "overlay-outline", error))
+        {
+          g_key_file_free (kf);
+          return FALSE;
+        }
+      g_object_notify (G_OBJECT (self), "overlay-outline-color");
+    }
+
+  g_key_file_free (kf);
+
+  return TRUE;
+}
+
+#define SET(T, k, v) g_key_file_set_##T (kf, "overview", k, v)
+
+gchar *
+overview_prefs_to_data (OverviewPrefs *self,
+                        gsize         *size,
+                        GError       **error)
+{
+  GKeyFile *kf;
+  gchar    *contents;
+
+  g_return_val_if_fail (OVERVIEW_IS_PREFS (self), NULL);
+
+  kf = g_key_file_new ();
+
+  SET (uint64,  "width",            self->width);
+  SET (integer, "zoom",             self->zoom);
+  SET (boolean, "show-tooltip",     self->show_tt);
+  SET (boolean, "show-scrollbar",   self->show_sb);
+  SET (boolean, "double-buffered",  self->dbl_buf);
+  SET (uint64,  "scroll-lines",     self->scr_lines);
+  SET (boolean, "overlay-enabled",  self->ovl_en);
+  SET (boolean, "overlay-inverted", self->ovl_inv);
+  SET (boolean, "visible",          self->visible);
+
+  g_key_file_set_string (kf, "overview", "position",
+                         self->position == GTK_POS_LEFT ? "left" : "right");
+
+  overview_color_to_keyfile (&self->ovl_clr, kf, "overview", "overlay");
+  overview_color_to_keyfile (&self->out_clr, kf, "overview", "overlay-outline");
+
+  contents = g_key_file_to_data (kf, size, error);
+  g_key_file_free (kf);
+  return contents;
+}
+
+#define BIND(prop) \
+  g_object_bind_property (self, prop, sci, prop, G_BINDING_SYNC_CREATE)
+
+void
+overview_prefs_bind_scintilla (OverviewPrefs *self,
+                               GObject       *sci)
+{
+  g_return_if_fail (OVERVIEW_IS_PREFS (self));
+  g_return_if_fail (OVERVIEW_IS_SCINTILLA (sci));
+
+  BIND ("width");
+  BIND ("zoom");
+  BIND ("show-tooltip");
+  BIND ("show-scrollbar");
+  BIND ("double-buffered");
+  BIND ("scroll-lines");
+  BIND ("overlay-enabled");
+  BIND ("overlay-color");
+  BIND ("overlay-outline-color");
+  BIND ("overlay-inverted");
+  BIND ("visible");
+}


Modified: overview/overview/overviewprefs.h
78 lines changed, 78 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,78 @@
+/*
+ * overviewprefs.h - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef OVERVIEWPREFS_H_
+#define OVERVIEWPREFS_H_ 1
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define OVERVIEW_TYPE_PREFS            (overview_prefs_get_type ())
+#define OVERVIEW_PREFS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVERVIEW_TYPE_PREFS, OverviewPrefs))
+#define OVERVIEW_PREFS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), OVERVIEW_TYPE_PREFS, OverviewPrefsClass))
+#define OVERVIEW_IS_PREFS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVERVIEW_TYPE_PREFS))
+#define OVERVIEW_IS_PREFS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVERVIEW_TYPE_PREFS))
+#define OVERVIEW_PREFS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), OVERVIEW_TYPE_PREFS, OverviewPrefsClass))
+
+typedef struct OverviewPrefs_      OverviewPrefs;
+typedef struct OverviewPrefsClass_ OverviewPrefsClass;
+
+GType          overview_prefs_get_type       (void);
+OverviewPrefs *overview_prefs_new            (void);
+gboolean       overview_prefs_load           (OverviewPrefs *prefs,
+                                              const gchar   *filename,
+                                              GError       **error);
+gboolean       overview_prefs_save           (OverviewPrefs *prefs,
+                                              const gchar   *filename,
+                                              GError       **error);
+gboolean       overview_prefs_from_data      (OverviewPrefs *prefs,
+                                              const gchar   *contents,
+                                              gssize         size,
+                                              GError       **error);
+gchar*         overview_prefs_to_data        (OverviewPrefs *prefs,
+                                              gsize         *size,
+                                              GError       **error);
+void           overview_prefs_bind_scintilla (OverviewPrefs *prefs,
+                                              GObject       *sci);
+
+#define OVERVIEW_PREFS_DEFAULT_CONFIG   \
+    "[overview]\n"                      \
+    "width = 120\n"                     \
+    "zoom = -10\n"                      \
+    "show-tooltip = true\n"             \
+    "double-buffered = true\n"          \
+    "scroll-lines = 4\n"                \
+    "show-scrollbar = true\n"           \
+    "overlay-enabled = true\n"          \
+    "overlay-color = #000000\n"         \
+    "overlay-alpha = 0.10\n"            \
+    "overlay-outline-color = #000000\n" \
+    "overlay-outline-alpha = 0.10\n"    \
+    "overlay-inverted = true\n"         \
+    "position = right\n"                \
+    "visible = true\n"                  \
+    "\n"
+
+G_END_DECLS
+
+#endif /* OVERVIEWPREFS_H_ */


Modified: overview/overview/overviewprefspanel.c
264 lines changed, 264 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,264 @@
+/*
+ * overviewprefspanel.c - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "overviewprefspanel.h"
+#include "overviewcolor.h"
+#include "overviewplugin.h"
+#include "overviewui.h"
+
+struct OverviewPrefsPanel_
+{
+  GtkFrame       parent;
+  OverviewPrefs *prefs;
+  GtkWidget     *prefs_table;
+  GtkWidget     *width_spin;
+  GtkWidget     *zoom_spin;
+  GtkWidget     *scr_lines_spin;
+  GtkWidget     *pos_left_check;
+  GtkWidget     *hide_tt_check;
+  GtkWidget     *hide_sb_check;
+  GtkWidget     *ovl_dis_check;
+  GtkWidget     *ovl_inv_check;
+  GtkWidget     *ovl_clr_btn;
+  GtkWidget     *out_clr_btn;
+};
+
+struct OverviewPrefsPanelClass_
+{
+  GtkFrameClass parent_class;
+};
+
+static void overview_prefs_panel_finalize (GObject *object);
+
+G_DEFINE_TYPE (OverviewPrefsPanel, overview_prefs_panel, GTK_TYPE_FRAME)
+
+static void
+overview_prefs_panel_class_init (OverviewPrefsPanelClass *klass)
+{
+  GObjectClass *g_object_class;
+
+  g_object_class = G_OBJECT_CLASS (klass);
+
+  g_object_class->finalize = overview_prefs_panel_finalize;
+
+  g_signal_new ("prefs-stored",
+                G_TYPE_FROM_CLASS (g_object_class),
+                G_SIGNAL_RUN_FIRST,
+                0, NULL, NULL,
+                g_cclosure_marshal_VOID__OBJECT,
+                G_TYPE_NONE,
+                1, OVERVIEW_TYPE_PREFS);
+
+  g_signal_new ("prefs-loaded",
+                G_TYPE_FROM_CLASS (g_object_class),
+                G_SIGNAL_RUN_FIRST,
+                0, NULL, NULL,
+                g_cclosure_marshal_VOID__OBJECT,
+                G_TYPE_NONE,
+                1, OVERVIEW_TYPE_PREFS);
+}
+
+static void
+overview_prefs_panel_finalize (GObject *object)
+{
+  OverviewPrefsPanel *self;
+
+  g_return_if_fail (OVERVIEW_IS_PREFS_PANEL (object));
+
+  self = OVERVIEW_PREFS_PANEL (object);
+
+  g_object_unref (self->prefs);
+
+  G_OBJECT_CLASS (overview_prefs_panel_parent_class)->finalize (object);
+}
+
+static GtkWidget *
+builder_get_widget (GtkBuilder  *builder,
+                    const gchar *name)
+{
+  GObject *result = NULL;
+  gchar   *real_name;
+
+  real_name = g_strdup_printf ("overview-%s", name);
+  result    = gtk_builder_get_object (builder, real_name);
+
+  if (! G_IS_OBJECT (result))
+    g_critical ("unable to find widget '%s' in UI file", real_name);
+  else if (! GTK_IS_WIDGET (result))
+    g_critical ("object '%s' in UI file is not a widget", real_name);
+
+  g_free (real_name);
+
+  return (GtkWidget*) result;
+}
+
+static void
+overview_prefs_panel_store_prefs (OverviewPrefsPanel *self)
+{
+  guint         width;
+  gint          zoom;
+  guint         scr_lines;
+  gboolean      pos_left  = FALSE;
+  OverviewColor ovl_clr   = {0,0,0,0};
+  OverviewColor out_clr   = {0,0,0,0};
+
+  width     = gtk_spin_button_get_value (GTK_SPIN_BUTTON (self->width_spin));
+  zoom      = gtk_spin_button_get_value (GTK_SPIN_BUTTON (self->zoom_spin));
+  scr_lines = gtk_spin_button_get_value (GTK_SPIN_BUTTON (self->scr_lines_spin));
+  pos_left  = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->pos_left_check));
+  overview_color_from_color_button (&ovl_clr, GTK_COLOR_BUTTON (self->ovl_clr_btn));
+  overview_color_from_color_button (&out_clr, GTK_COLOR_BUTTON (self->out_clr_btn));
+
+  g_object_set (self->prefs,
+                "width", width,
+                "zoom", zoom,
+                "scroll-lines", scr_lines,
+                "position", pos_left ? GTK_POS_LEFT : GTK_POS_RIGHT,
+                "show-tooltip", !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->hide_tt_check)),
+                "show-scrollbar", !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->hide_sb_check)),
+                "overlay-enabled", !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->ovl_dis_check)),
+                "overlay-inverted", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->ovl_inv_check)),
+                "overlay-color", &ovl_clr,
+                "overlay-outline-color", &out_clr,
+                NULL);
+
+  g_signal_emit_by_name (self, "prefs-stored", self->prefs);
+}
+
+static void
+overview_prefs_panel_load_prefs (OverviewPrefsPanel *self)
+{
+  gint            zoom      = 0;
+  guint           width     = 0;
+  guint           scr_lines = 0;
+  gboolean        show_tt   = FALSE;
+  gboolean        show_sb   = FALSE;
+  gboolean        ovl_en    = FALSE;
+  gboolean        ovl_inv   = FALSE;
+  GtkPositionType pos       = FALSE;
+  OverviewColor  *ovl_clr   = NULL;
+  OverviewColor  *out_clr   = NULL;
+
+  g_object_get (self->prefs,
+                "width", &width,
+                "zoom", &zoom,
+                "scroll-lines", &scr_lines,
+                "position", &pos,
+                "show-tooltip", &show_tt,
+                "show-scrollbar", &show_sb,
+                "overlay-enabled", &ovl_en,
+                "overlay-inverted", &ovl_inv,
+                "overlay-color", &ovl_clr,
+                "overlay-outline-color", &out_clr,
+                NULL);
+
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->width_spin), width);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->zoom_spin), zoom);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (self->scr_lines_spin), scr_lines);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->pos_left_check), (pos == GTK_POS_LEFT));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->hide_tt_check), !show_tt);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->hide_sb_check), !show_sb);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->ovl_inv_check), ovl_inv);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->ovl_dis_check), !ovl_en);
+  overview_color_to_color_button (ovl_clr, GTK_COLOR_BUTTON (self->ovl_clr_btn));
+  overview_color_to_color_button (out_clr, GTK_COLOR_BUTTON (self->out_clr_btn));
+
+  overview_color_free (ovl_clr);
+  overview_color_free (out_clr);
+
+  g_signal_emit_by_name (self, "prefs-loaded", self->prefs);
+}
+
+static void
+overview_prefs_panel_init (OverviewPrefsPanel *self)
+{
+  GtkBuilder *builder;
+  GError     *error = NULL;
+  GtkWidget  *overlay_frame;
+
+  builder = gtk_builder_new ();
+  if (! gtk_builder_add_from_file (builder, OVERVIEW_PREFS_UI_FILE, &error))
+    {
+      g_critical ("failed to open UI file '%s': %s", OVERVIEW_PREFS_UI_FILE, error->message);
+      g_error_free (error);
+      g_object_unref (builder);
+      return;
+    }
+
+  self->prefs_table    = builder_get_widget (builder, "prefs-table");
+  self->width_spin     = builder_get_widget (builder, "width-spin");
+  self->zoom_spin      = builder_get_widget (builder, "zoom-spin");
+  self->scr_lines_spin = builder_get_widget (builder, "scroll-lines-spin");
+  self->pos_left_check = builder_get_widget (builder, "position-left-check");
+  self->hide_tt_check  = builder_get_widget (builder, "hide-tooltip-check");
+  self->hide_sb_check  = builder_get_widget (builder, "hide-scrollbar-check");
+  self->ovl_inv_check = builder_get_widget (builder, "overlay-inverted-check");
+  self->ovl_clr_btn    = builder_get_widget (builder, "overlay-color");
+  self->out_clr_btn    = builder_get_widget (builder, "overlay-outline-color");
+
+  // The "Draw over visible area" checkbox hides/shows the "Overlay" frame
+  self->ovl_dis_check  = builder_get_widget (builder, "overlay-disable-check");
+  overlay_frame = builder_get_widget (builder, "overlay-frame");
+  g_object_bind_property (self->ovl_dis_check, "active", overlay_frame, "sensitive", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
+
+  gtk_widget_show_all (self->prefs_table);
+  gtk_container_add (GTK_CONTAINER (self), self->prefs_table);
+  g_object_unref (builder);
+
+#ifndef OVERVIEW_UI_SUPPORTS_LEFT_POSITION
+  gtk_widget_set_no_show_all (self->pos_left_check, TRUE);
+  gtk_widget_hide (self->pos_left_check);
+#endif
+}
+
+static void
+on_host_dialog_response (GtkDialog          *dialog,
+                         gint                response_id,
+                         OverviewPrefsPanel *self)
+{
+  switch (response_id)
+    {
+    case GTK_RESPONSE_APPLY:
+    case GTK_RESPONSE_OK:
+      overview_prefs_panel_store_prefs (self);
+      break;
+    case GTK_RESPONSE_CANCEL:
+    default:
+      break;
+    }
+}
+
+GtkWidget *
+overview_prefs_panel_new (OverviewPrefs *prefs,
+                          GtkDialog     *host_dialog)
+{
+  OverviewPrefsPanel *self;
+  self = g_object_new (OVERVIEW_TYPE_PREFS_PANEL, NULL);
+  self->prefs = g_object_ref (prefs);
+  g_signal_connect (host_dialog, "response", G_CALLBACK (on_host_dialog_response), self);
+  overview_prefs_panel_load_prefs (self);
+  return GTK_WIDGET (self);
+}


Modified: overview/overview/overviewprefspanel.h
47 lines changed, 47 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,47 @@
+/*
+ * overviewprefspanel.h - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifndef OVERVIEWPREFSPANEL_H_
+#define OVERVIEWPREFSPANEL_H_ 1
+
+#include "overviewprefs.h"
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define OVERVIEW_TYPE_PREFS_PANEL            (overview_prefs_panel_get_type ())
+#define OVERVIEW_PREFS_PANEL(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), OVERVIEW_TYPE_PREFS_PANEL, OverviewPrefsPanel))
+#define OVERVIEW_PREFS_PANEL_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), OVERVIEW_TYPE_PREFS_PANEL, OverviewPrefsPanelClass))
+#define OVERVIEW_IS_PREFS_PANEL(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), OVERVIEW_TYPE_PREFS_PANEL))
+#define OVERVIEW_IS_PREFS_PANEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), OVERVIEW_TYPE_PREFS_PANEL))
+#define OVERVIEW_PREFS_PANEL_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), OVERVIEW_TYPE_PREFS_PANEL, OverviewPrefsPanelClass))
+
+typedef struct OverviewPrefsPanel_      OverviewPrefsPanel;
+typedef struct OverviewPrefsPanelClass_ OverviewPrefsPanelClass;
+
+GType      overview_prefs_panel_get_type (void);
+GtkWidget *overview_prefs_panel_new      (OverviewPrefs *prefs,
+                                          GtkDialog     *host_dialog);
+
+G_END_DECLS
+
+#endif /* OVERVIEWPREFSPANEL_H_ */


Modified: overview/overview/overviewscintilla.c
1299 lines changed, 1299 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,1299 @@
+/*
+ * overviewscintilla.c - This file is part of the Geany Overview plugin
+ *
+ * Copyright (c) 2015 Matthew Brush <mbrush at codebrainz.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "overviewscintilla.h"
+#include "overviewplugin.h"
+#include <string.h>
+
+#define OVERVIEW_SCINTILLA_CURSOR        GDK_ARROW
+#define OVERVIEW_SCINTILLA_CURSOR_CLICK  GDK_ARROW
+#define OVERVIEW_SCINTILLA_CURSOR_SCROLL GDK_SB_V_DOUBLE_ARROW
+#define OVERVIEW_SCINTILLA_ZOOM_MIN      -100
+#define OVERVIEW_SCINTILLA_ZOOM_MAX      100
+#define OVERVIEW_SCINTILLA_ZOOM_DEF      -20
+#define OVERVIEW_SCINTILLA_WIDTH_MIN     16
+#define OVERVIEW_SCINTILLA_WIDTH_MAX     512
+#define OVERVIEW_SCINTILLA_WIDTH_DEF     120
+#define OVERVIEW_SCINTILLA_SCROLL_LINES  1
+
+#ifndef SC_MAX_MARGIN
+# define SC_MAX_MARGIN 4
+#endif
+
+#define sci_send(sci, msg, wParam, lParam) \
+  scintilla_send_message (SCINTILLA (sci), SCI_##msg, (uptr_t)(wParam), (sptr_t)(lParam))
+
+static const OverviewColor def_overlay_color         = { 0.0, 0.0, 0.0, 0.25 };
+static const OverviewColor def_overlay_outline_color = { 0.0, 0.0, 0.0, 0.0 };
+
+enum
+{
+  PROP_0,
+  PROP_SCINTILLA,
+  PROP_CURSOR,
+  PROP_VISIBLE_RECT,
+  PROP_WIDTH,
+  PROP_ZOOM,
+  PROP_SHOW_TOOLTIP,
+  PROP_OVERLAY_ENABLED,
+  PROP_OVERLAY_COLOR,
+  PROP_OVERLAY_OUTLINE_COLOR,
+  PROP_OVERLAY_INVERTED,
+  PROP_DOUBLE_BUFFERED,
+  PROP_SCROLL_LINES,
+  PROP_SHOW_SCROLLBAR,
+  N_PROPERTIES,
+};
+
+struct OverviewScintilla_
+{
+  ScintillaObject  parent;
+  ScintillaObject *sci;             // source scintilla
+  GtkWidget       *canvas;          // internal GtkDrawingArea of scintilla
+  GdkCursorType    cursor;          // the chosen mouse cursor to use over the scintilla
+  GdkCursorType    active_cursor;   // the cursor to draw
+  GdkRectangle     visible_rect;    // visible region rectangle
+  guint            width;           // width of the overview
+  gint             zoom;            // zoom level of scintilla
+  gboolean         show_tooltip;    // whether tooltip shown on hover
+  gboolean         overlay_enabled; // whether the visible overlay is drawn
+  OverviewColor    overlay_color;   // the color of the visible overlay
+  OverviewColor    overlay_outline_color; // the color of the outline of the overlay
+  gboolean         overlay_inverted;// draw overlay over the visible area instead of around it
+  gboolean         double_buffered; // whether to enable double-buffering on internal scintilla canvas
+  gint             scroll_lines;    // number of lines to scroll each scroll-event
+  gboolean         show_scrollbar;  // show the main scintilla's scrollbar
+  gboolean         mouse_down;      // whether the mouse is down
+  gulong           update_rect;     // signal id of idle rect handler
+  gulong           conf_event;      // signal id of the configure event on scintilla internal drawing area
+  GtkWidget       *src_canvas;      // internal drawing area of main scintilla
+};
+
+struct OverviewScintillaClass_
+{
+  ScintillaClass parent_class;
+};
+
+static GParamSpec *pspecs[N_PROPERTIES] = { NULL };
+
+static void overview_scintilla_finalize     (GObject           *object);
+static void overview_scintilla_set_property (GObject           *object,
+                                             guint              prop_id,
+                                             const GValue      *value,
+                                             GParamSpec        *pspec);
+static void overview_scintilla_get_property (GObject           *object,
+                                             guint              prop_id,
+                                             GValue            *value,
+                                             GParamSpec        *pspec);
+static void overview_scintilla_set_src_sci  (OverviewScintilla *self,
+                                             ScintillaObject   *sci);
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+static gboolean overview_scintilla_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data);
+#else
+static gboolean overview_scintilla_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer user_data);
+#endif
+
+G_DEFINE_TYPE (OverviewScintilla, overview_scintilla, scintilla_get_type())
+
+static void
+overview_scintilla_class_init (OverviewScintillaClass *klass)
+{
+  GObjectClass   *g_object_class;
+
+  g_object_class = G_OBJECT_CLASS (klass);
+
+  g_object_class->finalize     = overview_scintilla_finalize;
+  g_object_class->set_property = overview_scintilla_set_property;
+  g_object_class->get_property = overview_scintilla_get_property;
+
+  pspecs[PROP_SCINTILLA] =
+    g_param_spec_object ("scintilla",
+                         "Scintilla",
+                         "The source ScintillaObject",
+                         scintilla_get_type (),
+                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+
+  pspecs[PROP_CURSOR] =
+    g_param_spec_enum ("cursor",
+                       "Cursor",
+                       "The GdkCursorType to use for the mouse cursor",
+                       GDK_TYPE_CURSOR_TYPE,
+                       OVERVIEW_SCINTILLA_CURSOR,
+                       G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_VISIBLE_RECT] =
+    g_param_spec_boxed ("visible-rect",
+                       "VisibleRect",
+                       "The visible area indication rectangle to draw",
+                       GDK_TYPE_RECTANGLE,
+                       G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_WIDTH] =
+    g_param_spec_uint ("width",
+                       "Width",
+                       "Width of the overview",
+                       OVERVIEW_SCINTILLA_WIDTH_MIN,
+                       OVERVIEW_SCINTILLA_WIDTH_MAX,
+                       OVERVIEW_SCINTILLA_WIDTH_DEF,
+                       G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_ZOOM] =
+    g_param_spec_int ("zoom",
+                      "Zoom",
+                      "The zoom-level of the overview",
+                      OVERVIEW_SCINTILLA_ZOOM_MIN,
+                      OVERVIEW_SCINTILLA_ZOOM_MAX,
+                      OVERVIEW_SCINTILLA_ZOOM_DEF,
+                      G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_SHOW_TOOLTIP] =
+    g_param_spec_boolean ("show-tooltip",
+                          "ShowTooltip",
+                          "Whether to show a tooltip with addition info on mouse over",
+                          TRUE,
+                          G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_OVERLAY_ENABLED] =
+    g_param_spec_boolean ("overlay-enabled",
+                          "OverlayEnabled",
+                          "Whether an overlay is drawn ontop of the overview",
+                          TRUE,
+                          G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_OVERLAY_COLOR] =
+    g_param_spec_boxed ("overlay-color",
+                        "OverlayColor",
+                        "The color of the overlay, if enabled",
+                        OVERVIEW_TYPE_COLOR,
+                        G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_OVERLAY_OUTLINE_COLOR] =
+    g_param_spec_boxed ("overlay-outline-color",
+                        "OverlayOutlineColor",
+                        "The color of the overlay's outline, if enabled",
+                        OVERVIEW_TYPE_COLOR,
+                        G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_OVERLAY_INVERTED] =
+    g_param_spec_boolean ("overlay-inverted",
+                          "OverlayInverted",
+                          "Whether to draw the overlay over the visible area",
+                          TRUE,
+                          G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_DOUBLE_BUFFERED] =
+    g_param_spec_boolean ("double-buffered",
+                          "DoubleBuffered",
+                          "Whether the overview Scintilla's internal canvas is double-buffered",
+                          TRUE,
+                          G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_SCROLL_LINES] =
+    g_param_spec_int ("scroll-lines",
+                      "ScrollLines",
+                      "The number of lines to move each scroll, -1 for default, 0 to disable.",
+                      -1, 100, OVERVIEW_SCINTILLA_SCROLL_LINES,
+                      G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  pspecs[PROP_SHOW_SCROLLBAR] =
+    g_param_spec_boolean ("show-scrollbar",
+                          "ShowScrollbar",
+                          "Whether to show the scrollbar in the main Scintilla",
+                          TRUE,
+                          G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
+
+  g_object_class_install_properties (g_object_class, N_PROPERTIES, pspecs);
+}
+
+static void
+overview_scintilla_finalize (GObject *object)
+{
+  OverviewScintilla *self;
+
+  g_return_if_fail (OVERVIEW_IS_SCINTILLA (object));
+
+  self = OVERVIEW_SCINTILLA (object);
+
+  if (GTK_IS_WIDGET (self->src_canvas) && self->conf_event != 0)
+    g_signal_handler_disconnect (self->src_canvas, self->conf_event);
+
+  g_object_unref (self->sci);
+
+  G_OBJECT_CLASS (overview_scintilla_parent_class)->finalize (object);
+}
+
+static inline void
+cairo_set_source_overlay_color_ (cairo_t             *cr,
+                                 const OverviewColor *color)
+{
+  cairo_set_source_rgba (cr, color->red, color->green, color->blue, color->alpha);
+}
+
+static inline void
+overview_scintilla_draw_real (OverviewScintilla *self,
+                              cairo_t           *cr)
+{
+  if (! self->overlay_enabled)
+    return;
+
+  GtkAllocation alloc;
+
+  gtk_widget_get_allocation (GTK_WIDGET (self->canvas), &alloc);
+
+  cairo_save (cr);
+
+  cairo_set_line_width (cr, 1.0);
+  cairo_set_antialias (cr, CAIRO_ANTIALIAS_GOOD);
+
+  if (self->overlay_inverted)
+    {
+      cairo_set_source_overlay_color_ (cr, &self->overlay_color);
+      cairo_rectangle (cr,
+                       0,
+                       self->visible_rect.y,
+                       alloc.width,
+                       self->visible_rect.height);
+      cairo_fill (cr);
+    }
+  else
+    {
+      // draw a rectangle at the top and bottom to obscure the non-visible area
+      cairo_set_source_overlay_color_ (cr, &self->overlay_color);
+      cairo_rectangle (cr, 0, 0, alloc.width, self->visible_rect.y);
+      cairo_rectangle (cr,
+                       0,
+                       self->visible_rect.y + self->visible_rect.height,
+                       alloc.width,
+                       alloc.height - (self->visible_rect.y + self->visible_rect.height));
+      cairo_fill (cr);
+    }
+
+    // draw a highlighting border at top and bottom of visible rect
+    cairo_set_source_overlay_color_ (cr, &self->overlay_outline_color);
+    cairo_move_to (cr, self->visible_rect.x + 0.5, self->visible_rect.y + 0.5);
+    cairo_line_to (cr, self->visible_rect.width, self->visible_rect.y + 0.5);
+    cairo_move_to (cr, self->visible_rect.x + 0.5, self->visible_rect.y + 0.5 + self->visible_rect.height);
+    cairo_line_to (cr, self->visible_rect.width, self->visible_rect.y + 0.5 + self->visible_rect.height);
+    cairo_stroke (cr);
+
+    // draw a left border if there's no scrollbar
+    if (! overview_scintilla_get_show_scrollbar (self))
+      {
+        cairo_move_to (cr, 0.5, 0.5);
+        cairo_line_to (cr, 0.5, alloc.height);
+        cairo_stroke (cr);
+      }
+
+  cairo_restore (cr);
+}
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+static gboolean
+overview_scintilla_draw (GtkWidget *widget,
+                         cairo_t   *cr,
+                         gpointer   user_data)
+{
+  overview_scintilla_draw_real (OVERVIEW_SCINTILLA (user_data), cr);
+  return FALSE;
+}
+#else
+static gboolean
+overview_scintilla_expose_event (GtkWidget      *widget,
+                                 GdkEventExpose *event,
+                                 gpointer        user_data)
+{
+  cairo_t *cr;
+  cr = gdk_cairo_create (gtk_widget_get_window (widget));
+  overview_scintilla_draw_real (OVERVIEW_SCINTILLA (user_data), cr);
+  cairo_destroy (cr);
+  return FALSE;
+}
+#endif
+
+static gboolean
+on_focus_in_event (OverviewScintilla *self,
+                   GdkEventFocus     *event,
+                   ScintillaObject   *sci)
+{
+  sci_send (self, SETREADONLY, 1, 0);
+  return TRUE;
+}
+
+static gboolean
+on_focus_out_event (OverviewScintilla *self,
+                    GdkEventFocus     *event,
+                    ScintillaObject   *sci)
+{
+  GeanyDocument *doc = g_object_get_data (G_OBJECT (sci), "document");
+  if (DOC_VALID (doc))
+    sci_send (self, SETREADONLY, doc->readonly, 0);
+  else
+    sci_send (self, SETREADONLY, 0, 0);
+  return TRUE;
+}
+
+static gboolean
+on_enter_notify_event (OverviewScintilla *self,
+                       GdkEventCrossing  *event,
+                       ScintillaObject   *sci)
+{
+  return TRUE;
+}
+
+static gboolean
+on_leave_notify_event (OverviewScintilla *self,
+                       GdkEventCrossing  *event,
+                       ScintillaObject   *sci)
+{
+  return TRUE;
+}
+
+static void
+on_each_child (GtkWidget *child,
+               GList    **list)
+{
+  *list = g_list_prepend (*list, child);
+}
+
+static GList *
+gtk_container_get_internal_children_ (GtkContainer *cont)
+{
+  GList *list = NULL;
+  gtk_container_forall (cont, (GtkCallback) on_each_child, &list);
+  return g_list_reverse (list);
+}
+
+static GtkWidget *
+overview_scintilla_find_drawing_area (GtkWidget *root)
+{
+  GtkWidget *da = NULL;
+  if (GTK_IS_DRAWING_AREA (root))
+    da = root;
+  else if (GTK_IS_CONTAINER (root))
+    {
+      GList *children = gtk_container_get_internal_children_ (GTK_CONTAINER (root));
+      for (GList *iter = children; iter != NULL; iter = g_list_next (iter))
+        {
+          GtkWidget *wid = overview_scintilla_find_drawing_area (iter->data);
+          if (GTK_IS_DRAWING_AREA (wid))
+            {
+              da = wid;
+              break;
+            }
+        }
+      g_list_free (children);
+    }
+  return da;
+}
+
+static gboolean
+on_scroll_event (OverviewScintilla *self,
+                 GdkEventScroll    *event,
+                 GtkWidget         *widget)
+{
+  gint delta = 0;
+
+  if (self->scroll_lines == 0)
+    return TRUE;
+
+  if (event->direction == GDK_SCROLL_UP)
+    delta = -(self->scroll_lines);
+  else if (event->direction == GDK_SCROLL_DOWN)
+    delta = self->scroll_lines;
+
+  if (delta != 0)
+    sci_send (self->sci, LINESCROLL, 0, delta);
+
+  return TRUE;
+}
+
+static void
+overview_scintilla_goto_point (OverviewScintilla *self,
+                               gint               x,
+                               gint               y)
+{
+  gint pos;
+  pos = sci_send (self, POSITIONFROMPOINT, x, y);
+  if (pos >= 0)
+    sci_send (self->sci, GOTOPOS, pos, 0);
+}
+
+static void
+overview_scintilla_update_cursor (OverviewScintilla *self)
+{
+  if (GTK_IS_WIDGET (self->canvas) && gtk_widget_get_mapped (self->canvas))
+    {
+      GdkCursor *cursor = gdk_cursor_new (self->active_cursor);
+      gdk_window_set_cursor (gtk_widget_get_window (self->canvas), cursor);
+      gdk_cursor_unref (cursor);
+    }
+}
+
+static gboolean
+on_button_press_event (OverviewScintilla *self,
+                       GdkEventButton    *event,
+                       GtkWidget         *widget)
+{
+  self->mouse_down = TRUE;
+  self->active_cursor = OVERVIEW_SCINTILLA_CURSOR_CLICK;
+  overview_scintilla_update_cursor (self);
+  return TRUE;
+}
+
+static gboolean
+on_button_release_event (OverviewScintilla *self,
+                         GdkEventButton    *event,
+                         GtkWidget         *widget)
+{
+  self->mouse_down = FALSE;
+  self->active_cursor = OVERVIEW_SCINTILLA_CURSOR;
+  overview_scintilla_update_cursor (self);
+  overview_scintilla_goto_point (self, event->x, event->y);
+  return TRUE;
+}
+
+static gboolean
+on_motion_notify_event (OverviewScintilla *self,
+                        GdkEventMotion    *event,
+                        GtkWidget         *widget)
+{
+  if (self->mouse_down)
+    {
+      if (self->active_cursor != OVERVIEW_SCINTILLA_CURSOR_SCROLL)
+        {
+          self->active_cursor = OVERVIEW_SCINTILLA_CURSOR_SCROLL;
+          overview_scintilla_update_cursor (self);
+        }
+      overview_scintilla_goto_point (self, event->x, event->y);
+    }
+  return TRUE;
+}
+
+static gboolean
+overview_scintilla_setup_tooltip (OverviewScintilla *self,
+                                  gint               x,
+                                  gint               y,
+                                  GtkTooltip        *tooltip)
+{
+  gint pos;
+
+  if (!self->show_tooltip)
+    return FALSE;
+
+  pos = sci_send (self, POSITIONFROMPOINT, x, y);
+  if (pos >= 0)
+    {
+      gint line = sci_send (self, LINEFROMPOSITION, pos, 0);
+      gint column = sci_send (self, GETCOLUMN, pos, 0);
+      gchar *text =
+        g_strdup_printf (_("Line <b>%d</b>, Column <b>%d</b>, Position <b>%d</b>"),
+                         line, column, pos);
+      gtk_tooltip_set_markup (tooltip, text);
+      g_free (text);
+    }
+  else
+    gtk_tooltip_set_text (tooltip, NULL);
+
+  return TRUE;
+}
+
+static gboolean
+on_query_tooltip (OverviewScintilla *self,
+                  gint               x,
+                  gint               y,
+                  gboolean           kbd_mode,
+                  GtkTooltip        *tooltip,
+                  GtkWidget         *widget)
+{
+  if (!kbd_mode)
+    return overview_scintilla_setup_tooltip (self, x, y, tooltip);
+  return FALSE;
+}
+
+static void
+overview_scintilla_setup_canvas (OverviewScintilla *self)
+{
+  if (!GTK_IS_WIDGET (self->canvas))
+    {
+      self->canvas = overview_scintilla_find_drawing_area (GTK_WIDGET (self));
+
+      gtk_widget_add_events (self->canvas,
+                             GDK_EXPOSURE_MASK |
+                              GDK_BUTTON_PRESS_MASK |
+                              GDK_BUTTON_RELEASE_MASK |
+                              GDK_POINTER_MOTION_MASK |
+                              GDK_SCROLL_MASK);
+
+      g_signal_connect_swapped (self->canvas,
+                                "scroll-event",
+                                G_CALLBACK (on_scroll_event),
+                                self);
+      g_signal_connect_swapped (self->canvas,
+                                "button-press-event",
+                                G_CALLBACK (on_button_press_event),
+                                self);
+      g_signal_connect_swapped (self->canvas,
+                                "button-release-event",
+                                G_CALLBACK (on_button_release_event),
+                                self);
+      g_signal_connect_swapped (self->canvas,
+                                "motion-notify-event",
+                                G_CALLBACK (on_motion_notify_event),
+                                self);
+      g_signal_connect_swapped (self->canvas,
+                                "query-tooltip",
+                                G_CALLBACK (on_query_tooltip),
+                                self);
+
+      gtk_widget_set_has_tooltip (self->canvas, self->show_tooltip);
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+      g_signal_connect_after (self->canvas,
+                              "draw",
+                              G_CALLBACK (overview_scintilla_draw),
+                              self);
+#else
+      g_signal_connect_after (self->canvas,
+                              "expose-event",
+                              G_CALLBACK (overview_scintilla_expose_event),
+                              self);
+#endif
+
+    }
+}
+
+static void
+overview_scintilla_update_rect (OverviewScintilla *self)
+{
+  GtkAllocation alloc;
+  GdkRectangle  rect;
+  gint          first_line, n_lines, last_line;
+  gint          pos_start, pos_end;
+  gint          ystart, yend;
+
+  gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+  first_line = sci_send (self->sci, GETFIRSTVISIBLELINE, 0, 0);
+  n_lines = sci_send (self->sci, LINESONSCREEN, 0, 0);
+  last_line = first_line + n_lines;
+
+  pos_start = sci_send (self, POSITIONFROMLINE, first_line, 0);
+  pos_end = sci_send (self, POSITIONFROMLINE, last_line, 0);
+
+  ystart = sci_send (self, POINTYFROMPOSITION, 0, pos_start);
+  yend = sci_send (self, POINTYFROMPOSITION, 0, pos_end);
+
+  if (yend >= alloc.height || yend == 0)
+    {
+      n_lines = sci_send (self, GETLINECOUNT, 0, 0);
+      last_line = n_lines - 1;
+      pos_end = sci_send (self, POSITIONFROMLINE, last_line, 0);
+      yend = sci_send (self, POINTYFROMPOSITION, 0, pos_end);
+    }
+
+  rect.x      = 0;
+  rect.width  = alloc.width - 1;
+  rect.y      = ystart;
+  rect.height = yend - ystart;
+
+  overview_scintilla_set_visible_rect (self, &rect);
+}
+
+static gint
+sci_get_midline_ (gpointer sci)
+{
+  gint first, count;
+  first = sci_send (sci, GETFIRSTVISIBLELINE, 0, 0);
+  count = sci_send (sci, LINESONSCREEN, 0, 0);
+  return first + (count / 2);
+}
+
+static void
+overview_scintilla_sync_center (OverviewScintilla *self)
+{
+  gint mid_src = sci_get_midline_ (self->sci);
+  gint mid_dst = sci_get_midline_ (self);
+  gint delta = mid_src - mid_dst;
+  sci_send (self, LINESCROLL, 0, delta);
+  overview_scintilla_update_rect (self);
+}
+
+static gboolean
+on_map_event (OverviewScintilla *self,
+              GdkEventAny       *event,
+              ScintillaObject   *sci)
+{
+  overview_scintilla_setup_canvas (self);
+
+  if (GTK_IS_WIDGET (self->canvas) &&
+      gtk_widget_get_double_buffered (self->canvas) != self->double_buffered)
+    {
+      gtk_widget_set_double_buffered (self->canvas, self->double_buffered);
+      self->double_buffered = gtk_widget_get_double_buffered (self->canvas);
+    }
+
+  overview_scintilla_update_cursor (self);
+  overview_scintilla_update_rect (self);
+
+  return FALSE;
+}
+
+#define self_connect(name, cb) \
+  g_signal_connect_swapped (self, name, G_CALLBACK (cb), self)
+
+static void
+overview_scintilla_init (OverviewScintilla *self)
+{
+  self->sci             = NULL;
+  self->canvas          = NULL;
+  self->cursor          = OVERVIEW_SCINTILLA_CURSOR;
+  self->active_cursor   = OVERVIEW_SCINTILLA_CURSOR;
+  self->update_rect     = 0;
+  self->conf_event      = 0;
+  self->src_canvas      = NULL;
+  self->width           = OVERVIEW_SCINTILLA_WIDTH_DEF;
+  self->zoom            = OVERVIEW_SCINTILLA_ZOOM_DEF;
+  self->mouse_down      = FALSE;
+  self->show_tooltip    = TRUE;
+  self->double_buffered = TRUE;
+  self->scroll_lines    = OVERVIEW_SCINTILLA_SCROLL_LINES;
+  self->show_scrollbar  = TRUE;
+  self->overlay_inverted = TRUE;
+
+  memset (&self->visible_rect, 0, sizeof (GdkRectangle));
+  memcpy (&self->overlay_color, &def_overlay_color, sizeof (OverviewColor));
+  memcpy (&self->overlay_outline_color, &def_overlay_outline_color, sizeof (OverviewColor));
+
+  gtk_widget_add_events (GTK_WIDGET (self),
+                         GDK_EXPOSURE_MASK |
+                         GDK_FOCUS_CHANGE_MASK |
+                         GDK_ENTER_NOTIFY_MASK |
+                         GDK_STRUCTURE_MASK);
+
+  self_connect ("focus-in-event", on_focus_in_event);
+  self_connect ("focus-out-event", on_focus_out_event);
+  self_connect ("enter-notify-event", on_enter_notify_event);
+  self_connect ("leave-notify-event", on_leave_notify_event);
+  self_connect ("map-event", on_map_event);
+}
+
+static void
+overview_scintilla_set_property (GObject      *object,
+                                 guint         prop_id,
+                                 const GValue *value,
+                                 GParamSpec   *pspec)
+{
+  OverviewScintilla *self = OVERVIEW_SCINTILLA (object);
+
+  switch (prop_id)
+    {
+    case PROP_SCINTILLA:
+      overview_scintilla_set_src_sci (self, g_value_get_object (value));
+      break;
+    case PROP_CURSOR:
+      overview_scintilla_set_cursor (self, g_value_get_enum (value));
+      break;
+    case PROP_VISIBLE_RECT:
+      overview_scintilla_set_visible_rect (self, g_value_get_boxed (value));
+      break;
+    case PROP_WIDTH:
+      overview_scintilla_set_width (@@ Diff output truncated at 100000 characters. @@

--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Plugins-Commits mailing list