[gtksourceview/wip/chergert/vim: 12/73] start on idea for classes for state
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/vim: 12/73] start on idea for classes for state
- Date: Tue, 26 Oct 2021 23:20:36 +0000 (UTC)
commit a7607a2a4713775a9bd9bb74683c9ee74508885c
Author: Christian Hergert <chergert redhat com>
Date: Tue Oct 19 17:24:59 2021 -0700
start on idea for classes for state
the main thing is that we want a better way to handle repeat as well as
moving in/out of states (suspend/restore).
gtksourceview/gtksourcevimstate.c | 347 ++++++++++++++++++++++++++++++++++++++
gtksourceview/gtksourcevimstate.h | 70 ++++++++
gtksourceview/meson.build | 1 +
3 files changed, 418 insertions(+)
---
diff --git a/gtksourceview/gtksourcevimstate.c b/gtksourceview/gtksourcevimstate.c
new file mode 100644
index 00000000..ab6218b2
--- /dev/null
+++ b/gtksourceview/gtksourcevimstate.c
@@ -0,0 +1,347 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gtksourceview.h"
+#include "gtksourcevimstate.h"
+
+typedef struct
+{
+ GtkSourceVimState *parent;
+ GtkSourceView *view;
+} GtkSourceVimStatePrivate;
+
+struct _GtkSourceVimNormal
+{
+ GtkSourceVimState parent_instance;
+};
+
+struct _GtkSourceVimInsert
+{
+ GtkSourceVimState parent_instance;
+};
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkSourceVimState, gtk_source_vim_state, G_TYPE_OBJECT)
+G_DEFINE_TYPE (GtkSourceVimNormal, gtk_source_vim_normal, GTK_SOURCE_TYPE_VIM_STATE)
+G_DEFINE_TYPE (GtkSourceVimInsert, gtk_source_vim_insert, GTK_SOURCE_TYPE_VIM_STATE)
+
+enum {
+ STATE_PROP_0,
+ STATE_PROP_PARENT,
+ STATE_PROP_VIEW,
+ STATE_N_PROPS
+};
+
+static GParamSpec *state_properties [STATE_N_PROPS];
+
+static void
+gtk_source_vim_state_dispose (GObject *object)
+{
+ GtkSourceVimState *self = (GtkSourceVimState *)object;
+ GtkSourceVimStatePrivate *priv = gtk_source_vim_state_get_instance_private (self);
+
+ g_clear_object (&priv->parent);
+
+ G_OBJECT_CLASS (gtk_source_vim_state_parent_class)->dispose (object);
+}
+
+static void
+gtk_source_vim_state_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceVimState *self = GTK_SOURCE_VIM_STATE (object);
+
+ switch (prop_id)
+ {
+ case STATE_PROP_PARENT:
+ g_value_set_object (value, gtk_source_vim_state_get_parent (self));
+ break;
+
+ case STATE_PROP_VIEW:
+ g_value_set_object (value, gtk_source_vim_state_get_view (self));
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_vim_state_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GtkSourceVimState *self = GTK_SOURCE_VIM_STATE (object);
+ GtkSourceVimStatePrivate *priv = gtk_source_vim_state_get_instance_private (self);
+
+ switch (prop_id)
+ {
+ case STATE_PROP_PARENT:
+ priv->parent = g_value_dup_object (value);
+ break;
+
+ case STATE_PROP_VIEW:
+ priv->view = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gtk_source_vim_state_class_init (GtkSourceVimStateClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gtk_source_vim_state_dispose;
+ object_class->get_property = gtk_source_vim_state_get_property;
+ object_class->set_property = gtk_source_vim_state_set_property;
+
+ state_properties [STATE_PROP_PARENT] =
+ g_param_spec_object ("parent",
+ "Parent",
+ "The parent state",
+ GTK_SOURCE_TYPE_VIM_STATE,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ state_properties [STATE_PROP_VIEW] =
+ g_param_spec_object ("view",
+ "View",
+ "The source view",
+ GTK_SOURCE_TYPE_VIEW,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, STATE_N_PROPS, state_properties);
+}
+
+static void
+gtk_source_vim_state_init (GtkSourceVimState *self)
+{
+}
+
+void
+gtk_source_vim_state_get_iter (GtkSourceVimState *self,
+ GtkTextIter *iter)
+{
+ GtkSourceVimStatePrivate *priv = gtk_source_vim_state_get_instance_private (self);
+ GtkTextBuffer *buffer;
+ GtkTextMark *mark;
+
+ g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+ g_return_if_fail (iter != NULL);
+
+ buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->view));
+ mark = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, iter, mark);
+}
+
+void
+gtk_source_vim_state_move_to (GtkSourceVimState *self,
+ const GtkTextIter *iter)
+{
+ g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+ g_return_if_fail (iter != NULL);
+
+ gtk_text_buffer_select_range (gtk_text_iter_get_buffer (iter), iter, iter);
+}
+
+/**
+ * gtk_source_vim_state_get_parent:
+ *
+ * Returns: (transfer none) (nullable): a #GtkSourceVimState or %NULL
+ */
+GtkSourceVimState *
+gtk_source_vim_state_get_parent (GtkSourceVimState *self)
+{
+ GtkSourceVimStatePrivate *priv = gtk_source_vim_state_get_instance_private (self);
+
+ g_return_val_if_fail (GTK_SOURCE_IS_VIM_STATE (self), NULL);
+
+ return priv->parent;
+}
+
+/**
+ * gtk_source_vim_state_get_view:
+ *
+ * Returns: (transfer none): a #GtkSourceView
+ */
+GtkSourceView *
+gtk_source_vim_state_get_view (GtkSourceVimState *self)
+{
+ GtkSourceVimStatePrivate *priv = gtk_source_vim_state_get_instance_private (self);
+
+ g_return_val_if_fail (GTK_SOURCE_IS_VIM_STATE (self), NULL);
+
+ return priv->view;
+}
+
+/**
+ * gtk_source_vim_state_enter:
+ *
+ * Called when a new state has been placed on the stack
+ * so that the state can finish initial setup.
+ */
+void
+gtk_source_vim_state_enter (GtkSourceVimState *self)
+{
+ g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+
+ if (GTK_SOURCE_VIM_STATE_GET_CLASS (self)->enter)
+ GTK_SOURCE_VIM_STATE_GET_CLASS (self)->enter (self);
+}
+
+/**
+ * gtk_source_vim_state_leave:
+ *
+ * Called when a state is being removed from the stack
+ * (such as when it has completed).
+ */
+void
+gtk_source_vim_state_leave (GtkSourceVimState *self)
+{
+ g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+
+ if (GTK_SOURCE_VIM_STATE_GET_CLASS (self)->leave)
+ GTK_SOURCE_VIM_STATE_GET_CLASS (self)->leave (self);
+}
+
+/**
+ * gtk_source_vim_state_suspend:
+ *
+ * Called when a state is being suspended because another
+ * state has been pushed onto the stack.
+ */
+void
+gtk_source_vim_state_suspend (GtkSourceVimState *self,
+ GtkSourceVimState *to)
+{
+ g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+ g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (to));
+
+ if (GTK_SOURCE_VIM_STATE_GET_CLASS (self)->suspend)
+ GTK_SOURCE_VIM_STATE_GET_CLASS (self)->suspend (self, to);
+}
+
+/**
+ * gtk_source_vim_state_restore:
+ *
+ * Called when a state is being restored because another
+ * state has been popped off the stack and @self is now the
+ * current state.
+ */
+void
+gtk_source_vim_state_restore (GtkSourceVimState *self,
+ GtkSourceVimState *from)
+{
+ g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+ g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (from));
+
+ if (GTK_SOURCE_VIM_STATE_GET_CLASS (self)->restore)
+ GTK_SOURCE_VIM_STATE_GET_CLASS (self)->restore (self, from);
+}
+
+/**
+ * gtk_source_vim_state_handle:
+ *
+ * Handle an incoming key press or release event.
+ */
+gboolean
+gtk_source_vim_state_handle (GtkSourceVimState *self,
+ GdkEvent *event)
+{
+ g_return_val_if_fail (GTK_SOURCE_IS_VIM_STATE (self), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ if (GTK_SOURCE_VIM_STATE_GET_CLASS (self)->handle)
+ return GTK_SOURCE_VIM_STATE_GET_CLASS (self)->handle (self, event);
+
+ return FALSE;
+}
+
+static gboolean
+gtk_source_vim_normal_handle (GtkSourceVimState *state,
+ GdkEvent *event)
+{
+ GtkSourceVimNormal *self = (GtkSourceVimNormal *)state;
+
+ g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
+ g_assert (event != NULL);
+
+ return FALSE;
+}
+
+static void
+gtk_source_vim_normal_restore (GtkSourceVimState *state,
+ GtkSourceVimState *from)
+{
+ GtkSourceVimNormal *self = (GtkSourceVimNormal *)state;
+
+ g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
+
+ /* If we have a count to repeat, then we should perform that now. */
+
+ /* If we are restoring from an insert, then we need to move
+ * the cursor back one character so the block cursor appears
+ * on the right character.
+ */
+ if (GTK_SOURCE_IS_VIM_INSERT (from))
+ {
+ GtkTextIter iter;
+
+ gtk_source_vim_state_get_iter (state, &iter);
+
+ if (!gtk_text_iter_starts_line (&iter))
+ {
+ gtk_text_iter_backward_char (&iter);
+ gtk_source_vim_state_move_to (state, &iter);
+ }
+ }
+}
+
+static void
+gtk_source_vim_normal_class_init (GtkSourceVimNormalClass *klass)
+{
+ GtkSourceVimStateClass *state_class = GTK_SOURCE_VIM_STATE_CLASS (klass);
+
+ state_class->handle = gtk_source_vim_normal_handle;
+ state_class->restore = gtk_source_vim_normal_restore;
+}
+
+static void
+gtk_source_vim_normal_init (GtkSourceVimNormal *self)
+{
+}
+
+static void
+gtk_source_vim_insert_class_init (GtkSourceVimInsertClass *klass)
+{
+ GtkSourceVimStateClass *state_class = GTK_SOURCE_VIM_STATE_CLASS (klass);
+}
+
+static void
+gtk_source_vim_insert_init (GtkSourceVimInsert *self)
+{
+}
diff --git a/gtksourceview/gtksourcevimstate.h b/gtksourceview/gtksourcevimstate.h
new file mode 100644
index 00000000..c00a5553
--- /dev/null
+++ b/gtksourceview/gtksourcevimstate.h
@@ -0,0 +1,70 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include <gdk/gdk.h>
+
+#include "gtksourcetypes.h"
+#include "gtksourcetypes-private.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_VIM_STATE (gtk_source_vim_state_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GtkSourceVimState, gtk_source_vim_state, GTK_SOURCE, VIM_STATE, GObject)
+
+struct _GtkSourceVimStateClass
+{
+ GObject parent_class;
+
+ void (*enter) (GtkSourceVimState *state);
+ void (*leave) (GtkSourceVimState *state);
+ void (*suspend) (GtkSourceVimState *state,
+ GtkSourceVimState *to);
+ void (*restore) (GtkSourceVimState *state,
+ GtkSourceVimState *from);
+ gboolean (*handle) (GtkSourceVimState *state,
+ GdkEvent *event);
+};
+
+GtkSourceVimState *gtk_source_vim_state_get_parent (GtkSourceVimState *self);
+GtkSourceView *gtk_source_vim_state_get_view (GtkSourceVimState *self);
+void gtk_source_vim_state_enter (GtkSourceVimState *self);
+void gtk_source_vim_state_leave (GtkSourceVimState *self);
+void gtk_source_vim_state_suspend (GtkSourceVimState *self,
+ GtkSourceVimState *to);
+void gtk_source_vim_state_restore (GtkSourceVimState *self,
+ GtkSourceVimState *from);
+gboolean gtk_source_vim_state_handle (GtkSourceVimState *self,
+ GdkEvent *event);
+void gtk_source_vim_state_get_iter (GtkSourceVimState *self,
+ GtkTextIter *iter);
+void gtk_source_vim_state_move_to (GtkSourceVimState *self,
+ const GtkTextIter *iter);
+
+#define GTK_SOURCE_TYPE_VIM_NORMAL (gtk_source_vim_normal_get_type())
+G_DECLARE_FINAL_TYPE (GtkSourceVimNormal, gtk_source_vim_normal, GTK_SOURCE, VIM_NORMAL, GtkSourceVimState)
+
+#define GTK_SOURCE_TYPE_VIM_INSERT (gtk_source_vim_insert_get_type())
+G_DECLARE_FINAL_TYPE (GtkSourceVimInsert, gtk_source_vim_insert, GTK_SOURCE, VIM_INSERT, GtkSourceVimState)
+
+G_END_DECLS
diff --git a/gtksourceview/meson.build b/gtksourceview/meson.build
index 96afb5b1..d059af8c 100644
--- a/gtksourceview/meson.build
+++ b/gtksourceview/meson.build
@@ -136,6 +136,7 @@ core_private_c = files([
'gtksourcesnippetbundle-parser.c',
'gtksourceview-snippets.c',
'gtksourcevim.c',
+ 'gtksourcevimstate.c',
'implregex.c',
])
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]