[gnome-builder/wip/commands] commands: plumb sort command into generic command bar
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/commands] commands: plumb sort command into generic command bar
- Date: Tue, 7 Oct 2014 10:44:25 +0000 (UTC)
commit 48eee03fb3deb1133dd3aa9759a68468aa3bd9f0
Author: Christian Hergert <christian hergert me>
Date: Tue Oct 7 03:44:14 2014 -0700
commands: plumb sort command into generic command bar
The goal for this is to lose the per-editor command bar and move to a
global command bar at the bottom. The commands will determine the active
editor tab with workbench.get_active_workspace().get_active_tab().
src/app/gb-application.c | 2 +
src/commands/gb-command-bar.c | 40 ++++++++-
src/commands/gb-command-manager.c | 56 +++++++++++-
src/commands/gb-command-manager.h | 9 ++-
src/commands/gb-command.c | 22 ++++-
src/commands/gb-command.h | 9 ++-
src/commands/gb-commands-internal.c | 173 +++++++++++++++++++++++++++++++++++
src/commands/gb-commands-internal.h | 24 +++++
src/editor/gb-editor-workspace.c | 15 +++
src/editor/gb-editor-workspace.h | 8 +-
src/gnome-builder.mk | 2 +
11 files changed, 345 insertions(+), 15 deletions(-)
---
diff --git a/src/app/gb-application.c b/src/app/gb-application.c
index 83548dd..7f249fb 100644
--- a/src/app/gb-application.c
+++ b/src/app/gb-application.c
@@ -26,6 +26,7 @@
#include <glib/gi18n.h>
#include "gb-application.h"
+#include "gb-commands-internal.h"
#include "gb-editor-workspace.h"
#include "gb-log.h"
#include "gb-keybindings.h"
@@ -372,6 +373,7 @@ gb_application_startup (GApplication *app)
gb_application_register_actions (self);
gb_application_register_keybindings (self);
gb_application_register_theme_overrides (self);
+ gb_commands_internal_init ();
EXIT;
}
diff --git a/src/commands/gb-command-bar.c b/src/commands/gb-command-bar.c
index 598e6d2..2d25d1d 100644
--- a/src/commands/gb-command-bar.c
+++ b/src/commands/gb-command-bar.c
@@ -16,7 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "gb-command.h"
#include "gb-command-bar.h"
+#include "gb-command-manager.h"
#include "gb-string.h"
struct _GbCommandBarPrivate
@@ -65,9 +67,19 @@ gb_command_bar_show (GbCommandBar *bar)
}
static void
+gb_command_bar_push_task (GbCommandBar *bar,
+ GbCommandTask *task)
+{
+ g_return_if_fail (GB_IS_COMMAND_BAR (bar));
+ g_return_if_fail (GB_IS_COMMAND_TASK (task));
+}
+
+static void
gb_command_bar_on_entry_activate (GbCommandBar *bar,
GtkEntry *entry)
{
+ GbWorkbench *workbench = NULL;
+ GtkWidget *parent;
const gchar *text;
g_return_if_fail (GB_IS_COMMAND_BAR (bar));
@@ -75,11 +87,33 @@ gb_command_bar_on_entry_activate (GbCommandBar *bar,
text = gtk_entry_get_text (entry);
- if (gb_str_empty0 (text))
+ parent = gtk_widget_get_toplevel (GTK_WIDGET (bar));
+ if (GB_IS_WORKBENCH (parent))
+ workbench = GB_WORKBENCH (parent);
+
+ if (!gb_str_empty0 (text))
{
- gb_command_bar_hide (bar);
- return;
+ GbCommandManager *manager;
+ GbCommandTask *task = NULL;
+ GbCommand *command = NULL;
+ GVariant *parameters = NULL;
+
+ manager = gb_command_manager_get_default ();
+ command = gb_command_manager_lookup (manager, text, ¶meters);
+
+ if (command)
+ {
+ task = gb_command_execute (command, parameters, workbench);
+ if (task)
+ gb_command_bar_push_task (bar, task);
+ }
+
+ g_clear_object (&task);
+ g_clear_object (&command);
+ g_clear_pointer (¶meters, g_variant_unref);
}
+
+ gb_command_bar_hide (bar);
}
static gboolean
diff --git a/src/commands/gb-command-manager.c b/src/commands/gb-command-manager.c
index 83c6fe8..ba36b89 100644
--- a/src/commands/gb-command-manager.c
+++ b/src/commands/gb-command-manager.c
@@ -16,6 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <string.h>
+
#include "gb-command-manager.h"
/**
@@ -55,7 +57,7 @@ gb_command_manager_get_default (void)
if (!instance)
instance = gb_command_manager_new ();
-
+
return instance;
}
@@ -76,6 +78,58 @@ gb_command_manager_register (GbCommandManager *manager,
g_hash_table_replace (manager->priv->commands, name, g_object_ref (command));
}
+static gchar *
+gb_command_manager_parse (GbCommandManager *manager,
+ const gchar *command_text,
+ GVariant **parameters)
+{
+ GVariant *variant = NULL;
+ gchar *ret = NULL;
+
+ g_return_val_if_fail (GB_IS_COMMAND_MANAGER (manager), NULL);
+ g_return_val_if_fail (command_text, NULL);
+
+ /* shortcut for no parameters. */
+ if (strchr (command_text, '(') == NULL)
+ return g_strstrip (g_strdup (command_text));
+
+ /* TODO: parse parameters */
+
+ if (parameters)
+ *parameters = variant ? g_variant_ref (variant) : NULL;
+
+ g_clear_pointer (&variant, g_variant_unref);
+
+ return ret;
+}
+
+GbCommand *
+gb_command_manager_lookup (GbCommandManager *manager,
+ const gchar *command_text,
+ GVariant **parameters)
+{
+ GbCommandManagerPrivate *priv;
+ GbCommand *command;
+ GVariant *variant = NULL;
+ gchar *name;
+
+ g_return_val_if_fail (GB_IS_COMMAND_MANAGER (manager), NULL);
+ g_return_val_if_fail (command_text, NULL);
+
+ priv = manager->priv;
+
+ name = gb_command_manager_parse (manager, command_text, &variant);
+ command = g_hash_table_lookup (priv->commands, name);
+
+ if (command && parameters)
+ *parameters = variant ? g_variant_ref (variant) : NULL;
+
+ g_clear_pointer (&name, g_free);
+ g_clear_pointer (&variant, g_variant_unref);
+
+ return command;
+}
+
static void
gb_command_manager_finalize (GObject *object)
{
diff --git a/src/commands/gb-command-manager.h b/src/commands/gb-command-manager.h
index fff6da3..ac7f357 100644
--- a/src/commands/gb-command-manager.h
+++ b/src/commands/gb-command-manager.h
@@ -19,6 +19,8 @@
#ifndef GB_COMMAND_MANAGER_H
#define GB_COMMAND_MANAGER_H
+#include <gio/gio.h>
+
#include "gb-command.h"
G_BEGIN_DECLS
@@ -51,8 +53,11 @@ struct _GbCommandManagerClass
GType gb_command_manager_get_type (void) G_GNUC_CONST;
GbCommandManager *gb_command_manager_new (void);
GbCommandManager *gb_command_manager_get_default (void);
-void gb_command_manager_register (GbCommandManager *manager,
- GbCommand *command);
+void gb_command_manager_register (GbCommandManager *manager,
+ GbCommand *command);
+GbCommand *gb_command_manager_lookup (GbCommandManager *manager,
+ const gchar *command_text,
+ GVariant **parameters);
G_END_DECLS
diff --git a/src/commands/gb-command.c b/src/commands/gb-command.c
index 827e508..2057c55 100644
--- a/src/commands/gb-command.c
+++ b/src/commands/gb-command.c
@@ -71,6 +71,14 @@ gb_command_set_name (GbCommand *command,
}
}
+const gchar *
+gb_command_get_description (GbCommand *command)
+{
+ g_return_val_if_fail (GB_IS_COMMAND (command), NULL);
+
+ return command->priv->description;
+}
+
void
gb_command_set_description (GbCommand *command,
const gchar *description)
@@ -87,13 +95,17 @@ gb_command_set_description (GbCommand *command,
}
GbCommandTask *
-gb_command_execute (GbCommand *command)
+gb_command_execute (GbCommand *command,
+ GVariant *parameters,
+ GbWorkbench *workbench)
{
GbCommandTask *task = NULL;
g_return_val_if_fail (GB_IS_COMMAND (command), NULL);
- g_signal_emit (command, gSignals [EXECUTE], 0, &task);
+ g_signal_emit (command, gSignals [EXECUTE], 0,
+ parameters, workbench,
+ &task);
return task;
}
@@ -192,9 +204,11 @@ gb_command_class_init (GbCommandClass *klass)
G_STRUCT_OFFSET (GbCommandClass, execute),
g_signal_accumulator_first_wins,
NULL,
- g_cclosure_marshal_VOID__VOID,
+ NULL,
GB_TYPE_COMMAND_TASK,
- 0);
+ 2,
+ G_TYPE_VARIANT,
+ GB_TYPE_WORKBENCH);
}
static void
diff --git a/src/commands/gb-command.h b/src/commands/gb-command.h
index 96b7fcc..b88a6ae 100644
--- a/src/commands/gb-command.h
+++ b/src/commands/gb-command.h
@@ -22,6 +22,7 @@
#include <gio/gio.h>
#include "gb-command-task.h"
+#include "gb-workbench.h"
G_BEGIN_DECLS
@@ -49,7 +50,9 @@ struct _GbCommandClass
{
GObjectClass parent;
- GbCommandTask *(*execute) (GbCommand *command);
+ GbCommandTask *(*execute) (GbCommand *command,
+ GVariant *parameters,
+ GbWorkbench *workbench);
gpointer _padding1;
gpointer _padding2;
@@ -68,7 +71,9 @@ void gb_command_set_name (GbCommand *command,
const gchar *gb_command_get_description (GbCommand *command);
void gb_command_set_description (GbCommand *command,
const gchar *description);
-GbCommandTask *gb_command_execute (GbCommand *command);
+GbCommandTask *gb_command_execute (GbCommand *command,
+ GVariant *parameters,
+ GbWorkbench *workbench);
G_END_DECLS
diff --git a/src/commands/gb-commands-internal.c b/src/commands/gb-commands-internal.c
new file mode 100644
index 0000000..5b3c70b
--- /dev/null
+++ b/src/commands/gb-commands-internal.c
@@ -0,0 +1,173 @@
+/* gb-commands-internal.c
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gtksourceview/gtksource.h>
+#include <stdlib.h>
+
+#include "gb-command.h"
+#include "gb-command-manager.h"
+#include "gb-commands-internal.h"
+#include "gb-editor-tab.h"
+#include "gb-editor-workspace.h"
+
+typedef void (*TextCommandFunc) (GbCommand *command,
+ GVariant *parameters,
+ GbEditorTab *tab,
+ GbEditorDocument *document);
+
+typedef struct
+{
+ const gchar *name;
+ const gchar *description;
+ TextCommandFunc command;
+} TextCommand;
+
+static void
+text_iter_swap (GtkTextIter *a,
+ GtkTextIter *b)
+{
+ GtkTextIter tmp;
+
+ gtk_text_iter_assign (&tmp, a);
+ gtk_text_iter_assign (a, b);
+ gtk_text_iter_assign (b, &tmp);
+}
+
+static int
+str_compare_qsort (const void *aptr,
+ const void *bptr)
+{
+ const gchar * const *a = aptr;
+ const gchar * const *b = bptr;
+
+ return g_strcmp0 (*a, *b);
+}
+
+static void
+text_command_sort (GbCommand *command,
+ GVariant *parameters,
+ GbEditorTab *tab,
+ GbEditorDocument *document)
+{
+ GtkTextBuffer *buffer = (GtkTextBuffer *)document;
+ GtkTextMark *insert;
+ GtkTextIter begin;
+ GtkTextIter cursor;
+ GtkTextIter end;
+ gchar **parts;
+ gchar *text;
+ guint cursor_offset;
+
+ g_return_val_if_fail (GB_IS_COMMAND (command), NULL);
+ g_return_val_if_fail (GTK_IS_TEXT_BUFFER (buffer), NULL);
+
+ gtk_text_buffer_get_selection_bounds (buffer, &begin, &end);
+
+ if (gtk_text_iter_equal (&begin, &end))
+ return;
+
+ insert = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &cursor, insert);
+ cursor_offset = gtk_text_iter_get_offset (&cursor);
+
+ if (gtk_text_iter_compare (&begin, &end) > 0)
+ text_iter_swap (&begin, &end);
+
+ if (gtk_text_iter_starts_line (&end))
+ gtk_text_iter_backward_char (&end);
+
+ text = gtk_text_iter_get_slice (&begin, &end);
+ parts = g_strsplit (text, "\n", 0);
+ g_free (text);
+
+ qsort (parts, g_strv_length (parts), sizeof (gchar *),
+ str_compare_qsort);
+
+ text = g_strjoinv ("\n", parts);
+ gtk_text_buffer_delete (buffer, &begin, &end);
+ gtk_text_buffer_insert (buffer, &begin, text, -1);
+ g_free (text);
+ g_strfreev (parts);
+
+ gtk_text_buffer_get_iter_at_offset (buffer, &begin, cursor_offset);
+ gtk_text_buffer_select_range (buffer, &begin, &begin);
+}
+
+static GbCommandTask *
+text_command_execute (GbCommand *command,
+ GVariant *parameters,
+ GbWorkbench *workbench,
+ TextCommand *text_command)
+{
+ GbEditorDocument *document;
+ GbWorkspace *workspace;
+ GbEditorTab *tab;
+
+ g_return_val_if_fail (GB_IS_COMMAND (command), NULL);
+ g_return_val_if_fail (GB_IS_WORKBENCH (workbench), NULL);
+ g_return_val_if_fail (text_command, NULL);
+
+ workspace = gb_workbench_get_active_workspace (workbench);
+ if (!GB_IS_EDITOR_WORKSPACE (workspace))
+ return NULL;
+
+ tab = gb_editor_workspace_get_active_tab (GB_EDITOR_WORKSPACE (workspace));
+ if (!tab)
+ return NULL;
+
+ document = gb_editor_tab_get_document (tab);
+ if (!document)
+ return NULL;
+
+ text_command->command (command, parameters, tab, document);
+
+ return NULL;
+}
+
+static TextCommand gTextCommands[] = {
+ { "sort",
+ N_("Sort the selected text in the editor."),
+ text_command_sort },
+};
+
+void
+gb_commands_internal_init (void)
+{
+ GbCommandManager *manager;
+ guint i;
+
+ manager = gb_command_manager_get_default ();
+
+ for (i = 0; i < G_N_ELEMENTS (gTextCommands); i++)
+ {
+ GbCommand *command;
+
+ command = g_object_new (GB_TYPE_COMMAND,
+ "name", gTextCommands [i].name,
+ "description", gTextCommands [i].description,
+ NULL);
+ g_signal_connect (command,
+ "execute",
+ G_CALLBACK (text_command_execute),
+ &gTextCommands [i]);
+ gb_command_manager_register (manager, command);
+ g_object_unref (command);
+ }
+}
diff --git a/src/commands/gb-commands-internal.h b/src/commands/gb-commands-internal.h
new file mode 100644
index 0000000..aab3763
--- /dev/null
+++ b/src/commands/gb-commands-internal.h
@@ -0,0 +1,24 @@
+/* gb-commands-internal.h
+ *
+ * Copyright (C) 2014 Christian Hergert <christian hergert me>
+ *
+ * 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/>.
+ */
+
+#ifndef GB_COMMANDS_INTERNAL_H
+#define GB_COMMANDS_INTERNAL_H
+
+void gb_commands_internal_init (void);
+
+#endif /* GB_COMMANDS_INTERNAL_H */
diff --git a/src/editor/gb-editor-workspace.c b/src/editor/gb-editor-workspace.c
index 57dee44..73be30a 100644
--- a/src/editor/gb-editor-workspace.c
+++ b/src/editor/gb-editor-workspace.c
@@ -29,6 +29,21 @@ enum {
G_DEFINE_TYPE_WITH_PRIVATE (GbEditorWorkspace, gb_editor_workspace, GB_TYPE_WORKSPACE)
+GbEditorTab *
+gb_editor_workspace_get_active_tab (GbEditorWorkspace *workspace)
+{
+ GbTab *tab;
+
+ g_return_val_if_fail (GB_IS_EDITOR_WORKSPACE (workspace), NULL);
+
+ tab = gb_multi_notebook_get_active_tab (workspace->priv->multi_notebook);
+
+ if (GB_IS_EDITOR_TAB (tab))
+ return GB_EDITOR_TAB (tab);
+
+ return NULL;
+}
+
void
gb_editor_workspace_open (GbEditorWorkspace *workspace,
GFile *file)
diff --git a/src/editor/gb-editor-workspace.h b/src/editor/gb-editor-workspace.h
index 719fe66..c0bbd5c 100644
--- a/src/editor/gb-editor-workspace.h
+++ b/src/editor/gb-editor-workspace.h
@@ -19,6 +19,7 @@
#ifndef GB_EDITOR_WORKSPACE_H
#define GB_EDITOR_WORKSPACE_H
+#include "gb-editor-tab.h"
#include "gb-workspace.h"
G_BEGIN_DECLS
@@ -48,9 +49,10 @@ struct _GbEditorWorkspaceClass
GbWorkspaceClass parent_class;
};
-GType gb_editor_workspace_get_type (void) G_GNUC_CONST;
-void gb_editor_workspace_open (GbEditorWorkspace *workspace,
- GFile *file);
+GType gb_editor_workspace_get_type (void) G_GNUC_CONST;
+void gb_editor_workspace_open (GbEditorWorkspace *workspace,
+ GFile *file);
+GbEditorTab *gb_editor_workspace_get_active_tab (GbEditorWorkspace *workspace);
G_END_DECLS
diff --git a/src/gnome-builder.mk b/src/gnome-builder.mk
index f56701f..58919c5 100644
--- a/src/gnome-builder.mk
+++ b/src/gnome-builder.mk
@@ -17,6 +17,8 @@ libgnome_builder_la_SOURCES = \
src/commands/gb-command-manager.h \
src/commands/gb-command-task.c \
src/commands/gb-command-task.h \
+ src/commands/gb-commands-internal.c \
+ src/commands/gb-commands-internal.h \
src/devhelp/gb-devhelp-navigation-item.c \
src/devhelp/gb-devhelp-navigation-item.h \
src/devhelp/gb-devhelp-tab.c \
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]