[geany/geany-plugins] 5d66d0: Merge pull request #664 from LarsGit223/addons-colortip
Frank Lanitz
git-noreply at xxxxx
Mon Jan 29 17:56:09 UTC 2018
Branch: refs/heads/master
Author: Frank Lanitz <frank at frank.uvena.de>
Committer: GitHub <noreply at github.com>
Date: Mon, 29 Jan 2018 17:56:09 UTC
Commit: 5d66d039c5e938880dde19c4f005f7fd29a8e975
https://github.com/geany/geany-plugins/commit/5d66d039c5e938880dde19c4f005f7fd29a8e975
Log Message:
-----------
Merge pull request #664 from LarsGit223/addons-colortip
addons: show color tip and start Color Chooser with double click
Modified Paths:
--------------
addons/src/Makefile.am
addons/src/addons.c
addons/src/ao_colortip.c
addons/src/ao_colortip.h
Modified: addons/src/Makefile.am
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -25,7 +25,8 @@ addons_la_SOURCES = \
ao_tasks.c \
ao_xmltagging.c \
ao_wrapwords.c \
- ao_copyfilepath.c
+ ao_copyfilepath.c \
+ ao_colortip.c
addons_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DG_LOG_DOMAIN=\"Addons\"
Modified: addons/src/addons.c
42 lines changed, 42 insertions(+), 0 deletions(-)
===================================================================
@@ -39,6 +39,7 @@
#include "ao_xmltagging.h"
#include "ao_wrapwords.h"
#include "ao_copyfilepath.h"
+#include "ao_colortip.h"
GeanyPlugin *geany_plugin;
@@ -82,6 +83,8 @@ typedef struct
gboolean enable_enclose_words;
gboolean enable_enclose_words_auto;
gboolean strip_trailing_blank_lines;
+ gboolean enable_colortip;
+ gboolean enable_double_click_color_chooser;
gchar *tasks_token_list;
gboolean tasks_scan_all_documents;
@@ -96,6 +99,7 @@ typedef struct
AoMarkWord *markword;
AoTasks *tasks;
AoCopyFilePath *copyfilepath;
+ AoColorTip *colortip;
} AddonsInfo;
static AddonsInfo *ao_info = NULL;
@@ -181,6 +185,8 @@ gboolean ao_editor_notify_cb(GObject *object, GeanyEditor *editor,
ao_mark_editor_notify(ao_info->markword, editor, nt);
+ ao_color_tip_editor_notify(ao_info->colortip, editor, nt);
+
return FALSE;
}
@@ -208,6 +214,7 @@ static void ao_document_new_cb(GObject *obj, GeanyDocument *doc, gpointer data)
g_return_if_fail(doc != NULL && doc->is_valid);
ao_mark_document_new(ao_info->markword, doc);
+ ao_color_tip_document_new(ao_info->colortip, doc);
}
@@ -217,6 +224,7 @@ static void ao_document_open_cb(GObject *obj, GeanyDocument *doc, gpointer data)
ao_tasks_update(ao_info->tasks, doc);
ao_mark_document_open(ao_info->markword, doc);
+ ao_color_tip_document_open(ao_info->colortip, doc);
}
@@ -226,6 +234,7 @@ static void ao_document_close_cb(GObject *obj, GeanyDocument *doc, gpointer data
ao_tasks_remove(ao_info->tasks, doc);
ao_mark_document_close(ao_info->markword, doc);
+ ao_color_tip_document_close(ao_info->colortip, doc);
}
@@ -304,6 +313,10 @@ void plugin_init(GeanyData *data)
"enable_enclose_words", FALSE);
ao_info->enable_enclose_words_auto = utils_get_setting_boolean(config, "addons",
"enable_enclose_words_auto", FALSE);
+ ao_info->enable_colortip = utils_get_setting_boolean(config,
+ "addons", "enable_colortip", FALSE);
+ ao_info->enable_double_click_color_chooser = utils_get_setting_boolean(config,
+ "addons", "enable_double_click_color_chooser", FALSE);
plugin_module_make_resident(geany_plugin);
@@ -316,6 +329,8 @@ void plugin_init(GeanyData *data)
ao_info->tasks = ao_tasks_new(ao_info->enable_tasks,
ao_info->tasks_token_list, ao_info->tasks_scan_all_documents);
ao_info->copyfilepath = ao_copy_file_path_new();
+ ao_info->colortip = ao_color_tip_new(ao_info->enable_colortip,
+ ao_info->enable_double_click_color_chooser);
ao_blanklines_set_enable(ao_info->strip_trailing_blank_lines);
@@ -415,6 +430,10 @@ static void ao_configure_response_cb(GtkDialog *dialog, gint response, gpointer
g_object_get_data(G_OBJECT(dialog), "check_enclose_words"))));
ao_info->enable_enclose_words_auto = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
g_object_get_data(G_OBJECT(dialog), "check_enclose_words_auto"))));
+ ao_info->enable_colortip = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+ g_object_get_data(G_OBJECT(dialog), "check_colortip"))));
+ ao_info->enable_double_click_color_chooser = (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
+ g_object_get_data(G_OBJECT(dialog), "check_double_click_color_chooser"))));
ao_enclose_words_set_enabled (ao_info->enable_enclose_words, ao_info->enable_enclose_words_auto);
@@ -441,6 +460,9 @@ static void ao_configure_response_cb(GtkDialog *dialog, gint response, gpointer
ao_info->enable_enclose_words);
g_key_file_set_boolean(config, "addons", "enable_enclose_words_auto",
ao_info->enable_enclose_words_auto);
+ g_key_file_set_boolean(config, "addons", "enable_colortip", ao_info->enable_colortip);
+ g_key_file_set_boolean(config, "addons", "enable_double_click_color_chooser",
+ ao_info->enable_double_click_color_chooser);
g_object_set(ao_info->doclist, "enable-doclist", ao_info->enable_doclist, NULL);
g_object_set(ao_info->doclist, "sort-mode", ao_info->doclist_sort_mode, NULL);
@@ -458,6 +480,10 @@ static void ao_configure_response_cb(GtkDialog *dialog, gint response, gpointer
"tokens", ao_info->tasks_token_list,
NULL);
ao_blanklines_set_enable(ao_info->strip_trailing_blank_lines);
+ g_object_set(ao_info->colortip,
+ "enable-colortip", ao_info->enable_colortip,
+ "enable-double-click-color-chooser", ao_info->enable_double_click_color_chooser,
+ NULL);
if (! g_file_test(config_dir, G_FILE_TEST_IS_DIR) && utils_mkdir(config_dir, TRUE) != 0)
{
@@ -487,6 +513,7 @@ GtkWidget *plugin_configure(GtkDialog *dialog)
GtkWidget *check_tasks_scan_mode, *entry_tasks_tokens, *label_tasks_tokens, *tokens_hbox;
GtkWidget *check_blanklines, *check_xmltagging;
GtkWidget *check_enclose_words, *check_enclose_words_auto, *enclose_words_config_button, *enclose_words_hbox;
+ GtkWidget *check_colortip, *check_double_click_color_chooser;
vbox = gtk_vbox_new(FALSE, 6);
@@ -633,6 +660,17 @@ GtkWidget *plugin_configure(GtkDialog *dialog)
ao_info->enable_enclose_words_auto);
gtk_box_pack_start(GTK_BOX(vbox), check_enclose_words_auto, FALSE, FALSE, 3);
+ check_colortip = gtk_check_button_new_with_label(
+ _("Show a calltip when hovering over a color value"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_colortip),
+ ao_info->enable_colortip);
+ gtk_box_pack_start(GTK_BOX(vbox), check_colortip, FALSE, FALSE, 3);
+
+ check_double_click_color_chooser = gtk_check_button_new_with_label(
+ _("Open Color Chooser when double-clicking a color value"));
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_double_click_color_chooser),
+ ao_info->enable_double_click_color_chooser);
+ gtk_box_pack_start(GTK_BOX(vbox), check_double_click_color_chooser, FALSE, FALSE, 3);
g_object_set_data(G_OBJECT(dialog), "check_doclist", check_doclist);
g_object_set_data(G_OBJECT(dialog), "radio_doclist_name", radio_doclist_name);
@@ -653,6 +691,9 @@ GtkWidget *plugin_configure(GtkDialog *dialog)
g_object_set_data(G_OBJECT(dialog), "check_enclose_words", check_enclose_words);
g_object_set_data(G_OBJECT(dialog), "check_enclose_words_auto", check_enclose_words_auto);
g_object_set_data(G_OBJECT(dialog), "enclose_words_config_button", enclose_words_config_button);
+ g_object_set_data(G_OBJECT(dialog), "check_colortip", check_colortip);
+ g_object_set_data(G_OBJECT(dialog), "check_double_click_color_chooser",
+ check_double_click_color_chooser);
g_signal_connect(dialog, "response", G_CALLBACK(ao_configure_response_cb), NULL);
ao_configure_tasks_toggled_cb(GTK_TOGGLE_BUTTON(check_tasks), dialog);
@@ -678,6 +719,7 @@ void plugin_cleanup(void)
g_object_unref(ao_info->markword);
g_object_unref(ao_info->tasks);
g_object_unref(ao_info->copyfilepath);
+ g_object_unref(ao_info->colortip);
g_free(ao_info->tasks_token_list);
ao_blanklines_set_enable(FALSE);
Modified: addons/src/ao_colortip.c
385 lines changed, 385 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,385 @@
+/*
+ * ao_colortip.c - this file is part of Addons, a Geany plugin
+ *
+ * Copyright 2017 LarsGit223
+ *
+ * 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.
+ */
+
+
+#include <gtk/gtk.h>
+#include <glib-object.h>
+
+#include "geanyplugin.h"
+
+#include "addons.h"
+#include "ao_colortip.h"
+
+typedef struct _AoColorTipPrivate AoColorTipPrivate;
+
+#define AO_COLORTIP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj),\
+ AO_COLORTIP_TYPE, AoColorTipPrivate))
+
+struct _AoColorTip
+{
+ GObject parent;
+};
+
+struct _AoColorTipClass
+{
+ GObjectClass parent_class;
+};
+
+struct _AoColorTipPrivate
+{
+ gboolean enable_colortip;
+ gboolean enable_double_click_color_chooser;
+};
+
+enum
+{
+ PROP_0,
+ PROP_ENABLE_COLORTIP,
+ PROP_ENABLE_DOUBLE_CLICK_COLOR_CHOOSER,
+};
+
+G_DEFINE_TYPE(AoColorTip, ao_color_tip, G_TYPE_OBJECT)
+
+# define SSM(s, m, w, l) scintilla_send_message (s, m, w, l)
+
+
+/* Find a color value (short or long form, e.g. #fff or #ffffff) in the
+ given string. position must be inside the found color or at maximum
+ maxdist bytes in front of it (in front of the start of the color value)
+ or behind it (behind the end of the color value). */
+static gint contains_color_value(gchar *string, gint position, gint maxdist)
+{
+ gchar *start;
+ gint end, value, offset, color = -1;
+ guint length;
+
+ start = strchr(string, '#');
+ if (start == NULL)
+ {
+ return color;
+ }
+ end = start - string + 1;
+ while (g_ascii_isxdigit (string[end]))
+ {
+ end++;
+ }
+ end--;
+ length = &(string[end]) - start + 1;
+
+ if (maxdist != -1)
+ {
+ offset = start - string + 1;
+ if (position < offset &&
+ (offset - position) > maxdist)
+ {
+ return color;
+ }
+
+ offset = end;
+ if (position > offset &&
+ (position - offset) > maxdist)
+ {
+ return color;
+ }
+ }
+
+
+ if (length == 4)
+ {
+ start++;
+ color = (g_ascii_xdigit_value (*start) << 4)
+ | g_ascii_xdigit_value (*start);
+
+ start++;
+ value = (g_ascii_xdigit_value (*start) << 4)
+ | g_ascii_xdigit_value (*start);
+ color += value << 8;
+
+ start++;
+ value = (g_ascii_xdigit_value (*start) << 4)
+ | g_ascii_xdigit_value (*start);
+ color += value << 16;
+ }
+ else if (length == 7)
+ {
+ start++;
+ color = (g_ascii_xdigit_value (start[0]) << 4)
+ | g_ascii_xdigit_value (start[1]);
+
+ start += 2;
+ value = (g_ascii_xdigit_value (start[0]) << 4)
+ | g_ascii_xdigit_value (start[1]);
+ color += value << 8;
+
+ start += 2;
+ value = (g_ascii_xdigit_value (start[0]) << 4)
+ | g_ascii_xdigit_value (start[1]);
+ color += value << 16;
+ }
+
+ return color;
+}
+
+
+static gint get_color_value_at_current_doc_position(void)
+{
+ gint color = -1;
+ GeanyDocument *doc = document_get_current();
+ gchar *word = editor_get_word_at_pos(doc->editor, -1, "0123456789abcdefABCDEF");
+
+ if (word)
+ {
+ switch (strlen (word))
+ {
+ case 3:
+ color = ((g_ascii_xdigit_value(word[0]) * 0x11) << 16 |
+ (g_ascii_xdigit_value(word[1]) * 0x11) << 8 |
+ (g_ascii_xdigit_value(word[2]) * 0x11) << 0);
+ break;
+ case 6:
+ color = (g_ascii_xdigit_value(word[0]) << 20 |
+ g_ascii_xdigit_value(word[1]) << 16 |
+ g_ascii_xdigit_value(word[2]) << 12 |
+ g_ascii_xdigit_value(word[3]) << 8 |
+ g_ascii_xdigit_value(word[4]) << 4 |
+ g_ascii_xdigit_value(word[5]) << 0);
+ break;
+ default:
+ /* invalid color or other format */
+ break;
+ }
+ }
+
+ return color;
+}
+
+static gboolean on_editor_button_press_event(GtkWidget *widget, GdkEventButton *event,
+ AoColorTip *colortip)
+{
+ if (event->button == 1)
+ {
+ if (event->type == GDK_2BUTTON_PRESS)
+ {
+ AoColorTipPrivate *priv = AO_COLORTIP_GET_PRIVATE(colortip);
+
+ if (!priv->enable_double_click_color_chooser)
+ return FALSE;
+
+ if (get_color_value_at_current_doc_position() != -1)
+ {
+ keybindings_send_command
+ (GEANY_KEY_GROUP_TOOLS, GEANY_KEYS_TOOLS_OPENCOLORCHOOSER);
+ }
+ }
+ }
+ return FALSE;
+}
+
+
+void ao_color_tip_editor_notify(AoColorTip *colortip, GeanyEditor *editor, SCNotification *nt)
+{
+ ScintillaObject *sci = editor->sci;
+ AoColorTipPrivate *priv = AO_COLORTIP_GET_PRIVATE(colortip);
+
+ if (!priv->enable_colortip)
+ {
+ /* Ignore all events if color tips are disabled in preferences */
+ return;
+ }
+
+ switch (nt->nmhdr.code)
+ {
+ case SCN_DWELLSTART:
+ {
+ gchar *subtext;
+ gint start, end, pos, max;
+
+ /* Is position valid? */
+ if (nt->position < 0)
+ break;
+
+ /* Calculate range */
+ start = nt->position;
+ if (start >= 7)
+ {
+ start -= 7;
+ }
+ else
+ {
+ start = 0;
+ }
+ pos = nt->position - start;
+ end = nt->position + 7;
+ max = SSM(sci, SCI_GETTEXTLENGTH, 0, 0);
+ if (end > max)
+ {
+ end = max;
+ }
+
+ /* Get text in range and examine it */
+ subtext = sci_get_contents_range(sci, start, end);
+ if (subtext != NULL)
+ {
+ gint color;
+
+ color = contains_color_value (subtext, pos, 2);
+ if (color != -1)
+ {
+ SSM(sci, SCI_CALLTIPSETBACK, color, 0);
+ SSM(sci, SCI_CALLTIPSHOW, nt->position, (sptr_t)" ");
+ }
+ g_free(subtext);
+ }
+ }
+ break;
+
+ case SCN_DWELLEND:
+ SSM(sci, SCI_CALLTIPCANCEL, 0, 0);
+ break;
+ }
+}
+
+
+static void connect_document_button_press_signal_handler(AoColorTip *colortip, GeanyDocument *document)
+{
+ g_return_if_fail(DOC_VALID(document));
+
+ plugin_signal_connect(
+ geany_plugin,
+ G_OBJECT(document->editor->sci),
+ "button-press-event",
+ FALSE,
+ G_CALLBACK(on_editor_button_press_event),
+ colortip);
+}
+
+
+static void connect_documents_button_press_signal_handler(AoColorTip *colortip)
+{
+ guint i = 0;
+ /* connect the button-press event for all open documents */
+ foreach_document(i)
+ {
+ connect_document_button_press_signal_handler(colortip, documents[i]);
+ }
+}
+
+
+static void ao_color_tip_finalize(GObject *object)
+{
+ g_return_if_fail(object != NULL);
+ g_return_if_fail(IS_AO_COLORTIP(object));
+
+ G_OBJECT_CLASS(ao_color_tip_parent_class)->finalize(object);
+}
+
+
+static void ao_color_tip_set_property(GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ AoColorTipPrivate *priv = AO_COLORTIP_GET_PRIVATE(object);
+
+ switch (prop_id)
+ {
+ case PROP_ENABLE_COLORTIP:
+ priv->enable_colortip = g_value_get_boolean(value);
+ break;
+ case PROP_ENABLE_DOUBLE_CLICK_COLOR_CHOOSER:
+ priv->enable_double_click_color_chooser = g_value_get_boolean(value);
+
+ /* If the plugin is loaded while Geany is already running, we need to connect the
+ * button press signal for open documents, if Geany is just booting,
+ * it happens automatically */
+ if (priv->enable_double_click_color_chooser && main_is_realized())
+ {
+ connect_documents_button_press_signal_handler(AO_COLORTIP(object));
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+
+void ao_color_tip_document_new(AoColorTip *colortip, GeanyDocument *document)
+{
+ connect_document_button_press_signal_handler(colortip, document);
+ SSM(document->editor->sci, SCI_SETMOUSEDWELLTIME, 300, 0);
+}
+
+
+void ao_color_tip_document_open(AoColorTip *colortip, GeanyDocument *document)
+{
+ connect_document_button_press_signal_handler(colortip, document);
+ SSM(document->editor->sci, SCI_SETMOUSEDWELLTIME, 300, 0);
+}
+
+
+void ao_color_tip_document_close(AoColorTip *colortip, GeanyDocument *document)
+{
+ g_return_if_fail(DOC_VALID(document));
+
+ g_signal_handlers_disconnect_by_func(document->editor->sci, on_editor_button_press_event, colortip);
+}
+
+
+static void ao_color_tip_class_init(AoColorTipClass *klass)
+{
+ GObjectClass *g_object_class;
+
+ g_object_class = G_OBJECT_CLASS(klass);
+ g_object_class->finalize = ao_color_tip_finalize;
+ g_object_class->set_property = ao_color_tip_set_property;
+ g_type_class_add_private(klass, sizeof(AoColorTipPrivate));
+
+ g_object_class_install_property(g_object_class,
+ PROP_ENABLE_COLORTIP,
+ g_param_spec_boolean(
+ "enable-colortip",
+ "enable-colortip",
+ "Whether to show a calltip when hovering over a color value",
+ TRUE,
+ G_PARAM_WRITABLE));
+
+ g_object_class_install_property(g_object_class,
+ PROP_ENABLE_DOUBLE_CLICK_COLOR_CHOOSER,
+ g_param_spec_boolean(
+ "enable-double-click-color-chooser",
+ "enable-double-click-color-chooser",
+ "Enable starting the Color Chooser when double clicking on a color value",
+ TRUE,
+ G_PARAM_WRITABLE));
+}
+
+static void ao_color_tip_init(AoColorTip *self)
+{
+ AoColorTipPrivate *priv = AO_COLORTIP_GET_PRIVATE(self);
+ memset(priv, 0, sizeof(*priv));
+}
+
+AoColorTip *ao_color_tip_new(gboolean enable_tip, gboolean double_click_color_chooser)
+{
+ return g_object_new(
+ AO_COLORTIP_TYPE,
+ "enable-colortip", enable_tip,
+ "enable-double-click-color-chooser", double_click_color_chooser,
+ NULL);
+}
Modified: addons/src/ao_colortip.h
49 lines changed, 49 insertions(+), 0 deletions(-)
===================================================================
@@ -0,0 +1,49 @@
+/*
+ * ao_colortip.h - this file is part of Addons, a Geany plugin
+ *
+ * Copyright 2017 LarsGit223
+ *
+ * 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 __AO_COLORTIP_H__
+#define __AO_COLORTIP_H__
+
+G_BEGIN_DECLS
+
+#define AO_COLORTIP_TYPE (ao_color_tip_get_type())
+#define AO_COLORTIP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
+ AO_COLORTIP_TYPE, AoColorTip))
+#define AO_COLORTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\
+ AO_COLORTIP_TYPE, AoColorTipClass))
+#define IS_AO_COLORTIP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
+ AO_COLORTIP_TYPE))
+#define IS_AO_COLORTIP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
+ AO_COLORTIP_TYPE))
+
+typedef struct _AoColorTip AoColorTip;
+typedef struct _AoColorTipClass AoColorTipClass;
+
+GType ao_color_tip_get_type (void);
+AoColorTip* ao_color_tip_new (gboolean enable_tip, gboolean double_click_color_chooser);
+void ao_color_tip_document_new (AoColorTip *colortip, GeanyDocument *document);
+void ao_color_tip_document_open (AoColorTip *colortip, GeanyDocument *document);
+void ao_color_tip_document_close (AoColorTip *colortip, GeanyDocument *document);
+void ao_color_tip_editor_notify (AoColorTip *colortip, GeanyEditor *editor, SCNotification *nt);
+
+G_END_DECLS
+
+#endif /* __AO_COLORTIP_H__ */
--------------
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