Customizable popup menu
parent
e970a062af
commit
931c5e87f5
|
@ -794,6 +794,15 @@ moo_app_init_editor (MooApp *app)
|
|||
"Editor/Menubar/Tools/ToolsMenu");
|
||||
g_strfreev (files);
|
||||
}
|
||||
|
||||
if ((files = moo_edit_get_user_menu_files (&n_files)))
|
||||
{
|
||||
moo_edit_load_user_menu (files, n_files,
|
||||
moo_app_get_ui_xml (app),
|
||||
"Editor/Popup/PopupStart",
|
||||
"Editor/Popup/PopupEnd");
|
||||
g_strfreev (files);
|
||||
}
|
||||
}
|
||||
#endif /* MOO_BUILD_EDIT */
|
||||
|
||||
|
|
|
@ -6,11 +6,12 @@ mooedit = $(moo_prefix)/mooedit
|
|||
mooedit_srcdir = $(srcdir)/$(mooedit)
|
||||
|
||||
mooedit_toolsdir = $(MOO_DATA_DIR)
|
||||
mooedit_tools_DATA = $(mooedit)/tools.cfg
|
||||
mooedit_tools_DATA = $(mooedit)/tools.cfg $(mooedit)/menu.cfg
|
||||
|
||||
mooedit_include_headers = \
|
||||
$(mooedit)/moocmdview.h \
|
||||
$(mooedit)/moocompletion.h \
|
||||
$(mooedit)/mooedit-actions.h \
|
||||
$(mooedit)/mooedit-script.h \
|
||||
$(mooedit)/mooedit.h \
|
||||
$(mooedit)/mooeditconfig.h \
|
||||
|
@ -64,6 +65,7 @@ mooedit_sources = \
|
|||
$(mooedit)/gtksourceiter.c \
|
||||
$(mooedit)/moocmdview.c \
|
||||
$(mooedit)/moocompletion.c \
|
||||
$(mooedit)/mooedit-actions.c \
|
||||
$(mooedit)/mooedit-script.c \
|
||||
$(mooedit)/mooedit.c \
|
||||
$(mooedit)/mooeditconfig.c \
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
action: SwitchHeaderAndImpl
|
||||
label: _Switch Header And Implementation
|
||||
options: need-file
|
||||
lang: C
|
||||
h_ext = ['.h'];
|
||||
c_ext = ['.c'];
|
||||
new = none;
|
||||
if doc.ext in h_ext then
|
||||
new = c_ext;
|
||||
elif doc.ext in c_ext then
|
||||
new = h_ext;
|
||||
else
|
||||
return;
|
||||
fi;
|
||||
for e in new do
|
||||
file = doc.dir + '/' + doc.base + e;
|
||||
if FileExists(file) then
|
||||
Open(file);
|
||||
return;
|
||||
fi;
|
||||
od;
|
|
@ -0,0 +1,795 @@
|
|||
/*
|
||||
* mooedit-actions.c
|
||||
*
|
||||
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* See COPYING file that comes with this distribution.
|
||||
*/
|
||||
|
||||
#define MOOEDIT_COMPILATION
|
||||
#include "mooedit/mooedit-actions.h"
|
||||
#include "mooedit/mooedit-private.h"
|
||||
#include "mooutils/mooutils-gobject.h"
|
||||
#include "mooutils/mootoggleaction.h"
|
||||
#include "mooutils/moocompat.h"
|
||||
#include <string.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
|
||||
static void moo_edit_add_action (MooEdit *edit,
|
||||
MooAction *action);
|
||||
static void moo_edit_remove_action (MooEdit *edit,
|
||||
const char *action_id);
|
||||
static void moo_edit_action_check (MooEditAction *action);
|
||||
|
||||
|
||||
#define MOO_EDIT_ACTIONS_QUARK (moo_edit_get_actions_quark ())
|
||||
|
||||
typedef struct {
|
||||
MooObjectFactory *action;
|
||||
char **conditions;
|
||||
} ActionInfo;
|
||||
|
||||
|
||||
static GQuark
|
||||
moo_edit_get_actions_quark (void)
|
||||
{
|
||||
static GQuark q;
|
||||
|
||||
if (!q)
|
||||
q = g_quark_from_static_string ("moo-edit-actions");
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
static ActionInfo*
|
||||
action_info_new (MooObjectFactory *action,
|
||||
char **conditions)
|
||||
{
|
||||
ActionInfo *info;
|
||||
|
||||
g_return_val_if_fail (MOO_IS_OBJECT_FACTORY (action), NULL);
|
||||
|
||||
info = g_new0 (ActionInfo, 1);
|
||||
info->action = g_object_ref (action);
|
||||
info->conditions = g_strdupv (conditions);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
action_info_free (ActionInfo *info)
|
||||
{
|
||||
if (info)
|
||||
{
|
||||
g_object_unref (info->action);
|
||||
g_strfreev (info->conditions);
|
||||
g_free (info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_edit_add_action (MooEdit *edit,
|
||||
MooAction *action)
|
||||
{
|
||||
MooActionGroup *group;
|
||||
GtkWidget *toplevel;
|
||||
|
||||
g_return_if_fail (MOO_IS_EDIT (edit));
|
||||
g_return_if_fail (MOO_IS_ACTION (action));
|
||||
|
||||
g_object_set (action, "group-name", "MooEdit", NULL);
|
||||
|
||||
group = moo_edit_get_actions (edit);
|
||||
moo_action_group_add (group, action);
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (edit));
|
||||
|
||||
if (!action->dead && MOO_IS_EDIT_WINDOW (toplevel))
|
||||
{
|
||||
const char *accel_path;
|
||||
char *window_id;
|
||||
window_id = moo_window_get_id (MOO_WINDOW (toplevel));
|
||||
accel_path = moo_action_make_accel_path (window_id, moo_action_get_id (action));
|
||||
_moo_action_set_accel_path (action, accel_path);
|
||||
g_free (window_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_edit_remove_action (MooEdit *edit,
|
||||
const char *action_id)
|
||||
{
|
||||
MooActionGroup *group;
|
||||
|
||||
g_return_if_fail (MOO_IS_EDIT (edit));
|
||||
g_return_if_fail (action_id != NULL);
|
||||
|
||||
group = moo_edit_get_actions (edit);
|
||||
moo_action_group_remove_action (group, action_id);
|
||||
}
|
||||
|
||||
|
||||
static MooAction*
|
||||
create_action (const char *action_id,
|
||||
ActionInfo *info,
|
||||
MooEdit *edit)
|
||||
{
|
||||
MooAction *action;
|
||||
|
||||
g_return_val_if_fail (info != NULL, NULL);
|
||||
g_return_val_if_fail (MOO_IS_OBJECT_FACTORY (info->action), NULL);
|
||||
g_return_val_if_fail (action_id && action_id[0], NULL);
|
||||
|
||||
action = moo_object_factory_create_object (info->action, edit,
|
||||
"closure-object", edit,
|
||||
NULL);
|
||||
g_return_val_if_fail (action != NULL, NULL);
|
||||
g_object_set (action, "id", action_id, NULL);
|
||||
|
||||
if (g_type_is_a (info->action->object_type, MOO_TYPE_TOGGLE_ACTION))
|
||||
g_object_set (action, "toggled-object", edit, NULL);
|
||||
|
||||
if (g_type_is_a (info->action->object_type, MOO_TYPE_EDIT_ACTION))
|
||||
g_object_set (action, "doc", edit, NULL);
|
||||
|
||||
if (info->conditions)
|
||||
{
|
||||
char **p;
|
||||
|
||||
for (p = info->conditions; *p != NULL; p += 2)
|
||||
{
|
||||
if (p[1][0] == '!')
|
||||
moo_bind_bool_property (action, p[0], edit, p[1] + 1, TRUE);
|
||||
else
|
||||
moo_bind_bool_property (action, p[0], edit, p[1], FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moo_edit_class_new_action (MooEditClass *klass,
|
||||
const char *id,
|
||||
const char *first_prop_name,
|
||||
...)
|
||||
{
|
||||
va_list args;
|
||||
va_start (args, first_prop_name);
|
||||
moo_edit_class_new_actionv (klass, id, first_prop_name, args);
|
||||
va_end (args);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_edit_class_install_action (MooEditClass *klass,
|
||||
const char *action_id,
|
||||
MooObjectFactory *action,
|
||||
char **conditions)
|
||||
{
|
||||
GHashTable *actions;
|
||||
ActionInfo *info;
|
||||
GType type;
|
||||
GSList *l;
|
||||
|
||||
g_return_if_fail (MOO_IS_EDIT_CLASS (klass));
|
||||
g_return_if_fail (MOO_IS_OBJECT_FACTORY (action));
|
||||
g_return_if_fail (action_id && action_id[0]);
|
||||
|
||||
type = G_OBJECT_CLASS_TYPE (klass);
|
||||
actions = g_type_get_qdata (type, MOO_EDIT_ACTIONS_QUARK);
|
||||
|
||||
if (!actions)
|
||||
{
|
||||
actions = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
g_free, (GDestroyNotify) action_info_free);
|
||||
g_type_set_qdata (type, MOO_EDIT_ACTIONS_QUARK, actions);
|
||||
}
|
||||
|
||||
if (g_hash_table_lookup (actions, action_id))
|
||||
moo_edit_class_remove_action (klass, action_id);
|
||||
|
||||
info = action_info_new (action, conditions);
|
||||
g_hash_table_insert (actions, g_strdup (action_id), info);
|
||||
|
||||
for (l = _moo_edit_instances; l != NULL; l = l->next)
|
||||
{
|
||||
if (g_type_is_a (G_OBJECT_TYPE (l->data), type))
|
||||
{
|
||||
MooAction *action = create_action (action_id, info, l->data);
|
||||
|
||||
if (action)
|
||||
moo_edit_add_action (l->data, action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moo_edit_class_new_actionv (MooEditClass *klass,
|
||||
const char *action_id,
|
||||
const char *first_prop_name,
|
||||
va_list var_args)
|
||||
{
|
||||
const char *name;
|
||||
GType action_type = 0;
|
||||
GObjectClass *action_class = NULL;
|
||||
GArray *action_params = NULL;
|
||||
GPtrArray *conditions = NULL;
|
||||
|
||||
g_return_if_fail (MOO_IS_EDIT_CLASS (klass));
|
||||
g_return_if_fail (first_prop_name != NULL);
|
||||
g_return_if_fail (action_id != NULL);
|
||||
|
||||
action_params = g_array_new (FALSE, TRUE, sizeof (GParameter));
|
||||
conditions = g_ptr_array_new ();
|
||||
|
||||
name = first_prop_name;
|
||||
while (name)
|
||||
{
|
||||
GParameter param = {NULL, {0, {{0}, {0}}}};
|
||||
GParamSpec *pspec;
|
||||
char *err = NULL;
|
||||
|
||||
/* ignore id property */
|
||||
if (!strcmp (name, "id"))
|
||||
{
|
||||
g_critical ("%s: id property specified", G_STRLOC);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!strcmp (name, "action-type::") || !strcmp (name, "action_type::"))
|
||||
{
|
||||
g_value_init (¶m.value, MOO_TYPE_GTYPE);
|
||||
G_VALUE_COLLECT (¶m.value, var_args, 0, &err);
|
||||
|
||||
if (err)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRLOC, err);
|
||||
g_free (err);
|
||||
goto error;
|
||||
}
|
||||
|
||||
action_type = moo_value_get_gtype (¶m.value);
|
||||
|
||||
if (!g_type_is_a (action_type, MOO_TYPE_ACTION))
|
||||
{
|
||||
g_warning ("%s: invalid action type", G_STRLOC);
|
||||
goto error;
|
||||
}
|
||||
|
||||
action_class = g_type_class_ref (action_type);
|
||||
}
|
||||
else if (!strncmp (name, "condition::", strlen ("condition::")))
|
||||
{
|
||||
const char *suffix = strstr (name, "::");
|
||||
|
||||
if (!suffix || !suffix[1] || !suffix[2])
|
||||
{
|
||||
g_warning ("%s: invalid condition name '%s'", G_STRLOC, name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_ptr_array_add (conditions, g_strdup (suffix + 2));
|
||||
|
||||
name = va_arg (var_args, gchar*);
|
||||
|
||||
if (!name)
|
||||
{
|
||||
g_warning ("%s: unterminated '%s' property",
|
||||
G_STRLOC,
|
||||
(char*) g_ptr_array_index (conditions, conditions->len - 1));
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_ptr_array_add (conditions, g_strdup (name));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!action_class)
|
||||
{
|
||||
if (!action_type)
|
||||
action_type = MOO_TYPE_EDIT_ACTION;
|
||||
action_class = g_type_class_ref (action_type);
|
||||
}
|
||||
|
||||
pspec = g_object_class_find_property (action_class, name);
|
||||
|
||||
if (!pspec)
|
||||
{
|
||||
g_warning ("%s: no property '%s' in class '%s'",
|
||||
G_STRLOC, name, g_type_name (action_type));
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_value_init (¶m.value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||
G_VALUE_COLLECT (¶m.value, var_args, 0, &err);
|
||||
|
||||
if (err)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRLOC, err);
|
||||
g_free (err);
|
||||
g_value_unset (¶m.value);
|
||||
goto error;
|
||||
}
|
||||
|
||||
param.name = g_strdup (name);
|
||||
g_array_append_val (action_params, param);
|
||||
}
|
||||
|
||||
name = va_arg (var_args, gchar*);
|
||||
}
|
||||
|
||||
G_STMT_START
|
||||
{
|
||||
MooObjectFactory *action_factory = NULL;
|
||||
|
||||
action_factory = moo_object_factory_new_a (action_type,
|
||||
(GParameter*) action_params->data,
|
||||
action_params->len);
|
||||
|
||||
if (!action_factory)
|
||||
{
|
||||
g_warning ("%s: error in moo_object_factory_new_a()", G_STRLOC);
|
||||
goto error;
|
||||
}
|
||||
|
||||
g_array_free (action_params, FALSE);
|
||||
action_params = NULL;
|
||||
|
||||
g_ptr_array_add (conditions, NULL);
|
||||
|
||||
moo_edit_class_install_action (klass,
|
||||
action_id,
|
||||
action_factory,
|
||||
(char**) conditions->pdata);
|
||||
|
||||
g_strfreev ((char**) conditions->pdata);
|
||||
g_ptr_array_free (conditions, FALSE);
|
||||
|
||||
if (action_class)
|
||||
g_type_class_unref (action_class);
|
||||
if (action_factory)
|
||||
g_object_unref (action_factory);
|
||||
|
||||
return;
|
||||
}
|
||||
G_STMT_END;
|
||||
|
||||
error:
|
||||
if (action_params)
|
||||
{
|
||||
guint i;
|
||||
GParameter *params = (GParameter*) action_params->data;
|
||||
|
||||
for (i = 0; i < action_params->len; ++i)
|
||||
{
|
||||
g_value_unset (¶ms[i].value);
|
||||
g_free ((char*) params[i].name);
|
||||
}
|
||||
|
||||
g_array_free (action_params, TRUE);
|
||||
}
|
||||
|
||||
if (conditions)
|
||||
{
|
||||
guint i;
|
||||
for (i = 0; i < conditions->len; ++i)
|
||||
g_free (g_ptr_array_index (conditions, i));
|
||||
g_ptr_array_free (conditions, TRUE);
|
||||
}
|
||||
|
||||
if (action_class)
|
||||
g_type_class_unref (action_class);
|
||||
}
|
||||
|
||||
|
||||
static GObject*
|
||||
custom_action_factory_func (MooEdit *edit,
|
||||
MooObjectFactory *factory)
|
||||
{
|
||||
const char *action_id;
|
||||
MooEditActionFunc func;
|
||||
gpointer func_data;
|
||||
MooAction *action;
|
||||
|
||||
g_return_val_if_fail (MOO_IS_EDIT (edit), NULL);
|
||||
|
||||
action_id = g_object_get_data (G_OBJECT (factory), "moo-edit-class-action-id");
|
||||
func = g_object_get_data (G_OBJECT (factory), "moo-edit-class-action-func");
|
||||
func_data = g_object_get_data (G_OBJECT (factory), "moo-edit-class-action-func-data");
|
||||
|
||||
g_return_val_if_fail (action_id != NULL, NULL);
|
||||
g_return_val_if_fail (func != NULL, NULL);
|
||||
|
||||
action = func (edit, func_data);
|
||||
|
||||
return action ? G_OBJECT (action) : NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moo_edit_class_new_action_custom (MooEditClass *klass,
|
||||
const char *action_id,
|
||||
MooEditActionFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
MooObjectFactory *action_factory;
|
||||
|
||||
g_return_if_fail (MOO_IS_EDIT_CLASS (klass));
|
||||
g_return_if_fail (action_id && action_id[0]);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
action_factory = moo_object_factory_new_func ((MooObjectFactoryFunc) custom_action_factory_func, NULL);
|
||||
g_object_set_data (G_OBJECT (action_factory), "moo-edit-class", klass);
|
||||
g_object_set_data_full (G_OBJECT (action_factory), "moo-edit-class-action-id",
|
||||
g_strdup (action_id), g_free);
|
||||
g_object_set_data (G_OBJECT (action_factory), "moo-edit-class-action-func", func);
|
||||
g_object_set_data_full (G_OBJECT (action_factory), "moo-edit-class-action-func-data",
|
||||
data, notify);
|
||||
|
||||
moo_edit_class_install_action (klass, action_id, action_factory, NULL);
|
||||
g_object_unref (action_factory);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moo_edit_class_remove_action (MooEditClass *klass,
|
||||
const char *action_id)
|
||||
{
|
||||
GHashTable *actions;
|
||||
GType type;
|
||||
GSList *l;
|
||||
|
||||
g_return_if_fail (MOO_IS_EDIT_CLASS (klass));
|
||||
|
||||
type = G_OBJECT_CLASS_TYPE (klass);
|
||||
actions = g_type_get_qdata (type, MOO_EDIT_ACTIONS_QUARK);
|
||||
|
||||
if (actions)
|
||||
g_hash_table_remove (actions, action_id);
|
||||
|
||||
for (l = _moo_edit_instances; l != NULL; l = l->next)
|
||||
if (g_type_is_a (G_OBJECT_TYPE (l->data), type))
|
||||
moo_edit_remove_action (l->data, action_id);
|
||||
}
|
||||
|
||||
|
||||
MooActionGroup *
|
||||
moo_edit_get_actions (MooEdit *edit)
|
||||
{
|
||||
g_return_val_if_fail (MOO_IS_EDIT (edit), NULL);
|
||||
return edit->priv->actions;
|
||||
}
|
||||
|
||||
|
||||
MooAction *
|
||||
moo_edit_get_action_by_id (MooEdit *edit,
|
||||
const char *action_id)
|
||||
{
|
||||
MooActionGroup *actions;
|
||||
|
||||
g_return_val_if_fail (MOO_IS_EDIT (edit), NULL);
|
||||
g_return_val_if_fail (action_id != NULL, NULL);
|
||||
|
||||
actions = moo_edit_get_actions (edit);
|
||||
return moo_action_group_get_action (actions, action_id);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_action (const char *id,
|
||||
ActionInfo *info,
|
||||
MooEdit *edit)
|
||||
{
|
||||
MooAction *action = create_action (id, info, edit);
|
||||
|
||||
if (action)
|
||||
moo_edit_add_action (edit, action);
|
||||
}
|
||||
|
||||
void
|
||||
_moo_edit_add_class_actions (MooEdit *edit)
|
||||
{
|
||||
GType type;
|
||||
|
||||
g_return_if_fail (MOO_IS_EDIT (edit));
|
||||
|
||||
type = G_OBJECT_TYPE (edit);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
GHashTable *actions;
|
||||
|
||||
actions = g_type_get_qdata (type, MOO_EDIT_ACTIONS_QUARK);
|
||||
|
||||
if (actions)
|
||||
g_hash_table_foreach (actions, (GHFunc) add_action, edit);
|
||||
|
||||
if (type == MOO_TYPE_EDIT)
|
||||
break;
|
||||
|
||||
type = g_type_parent (type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
check_action (G_GNUC_UNUSED MooActionGroup *group,
|
||||
MooAction *action,
|
||||
G_GNUC_UNUSED gpointer data)
|
||||
{
|
||||
if (MOO_IS_EDIT_ACTION (action))
|
||||
moo_edit_action_check (MOO_EDIT_ACTION (action));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_moo_edit_check_actions (MooEdit *edit)
|
||||
{
|
||||
moo_action_group_foreach (edit->priv->actions,
|
||||
check_action, NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_moo_edit_class_init_actions (MooEditClass *klass)
|
||||
{
|
||||
moo_edit_class_new_action (klass, "Undo",
|
||||
"name", "Undo",
|
||||
"label", "_Undo",
|
||||
"tooltip", "Undo",
|
||||
"icon-stock-id", GTK_STOCK_UNDO,
|
||||
"closure-signal", "undo",
|
||||
"condition::sensitive", "can-undo",
|
||||
NULL);
|
||||
|
||||
moo_edit_class_new_action (klass, "Redo",
|
||||
"name", "Redo",
|
||||
"label", "_Redo",
|
||||
"tooltip", "Redo",
|
||||
"icon-stock-id", GTK_STOCK_REDO,
|
||||
"closure-signal", "redo",
|
||||
"condition::sensitive", "can-redo",
|
||||
NULL);
|
||||
|
||||
moo_edit_class_new_action (klass, "Cut",
|
||||
"name", "Cut",
|
||||
"stock-id", GTK_STOCK_CUT,
|
||||
"closure-signal", "cut-clipboard",
|
||||
"condition::sensitive", "has-selection",
|
||||
NULL);
|
||||
|
||||
moo_edit_class_new_action (klass, "Copy",
|
||||
"name", "Copy",
|
||||
"stock-id", GTK_STOCK_COPY,
|
||||
"closure-signal", "copy-clipboard",
|
||||
"condition::sensitive", "has-selection",
|
||||
NULL);
|
||||
|
||||
moo_edit_class_new_action (klass, "Paste",
|
||||
"name", "Paste",
|
||||
"stock-id", GTK_STOCK_PASTE,
|
||||
"closure-signal", "paste-clipboard",
|
||||
NULL);
|
||||
|
||||
moo_edit_class_new_action (klass, "SelectAll",
|
||||
"name", "Select All",
|
||||
"label", "Select _All",
|
||||
"tooltip", "Select all",
|
||||
"icon-stock-id", GTK_STOCK_SELECT_ALL,
|
||||
"closure-callback", moo_text_view_select_all,
|
||||
"condition::sensitive", "has-text",
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* MooEditAction
|
||||
*/
|
||||
|
||||
G_DEFINE_TYPE (MooEditAction, moo_edit_action, MOO_TYPE_ACTION);
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DOC,
|
||||
PROP_FLAGS,
|
||||
PROP_LANGS
|
||||
};
|
||||
|
||||
static void
|
||||
moo_edit_action_finalize (GObject *object)
|
||||
{
|
||||
MooEditAction *action = MOO_EDIT_ACTION (object);
|
||||
g_slist_foreach (action->langs, (GFunc) g_free, NULL);
|
||||
g_slist_free (action->langs);
|
||||
G_OBJECT_CLASS(moo_edit_action_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_edit_action_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MooEditAction *action = MOO_EDIT_ACTION (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOC:
|
||||
g_value_set_object (value, action->doc);
|
||||
break;
|
||||
|
||||
case PROP_FLAGS:
|
||||
g_value_set_flags (value, action->flags);
|
||||
break;
|
||||
|
||||
case PROP_LANGS:
|
||||
g_value_set_pointer (value, action->langs);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
string_slist_free (GSList *list)
|
||||
{
|
||||
g_slist_foreach (list, (GFunc) g_free, NULL);
|
||||
g_slist_free (list);
|
||||
}
|
||||
|
||||
|
||||
static GSList *
|
||||
string_slist_copy (GSList *list)
|
||||
{
|
||||
GSList *copy = NULL;
|
||||
|
||||
while (list)
|
||||
{
|
||||
copy = g_slist_prepend (copy, g_strdup (list->data));
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return g_slist_reverse (copy);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_edit_action_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
MooEditAction *action = MOO_EDIT_ACTION (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DOC:
|
||||
action->doc = g_value_get_object (value);
|
||||
g_object_notify (object, "doc");
|
||||
break;
|
||||
|
||||
case PROP_FLAGS:
|
||||
action->flags = g_value_get_flags (value);
|
||||
g_object_notify (object, "flags");
|
||||
break;
|
||||
|
||||
case PROP_LANGS:
|
||||
string_slist_free (action->langs);
|
||||
action->langs = string_slist_copy (g_value_get_pointer (value));
|
||||
g_object_notify (object, "langs");
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_edit_action_class_init (MooEditActionClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = moo_edit_action_finalize;
|
||||
gobject_class->set_property = moo_edit_action_set_property;
|
||||
gobject_class->get_property = moo_edit_action_get_property;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DOC,
|
||||
g_param_spec_object ("doc",
|
||||
"doc",
|
||||
"doc",
|
||||
MOO_TYPE_EDIT,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_FLAGS,
|
||||
g_param_spec_flags ("flags",
|
||||
"flags",
|
||||
"flags",
|
||||
MOO_TYPE_EDIT_ACTION_FLAGS, 0,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_LANGS,
|
||||
g_param_spec_pointer ("langs",
|
||||
"langs",
|
||||
"langs",
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_edit_action_init (G_GNUC_UNUSED MooEditAction *action)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_edit_action_check (MooEditAction *action)
|
||||
{
|
||||
g_return_if_fail (action->doc != NULL);
|
||||
|
||||
if (action->flags)
|
||||
{
|
||||
gboolean sensitive = (action->flags & MOO_EDIT_ACTION_NEED_FILE) ?
|
||||
moo_edit_get_filename (action->doc) != NULL : TRUE;
|
||||
g_object_set (action, "sensitive", sensitive, NULL);
|
||||
}
|
||||
|
||||
if (action->langs)
|
||||
{
|
||||
GSList *l;
|
||||
MooLang *lang = moo_text_view_get_lang (MOO_TEXT_VIEW (action->doc));
|
||||
const char *lang_id = lang ? lang->id : MOO_LANG_NONE;
|
||||
gboolean visible = FALSE;
|
||||
|
||||
for (l = action->langs; l != NULL; l = l->next)
|
||||
{
|
||||
if (l->data && !strcmp (l->data, lang_id))
|
||||
{
|
||||
visible = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_object_set (action, "visible", visible, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GType
|
||||
moo_edit_action_flags_get_type (void)
|
||||
{
|
||||
static GType type;
|
||||
|
||||
if (!type)
|
||||
{
|
||||
static GFlagsValue values[] = {
|
||||
{ MOO_EDIT_ACTION_NEED_FILE, (char*) "MOO_EDIT_ACTION_NEED_FILE", (char*) "need-file" },
|
||||
{ 0, NULL, NULL },
|
||||
};
|
||||
|
||||
type = g_flags_register_static ("MooEditActionFlags", values);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* mooedit-actions.h
|
||||
*
|
||||
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* See COPYING file that comes with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef __MOO_EDIT_ACTIONS_H__
|
||||
#define __MOO_EDIT_ACTIONS_H__
|
||||
|
||||
#include <mooutils/mooactiongroup.h>
|
||||
#include <mooutils/moouixml.h>
|
||||
#include <mooedit/mooedit.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define MOO_TYPE_EDIT_ACTION_FLAGS (moo_edit_action_flags_get_type ())
|
||||
#define MOO_TYPE_EDIT_ACTION (moo_edit_action_get_type ())
|
||||
#define MOO_EDIT_ACTION(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_EDIT_ACTION, MooEditAction))
|
||||
#define MOO_EDIT_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOO_TYPE_EDIT_ACTION, MooEditActionClass))
|
||||
#define MOO_IS_EDIT_ACTION(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_EDIT_ACTION))
|
||||
#define MOO_IS_EDIT_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOO_TYPE_EDIT_ACTION))
|
||||
#define MOO_EDIT_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOO_TYPE_EDIT_ACTION, MooEditActionClass))
|
||||
|
||||
typedef struct _MooEditAction MooEditAction;
|
||||
typedef struct _MooEditActionPrivate MooEditActionPrivate;
|
||||
typedef struct _MooEditActionClass MooEditActionClass;
|
||||
|
||||
typedef enum {
|
||||
MOO_EDIT_ACTION_NEED_FILE = 1 << 0
|
||||
} MooEditActionFlags;
|
||||
|
||||
struct _MooEditAction
|
||||
{
|
||||
MooAction parent;
|
||||
MooEdit *doc;
|
||||
GSList *langs;
|
||||
MooEditActionFlags flags;
|
||||
};
|
||||
|
||||
struct _MooEditActionClass
|
||||
{
|
||||
MooActionClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
typedef MooAction *(*MooEditActionFunc) (MooEdit *edit,
|
||||
gpointer data);
|
||||
|
||||
GType moo_edit_action_get_type (void) G_GNUC_CONST;
|
||||
GType moo_edit_action_flags_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void moo_edit_class_new_action (MooEditClass *klass,
|
||||
const char *id,
|
||||
const char *first_prop_name,
|
||||
...);
|
||||
void moo_edit_class_new_actionv (MooEditClass *klass,
|
||||
const char *id,
|
||||
const char *first_prop_name,
|
||||
va_list props);
|
||||
void moo_edit_class_new_action_custom (MooEditClass *klass,
|
||||
const char *id,
|
||||
MooEditActionFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
void moo_edit_class_remove_action (MooEditClass *klass,
|
||||
const char *id);
|
||||
|
||||
MooActionGroup *moo_edit_get_actions (MooEdit *edit);
|
||||
MooAction *moo_edit_get_action_by_id (MooEdit *edit,
|
||||
const char *action_id);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MOO_EDIT_ACTIONS_H__ */
|
|
@ -25,6 +25,15 @@
|
|||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
extern GSList *_moo_edit_instances;
|
||||
void _moo_edit_add_class_actions (MooEdit *edit);
|
||||
void _moo_edit_check_actions (MooEdit *edit);
|
||||
void _moo_edit_class_init_actions (MooEditClass *klass);
|
||||
|
||||
void _moo_edit_do_popup (MooEdit *edit,
|
||||
GdkEventButton *event);
|
||||
|
||||
|
||||
/***********************************************************************/
|
||||
/* Preferences
|
||||
/*/
|
||||
|
@ -90,6 +99,12 @@ struct _MooEditPrivate {
|
|||
gboolean enable_bookmarks;
|
||||
GSList *bookmarks; /* sorted by line number */
|
||||
guint update_bookmarks_idle;
|
||||
|
||||
/***********************************************************************/
|
||||
/* Actions
|
||||
/*/
|
||||
GtkMenu *menu;
|
||||
MooActionGroup *actions;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
*/
|
||||
|
||||
#define MOOEDIT_COMPILATION
|
||||
|
||||
#include "mooedit/mooedit-actions.h"
|
||||
#include "mooedit/mooedit-private.h"
|
||||
#include "mooedit/mootextview-private.h"
|
||||
#include "mooedit/mooeditdialogs.h"
|
||||
|
@ -25,6 +25,9 @@
|
|||
#include <string.h>
|
||||
|
||||
|
||||
GSList *_moo_edit_instances = NULL;
|
||||
|
||||
|
||||
static GObject *moo_edit_constructor (GType type,
|
||||
guint n_construct_properties,
|
||||
GObjectConstructParam *construct_param);
|
||||
|
@ -39,6 +42,8 @@ static void moo_edit_get_property (GObject *object,
|
|||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
|
||||
static gboolean moo_edit_popup_menu (GtkWidget *widget);
|
||||
|
||||
static void moo_edit_filename_changed (MooEdit *edit,
|
||||
const char *new_filename);
|
||||
static gboolean moo_edit_line_mark_clicked (MooTextView *view,
|
||||
|
@ -100,14 +105,14 @@ static void
|
|||
moo_edit_class_init (MooEditClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
MooTextViewClass *view_class = MOO_TEXT_VIEW_CLASS (klass);
|
||||
|
||||
gobject_class->set_property = moo_edit_set_property;
|
||||
gobject_class->get_property = moo_edit_get_property;
|
||||
gobject_class->constructor = moo_edit_constructor;
|
||||
gobject_class->finalize = moo_edit_finalize;
|
||||
|
||||
view_class->line_mark_clicked = moo_edit_line_mark_clicked;
|
||||
MOO_TEXT_VIEW_CLASS(klass)->line_mark_clicked = moo_edit_line_mark_clicked;
|
||||
GTK_WIDGET_CLASS(klass)->popup_menu = moo_edit_popup_menu;
|
||||
|
||||
klass->filename_changed = moo_edit_filename_changed;
|
||||
klass->config_notify = moo_edit_config_notify;
|
||||
|
@ -141,6 +146,8 @@ moo_edit_class_init (MooEditClass *klass)
|
|||
FALSE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
_moo_edit_class_init_actions (klass);
|
||||
|
||||
signals[CONFIG_NOTIFY] =
|
||||
g_signal_new ("config-notify",
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
|
@ -232,6 +239,8 @@ moo_edit_init (MooEdit *edit)
|
|||
|
||||
edit->priv->file_watch_policy = MOO_EDIT_RELOAD_IF_SAFE;
|
||||
|
||||
edit->priv->actions = moo_action_group_new ("MooEdit");
|
||||
|
||||
indent = moo_indenter_new (edit, NULL);
|
||||
moo_text_view_set_indenter (MOO_TEXT_VIEW (edit), indent);
|
||||
g_object_unref (indent);
|
||||
|
@ -254,6 +263,9 @@ moo_edit_constructor (GType type,
|
|||
|
||||
edit = MOO_EDIT (object);
|
||||
|
||||
_moo_edit_add_class_actions (edit);
|
||||
_moo_edit_instances = g_slist_prepend (_moo_edit_instances, edit);
|
||||
|
||||
edit->priv->modified_changed_handler_id =
|
||||
g_signal_connect (get_buffer (edit),
|
||||
"modified-changed",
|
||||
|
@ -284,6 +296,8 @@ moo_edit_finalize (GObject *object)
|
|||
{
|
||||
MooEdit *edit = MOO_EDIT (object);
|
||||
|
||||
_moo_edit_instances = g_slist_remove (_moo_edit_instances, edit);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (edit->config,
|
||||
(gpointer) config_changed,
|
||||
edit);
|
||||
|
@ -305,6 +319,10 @@ moo_edit_finalize (GObject *object)
|
|||
g_slist_foreach (edit->priv->bookmarks, (GFunc) g_object_unref, NULL);
|
||||
g_slist_free (edit->priv->bookmarks);
|
||||
|
||||
if (edit->priv->menu)
|
||||
g_object_unref (edit->priv->menu);
|
||||
g_object_unref (edit->priv->actions);
|
||||
|
||||
g_free (edit->priv);
|
||||
edit->priv = NULL;
|
||||
|
||||
|
@ -1600,3 +1618,132 @@ moo_edit_uncomment (MooEdit *edit)
|
|||
|
||||
end_comment_action (edit);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* popup menu
|
||||
*/
|
||||
|
||||
/* gtktextview.c */
|
||||
static void
|
||||
popup_position_func (GtkMenu *menu,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gboolean *push_in,
|
||||
gpointer user_data)
|
||||
{
|
||||
GtkTextView *text_view;
|
||||
GtkWidget *widget;
|
||||
GdkRectangle cursor_rect;
|
||||
GdkRectangle onscreen_rect;
|
||||
gint root_x, root_y;
|
||||
GtkTextIter iter;
|
||||
GtkRequisition req;
|
||||
GdkScreen *screen;
|
||||
gint monitor_num;
|
||||
GdkRectangle monitor;
|
||||
|
||||
text_view = GTK_TEXT_VIEW (user_data);
|
||||
widget = GTK_WIDGET (text_view);
|
||||
|
||||
g_return_if_fail (GTK_WIDGET_REALIZED (text_view));
|
||||
|
||||
screen = gtk_widget_get_screen (widget);
|
||||
|
||||
gdk_window_get_origin (widget->window, &root_x, &root_y);
|
||||
|
||||
gtk_text_buffer_get_iter_at_mark (gtk_text_view_get_buffer (text_view),
|
||||
&iter,
|
||||
gtk_text_buffer_get_insert (gtk_text_view_get_buffer (text_view)));
|
||||
|
||||
gtk_text_view_get_iter_location (text_view,
|
||||
&iter,
|
||||
&cursor_rect);
|
||||
|
||||
gtk_text_view_get_visible_rect (text_view, &onscreen_rect);
|
||||
|
||||
gtk_widget_size_request (text_view->popup_menu, &req);
|
||||
|
||||
/* can't use rectangle_intersect since cursor rect can have 0 width */
|
||||
if (cursor_rect.x >= onscreen_rect.x &&
|
||||
cursor_rect.x < onscreen_rect.x + onscreen_rect.width &&
|
||||
cursor_rect.y >= onscreen_rect.y &&
|
||||
cursor_rect.y < onscreen_rect.y + onscreen_rect.height)
|
||||
{
|
||||
gtk_text_view_buffer_to_window_coords (text_view,
|
||||
GTK_TEXT_WINDOW_WIDGET,
|
||||
cursor_rect.x, cursor_rect.y,
|
||||
&cursor_rect.x, &cursor_rect.y);
|
||||
|
||||
*x = root_x + cursor_rect.x + cursor_rect.width;
|
||||
*y = root_y + cursor_rect.y + cursor_rect.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just center the menu, since cursor is offscreen. */
|
||||
*x = root_x + (widget->allocation.width / 2 - req.width / 2);
|
||||
*y = root_y + (widget->allocation.height / 2 - req.height / 2);
|
||||
}
|
||||
|
||||
/* Ensure sanity */
|
||||
*x = CLAMP (*x, root_x, (root_x + widget->allocation.width));
|
||||
*y = CLAMP (*y, root_y, (root_y + widget->allocation.height));
|
||||
|
||||
monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
|
||||
gtk_menu_set_monitor (menu, monitor_num);
|
||||
gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
|
||||
|
||||
*x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width));
|
||||
*y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height));
|
||||
|
||||
*push_in = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_moo_edit_do_popup (MooEdit *edit,
|
||||
GdkEventButton *event)
|
||||
{
|
||||
GtkWidget *window;
|
||||
MooUIXML *xml;
|
||||
|
||||
xml = moo_editor_get_ui_xml (edit->priv->editor);
|
||||
g_return_if_fail (xml != NULL);
|
||||
|
||||
window = gtk_widget_get_toplevel (GTK_WIDGET (edit));
|
||||
|
||||
if (!edit->priv->menu)
|
||||
{
|
||||
edit->priv->menu =
|
||||
moo_ui_xml_create_widget (xml, MOO_UI_MENU, "Editor/Popup",
|
||||
moo_edit_get_actions (edit),
|
||||
MOO_IS_EDIT_WINDOW (window) ?
|
||||
MOO_WINDOW(window)->accel_group : NULL);
|
||||
gtk_object_sink (g_object_ref (edit->priv->menu));
|
||||
}
|
||||
|
||||
g_return_if_fail (edit->priv->menu != NULL);
|
||||
|
||||
_moo_edit_check_actions (edit);
|
||||
|
||||
if (event)
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (edit->priv->menu),
|
||||
NULL, NULL, NULL, NULL,
|
||||
event->button, event->time);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_menu_popup (GTK_MENU (edit->priv->menu), NULL, NULL,
|
||||
popup_position_func, edit,
|
||||
0, gtk_get_current_event_time ());
|
||||
gtk_menu_shell_select_first (GTK_MENU_SHELL (edit->priv->menu), FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
moo_edit_popup_menu (GtkWidget *widget)
|
||||
{
|
||||
_moo_edit_do_popup (MOO_EDIT (widget), NULL);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*-
|
||||
*
|
||||
/*
|
||||
* mooedit.h
|
||||
*
|
||||
* Copyright (C) 2004-2006 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#define MOOEDIT_COMPILATION
|
||||
#include "mooedit/mootextview-private.h"
|
||||
#include "mooedit/mooedit-private.h"
|
||||
#include "mooedit/mootextiter.h"
|
||||
#include "mooedit/mootextbuffer.h"
|
||||
#include "mooutils/moocompat.h"
|
||||
|
@ -536,11 +537,17 @@ _moo_text_view_button_press_event (GtkWidget *widget,
|
|||
gtk_text_buffer_place_cursor (buffer, &iter);
|
||||
view->priv->drag_type = MOO_TEXT_VIEW_DRAG_SELECT;
|
||||
}
|
||||
else if (event->button == 2 || event->button == 3) {
|
||||
/* let GtkSourceView worry about this */
|
||||
else if (event->button == 3 && MOO_IS_EDIT (widget))
|
||||
{
|
||||
_moo_edit_do_popup (MOO_EDIT (widget), event);
|
||||
return TRUE;
|
||||
}
|
||||
else if (event->button == 2 || event->button == 3)
|
||||
{
|
||||
return parent_class()->button_press_event (widget, event);
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
g_warning ("got button %d in button_press callback", event->button);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -898,6 +898,22 @@ static void update_window_title (MooEditWindow *window)
|
|||
}
|
||||
|
||||
|
||||
MooEditWindow *
|
||||
moo_edit_get_window (MooEdit *edit)
|
||||
{
|
||||
GtkWidget *toplevel;
|
||||
|
||||
g_return_val_if_fail (MOO_IS_EDIT (edit), NULL);
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (edit));
|
||||
|
||||
if (MOO_IS_EDIT_WINDOW (toplevel))
|
||||
return MOO_EDIT_WINDOW (toplevel);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Actions
|
||||
*/
|
||||
|
@ -1307,8 +1323,9 @@ _moo_edit_window_insert_doc (MooEditWindow *window,
|
|||
}
|
||||
|
||||
|
||||
void _moo_edit_window_remove_doc (MooEditWindow *window,
|
||||
MooEdit *doc)
|
||||
void
|
||||
_moo_edit_window_remove_doc (MooEditWindow *window,
|
||||
MooEdit *doc)
|
||||
{
|
||||
int page;
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ void moo_edit_window_remove_action_check (const char *action_id,
|
|||
MooEdit *moo_edit_window_get_active_doc (MooEditWindow *window);
|
||||
void moo_edit_window_set_active_doc (MooEditWindow *window,
|
||||
MooEdit *edit);
|
||||
MooEditWindow *moo_edit_get_window (MooEdit *edit);
|
||||
|
||||
GSList *moo_edit_window_list_docs (MooEditWindow *window);
|
||||
guint moo_edit_window_num_docs (MooEditWindow *window);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "mooedit/mooeditwindow.h"
|
||||
#include "mooedit/mooedit-script.h"
|
||||
#include "mooedit/moocmdview.h"
|
||||
#include "mooedit/mooedit-actions.h"
|
||||
#include "mooutils/mooutils-misc.h"
|
||||
#include "mooutils/mooconfig.h"
|
||||
#include "mooutils/moocommand.h"
|
||||
|
@ -22,6 +23,11 @@
|
|||
#include <string.h>
|
||||
|
||||
|
||||
typedef enum {
|
||||
FILE_TOOLS,
|
||||
FILE_MENU
|
||||
} FileType;
|
||||
|
||||
typedef enum {
|
||||
ACTION_NEED_DOC = 1 << 0,
|
||||
ACTION_NEED_FILE = 1 << 1,
|
||||
|
@ -40,20 +46,30 @@ typedef struct {
|
|||
MooUIXML *xml;
|
||||
guint merge_id;
|
||||
|
||||
FileType type;
|
||||
ActionOptions options;
|
||||
} ActionData;
|
||||
|
||||
static GSList *actions;
|
||||
static GSList *tools_actions;
|
||||
static GSList *menu_actions;
|
||||
|
||||
|
||||
static void remove_actions (void);
|
||||
static void load_file (const char *file,
|
||||
static void remove_tools (void);
|
||||
static void remove_menu_actions (void);
|
||||
|
||||
static void load_file (FileType type,
|
||||
const char *file,
|
||||
MooUIXML *xml,
|
||||
const char *ui_path);
|
||||
static void load_config_item (MooConfigItem *item,
|
||||
const char *ui_path1,
|
||||
const char *ui_path2);
|
||||
static void load_config_item (FileType type,
|
||||
MooConfigItem *item,
|
||||
MooUIXML *xml,
|
||||
const char *ui_path);
|
||||
static MooAction *create_action (MooWindow *window,
|
||||
const char *ui_path1,
|
||||
const char *ui_path2);
|
||||
static MooAction *create_tool_action (MooWindow *window,
|
||||
gpointer user_data);
|
||||
static MooAction *create_edit_action (MooEdit *edit,
|
||||
gpointer user_data);
|
||||
|
||||
static void check_visible_func (MooAction *action,
|
||||
|
@ -67,7 +83,8 @@ static void check_sensitive_func(MooAction *action,
|
|||
GValue *prop_value,
|
||||
gpointer dummy);
|
||||
|
||||
static ActionData *action_data_new (const char *name,
|
||||
static ActionData *action_data_new (FileType type,
|
||||
const char *name,
|
||||
const char *label,
|
||||
const char *accel,
|
||||
GSList *langs,
|
||||
|
@ -76,15 +93,25 @@ static ActionData *action_data_new (const char *name,
|
|||
static void action_data_free (ActionData *data);
|
||||
|
||||
|
||||
char **
|
||||
moo_edit_get_user_tools_files (guint *n_files_p)
|
||||
static char **
|
||||
get_files (FileType type,
|
||||
guint *n_files_p)
|
||||
{
|
||||
guint n_files, i;
|
||||
char **files;
|
||||
GSList *list = NULL;
|
||||
|
||||
files = moo_get_data_files (MOO_USER_TOOLS_FILE,
|
||||
MOO_DATA_SHARE, &n_files);
|
||||
switch (type)
|
||||
{
|
||||
case FILE_TOOLS:
|
||||
files = moo_get_data_files (MOO_USER_TOOLS_FILE,
|
||||
MOO_DATA_SHARE, &n_files);
|
||||
break;
|
||||
case FILE_MENU:
|
||||
files = moo_get_data_files (MOO_USER_MENU_FILE,
|
||||
MOO_DATA_SHARE, &n_files);
|
||||
break;
|
||||
}
|
||||
|
||||
if (n_files)
|
||||
{
|
||||
|
@ -103,8 +130,17 @@ moo_edit_get_user_tools_files (guint *n_files_p)
|
|||
g_strfreev (files);
|
||||
|
||||
|
||||
files = moo_get_data_files (MOO_USER_TOOLS_ADD_FILE,
|
||||
MOO_DATA_SHARE, &n_files);
|
||||
switch (type)
|
||||
{
|
||||
case FILE_TOOLS:
|
||||
files = moo_get_data_files (MOO_USER_TOOLS_ADD_FILE,
|
||||
MOO_DATA_SHARE, &n_files);
|
||||
break;
|
||||
case FILE_MENU:
|
||||
files = moo_get_data_files (MOO_USER_MENU_ADD_FILE,
|
||||
MOO_DATA_SHARE, &n_files);
|
||||
break;
|
||||
}
|
||||
|
||||
if (n_files)
|
||||
{
|
||||
|
@ -138,6 +174,20 @@ moo_edit_get_user_tools_files (guint *n_files_p)
|
|||
}
|
||||
|
||||
|
||||
char **
|
||||
moo_edit_get_user_tools_files (guint *n_files_p)
|
||||
{
|
||||
return get_files (FILE_TOOLS, n_files_p);
|
||||
}
|
||||
|
||||
|
||||
char **
|
||||
moo_edit_get_user_menu_files (guint *n_files_p)
|
||||
{
|
||||
return get_files (FILE_MENU, n_files_p);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moo_edit_load_user_tools (char **files,
|
||||
guint n_files,
|
||||
|
@ -151,17 +201,40 @@ moo_edit_load_user_tools (char **files,
|
|||
|
||||
g_return_if_fail (files || !n_files);
|
||||
|
||||
remove_actions ();
|
||||
remove_tools ();
|
||||
|
||||
for (i = 0; i < n_files; ++i)
|
||||
load_file (files[i], xml, ui_path);
|
||||
load_file (FILE_TOOLS, files[i], xml, ui_path, NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moo_edit_load_user_menu (char **files,
|
||||
guint n_files,
|
||||
MooUIXML *xml,
|
||||
const char *start_path,
|
||||
const char *end_path)
|
||||
{
|
||||
guint i;
|
||||
|
||||
if (!n_files)
|
||||
return;
|
||||
|
||||
g_return_if_fail (files || !n_files);
|
||||
|
||||
remove_menu_actions ();
|
||||
|
||||
for (i = 0; i < n_files; ++i)
|
||||
load_file (FILE_MENU, files[i], xml, start_path, end_path);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
load_file (const char *file,
|
||||
MooUIXML *xml,
|
||||
const char *ui_path)
|
||||
load_file (FileType type,
|
||||
const char *file,
|
||||
MooUIXML *xml,
|
||||
const char *ui_path1,
|
||||
const char *ui_path2)
|
||||
{
|
||||
MooConfig *config;
|
||||
guint n_items, i;
|
||||
|
@ -174,7 +247,8 @@ load_file (const char *file,
|
|||
n_items = moo_config_n_items (config);
|
||||
|
||||
for (i = 0; i < n_items; ++i)
|
||||
load_config_item (moo_config_nth_item (config, i), xml, ui_path);
|
||||
load_config_item (type, moo_config_nth_item (config, i),
|
||||
xml, ui_path1, ui_path2);
|
||||
|
||||
moo_config_free (config);
|
||||
}
|
||||
|
@ -276,22 +350,25 @@ config_item_get_options (MooConfigItem *item)
|
|||
|
||||
|
||||
static void
|
||||
load_config_item (MooConfigItem *item,
|
||||
load_config_item (FileType type,
|
||||
MooConfigItem *item,
|
||||
MooUIXML *xml,
|
||||
const char *ui_path)
|
||||
const char *ui_path1,
|
||||
const char *ui_path2)
|
||||
{
|
||||
MooCommand *cmd;
|
||||
ActionData *data;
|
||||
ActionOptions options;
|
||||
GSList *langs;
|
||||
const char *name, *label, *accel;
|
||||
MooWindowClass *klass;
|
||||
const char *name, *label, *accel, *pos;
|
||||
gpointer klass;
|
||||
|
||||
g_return_if_fail (item != NULL);
|
||||
|
||||
name = moo_config_item_get_value (item, "action");
|
||||
label = moo_config_item_get_value (item, "label");
|
||||
accel = moo_config_item_get_value (item, "accel");
|
||||
pos = moo_config_item_get_value (item, "position");
|
||||
g_return_if_fail (name != NULL);
|
||||
|
||||
cmd = config_item_get_command (item);
|
||||
|
@ -300,40 +377,74 @@ load_config_item (MooConfigItem *item,
|
|||
options = config_item_get_options (item);
|
||||
langs = config_item_get_langs (item);
|
||||
|
||||
data = action_data_new (name, label, accel, langs, cmd, options);
|
||||
data = action_data_new (type, name, label, accel, langs, cmd, options);
|
||||
g_return_if_fail (data != NULL);
|
||||
|
||||
klass = g_type_class_ref (MOO_TYPE_EDIT_WINDOW);
|
||||
switch (type)
|
||||
{
|
||||
case FILE_TOOLS:
|
||||
klass = g_type_class_ref (MOO_TYPE_EDIT_WINDOW);
|
||||
|
||||
moo_window_class_new_action_custom (klass, data->id,
|
||||
create_action, data,
|
||||
(GDestroyNotify) action_data_free);
|
||||
moo_window_class_new_action_custom (klass, data->id,
|
||||
create_tool_action, data,
|
||||
(GDestroyNotify) action_data_free);
|
||||
|
||||
if (data->langs)
|
||||
moo_edit_window_add_action_check (data->id, "visible",
|
||||
check_visible_func,
|
||||
NULL, NULL);
|
||||
if (data->options)
|
||||
moo_edit_window_add_action_check (data->id, "sensitive",
|
||||
check_sensitive_func,
|
||||
NULL, NULL);
|
||||
if (data->langs)
|
||||
moo_edit_window_add_action_check (data->id, "visible",
|
||||
check_visible_func,
|
||||
NULL, NULL);
|
||||
if (data->options)
|
||||
moo_edit_window_add_action_check (data->id, "sensitive",
|
||||
check_sensitive_func,
|
||||
NULL, NULL);
|
||||
|
||||
g_type_class_unref (klass);
|
||||
break;
|
||||
|
||||
case FILE_MENU:
|
||||
klass = g_type_class_ref (MOO_TYPE_EDIT);
|
||||
moo_edit_class_new_action_custom (klass, data->id,
|
||||
create_edit_action, data,
|
||||
(GDestroyNotify) action_data_free);
|
||||
g_type_class_unref (klass);
|
||||
break;
|
||||
}
|
||||
|
||||
if (xml)
|
||||
{
|
||||
const char *ui_path = ui_path1;
|
||||
char *markup = g_markup_printf_escaped ("<item action=\"%s\"/>",
|
||||
data->id);
|
||||
data->xml = g_object_ref (xml);
|
||||
data->merge_id = moo_ui_xml_new_merge_id (xml);
|
||||
|
||||
if (type == FILE_MENU)
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
char *c = g_ascii_strdown (pos, -1);
|
||||
|
||||
if (!strcmp (c, "end"))
|
||||
ui_path = ui_path2;
|
||||
|
||||
g_free (c);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui_path = ui_path2;
|
||||
}
|
||||
}
|
||||
|
||||
moo_ui_xml_insert_markup (xml, data->merge_id, ui_path, -1, markup);
|
||||
g_free (markup);
|
||||
}
|
||||
|
||||
g_type_class_unref (klass);
|
||||
}
|
||||
|
||||
|
||||
static ActionData *
|
||||
action_data_new (const char *name,
|
||||
action_data_new (FileType type,
|
||||
const char *name,
|
||||
const char *label,
|
||||
const char *accel,
|
||||
GSList *langs,
|
||||
|
@ -347,6 +458,7 @@ action_data_new (const char *name,
|
|||
|
||||
data = g_new0 (ActionData, 1);
|
||||
|
||||
data->type = type;
|
||||
data->id = g_strdup (name);
|
||||
data->name = g_strdup (name);
|
||||
data->label = label ? g_strdup (label) : g_strdup (name);
|
||||
|
@ -358,7 +470,15 @@ action_data_new (const char *name,
|
|||
if (options & ACTION_SILENT)
|
||||
moo_command_add_flags (cmd, MOO_COMMAND_SILENT);
|
||||
|
||||
actions = g_slist_prepend (actions, data);
|
||||
switch (type)
|
||||
{
|
||||
case FILE_TOOLS:
|
||||
tools_actions = g_slist_prepend (tools_actions, data);
|
||||
break;
|
||||
case FILE_MENU:
|
||||
menu_actions = g_slist_prepend (menu_actions, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
@ -369,13 +489,7 @@ action_data_free (ActionData *data)
|
|||
{
|
||||
if (data)
|
||||
{
|
||||
MooWindowClass *klass = g_type_class_ref (MOO_TYPE_EDIT_WINDOW);
|
||||
/* XXX */
|
||||
if (data->langs)
|
||||
moo_edit_window_remove_action_check (data->id, "visible");
|
||||
if (data->options)
|
||||
moo_edit_window_remove_action_check (data->id, "sensitive");
|
||||
g_type_class_unref (klass);
|
||||
gpointer *klass;
|
||||
|
||||
if (data->xml)
|
||||
{
|
||||
|
@ -383,7 +497,23 @@ action_data_free (ActionData *data)
|
|||
g_object_unref (data->xml);
|
||||
}
|
||||
|
||||
actions = g_slist_remove (actions, data);
|
||||
switch (data->type)
|
||||
{
|
||||
case FILE_TOOLS:
|
||||
tools_actions = g_slist_remove (tools_actions, data);
|
||||
|
||||
klass = g_type_class_ref (MOO_TYPE_EDIT_WINDOW);
|
||||
if (data->langs)
|
||||
moo_edit_window_remove_action_check (data->id, "visible");
|
||||
if (data->options)
|
||||
moo_edit_window_remove_action_check (data->id, "sensitive");
|
||||
g_type_class_unref (klass);
|
||||
break;
|
||||
|
||||
case FILE_MENU:
|
||||
menu_actions = g_slist_remove (menu_actions, data);
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (data->id);
|
||||
g_free (data->name);
|
||||
|
@ -406,12 +536,12 @@ add_id (ActionData *data,
|
|||
}
|
||||
|
||||
static void
|
||||
remove_actions (void)
|
||||
remove_tools (void)
|
||||
{
|
||||
GSList *names = NULL;
|
||||
MooWindowClass *klass = g_type_class_ref (MOO_TYPE_EDIT_WINDOW);
|
||||
|
||||
g_slist_foreach (actions, (GFunc) add_id, &names);
|
||||
g_slist_foreach (tools_actions, (GFunc) add_id, &names);
|
||||
|
||||
while (names)
|
||||
{
|
||||
|
@ -424,21 +554,40 @@ remove_actions (void)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
remove_menu_actions (void)
|
||||
{
|
||||
GSList *names = NULL;
|
||||
MooEditClass *klass = g_type_class_ref (MOO_TYPE_EDIT);
|
||||
|
||||
g_slist_foreach (menu_actions, (GFunc) add_id, &names);
|
||||
|
||||
while (names)
|
||||
{
|
||||
moo_edit_class_remove_action (klass, names->data);
|
||||
g_free (names->data);
|
||||
names = g_slist_delete_link (names, names);
|
||||
}
|
||||
|
||||
g_type_class_unref (klass);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* MooUserToolAction
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
MooAction parent;
|
||||
MooEditAction parent;
|
||||
MooEditWindow *window;
|
||||
ActionData *data;
|
||||
} MooToolAction;
|
||||
|
||||
typedef MooActionClass MooToolActionClass;
|
||||
typedef MooEditActionClass MooToolActionClass;
|
||||
|
||||
GType _moo_tool_action_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_DEFINE_TYPE (MooToolAction, _moo_tool_action, MOO_TYPE_ACTION);
|
||||
G_DEFINE_TYPE (MooToolAction, _moo_tool_action, MOO_TYPE_EDIT_ACTION);
|
||||
#define MOO_IS_TOOL_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, _moo_tool_action_get_type()))
|
||||
#define MOO_TOOL_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, _moo_tool_action_get_type(), MooToolAction))
|
||||
|
||||
|
@ -477,7 +626,8 @@ moo_tool_action_activate (MooAction *_action)
|
|||
action = MOO_TOOL_ACTION (_action);
|
||||
g_return_if_fail (action->data != NULL);
|
||||
|
||||
doc = moo_edit_window_get_active_doc (action->window);
|
||||
doc = MOO_EDIT_ACTION(action)->doc;
|
||||
doc = doc ? doc : moo_edit_window_get_active_doc (action->window);
|
||||
|
||||
if ((action->data->options & ACTION_NEED_DOC) && !doc)
|
||||
return;
|
||||
|
@ -514,9 +664,9 @@ moo_tool_action_activate (MooAction *_action)
|
|||
|
||||
|
||||
static void
|
||||
_moo_tool_action_class_init (MooActionClass *klass)
|
||||
_moo_tool_action_class_init (MooToolActionClass *klass)
|
||||
{
|
||||
klass->activate = moo_tool_action_activate;
|
||||
MOO_ACTION_CLASS(klass)->activate = moo_tool_action_activate;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -526,8 +676,8 @@ _moo_tool_action_init (G_GNUC_UNUSED MooToolAction *action)
|
|||
|
||||
|
||||
static MooAction *
|
||||
create_action (MooWindow *window,
|
||||
gpointer user_data)
|
||||
create_tool_action (MooWindow *window,
|
||||
gpointer user_data)
|
||||
{
|
||||
ActionData *data = user_data;
|
||||
MooToolAction *action;
|
||||
|
@ -547,6 +697,30 @@ create_action (MooWindow *window,
|
|||
}
|
||||
|
||||
|
||||
static MooAction *
|
||||
create_edit_action (MooEdit *edit,
|
||||
gpointer user_data)
|
||||
{
|
||||
ActionData *data = user_data;
|
||||
MooToolAction *action;
|
||||
|
||||
g_return_val_if_fail (MOO_IS_EDIT (edit), NULL);
|
||||
g_return_val_if_fail (data != NULL, NULL);
|
||||
|
||||
action = g_object_new (_moo_tool_action_get_type(),
|
||||
"name", data->name,
|
||||
"label", data->label,
|
||||
"accel", data->accel,
|
||||
"doc", edit,
|
||||
"langs", data->langs,
|
||||
NULL);
|
||||
action->window = moo_edit_get_window (edit);
|
||||
action->data = data;
|
||||
|
||||
return MOO_ACTION (action);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
check_visible_func (MooAction *_action,
|
||||
MooEdit *doc,
|
||||
|
|
|
@ -21,6 +21,8 @@ G_BEGIN_DECLS
|
|||
|
||||
#define MOO_USER_TOOLS_FILE "tools.cfg"
|
||||
#define MOO_USER_TOOLS_ADD_FILE "tools-add.cfg"
|
||||
#define MOO_USER_MENU_FILE "menu.cfg"
|
||||
#define MOO_USER_MENU_ADD_FILE "menu-add.cfg"
|
||||
|
||||
|
||||
char **moo_edit_get_user_tools_files (guint *n_files);
|
||||
|
@ -29,6 +31,13 @@ void moo_edit_load_user_tools (char **files,
|
|||
MooUIXML *xml,
|
||||
const char *ui_path);
|
||||
|
||||
char **moo_edit_get_user_menu_files (guint *n_files);
|
||||
void moo_edit_load_user_menu (char **files,
|
||||
guint n_files,
|
||||
MooUIXML *xml,
|
||||
const char *start_path,
|
||||
const char *end_path);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -138,29 +138,15 @@ moo_closure_signal_call (MooClosure *cl)
|
|||
|
||||
if (!closure->proxy)
|
||||
{
|
||||
GValue ret_val;
|
||||
|
||||
if (closure->ret_type != G_TYPE_NONE)
|
||||
{
|
||||
ret_val.g_type = 0;
|
||||
g_value_init (&ret_val, closure->ret_type);
|
||||
}
|
||||
|
||||
g_object_ref (closure->object->target);
|
||||
g_signal_emit (closure->object->target, closure->signal_id, 0);
|
||||
g_object_unref (closure->object->target);
|
||||
|
||||
if (closure->ret_type != G_TYPE_NONE)
|
||||
g_value_unset (&ret_val);
|
||||
gboolean ret;
|
||||
g_signal_emit (closure->object->target, closure->signal_id, 0, &ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
gboolean ret;
|
||||
gpointer object = closure->proxy (closure->object->target);
|
||||
g_return_if_fail (object != NULL);
|
||||
g_object_ref (object);
|
||||
g_signal_emit_by_name (object, closure->signal, &ret);
|
||||
g_object_unref (object);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,6 +127,25 @@
|
|||
|
||||
</widget> <!-- Toolbar -->
|
||||
|
||||
<widget name="Popup">
|
||||
<separator/>
|
||||
<placeholder name="PopupStart"/>
|
||||
<separator/>
|
||||
<item action="Undo"/>
|
||||
<item action="Redo"/>
|
||||
<separator/>
|
||||
<item action="Cut"/>
|
||||
<item action="Copy"/>
|
||||
<item action="Paste"/>
|
||||
<separator/>
|
||||
<item action="SelectAll"/>
|
||||
<separator/>
|
||||
<item action="BookmarksMenu"/>
|
||||
<separator/>
|
||||
<placeholder name="PopupEnd"/>
|
||||
<separator/>
|
||||
</widget> <!-- Popup -->
|
||||
|
||||
</object> <!-- Editor -->
|
||||
|
||||
<object name="Terminal">
|
||||
|
|
Loading…
Reference in New Issue