[gnome-text-editor] spellcheck: plumb buffer information to spell adapter
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-text-editor] spellcheck: plumb buffer information to spell adapter
- Date: Fri, 25 Jun 2021 23:23:41 +0000 (UTC)
commit ad3c4c3e4e55b3bff8a32dc5242b3aa85e46acff
Author: Christian Hergert <chergert redhat com>
Date: Fri Jun 25 16:23:30 2021 -0700
spellcheck: plumb buffer information to spell adapter
The goal of the spell adapter is to handle the details of driving the
spellcheck so that it can live outside of EditorDocument. That also makes
it easier to migrate or use elsewhere in the future without having to
extract it from EditorDocument (such as into GtkTextBuffer).
src/editor-document.c | 59 ++++++---
src/editor-text-buffer-spell-adapter.c | 233 +++++++++++++++++++++++++++++++++
src/editor-text-buffer-spell-adapter.h | 47 +++++++
src/meson.build | 1 +
4 files changed, 325 insertions(+), 15 deletions(-)
---
diff --git a/src/editor-document.c b/src/editor-document.c
index 019fbdd..5c88059 100644
--- a/src/editor-document.c
+++ b/src/editor-document.c
@@ -29,6 +29,7 @@
#include "editor-buffer-monitor-private.h"
#include "editor-document-private.h"
#include "editor-spell-checker.h"
+#include "editor-text-buffer-spell-adapter.h"
#include "editor-session-private.h"
#include "editor-window.h"
@@ -38,23 +39,25 @@
struct _EditorDocument
{
- GtkSourceBuffer parent_instance;
+ GtkSourceBuffer parent_instance;
- EditorBufferMonitor *monitor;
- GtkSourceFile *file;
- gchar *draft_id;
- GtkTextTag *line_spacing_tag;
- const GtkSourceEncoding *encoding;
- EditorSpellChecker *spell_checker;
+ EditorBufferMonitor *monitor;
+ GtkSourceFile *file;
+ gchar *draft_id;
+ GtkTextTag *line_spacing_tag;
+ const GtkSourceEncoding *encoding;
- GtkSourceNewlineType newline_type;
- guint busy_count;
- gdouble busy_progress;
+ EditorSpellChecker *spell_checker;
+ EditorTextBufferSpellAdapter *spell_adapter;
- guint readonly : 1;
- guint needs_autosave : 1;
- guint was_restored : 1;
- guint externally_modified : 1;
+ GtkSourceNewlineType newline_type;
+ guint busy_count;
+ gdouble busy_progress;
+
+ guint readonly : 1;
+ guint needs_autosave : 1;
+ guint was_restored : 1;
+ guint externally_modified : 1;
};
typedef struct
@@ -193,6 +196,7 @@ editor_document_insert_text (GtkTextBuffer *buffer,
{
EditorDocument *self = (EditorDocument *)buffer;
guint offset;
+ guint length;
g_assert (GTK_IS_TEXT_BUFFER (buffer));
g_assert (pos != NULL);
@@ -202,6 +206,11 @@ editor_document_insert_text (GtkTextBuffer *buffer,
GTK_TEXT_BUFFER_CLASS (editor_document_parent_class)->insert_text (buffer, pos, new_text, new_text_length);
+ length = gtk_text_iter_get_offset (pos) - offset;
+
+ if (length > 0)
+ editor_text_buffer_spell_adapter_insert_text (self->spell_adapter, offset, length);
+
if (offset < TITLE_MAX_LEN && editor_document_get_file (self) == NULL)
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
}
@@ -213,15 +222,21 @@ editor_document_delete_range (GtkTextBuffer *buffer,
{
EditorDocument *self = (EditorDocument *)buffer;
guint offset;
+ guint length;
g_assert (GTK_IS_TEXT_BUFFER (buffer));
g_assert (start != NULL);
g_assert (end != NULL);
+ g_assert (gtk_text_iter_compare (start, end) <= 0);
offset = gtk_text_iter_get_offset (start);
+ length = gtk_text_iter_get_offset (end) - offset;
GTK_TEXT_BUFFER_CLASS (editor_document_parent_class)->delete_range (buffer, start, end);
+ if (length > 0)
+ editor_text_buffer_spell_adapter_delete_range (self->spell_adapter, offset, length);
+
if (offset < TITLE_MAX_LEN && editor_document_get_file (self) == NULL)
g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
}
@@ -294,6 +309,12 @@ editor_document_monitor_notify_changed_cb (EditorDocument *self,
_editor_document_set_externally_modified (self, changed);
}
+static void
+on_cursor_moved_cb (EditorDocument *self)
+{
+ editor_text_buffer_spell_adapter_cursor_moved (self->spell_adapter);
+}
+
static void
editor_document_constructed (GObject *object)
{
@@ -316,6 +337,7 @@ editor_document_finalize (GObject *object)
g_clear_object (&self->monitor);
g_clear_object (&self->file);
g_clear_object (&self->spell_checker);
+ g_clear_object (&self->spell_adapter);
g_clear_pointer (&self->draft_id, g_free);
G_OBJECT_CLASS (editor_document_parent_class)->finalize (object);
@@ -450,6 +472,8 @@ editor_document_init (EditorDocument *self)
self->file = gtk_source_file_new ();
self->draft_id = g_uuid_string_random ();
self->spell_checker = editor_spell_checker_new (NULL, NULL);
+ self->spell_adapter = editor_text_buffer_spell_adapter_new (GTK_TEXT_BUFFER (self),
+ self->spell_checker);
self->monitor = editor_buffer_monitor_new ();
g_signal_connect_object (self->monitor,
@@ -460,6 +484,8 @@ editor_document_init (EditorDocument *self)
g_object_bind_property (self->file, "location",
self->monitor, "file",
G_BINDING_SYNC_CREATE);
+
+ g_signal_connect (self, "cursor-moved", G_CALLBACK (on_cursor_moved_cb), NULL);
}
EditorDocument *
@@ -1704,5 +1730,8 @@ editor_document_set_spell_checker (EditorDocument *self,
g_return_if_fail (!spell_checker || EDITOR_IS_SPELL_CHECKER (spell_checker));
if (g_set_object (&self->spell_checker, spell_checker))
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SPELL_CHECKER]);
+ {
+ editor_text_buffer_spell_adapter_set_checker (self->spell_adapter, spell_checker);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SPELL_CHECKER]);
+ }
}
diff --git a/src/editor-text-buffer-spell-adapter.c b/src/editor-text-buffer-spell-adapter.c
new file mode 100644
index 0000000..0549e96
--- /dev/null
+++ b/src/editor-text-buffer-spell-adapter.c
@@ -0,0 +1,233 @@
+/* editor-text-buffer-spell-adapter.c
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include "config.h"
+
+#include "cjhtextregionprivate.h"
+
+#include "editor-spell-checker.h"
+#include "editor-text-buffer-spell-adapter.h"
+
+#define UNCHECKED GSIZE_TO_POINTER(0)
+#define CHECKED GSIZE_TO_POINTER(1)
+
+struct _EditorTextBufferSpellAdapter
+{
+ GObject parent_instance;
+ GtkTextBuffer *buffer;
+ EditorSpellChecker *checker;
+ CjhTextRegion *region;
+};
+
+G_DEFINE_TYPE (EditorTextBufferSpellAdapter, editor_text_buffer_spell_adapter, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_BUFFER,
+ PROP_CHECKER,
+ N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+EditorTextBufferSpellAdapter *
+editor_text_buffer_spell_adapter_new (GtkTextBuffer *buffer,
+ EditorSpellChecker *checker)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+ g_return_val_if_fail (!checker || EDITOR_IS_SPELL_CHECKER (checker), NULL);
+
+ return g_object_new (EDITOR_TYPE_TEXT_BUFFER_SPELL_ADAPTER,
+ "buffer", buffer,
+ "checker", checker,
+ NULL);
+}
+
+static void
+editor_text_buffer_spell_adapter_set_buffer (EditorTextBufferSpellAdapter *self,
+ GtkTextBuffer *buffer)
+{
+ g_assert (EDITOR_IS_TEXT_BUFFER_SPELL_ADAPTER (self));
+ g_assert (GTK_IS_TEXT_BUFFER (buffer));
+
+ if (g_set_weak_pointer (&self->buffer, buffer))
+ {
+ GtkTextIter begin, end;
+ guint offset;
+ guint length;
+
+ gtk_text_buffer_get_bounds (buffer, &begin, &end);
+
+ offset = gtk_text_iter_get_offset (&begin);
+ length = gtk_text_iter_get_offset (&end) - offset;
+
+ _cjh_text_region_insert (self->region, offset, length, UNCHECKED);
+ }
+}
+
+static void
+editor_text_buffer_spell_adapter_finalize (GObject *object)
+{
+ EditorTextBufferSpellAdapter *self = (EditorTextBufferSpellAdapter *)object;
+
+ g_clear_object (&self->checker);
+ g_clear_weak_pointer (&self->buffer);
+ g_clear_pointer (&self->region, _cjh_text_region_free);
+
+ G_OBJECT_CLASS (editor_text_buffer_spell_adapter_parent_class)->finalize (object);
+}
+
+static void
+editor_text_buffer_spell_adapter_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EditorTextBufferSpellAdapter *self = EDITOR_TEXT_BUFFER_SPELL_ADAPTER (object);
+
+ switch (prop_id)
+ {
+ case PROP_BUFFER:
+ g_value_set_object (value, self->buffer);
+ break;
+
+ case PROP_CHECKER:
+ g_value_set_object (value, editor_text_buffer_spell_adapter_get_checker (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_text_buffer_spell_adapter_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EditorTextBufferSpellAdapter *self = EDITOR_TEXT_BUFFER_SPELL_ADAPTER (object);
+
+ switch (prop_id)
+ {
+ case PROP_BUFFER:
+ editor_text_buffer_spell_adapter_set_buffer (self, g_value_get_object (value));
+ break;
+
+ case PROP_CHECKER:
+ editor_text_buffer_spell_adapter_set_checker (self, g_value_get_object (value));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+editor_text_buffer_spell_adapter_class_init (EditorTextBufferSpellAdapterClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = editor_text_buffer_spell_adapter_finalize;
+ object_class->get_property = editor_text_buffer_spell_adapter_get_property;
+ object_class->set_property = editor_text_buffer_spell_adapter_set_property;
+
+ properties [PROP_BUFFER] =
+ g_param_spec_object ("buffer",
+ "Buffer",
+ "Buffer",
+ GTK_TYPE_TEXT_BUFFER,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_CHECKER] =
+ g_param_spec_object ("checker",
+ "Checker",
+ "Checker",
+ EDITOR_TYPE_SPELL_CHECKER,
+ (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+editor_text_buffer_spell_adapter_init (EditorTextBufferSpellAdapter *self)
+{
+ self->region = _cjh_text_region_new (NULL, NULL);
+}
+
+EditorSpellChecker *
+editor_text_buffer_spell_adapter_get_checker (EditorTextBufferSpellAdapter *self)
+{
+ g_return_val_if_fail (EDITOR_IS_TEXT_BUFFER_SPELL_ADAPTER (self), NULL);
+
+ return self->checker;
+}
+
+void
+editor_text_buffer_spell_adapter_set_checker (EditorTextBufferSpellAdapter *self,
+ EditorSpellChecker *checker)
+{
+ g_return_if_fail (EDITOR_IS_TEXT_BUFFER_SPELL_ADAPTER (self));
+ g_return_if_fail (!checker || EDITOR_IS_SPELL_CHECKER (checker));
+
+ if (g_set_object (&self->checker, checker))
+ {
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CHECKER]);
+ }
+}
+
+GtkTextBuffer *
+editor_text_buffer_spell_adapter_get_buffer (EditorTextBufferSpellAdapter *self)
+{
+ g_return_val_if_fail (EDITOR_IS_TEXT_BUFFER_SPELL_ADAPTER (self), NULL);
+
+ return self->buffer;
+}
+
+void
+editor_text_buffer_spell_adapter_insert_text (EditorTextBufferSpellAdapter *self,
+ guint offset,
+ guint length)
+{
+ g_return_if_fail (EDITOR_IS_TEXT_BUFFER_SPELL_ADAPTER (self));
+ g_return_if_fail (length > 0);
+
+ _cjh_text_region_insert (self->region, offset, length, UNCHECKED);
+}
+
+void
+editor_text_buffer_spell_adapter_delete_range (EditorTextBufferSpellAdapter *self,
+ guint offset,
+ guint length)
+{
+ g_return_if_fail (EDITOR_IS_TEXT_BUFFER_SPELL_ADAPTER (self));
+ g_return_if_fail (self->buffer != NULL);
+ g_return_if_fail (length > 0);
+
+ _cjh_text_region_remove (self->region, offset, length);
+}
+
+void
+editor_text_buffer_spell_adapter_cursor_moved (EditorTextBufferSpellAdapter *self)
+{
+ g_return_if_fail (EDITOR_IS_TEXT_BUFFER_SPELL_ADAPTER (self));
+ g_return_if_fail (self->buffer != NULL);
+
+}
diff --git a/src/editor-text-buffer-spell-adapter.h b/src/editor-text-buffer-spell-adapter.h
new file mode 100644
index 0000000..bd676ac
--- /dev/null
+++ b/src/editor-text-buffer-spell-adapter.h
@@ -0,0 +1,47 @@
+/* editor-text-buffer-spell-adapter.h
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gtk/gtk.h>
+
+#include "editor-types.h"
+
+G_BEGIN_DECLS
+
+#define EDITOR_TYPE_TEXT_BUFFER_SPELL_ADAPTER (editor_text_buffer_spell_adapter_get_type())
+
+G_DECLARE_FINAL_TYPE (EditorTextBufferSpellAdapter, editor_text_buffer_spell_adapter, EDITOR,
TEXT_BUFFER_SPELL_ADAPTER, GObject)
+
+EditorTextBufferSpellAdapter *editor_text_buffer_spell_adapter_new (GtkTextBuffer
*buffer,
+ EditorSpellChecker
*checker);
+GtkTextBuffer *editor_text_buffer_spell_adapter_get_buffer (EditorTextBufferSpellAdapter
*self);
+EditorSpellChecker *editor_text_buffer_spell_adapter_get_checker (EditorTextBufferSpellAdapter
*self);
+void editor_text_buffer_spell_adapter_set_checker (EditorTextBufferSpellAdapter
*self,
+ EditorSpellChecker
*checker);
+void editor_text_buffer_spell_adapter_insert_text (EditorTextBufferSpellAdapter
*self,
+ guint
offset,
+ guint
len);
+void editor_text_buffer_spell_adapter_delete_range (EditorTextBufferSpellAdapter
*self,
+ guint
offset,
+ guint
len);
+void editor_text_buffer_spell_adapter_cursor_moved (EditorTextBufferSpellAdapter
*self);
+
+G_END_DECLS
diff --git a/src/meson.build b/src/meson.build
index 3ba3182..96431d4 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -36,6 +36,7 @@ editor_sources = [
'editor-spell-language.c',
'editor-spell-menu.c',
'editor-spell-provider.c',
+ 'editor-text-buffer-spell-adapter.c',
'editor-theme-selector.c',
'editor-utils.c',
'editor-window.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]