[gnome-builder/wip/libide] libide: add IdeSourceView:mode property



commit d9fbce2d20f501a2745a8d43e2f76f92df1441a9
Author: Christian Hergert <christian hergert me>
Date:   Tue Mar 3 15:51:43 2015 -0800

    libide: add IdeSourceView:mode property
    
    This is a fairly straightforward port of Alex's work on GbSourceViewMode
    but down into LibIDE.
    
    --
    
    
    This lets you set up modal keyboar accelerators.
    For instance, you can emulate the emacs "c-x c-c" exit keybinding with
    this CSS snippet:
    
    @binding-set bindings-emacs {
      bind "<ctrl>x" { "set-mode" ("emacs-x", transient) };
    }
    
    @binding-set bindings-emacs-x {
      bind "<ctrl>c" { "action" ("app", "quit", "") };
    }
    
    GbSourceView {
      gtk-key-bindings: bindings-emacs;
    }
    
    GbSourceViewMode.emacs-x {
      gtk-key-bindings: bindings-emacs-x;
    }

 libide/.gitignore             |    2 +
 libide/Makefile.am            |   21 ++++++++++++++-
 libide/ide-enums.c.template   |   41 ++++++++++++++++++++++++++++++
 libide/ide-enums.h.template   |   24 +++++++++++++++++
 libide/ide-source-view-mode.c |    1 +
 libide/ide-source-view-mode.h |   18 -------------
 libide/ide-source-view.c      |   56 +++++++++++++++++++++++++++++++++++++++++
 libide/ide-source-view.h      |   18 +++++++++++++
 libide/ide.h                  |    1 +
 9 files changed, 163 insertions(+), 19 deletions(-)
---
diff --git a/libide/.gitignore b/libide/.gitignore
new file mode 100644
index 0000000..071b813
--- /dev/null
+++ b/libide/.gitignore
@@ -0,0 +1,2 @@
+ide-enums.c
+ide-enums.h
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 4012c4b..518687c 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -302,9 +302,15 @@ else
 AM_CPPFLAGS += -DIDE_DISABLE_DEBUG
 endif
 
+libide_1_0_la_type_headers = \
+       libide/ide-source-view.h \
+       $(NULL)
+
 libide_1_0_la_built_sources = \
        libide/resources/ide-resources.c \
        libide/resources/ide-resources.h \
+       libide/ide-enums.c \
+       libide/ide-enums.h \
        $(NULL)
 
 libide_resource_files = $(shell glib-compile-resources --sourcedir=$(top_srcdir)/libide/resources 
--generate-dependencies $(top_srcdir)/libide/resources/libide.gresource.xml)
@@ -313,6 +319,13 @@ libide/resources/ide-resources.c: libide/resources/libide.gresource.xml $(libide
 libide/resources/ide-resources.h: libide/resources/libide.gresource.xml $(libide_resource_files)
        $(AM_V_GEN)glib-compile-resources --target=$@ --sourcedir=$(top_srcdir)/libide/resources 
--generate-header --c-name ide $(top_srcdir)/libide/resources/libide.gresource.xml
 
+libide/ide-enums.h: $(libide_1_0_la_type_headers) libide/ide-enums.h.template
+       $(AM_V_GEN) ( cd $(srcdir) && glib-mkenums --template libide/ide-enums.h.template 
$(libide_1_0_la_type_headers) ) > libide/ide-enums.h.tmp
+       @ mv libide/ide-enums.h.tmp libide/ide-enums.h
+libide/ide-enums.c: $(libide_1_0_la_type_headers) libide/ide-enums.c.template
+       $(AM_V_GEN) ( cd $(srcdir) && glib-mkenums --template libide/ide-enums.c.template 
$(libide_1_0_la_type_headers) ) > libide/ide-enums.c.tmp
+       @ mv libide/ide-enums.c.tmp libide/ide-enums.c
+
 nodist_libide_1_0_la_SOURCES = \
        $(libide_1_0_la_built_sources) \
        $(NULL)
@@ -324,6 +337,8 @@ DISTCLEANFILES += $(libide_1_0_la_built_sources)
 EXTRA_DIST += \
        $(libide_resource_files) \
        libide/resources/libide.gresource.xml \
+       libide/ide-enums.c.template \
+       libide/ide-enums.h.template \
        $(libide_1_0_la_built_sources) \
        $(NULL)
 
@@ -335,7 +350,11 @@ INTROSPECTION_SCANNER_ARGS = --add-include-path=$(top_srcdir)/libide --warn-all
 INTROSPECTION_COMPILER_ARGS = --includedir=$(top_srcdir)/libide
 
 if HAVE_INTROSPECTION
-introspection_sources = $(libide_1_0_la_public_sources)
+introspection_sources = \
+       $(libide_1_0_la_public_sources) \
+       libide/ide-enums.c \
+       libide/ide-enums.h \
+       $(NULL)
 
 Ide-1.0.gir: libide-1.0.la
 Ide_1_0_gir_INCLUDES = Gio-2.0 GtkSource-3.0 Ggit-1.0
diff --git a/libide/ide-enums.c.template b/libide/ide-enums.c.template
new file mode 100644
index 0000000..a033aef
--- /dev/null
+++ b/libide/ide-enums.c.template
@@ -0,0 +1,41 @@
+/*** BEGIN file-header ***/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "ide-enums.h"
+
+#include "ide-source-view.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+ enum_name@_get_type (void)
+{
+    static GType etype = 0;
+    if (G_UNLIKELY(etype == 0)) {
+        static const G Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+            { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+            { 0, NULL, NULL }
+        };
+        etype = g_ type@_register_static (g_intern_static_string ("@EnumName@"), values);
+    }
+    return etype;
+}
+
+/*** END value-tail ***/
+
+/*** BEGIN file-tail ***/
+
+/*** END file-tail ***/
diff --git a/libide/ide-enums.h.template b/libide/ide-enums.h.template
new file mode 100644
index 0000000..3722cdc
--- /dev/null
+++ b/libide/ide-enums.h.template
@@ -0,0 +1,24 @@
+/*** BEGIN file-header ***/
+#ifndef __IDE_ENUMS_H__
+#define __IDE_ENUMS_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name _get_type (void);
+#define @ENUMPREFIX _TYPE_@ENUMSHORT@ (@enum_name _get_type ())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* __IDE_ENUMS_H__ */
+/*** END file-tail ***/
diff --git a/libide/ide-source-view-mode.c b/libide/ide-source-view-mode.c
index fbee293..15a5abd 100644
--- a/libide/ide-source-view-mode.c
+++ b/libide/ide-source-view-mode.c
@@ -20,6 +20,7 @@
 
 #include <glib/gi18n.h>
 
+#include "ide-source-view.h"
 #include "ide-source-view-mode.h"
 
 typedef struct
diff --git a/libide/ide-source-view-mode.h b/libide/ide-source-view-mode.h
index e705b3e..7f72b3c 100644
--- a/libide/ide-source-view-mode.h
+++ b/libide/ide-source-view-mode.h
@@ -21,7 +21,6 @@
 
 #include <gtk/gtk.h>
 
-#include "ide-source-view.h"
 #include "ide-types.h"
 
 G_BEGIN_DECLS
@@ -47,23 +46,6 @@ struct _IdeSourceViewModeClass
   GtkWidgetClass parent_class;
 };
 
-/**
- * IdeSourceViewModeType:
- * @IDE_SOURCE_VIEW_MODE_TRANSIENT: Transient
- * @IDE_SOURCE_VIEW_MODE_PERMANENT: Permanent
- * @IDE_SOURCE_VIEW_MODE_MODAL: Modal
- *
- * The type of keyboard mode.
- */
-typedef enum
-{
-  IDE_SOURCE_VIEW_MODE_TYPE_TRANSIENT,
-  IDE_SOURCE_VIEW_MODE_TYPE_PERMANENT,
-  IDE_SOURCE_VIEW_MODE_TYPE_MODAL
-} IdeSourceViewModeType;
-
-GType ide_source_view_mode_get_type (void);
-
 G_END_DECLS
 
 #endif /* IDE_SOURCE_VIEW_MODE_H */
diff --git a/libide/ide-source-view.c b/libide/ide-source-view.c
index edca35e..42eb579 100644
--- a/libide/ide-source-view.c
+++ b/libide/ide-source-view.c
@@ -26,10 +26,13 @@
 #include "ide-box-theatric.h"
 #include "ide-buffer.h"
 #include "ide-context.h"
+#include "ide-debug.h"
 #include "ide-diagnostic.h"
+#include "ide-enums.h"
 #include "ide-file.h"
 #include "ide-file-settings.h"
 #include "ide-highlighter.h"
+#include "ide-internal.h"
 #include "ide-indenter.h"
 #include "ide-language.h"
 #include "ide-line-change-gutter-renderer.h"
@@ -43,6 +46,7 @@
 #include "ide-source-snippets-manager.h"
 #include "ide-source-location.h"
 #include "ide-source-view.h"
+#include "ide-source-view-mode.h"
 
 #define DEFAULT_FONT_DESC "Monospace 11"
 #define ANIMATION_X_GROW  50
@@ -57,6 +61,7 @@ typedef struct
   IdeIndenter                 *indenter;
   GtkSourceGutterRenderer     *line_change_renderer;
   GtkSourceGutterRenderer     *line_diagnostics_renderer;
+  IdeSourceViewMode           *mode;
   GQueue                      *snippets;
   GtkSourceCompletionProvider *snippets_provider;
 
@@ -99,6 +104,7 @@ enum {
   JUMP,
   PUSH_SNIPPET,
   POP_SNIPPET,
+  SET_MODE,
   LAST_SIGNAL
 };
 
@@ -1124,6 +1130,24 @@ ide_source_view_key_press_event (GtkWidget   *widget,
 
   g_assert (IDE_IS_SOURCE_VIEW (self));
 
+  /*
+   * If we are in a non-default mode, dispatch the event to the mode. This allows custom
+   * keybindings like Emacs and Vim to be implemented using gtk-bindings CSS.
+   */
+  if (priv->mode)
+    {
+      gboolean handled;
+      gboolean remove = FALSE;
+
+      handled = _ide_source_view_mode_do_event (priv->mode, event, &remove);
+
+      if (remove)
+        g_clear_object (&priv->mode);
+
+      if (handled)
+        return TRUE;
+    }
+
   buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self));
 
   /*
@@ -1332,6 +1356,25 @@ ide_source_view_real_jump (IdeSourceView     *self,
 }
 
 static void
+ide_source_view_real_set_mode (IdeSourceView         *self,
+                               const gchar           *mode,
+                               IdeSourceViewModeType  type)
+{
+  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_SOURCE_VIEW (self));
+
+  g_clear_object (&priv->mode);
+
+  if (mode != NULL)
+    priv->mode = _ide_source_view_mode_new (GTK_WIDGET (self), mode, type);
+
+  IDE_EXIT;
+}
+
+static void
 ide_source_view_constructed (GObject *object)
 {
   IdeSourceView *self = (IdeSourceView *)object;
@@ -1373,6 +1416,7 @@ ide_source_view_dispose (GObject *object)
   g_clear_object (&priv->line_diagnostics_renderer);
   g_clear_object (&priv->snippets_provider);
   g_clear_object (&priv->css_provider);
+  g_clear_object (&priv->mode);
 
   if (priv->buffer)
     {
@@ -1504,6 +1548,7 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
   widget_class->query_tooltip = ide_source_view_query_tooltip;
 
   klass->jump = ide_source_view_real_jump;
+  klass->set_mode = ide_source_view_real_set_mode;
 
   g_object_class_override_property (object_class, PROP_AUTO_INDENT, "auto-indent");
 
@@ -1580,6 +1625,17 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
                                   1,
                                   GTK_TYPE_TEXT_ITER);
 
+  gSignals [SET_MODE] = g_signal_new ("set-mode",
+                                      G_TYPE_FROM_CLASS (klass),
+                                      G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                                      G_STRUCT_OFFSET (IdeSourceViewClass, set_mode),
+                                      NULL, NULL,
+                                      g_cclosure_marshal_generic,
+                                      G_TYPE_NONE,
+                                      2,
+                                      G_TYPE_STRING,
+                                      IDE_TYPE_SOURCE_VIEW_MODE_TYPE);
+
   gSignals [POP_SNIPPET] = g_signal_new ("pop-snippet",
                                          G_TYPE_FROM_CLASS (klass),
                                          G_SIGNAL_RUN_LAST,
diff --git a/libide/ide-source-view.h b/libide/ide-source-view.h
index 0194e87..f0ee91e 100644
--- a/libide/ide-source-view.h
+++ b/libide/ide-source-view.h
@@ -36,6 +36,21 @@ G_BEGIN_DECLS
 typedef struct _IdeSourceView      IdeSourceView;
 typedef struct _IdeSourceViewClass IdeSourceViewClass;
 
+/**
+ * IdeSourceViewModeType:
+ * @IDE_SOURCE_VIEW_MODE_TRANSIENT: Transient
+ * @IDE_SOURCE_VIEW_MODE_PERMANENT: Permanent
+ * @IDE_SOURCE_VIEW_MODE_MODAL: Modal
+ *
+ * The type of keyboard mode.
+ */
+typedef enum
+{
+  IDE_SOURCE_VIEW_MODE_TYPE_TRANSIENT,
+  IDE_SOURCE_VIEW_MODE_TYPE_PERMANENT,
+  IDE_SOURCE_VIEW_MODE_TYPE_MODAL
+} IdeSourceViewModeType;
+
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdeSourceView, g_object_unref)
 
 struct _IdeSourceView
@@ -55,6 +70,9 @@ struct _IdeSourceViewClass
                         IdeSourceSnippet        *snippet,
                         IdeSourceSnippetContext *context,
                         const GtkTextIter       *location);
+  void (*set_mode)     (IdeSourceView           *self,
+                        const gchar             *mode,
+                        IdeSourceViewModeType    type);
 };
 
 void                        ide_source_view_clear_snippets            (IdeSourceView              *self);
diff --git a/libide/ide.h b/libide/ide.h
index 5f7ba98..84eb0ae 100644
--- a/libide/ide.h
+++ b/libide/ide.h
@@ -42,6 +42,7 @@ G_BEGIN_DECLS
 #include "ide-diagnostics.h"
 #include "ide-diagnostician.h"
 #include "ide-diagnostic-provider.h"
+#include "ide-enums.h"
 #include "ide-executable.h"
 #include "ide-executer.h"
 #include "ide-file.h"


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]