[gnome-builder/wip/vim] vim: make GtkEntry for command entry almost functional.
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/vim] vim: make GtkEntry for command entry almost functional.
- Date: Wed, 1 Oct 2014 06:30:30 +0000 (UTC)
commit 3b38b6cf483d01397a696779335ce62b2f80c7fd
Author: Christian Hergert <christian hergert me>
Date: Tue Sep 30 23:20:46 2014 -0700
vim: make GtkEntry for command entry almost functional.
src/editor/gb-editor-tab-private.h | 1 +
src/editor/gb-editor-tab.c | 79 ++++++++++++++-
src/editor/gb-editor-vim.c | 207 +++++++++++++-----------------------
src/editor/gb-editor-vim.h | 20 ++--
src/resources/ui/gb-editor-tab.ui | 8 +-
5 files changed, 167 insertions(+), 148 deletions(-)
---
diff --git a/src/editor/gb-editor-tab-private.h b/src/editor/gb-editor-tab-private.h
index 89010ba..49d30e9 100644
--- a/src/editor/gb-editor-tab-private.h
+++ b/src/editor/gb-editor-tab-private.h
@@ -107,6 +107,7 @@ struct _GbEditorTabPrivate
GdTaggedEntry *search_entry;
GdTaggedEntryTag *search_entry_tag;
GtkEntry *vim_command_entry;
+ GtkRevealer *vim_command_entry_revealer;
/*
* Information about our target file and encoding.
diff --git a/src/editor/gb-editor-tab.c b/src/editor/gb-editor-tab.c
index e70d470..261ce46 100644
--- a/src/editor/gb-editor-tab.c
+++ b/src/editor/gb-editor-tab.c
@@ -945,6 +945,68 @@ gb_editor_tab_scroll_to_line (GbEditorTab *tab,
0.0, FALSE, 0.0, 0.5);
}
+static void
+on_vim_command_visibility_toggled (GbEditorVim *vim,
+ gboolean visible,
+ GbEditorTab *tab)
+{
+ ENTRY;
+
+ g_return_if_fail (GB_IS_EDITOR_VIM (vim));
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ gtk_revealer_set_reveal_child (tab->priv->vim_command_entry_revealer,
+ visible);
+
+ if (visible)
+ {
+ gtk_entry_set_text (tab->priv->vim_command_entry, "");
+ gtk_widget_grab_focus (GTK_WIDGET (tab->priv->vim_command_entry));
+ }
+ else
+ gtk_widget_grab_focus (GTK_WIDGET (tab->priv->source_view));
+
+ EXIT;
+}
+
+static void
+on_vim_command_entry_activate (GtkEntry *entry,
+ GbEditorTab *tab)
+{
+ const gchar *text;
+
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ /*
+ * Execute the command in the command entry.
+ */
+ text = gtk_entry_get_text (entry);
+ gb_editor_vim_execute_command (tab->priv->vim, text);
+}
+
+static gboolean
+on_vim_command_entry_key_press_event (GtkEntry *entry,
+ GdkEventKey *event,
+ GbEditorTab *tab)
+{
+ ENTRY;
+
+ g_return_if_fail (GTK_IS_ENTRY (entry));
+ g_return_if_fail (event);
+ g_return_if_fail (GB_IS_EDITOR_TAB (tab));
+
+ switch (event->keyval)
+ {
+ case GDK_KEY_Escape:
+ gb_editor_vim_set_mode (tab->priv->vim, GB_EDITOR_VIM_NORMAL);
+ RETURN (TRUE);
+
+ default:
+ RETURN (FALSE);
+ }
+}
+
static gboolean
transform_file_to_language (GBinding *binding,
const GValue *src_value,
@@ -1129,10 +1191,23 @@ gb_editor_tab_constructed (GObject *object)
gtk_source_gutter_insert (gutter, priv->change_renderer, 0);
priv->vim = g_object_new (GB_TYPE_EDITOR_VIM,
- "command-entry", priv->vim_command_entry,
"enabled", TRUE,
"text-view", priv->source_view,
NULL);
+ g_signal_connect (priv->vim,
+ "command-visibility-toggled",
+ G_CALLBACK (on_vim_command_visibility_toggled),
+ tab);
+
+ g_signal_connect (priv->vim_command_entry,
+ "activate",
+ G_CALLBACK (on_vim_command_entry_activate),
+ tab);
+
+ g_signal_connect (priv->vim_command_entry,
+ "key-press-event",
+ G_CALLBACK (on_vim_command_entry_key_press_event),
+ tab);
gb_editor_tab_cursor_moved (tab, priv->document);
@@ -1355,6 +1430,8 @@ gb_editor_tab_class_init (GbEditorTabClass *klass)
source_view);
gtk_widget_class_bind_template_child_private (widget_class, GbEditorTab,
vim_command_entry);
+ gtk_widget_class_bind_template_child_private (widget_class, GbEditorTab,
+ vim_command_entry_revealer);
g_type_ensure (GB_TYPE_EDITOR_DOCUMENT);
g_type_ensure (GB_TYPE_SOURCE_CHANGE_MONITOR);
diff --git a/src/editor/gb-editor-vim.c b/src/editor/gb-editor-vim.c
index 7ae5b26..1ccc273 100644
--- a/src/editor/gb-editor-vim.c
+++ b/src/editor/gb-editor-vim.c
@@ -28,12 +28,11 @@
struct _GbEditorVimPrivate
{
GtkTextView *text_view;
- GtkEntry *command_entry;
GbEditorVimMode mode;
gulong key_press_event_handler;
+ gulong focus_in_event_handler;
gulong mark_set_handler;
gulong delete_range_handler;
- gulong command_entry_activate_handler;
guint target_line_offset;
guint enabled : 1;
guint connected : 1;
@@ -42,16 +41,22 @@ struct _GbEditorVimPrivate
enum
{
PROP_0,
- PROP_COMMAND_ENTRY,
PROP_ENABLED,
PROP_MODE,
PROP_TEXT_VIEW,
LAST_PROP
};
+enum
+{
+ COMMAND_VISIBILITY_TOGGLED,
+ LAST_SIGNAL
+};
+
G_DEFINE_TYPE_WITH_PRIVATE (GbEditorVim, gb_editor_vim, G_TYPE_OBJECT)
static GParamSpec *gParamSpecs [LAST_PROP];
+static guint gSignals [LAST_SIGNAL];
GbEditorVim *
gb_editor_vim_new (GtkTextView *text_view)
@@ -85,21 +90,12 @@ gb_editor_vim_get_mode (GbEditorVim *vim)
return vim->priv->mode;
}
-static void
+void
gb_editor_vim_set_mode (GbEditorVim *vim,
GbEditorVimMode mode)
{
g_return_if_fail (GB_IS_EDITOR_VIM (vim));
- /*
- * Don't allow changing to command mode if we don't have an editable widget.
- */
- if ((mode == GB_EDITOR_VIM_COMMAND) && !vim->priv->command_entry)
- {
- g_warning ("Cannot change to command mode, no command entry widget set.");
- mode = GB_EDITOR_VIM_NORMAL;
- }
-
vim->priv->mode = mode;
/*
@@ -124,44 +120,21 @@ gb_editor_vim_set_mode (GbEditorVim *vim,
gb_source_view_clear_snippets (GB_SOURCE_VIEW (vim->priv->text_view));
/*
- * Clear the command line text.
- */
- if (GTK_IS_ENTRY (vim->priv->command_entry))
- gtk_entry_set_text (GTK_ENTRY (vim->priv->command_entry), "");
-
- /*
* Make the command entry visible if necessary.
*/
- if (vim->priv->command_entry)
- {
- gtk_widget_set_visible (GTK_WIDGET (vim->priv->command_entry),
- (mode == GB_EDITOR_VIM_COMMAND));
- gtk_editable_set_editable (GTK_EDITABLE (vim->priv->command_entry),
- (mode == GB_EDITOR_VIM_COMMAND));
- if (mode == GB_EDITOR_VIM_COMMAND)
- gtk_widget_grab_focus (GTK_WIDGET (vim->priv->command_entry));
- else
- gtk_widget_grab_focus (GTK_WIDGET (vim->priv->text_view));
- }
+ g_signal_emit (vim, gSignals [COMMAND_VISIBILITY_TOGGLED], 0,
+ (mode == GB_EDITOR_VIM_COMMAND));
/*
+ * TODO: This should actually happen always on insert->normal transition.
+ *
* If we are are going to normal mode and are at the end of the line,
* then move back a character so we are on the last character as opposed
* to after it. This matches closer to VIM.
*/
if (mode == GB_EDITOR_VIM_NORMAL)
{
- GtkTextBuffer *buffer;
- GtkTextMark *insert;
- GtkTextIter iter;
-
- buffer = gtk_text_view_get_buffer (vim->priv->text_view);
- insert = gtk_text_buffer_get_insert (buffer);
- gtk_text_buffer_get_iter_at_mark (buffer, &iter, insert);
-
- if (gtk_text_iter_ends_line (&iter) && !gtk_text_iter_starts_line (&iter))
- if (gtk_text_iter_backward_char (&iter))
- gtk_text_buffer_select_range (buffer, &iter, &iter);
+ /* TODO: Old code did not respect selections */
}
g_object_notify_by_pspec (G_OBJECT (vim), gParamSpecs [PROP_MODE]);
@@ -1347,22 +1320,6 @@ gb_editor_vim_get_has_selection (GbEditorVim *vim)
return gtk_text_buffer_get_has_selection (buffer);
}
-static void
-gb_editor_vim_command_entry_activate_cb (GtkEntry *entry,
- GbEditorVim *vim)
-{
- const gchar *text;
-
- g_return_if_fail (GTK_IS_ENTRY (entry));
- g_return_if_fail (GB_IS_EDITOR_VIM (vim));
-
- text = gtk_entry_get_text (entry);
-
- g_print ("Execute Command Line: \"%s\"\n", text);
-
- gb_editor_vim_set_mode (vim, GB_EDITOR_VIM_NORMAL);
-}
-
static gboolean
gb_editor_vim_handle_normal (GbEditorVim *vim,
GdkEventKey *event)
@@ -1721,22 +1678,17 @@ gb_editor_vim_handle_command (GbEditorVim *vim,
gb_editor_vim_set_mode (vim, GB_EDITOR_VIM_NORMAL);
return TRUE;
- /*
- * Execute the command line if we can.
- */
- case GDK_KEY_KP_Enter:
- case GDK_KEY_Return:
- if (vim->priv->command_entry)
- gb_editor_vim_command_entry_activate_cb (vim->priv->command_entry, vim);
- else
- gb_editor_vim_set_mode (vim, GB_EDITOR_VIM_NORMAL);
- return TRUE;
-
default:
break;
}
- gtk_bindings_activate_event (G_OBJECT (vim->priv->text_view), event);
+ if (!gtk_bindings_activate_event (G_OBJECT (vim->priv->text_view), event))
+ {
+ /*
+ * TODO: Show visual error because we can't input right now. We shouldn't
+ * even get here though.
+ */
+ }
return TRUE;
}
@@ -1775,6 +1727,21 @@ gb_editor_vim_key_press_event_cb (GtkTextView *text_view,
RETURN (FALSE);
}
+static gboolean
+gb_editor_vim_focus_in_event_cb (GtkTextView *text_view,
+ GdkEvent *event,
+ GbEditorVim *vim)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+ g_return_val_if_fail (event, FALSE);
+ g_return_val_if_fail (GB_IS_EDITOR_VIM (vim), FALSE);
+
+ if (vim->priv->mode != GB_EDITOR_VIM_NORMAL)
+ gb_editor_vim_set_mode (vim, GB_EDITOR_VIM_NORMAL);
+
+ return FALSE;
+}
+
static void
gb_editor_vim_mark_set_cb (GtkTextBuffer *buffer,
GtkTextIter *iter,
@@ -1860,6 +1827,12 @@ gb_editor_vim_connect (GbEditorVim *vim)
G_CALLBACK (gb_editor_vim_key_press_event_cb),
vim);
+ vim->priv->focus_in_event_handler =
+ g_signal_connect (vim->priv->text_view,
+ "focus-in-event",
+ G_CALLBACK (gb_editor_vim_focus_in_event_cb),
+ vim);
+
vim->priv->mark_set_handler =
g_signal_connect (buffer,
"mark-set",
@@ -1887,6 +1860,10 @@ gb_editor_vim_disconnect (GbEditorVim *vim)
vim->priv->key_press_event_handler);
vim->priv->key_press_event_handler = 0;
+ g_signal_handler_disconnect (vim->priv->text_view,
+ vim->priv->focus_in_event_handler);
+ vim->priv->focus_in_event_handler = 0;
+
g_signal_handler_disconnect (gtk_text_view_get_buffer (vim->priv->text_view),
vim->priv->mark_set_handler);
vim->priv->mark_set_handler = 0;
@@ -1976,51 +1953,19 @@ gb_editor_vim_set_text_view (GbEditorVim *vim,
g_object_notify_by_pspec (G_OBJECT (vim), gParamSpecs [PROP_TEXT_VIEW]);
}
-GtkEntry *
-gb_editor_vim_get_command_entry (GbEditorVim *vim)
-{
- g_return_val_if_fail (GB_IS_EDITOR_VIM (vim), NULL);
-
- return vim->priv->command_entry;
-}
void
-gb_editor_vim_set_command_entry (GbEditorVim *vim,
- GtkEntry *command_entry)
+gb_editor_vim_execute_command (GbEditorVim *vim,
+ const gchar *command)
{
- GbEditorVimPrivate *priv;
-
g_return_if_fail (GB_IS_EDITOR_VIM (vim));
- g_return_if_fail (!command_entry || GTK_IS_ENTRY (command_entry));
+ g_return_if_fail (command);
- priv = vim->priv;
+ /* TODO: execute command */
+ g_print ("Execute command: '%s'\n", command);
- if (priv->command_entry == command_entry)
- return;
-
- if (priv->command_entry)
- {
- g_signal_handler_disconnect (priv->command_entry,
- priv->command_entry_activate_handler);
- priv->command_entry_activate_handler = 0;
- g_object_remove_weak_pointer (G_OBJECT (priv->command_entry),
- (gpointer *)&priv->command_entry);
- priv->command_entry = NULL;
- }
-
- if (command_entry)
- {
- priv->command_entry = command_entry;
- g_object_add_weak_pointer (G_OBJECT (priv->command_entry),
- (gpointer *)&priv->command_entry);
- priv->command_entry_activate_handler =
- g_signal_connect (priv->command_entry,
- "activate",
- G_CALLBACK (gb_editor_vim_command_entry_activate_cb),
- vim);
- }
-
- g_object_notify_by_pspec (G_OBJECT (vim), gParamSpecs [PROP_COMMAND_ENTRY]);
+ gb_editor_vim_clear_selection (vim);
+ gb_editor_vim_set_mode (vim, GB_EDITOR_VIM_NORMAL);
}
static void
@@ -2036,13 +1981,6 @@ gb_editor_vim_finalize (GObject *object)
priv->text_view = NULL;
}
- if (priv->command_entry_activate_handler && priv->command_entry)
- {
- g_signal_handler_disconnect (priv->command_entry,
- priv->command_entry_activate_handler);
- priv->command_entry_activate_handler = 0;
- }
-
G_OBJECT_CLASS (gb_editor_vim_parent_class)->finalize (object);
}
@@ -2056,10 +1994,6 @@ gb_editor_vim_get_property (GObject *object,
switch (prop_id)
{
- case PROP_COMMAND_ENTRY:
- g_value_set_object (value, gb_editor_vim_get_command_entry (vim));
- break;
-
case PROP_ENABLED:
g_value_set_boolean (value, gb_editor_vim_get_enabled (vim));
break;
@@ -2087,10 +2021,6 @@ gb_editor_vim_set_property (GObject *object,
switch (prop_id)
{
- case PROP_COMMAND_ENTRY:
- gb_editor_vim_set_command_entry (vim, g_value_get_object (value));
- break;
-
case PROP_ENABLED:
gb_editor_vim_set_enabled (vim, g_value_get_boolean (value));
break;
@@ -2114,17 +2044,6 @@ gb_editor_vim_class_init (GbEditorVimClass *klass)
object_class->get_property = gb_editor_vim_get_property;
object_class->set_property = gb_editor_vim_set_property;
- gParamSpecs [PROP_COMMAND_ENTRY] =
- g_param_spec_object ("command-entry",
- _("Command Entry"),
- _("The command entry widget for command mode."),
- GTK_TYPE_ENTRY,
- (G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (object_class, PROP_COMMAND_ENTRY,
- gParamSpecs [PROP_COMMAND_ENTRY]);
-
gParamSpecs [PROP_ENABLED] =
g_param_spec_boolean ("enabled",
_("Enabled"),
@@ -2156,6 +2075,26 @@ gb_editor_vim_class_init (GbEditorVimClass *klass)
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_TEXT_VIEW,
gParamSpecs [PROP_TEXT_VIEW]);
+
+ /**
+ * GbEditorVim::command-visibility-toggled:
+ * @visible: If the the command entry should be visible.
+ *
+ * The "command-visibility-toggled" signal is emitted when the command entry
+ * should be shown or hidden. The command entry is used to interact with the
+ * VIM style command line.
+ */
+ gSignals [COMMAND_VISIBILITY_TOGGLED] =
+ g_signal_new ("command-visibility-toggled",
+ GB_TYPE_EDITOR_VIM,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
}
static void
diff --git a/src/editor/gb-editor-vim.h b/src/editor/gb-editor-vim.h
index a775579..8b7d039 100644
--- a/src/editor/gb-editor-vim.h
+++ b/src/editor/gb-editor-vim.h
@@ -56,14 +56,18 @@ struct _GbEditorVimClass
GObjectClass parent_class;
};
-GType gb_editor_vim_get_type (void) G_GNUC_CONST;
-GType gb_editor_vim_mode_get_type (void) G_GNUC_CONST;
-GbEditorVim *gb_editor_vim_new (GtkTextView *text_view);
-GbEditorVimMode gb_editor_vim_get_mode (GbEditorVim *vim);
-gboolean gb_editor_vim_get_enabled (GbEditorVim *vim);
-void gb_editor_vim_set_enabled (GbEditorVim *vim,
- gboolean enabled);
-GtkWidget *gb_editor_vim_get_text_view (GbEditorVim *vim);
+GType gb_editor_vim_get_type (void) G_GNUC_CONST;
+GType gb_editor_vim_mode_get_type (void) G_GNUC_CONST;
+GbEditorVim *gb_editor_vim_new (GtkTextView *text_view);
+GbEditorVimMode gb_editor_vim_get_mode (GbEditorVim *vim);
+void gb_editor_vim_set_mode (GbEditorVim *vim,
+ GbEditorVimMode mode);
+gboolean gb_editor_vim_get_enabled (GbEditorVim *vim);
+void gb_editor_vim_set_enabled (GbEditorVim *vim,
+ gboolean enabled);
+GtkWidget *gb_editor_vim_get_text_view (GbEditorVim *vim);
+void gb_editor_vim_execute_command (GbEditorVim *vim,
+ const gchar *command);
G_END_DECLS
diff --git a/src/resources/ui/gb-editor-tab.ui b/src/resources/ui/gb-editor-tab.ui
index b61c2b9..32033b2 100644
--- a/src/resources/ui/gb-editor-tab.ui
+++ b/src/resources/ui/gb-editor-tab.ui
@@ -116,12 +116,12 @@
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="valign">end</property>
- <property name="reveal_child">True</property>
+ <property name="reveal_child">False</property>
+ <property name="transition_type">GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT</property>
<child>
<object class="GtkFrame" id="vim_command_frame">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="margin_start">0</property>
<style>
<class name="gb-vim-command-slider"/>
</style>
@@ -129,8 +129,7 @@
<object class="GtkEntry" id="vim_command_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="width_request">260</property>
- <property name="placeholder_text">:</property>
+ <property name="width_chars">20</property>
</object>
</child>
</object>
@@ -158,7 +157,6 @@
<property name="source-view">source_view</property>
</object>
<object class="GtkSourceSearchSettings" id="search_settings">
- <property name="at-word-boundaries">True</property>
</object>
<object class="GtkSourceSearchContext" id="search_context">
<property name="buffer">document</property>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]