Generic Cut/Copy/Paste/Delete/Select All/Undo/Redo actions
parent
3b3d54f1ed
commit
8c65b775fa
|
@ -8,12 +8,6 @@
|
|||
#define MOO_EDIT_ACCEL_SAVE MOO_ACCEL_SAVE
|
||||
#define MOO_EDIT_ACCEL_SAVE_AS MOO_ACCEL_SAVE_AS
|
||||
#define MOO_EDIT_ACCEL_CLOSE MOO_ACCEL_CLOSE
|
||||
#define MOO_EDIT_ACCEL_UNDO MOO_ACCEL_UNDO
|
||||
#define MOO_EDIT_ACCEL_REDO MOO_ACCEL_REDO
|
||||
#define MOO_EDIT_ACCEL_CUT MOO_ACCEL_CUT
|
||||
#define MOO_EDIT_ACCEL_COPY MOO_ACCEL_COPY
|
||||
#define MOO_EDIT_ACCEL_PASTE MOO_ACCEL_PASTE
|
||||
#define MOO_EDIT_ACCEL_SELECT_ALL MOO_ACCEL_SELECT_ALL
|
||||
#define MOO_EDIT_ACCEL_PAGE_SETUP MOO_ACCEL_PAGE_SETUP
|
||||
#define MOO_EDIT_ACCEL_PRINT MOO_ACCEL_PRINT
|
||||
|
||||
|
|
|
@ -265,11 +265,7 @@ enum {
|
|||
/* aux properties */
|
||||
PROP_CAN_RELOAD,
|
||||
PROP_HAS_OPEN_DOCUMENT,
|
||||
PROP_CAN_UNDO,
|
||||
PROP_CAN_REDO,
|
||||
PROP_HAS_SELECTION,
|
||||
PROP_HAS_COMMENTS,
|
||||
PROP_HAS_TEXT,
|
||||
PROP_HAS_JOBS_RUNNING,
|
||||
PROP_HAS_STOP_CLIENTS
|
||||
};
|
||||
|
@ -358,11 +354,7 @@ moo_edit_window_class_init (MooEditWindowClass *klass)
|
|||
|
||||
INSTALL_PROP (PROP_CAN_RELOAD, "can-reload");
|
||||
INSTALL_PROP (PROP_HAS_OPEN_DOCUMENT, "has-open-document");
|
||||
INSTALL_PROP (PROP_CAN_UNDO, "can-undo");
|
||||
INSTALL_PROP (PROP_CAN_REDO, "can-redo");
|
||||
INSTALL_PROP (PROP_HAS_SELECTION, "has-selection");
|
||||
INSTALL_PROP (PROP_HAS_COMMENTS, "has-comments");
|
||||
INSTALL_PROP (PROP_HAS_TEXT, "has-text");
|
||||
INSTALL_PROP (PROP_HAS_JOBS_RUNNING, "has-jobs-running");
|
||||
INSTALL_PROP (PROP_HAS_STOP_CLIENTS, "has-stop-clients");
|
||||
|
||||
|
@ -443,81 +435,6 @@ moo_edit_window_class_init (MooEditWindowClass *klass)
|
|||
"condition::sensitive", "has-open-document",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (window_class, "Undo", NULL,
|
||||
"display-name", GTK_STOCK_UNDO,
|
||||
"label", GTK_STOCK_UNDO,
|
||||
"tooltip", GTK_STOCK_UNDO,
|
||||
"stock-id", GTK_STOCK_UNDO,
|
||||
"accel", MOO_EDIT_ACCEL_UNDO,
|
||||
"closure-signal", "undo",
|
||||
"closure-proxy-func", moo_edit_window_get_active_doc,
|
||||
"condition::sensitive", "can-undo",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (window_class, "Redo", NULL,
|
||||
"display-name", GTK_STOCK_REDO,
|
||||
"label", GTK_STOCK_REDO,
|
||||
"tooltip", GTK_STOCK_REDO,
|
||||
"stock-id", GTK_STOCK_REDO,
|
||||
"accel", MOO_EDIT_ACCEL_REDO,
|
||||
"closure-signal", "redo",
|
||||
"closure-proxy-func", moo_edit_window_get_active_doc,
|
||||
"condition::sensitive", "can-redo",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (window_class, "Cut", NULL,
|
||||
"display-name", GTK_STOCK_CUT,
|
||||
"label", GTK_STOCK_CUT,
|
||||
"tooltip", GTK_STOCK_CUT,
|
||||
"stock-id", GTK_STOCK_CUT,
|
||||
"accel", MOO_EDIT_ACCEL_CUT,
|
||||
"closure-signal", "cut-clipboard",
|
||||
"closure-proxy-func", moo_edit_window_get_active_doc,
|
||||
"condition::sensitive", "has-selection",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (window_class, "Copy", NULL,
|
||||
"display-name", GTK_STOCK_COPY,
|
||||
"label", GTK_STOCK_COPY,
|
||||
"tooltip", GTK_STOCK_COPY,
|
||||
"stock-id", GTK_STOCK_COPY,
|
||||
"accel", MOO_EDIT_ACCEL_COPY,
|
||||
"closure-signal", "copy-clipboard",
|
||||
"closure-proxy-func", moo_edit_window_get_active_doc,
|
||||
"condition::sensitive", "has-selection",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (window_class, "Paste", NULL,
|
||||
"display-name", GTK_STOCK_PASTE,
|
||||
"label", GTK_STOCK_PASTE,
|
||||
"tooltip", GTK_STOCK_PASTE,
|
||||
"stock-id", GTK_STOCK_PASTE,
|
||||
"accel", MOO_EDIT_ACCEL_PASTE,
|
||||
"closure-signal", "paste-clipboard",
|
||||
"closure-proxy-func", moo_edit_window_get_active_doc,
|
||||
"condition::sensitive", "has-open-document",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (window_class, "Delete", NULL,
|
||||
"display-name", GTK_STOCK_DELETE,
|
||||
"label", GTK_STOCK_DELETE,
|
||||
"tooltip", GTK_STOCK_DELETE,
|
||||
"stock-id", GTK_STOCK_DELETE,
|
||||
"closure-signal", "delete-selection",
|
||||
"closure-proxy-func", moo_edit_window_get_active_doc,
|
||||
"condition::sensitive", "has-selection",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (window_class, "SelectAll", NULL,
|
||||
"display-name", GTK_STOCK_SELECT_ALL,
|
||||
"label", GTK_STOCK_SELECT_ALL,
|
||||
"tooltip", GTK_STOCK_SELECT_ALL,
|
||||
"accel", MOO_EDIT_ACCEL_SELECT_ALL,
|
||||
"closure-callback", moo_text_view_select_all,
|
||||
"closure-proxy-func", moo_edit_window_get_active_doc,
|
||||
"condition::sensitive", "has-text",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (window_class, "PreviousTab", NULL,
|
||||
"display-name", _("Previous Tab"),
|
||||
"label", _("_Previous Tab"),
|
||||
|
@ -963,26 +880,10 @@ static void moo_edit_window_get_property(GObject *object,
|
|||
case PROP_HAS_OPEN_DOCUMENT:
|
||||
g_value_set_boolean (value, ACTIVE_DOC (window) != NULL);
|
||||
break;
|
||||
case PROP_CAN_UNDO:
|
||||
doc = ACTIVE_DOC (window);
|
||||
g_value_set_boolean (value, doc && moo_text_view_can_undo (MOO_TEXT_VIEW (doc)));
|
||||
break;
|
||||
case PROP_CAN_REDO:
|
||||
doc = ACTIVE_DOC (window);
|
||||
g_value_set_boolean (value, doc && moo_text_view_can_redo (MOO_TEXT_VIEW (doc)));
|
||||
break;
|
||||
case PROP_HAS_SELECTION:
|
||||
doc = ACTIVE_DOC (window);
|
||||
g_value_set_boolean (value, doc && moo_text_view_has_selection (MOO_TEXT_VIEW (doc)));
|
||||
break;
|
||||
case PROP_HAS_COMMENTS:
|
||||
doc = ACTIVE_DOC (window);
|
||||
g_value_set_boolean (value, doc && _moo_edit_has_comments (doc, NULL, NULL));
|
||||
break;
|
||||
case PROP_HAS_TEXT:
|
||||
doc = ACTIVE_DOC (window);
|
||||
g_value_set_boolean (value, doc && moo_text_view_has_text (MOO_TEXT_VIEW (doc)));
|
||||
break;
|
||||
case PROP_HAS_JOBS_RUNNING:
|
||||
g_value_set_boolean (value, window->priv->jobs != NULL);
|
||||
break;
|
||||
|
@ -2133,11 +2034,7 @@ edit_changed (MooEditWindow *window,
|
|||
g_object_freeze_notify (G_OBJECT (window));
|
||||
g_object_notify (G_OBJECT (window), "can-reload");
|
||||
g_object_notify (G_OBJECT (window), "has-open-document");
|
||||
g_object_notify (G_OBJECT (window), "can-undo");
|
||||
g_object_notify (G_OBJECT (window), "can-redo");
|
||||
g_object_notify (G_OBJECT (window), "has-selection");
|
||||
g_object_notify (G_OBJECT (window), "has-comments");
|
||||
g_object_notify (G_OBJECT (window), "has-text");
|
||||
g_object_thaw_notify (G_OBJECT (window));
|
||||
|
||||
update_window_title (window);
|
||||
|
@ -2400,16 +2297,8 @@ _moo_edit_window_insert_doc (MooEditWindow *window,
|
|||
G_CALLBACK (edit_show_line_numbers_changed), window);
|
||||
g_signal_connect_swapped (edit, "filename_changed",
|
||||
G_CALLBACK (edit_filename_changed), window);
|
||||
g_signal_connect_swapped (edit, "notify::can-undo",
|
||||
G_CALLBACK (proxy_boolean_property), window);
|
||||
g_signal_connect_swapped (edit, "notify::can-redo",
|
||||
G_CALLBACK (proxy_boolean_property), window);
|
||||
g_signal_connect_swapped (edit, "notify::has-selection",
|
||||
G_CALLBACK (proxy_boolean_property), window);
|
||||
g_signal_connect_swapped (edit, "notify::has-comments",
|
||||
G_CALLBACK (proxy_boolean_property), window);
|
||||
g_signal_connect_swapped (edit, "notify::has-text",
|
||||
G_CALLBACK (proxy_boolean_property), window);
|
||||
g_signal_connect_swapped (edit, "config-notify::lang",
|
||||
G_CALLBACK (edit_lang_changed), window);
|
||||
g_signal_connect_swapped (edit, "cursor-moved",
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "mooutils/moostock.h"
|
||||
#include "mooutils/mooactionfactory.h"
|
||||
#include "mooutils/mooaction-private.h"
|
||||
#include "mooutils/mooeditops.h"
|
||||
#include "marshals.h"
|
||||
#include "mooutils/mooi18n.h"
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
|
@ -425,9 +426,12 @@ static void file_view_cut_clipboard (MooFileView *fileview);
|
|||
static void file_view_copy_clipboard (MooFileView *fileview);
|
||||
static void file_view_paste_clipboard (MooFileView *fileview);
|
||||
|
||||
static void edit_ops_iface_init (MooEditOpsIface *iface);
|
||||
|
||||
/* MOO_TYPE_FILE_VIEW */
|
||||
G_DEFINE_TYPE (MooFileView, moo_file_view, GTK_TYPE_VBOX)
|
||||
G_DEFINE_TYPE_WITH_CODE (MooFileView, moo_file_view, GTK_TYPE_VBOX,
|
||||
G_IMPLEMENT_INTERFACE (MOO_TYPE_EDIT_OPS,
|
||||
edit_ops_iface_init))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
@ -2420,6 +2424,62 @@ moo_file_view_get_home_dir (MooFileView *fileview)
|
|||
/* Clipboard
|
||||
*/
|
||||
|
||||
static void
|
||||
edit_ops_do_op (MooEditOps *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
MooFileView *fileview = MOO_FILE_VIEW (obj);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_CUT:
|
||||
g_signal_emit_by_name (fileview, "cut-clipboard");
|
||||
break;
|
||||
case MOO_EDIT_OP_COPY:
|
||||
g_signal_emit_by_name (fileview, "copy-clipboard");
|
||||
break;
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
g_signal_emit_by_name (fileview, "paste-clipboard");
|
||||
break;
|
||||
case MOO_EDIT_OP_DELETE:
|
||||
g_signal_emit_by_name (fileview, "delete-selected");
|
||||
break;
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
_moo_icon_view_select_all (fileview->priv->iconview);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
edit_ops_can_do_op (MooEditOps *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
MooFileView *fileview = MOO_FILE_VIEW (obj);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_CUT:
|
||||
return !_moo_tree_view_selection_is_empty (fileview->priv->view);
|
||||
case MOO_EDIT_OP_COPY:
|
||||
return !_moo_tree_view_selection_is_empty (fileview->priv->view);
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
return TRUE;
|
||||
case MOO_EDIT_OP_DELETE:
|
||||
return !_moo_tree_view_selection_is_empty (fileview->priv->view);
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
edit_ops_iface_init (MooEditOpsIface *iface)
|
||||
{
|
||||
iface->do_op = edit_ops_do_op;
|
||||
iface->can_do_op = edit_ops_can_do_op;
|
||||
}
|
||||
|
||||
enum {
|
||||
CB_TARGET_CLIPBOARD = 1,
|
||||
CB_TARGET_URI_LIST = 2,
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "mooterm/mooterm-selection.h"
|
||||
#include "mooterm/mootermline-private.h"
|
||||
#include "mooutils/mooutils-misc.h"
|
||||
#include "mooutils/mooeditops.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
|
@ -290,6 +291,13 @@ invalidate_segment (Segment *segm, guint num)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
notify_has_selection (MooTerm *term)
|
||||
{
|
||||
g_object_notify (G_OBJECT (term), "has-selection");
|
||||
moo_edit_ops_can_do_op_changed (G_OBJECT (term), MOO_EDIT_OP_COPY);
|
||||
}
|
||||
|
||||
static void
|
||||
_moo_term_select_range (MooTerm *term,
|
||||
const MooTermIter *start,
|
||||
|
@ -299,12 +307,14 @@ _moo_term_select_range (MooTerm *term,
|
|||
Segment new_sel;
|
||||
Segment old_selection;
|
||||
gboolean inv = FALSE;
|
||||
gboolean had_selection;
|
||||
|
||||
CHECK_ITER (start);
|
||||
CHECK_ITER (end);
|
||||
|
||||
old_selection = *GET_SELECTION (ITER_TERM (start));
|
||||
CHECK_SEGMENT (&old_selection);
|
||||
had_selection = !segment_empty (&old_selection);
|
||||
|
||||
new_sel.start = *start;
|
||||
new_sel.end = *end;
|
||||
|
@ -352,9 +362,19 @@ _moo_term_select_range (MooTerm *term,
|
|||
diff));
|
||||
|
||||
if (_moo_term_selection_empty (term))
|
||||
{
|
||||
_moo_term_release_selection (term);
|
||||
|
||||
if (had_selection)
|
||||
notify_has_selection (term);
|
||||
}
|
||||
else
|
||||
{
|
||||
_moo_term_grab_selection (term);
|
||||
|
||||
if (!had_selection)
|
||||
notify_has_selection (term);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,9 +20,11 @@
|
|||
#include "marshals.h"
|
||||
#include "mooutils/mooutils-misc.h"
|
||||
#include "mooutils/mooutils-debug.h"
|
||||
#include "mooutils/mooeditops.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void moo_term_edit_ops_init (MooEditOpsIface *iface);
|
||||
static void moo_term_class_init (MooTermClass *klass);
|
||||
static void moo_term_init (MooTerm *term);
|
||||
static void moo_term_finalize (GObject *object);
|
||||
|
@ -110,12 +112,15 @@ enum {
|
|||
enum {
|
||||
PROP_0,
|
||||
PROP_CURSOR_BLINKS,
|
||||
PROP_FONT_NAME
|
||||
PROP_FONT_NAME,
|
||||
PROP_HAS_SELECTION
|
||||
};
|
||||
|
||||
|
||||
/* MOO_TYPE_TERM */
|
||||
G_DEFINE_TYPE (MooTerm, moo_term, GTK_TYPE_WIDGET)
|
||||
G_DEFINE_TYPE_WITH_CODE (MooTerm, moo_term, GTK_TYPE_WIDGET,
|
||||
G_IMPLEMENT_INTERFACE (MOO_TYPE_EDIT_OPS,
|
||||
moo_term_edit_ops_init))
|
||||
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
@ -151,21 +156,17 @@ static void moo_term_class_init (MooTermClass *klass)
|
|||
klass->reset = moo_term_reset_real;
|
||||
klass->bell = moo_term_bell_real;
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_CURSOR_BLINKS,
|
||||
g_param_spec_boolean ("cursor-blinks",
|
||||
"cursor-blinks",
|
||||
"cursor-blinks",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (gobject_class, PROP_CURSOR_BLINKS,
|
||||
g_param_spec_boolean ("cursor-blinks", "cursor-blinks", "cursor-blinks",
|
||||
FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_FONT_NAME,
|
||||
g_param_spec_string ("font-name",
|
||||
"font-name",
|
||||
"font-name",
|
||||
DEFAULT_MONOSPACE_FONT,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (gobject_class, PROP_FONT_NAME,
|
||||
g_param_spec_string ("font-name", "font-name", "font-name",
|
||||
DEFAULT_MONOSPACE_FONT, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_object_class_install_property (gobject_class, PROP_HAS_SELECTION,
|
||||
g_param_spec_boolean ("has-selection", "has-selection", "has-selection",
|
||||
FALSE, G_PARAM_READABLE));
|
||||
|
||||
signals[SET_SCROLL_ADJUSTMENTS] =
|
||||
g_signal_new ("set-scroll-adjustments",
|
||||
|
@ -455,11 +456,16 @@ static void moo_term_get_property (GObject *object,
|
|||
{
|
||||
MooTerm *term = MOO_TERM (object);
|
||||
|
||||
switch (prop_id) {
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_CURSOR_BLINKS:
|
||||
g_value_set_boolean (value, term->priv->cursor_blinks);
|
||||
break;
|
||||
|
||||
case PROP_HAS_SELECTION:
|
||||
g_value_set_boolean (value, moo_term_get_selection_bounds (term, NULL, NULL));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -1073,6 +1079,68 @@ moo_term_paste_clipboard (MooTerm *term,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
moo_term_do_edit_op (MooEditOps *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
MooTerm *term;
|
||||
|
||||
g_return_if_fail (MOO_IS_TERM (obj));
|
||||
term = MOO_TERM (obj);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_COPY:
|
||||
moo_term_copy_clipboard (term, GDK_SELECTION_CLIPBOARD);
|
||||
break;
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
moo_term_paste_clipboard (term, GDK_SELECTION_CLIPBOARD);
|
||||
break;
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
moo_term_select_all (term);
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
moo_term_can_do_edit_op (MooEditOps *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
MooTerm *term;
|
||||
|
||||
g_return_val_if_fail (MOO_IS_TERM (obj), FALSE);
|
||||
term = MOO_TERM (obj);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_COPY:
|
||||
return moo_term_get_selection_bounds (term, NULL, NULL);
|
||||
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
return TRUE;
|
||||
|
||||
case MOO_EDIT_OP_CUT:
|
||||
case MOO_EDIT_OP_DELETE:
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (FALSE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
moo_term_edit_ops_init (MooEditOpsIface *iface)
|
||||
{
|
||||
iface->do_op = moo_term_do_edit_op;
|
||||
iface->can_do_op = moo_term_can_do_edit_op;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
process_incoming (MooTerm *term)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,7 @@ mooutils_include_headers = \
|
|||
moobigpaned.h \
|
||||
mooclosure.h \
|
||||
moocombo.h \
|
||||
mooeditops.h \
|
||||
mooentry.h \
|
||||
moofiledialog.h \
|
||||
moofiltermgr.h \
|
||||
|
@ -87,6 +88,7 @@ mooutils_sources = \
|
|||
moocompat.h \
|
||||
moodialogs.c \
|
||||
moodialogs.h \
|
||||
mooeditops.c \
|
||||
mooencodings.c \
|
||||
mooencodings.h \
|
||||
mooencodings-data.h \
|
||||
|
|
|
@ -0,0 +1,449 @@
|
|||
/*
|
||||
* mooeditops.c
|
||||
*
|
||||
* Copyright (C) 2004-2008 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* See COPYING file that comes with this distribution.
|
||||
*/
|
||||
|
||||
#include "mooeditops.h"
|
||||
#include "marshals.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static void
|
||||
moo_edit_ops_class_init (G_GNUC_UNUSED MooEditOpsIface *iface)
|
||||
{
|
||||
g_signal_new ("moo-edit-ops-can-do-op-changed",
|
||||
MOO_TYPE_EDIT_OPS,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
_moo_marshal_VOID__UINT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_UINT);
|
||||
}
|
||||
|
||||
GType
|
||||
moo_edit_ops_get_type (void)
|
||||
{
|
||||
static GType type;
|
||||
|
||||
if (G_UNLIKELY (!type))
|
||||
{
|
||||
GTypeInfo type_info = {
|
||||
sizeof (MooEditOpsIface), /* class_size */
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) moo_edit_ops_class_init, /* class_init */
|
||||
NULL
|
||||
};
|
||||
|
||||
type = g_type_register_static (G_TYPE_INTERFACE, "MooEditOps",
|
||||
&type_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moo_edit_ops_can_do_op_changed (GObject *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
g_return_if_fail (type < MOO_N_EDIT_OPS);
|
||||
g_signal_emit_by_name (obj, "moo-edit-ops-can-do-op-changed", type);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
emit_can_do_op_changed (GObject *obj)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < MOO_N_EDIT_OPS; i++)
|
||||
moo_edit_ops_can_do_op_changed (obj, i);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
editable_do_op (GtkEditable *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_CUT:
|
||||
gtk_editable_cut_clipboard (obj);
|
||||
break;
|
||||
case MOO_EDIT_OP_COPY:
|
||||
gtk_editable_copy_clipboard (obj);
|
||||
break;
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
gtk_editable_paste_clipboard (obj);
|
||||
break;
|
||||
case MOO_EDIT_OP_DELETE:
|
||||
gtk_editable_delete_selection (obj);
|
||||
break;
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
gtk_editable_select_region (obj, 0, -1);
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
entry_can_do_op (GtkEntry *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_CUT:
|
||||
return gtk_editable_get_editable (GTK_EDITABLE (obj)) &&
|
||||
gtk_editable_get_selection_bounds (GTK_EDITABLE (obj), NULL, NULL);
|
||||
case MOO_EDIT_OP_COPY:
|
||||
return gtk_editable_get_selection_bounds (GTK_EDITABLE (obj), NULL, NULL);
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
return gtk_editable_get_editable (GTK_EDITABLE (obj));
|
||||
case MOO_EDIT_OP_DELETE:
|
||||
return gtk_editable_get_selection_bounds (GTK_EDITABLE (obj), NULL, NULL);
|
||||
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
{
|
||||
const char *text = gtk_entry_get_text (obj);
|
||||
return text && text[0];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
entry_connect (GtkEntry *obj)
|
||||
{
|
||||
g_signal_connect (obj, "notify::selection-bound",
|
||||
G_CALLBACK (emit_can_do_op_changed), NULL);
|
||||
g_signal_connect (obj, "notify::text",
|
||||
G_CALLBACK (emit_can_do_op_changed), NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
entry_disconnect (GtkEntry *obj)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (obj, (gpointer) emit_can_do_op_changed, NULL);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
textview_do_op (GtkTextView *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_CUT:
|
||||
g_signal_emit_by_name (obj, "cut-clipboard");
|
||||
break;
|
||||
case MOO_EDIT_OP_COPY:
|
||||
g_signal_emit_by_name (obj, "copy-clipboard");
|
||||
break;
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
g_signal_emit_by_name (obj, "paste-clipboard");
|
||||
break;
|
||||
case MOO_EDIT_OP_DELETE:
|
||||
g_signal_emit_by_name (obj, "delete-from-cursor", GTK_DELETE_CHARS, 1);
|
||||
break;
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
g_signal_emit_by_name (obj, "select-all");
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
textview_can_do_op (GtkTextView *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
GtkTextBuffer *buffer = obj->buffer;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_CUT:
|
||||
return gtk_text_view_get_editable (obj) &&
|
||||
gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL);
|
||||
case MOO_EDIT_OP_COPY:
|
||||
return gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL);
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
return gtk_text_view_get_editable (obj);
|
||||
case MOO_EDIT_OP_DELETE:
|
||||
return gtk_text_buffer_get_selection_bounds (buffer, NULL, NULL);
|
||||
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
return gtk_text_buffer_get_char_count (buffer) != 0;
|
||||
|
||||
default:
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
textview_connect (GtkTextView *obj)
|
||||
{
|
||||
/* XXX */
|
||||
GtkTextBuffer *buffer = obj->buffer;
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
g_signal_connect_swapped (buffer, "notify::has-selection",
|
||||
G_CALLBACK (emit_can_do_op_changed), obj);
|
||||
g_signal_connect_swapped (buffer, "changed",
|
||||
G_CALLBACK (emit_can_do_op_changed), obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
textview_disconnect (GtkTextView *obj)
|
||||
{
|
||||
/* XXX */
|
||||
GtkTextBuffer *buffer = obj->buffer;
|
||||
|
||||
if (buffer)
|
||||
g_signal_handlers_disconnect_by_func (buffer, (gpointer) emit_can_do_op_changed, obj);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_moo_edit_ops_do_op (GObject *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
g_return_if_fail (type < MOO_N_EDIT_OPS);
|
||||
|
||||
if (MOO_IS_EDIT_OPS (obj))
|
||||
{
|
||||
g_return_if_fail (MOO_EDIT_OPS_GET_IFACE (obj)->do_op != NULL);
|
||||
MOO_EDIT_OPS_GET_IFACE (obj)->do_op (MOO_EDIT_OPS (obj), type);
|
||||
}
|
||||
else if (GTK_IS_ENTRY (obj))
|
||||
{
|
||||
editable_do_op (GTK_EDITABLE (obj), type);
|
||||
}
|
||||
else if (GTK_IS_TEXT_VIEW (obj))
|
||||
{
|
||||
textview_do_op (GTK_TEXT_VIEW (obj), type);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_moo_edit_ops_can_do_op (GObject *obj,
|
||||
MooEditOpType type)
|
||||
{
|
||||
g_return_val_if_fail (type < MOO_N_EDIT_OPS, FALSE);
|
||||
|
||||
if (MOO_IS_EDIT_OPS (obj))
|
||||
{
|
||||
g_return_val_if_fail (MOO_EDIT_OPS_GET_IFACE (obj)->can_do_op != NULL, FALSE);
|
||||
return MOO_EDIT_OPS_GET_IFACE (obj)->can_do_op (MOO_EDIT_OPS (obj), type);
|
||||
}
|
||||
else if (GTK_IS_TEXT_VIEW (obj))
|
||||
{
|
||||
return textview_can_do_op (GTK_TEXT_VIEW (obj), type);
|
||||
}
|
||||
else if (GTK_IS_ENTRY (obj))
|
||||
{
|
||||
return entry_can_do_op (GTK_ENTRY (obj), type);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_moo_edit_ops_connect (GObject *obj)
|
||||
{
|
||||
if (!MOO_IS_EDIT_OPS (obj))
|
||||
{
|
||||
if (GTK_IS_TEXT_VIEW (obj))
|
||||
textview_connect (GTK_TEXT_VIEW (obj));
|
||||
else if (GTK_IS_ENTRY (obj))
|
||||
entry_connect (GTK_ENTRY (obj));
|
||||
else
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_moo_edit_ops_disconnect (GObject *obj)
|
||||
{
|
||||
if (!MOO_IS_EDIT_OPS (obj))
|
||||
{
|
||||
if (GTK_IS_TEXT_VIEW (obj))
|
||||
textview_disconnect (GTK_TEXT_VIEW (obj));
|
||||
else if (GTK_IS_ENTRY (obj))
|
||||
entry_disconnect (GTK_ENTRY (obj));
|
||||
else
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_moo_edit_ops_check (GObject *obj)
|
||||
{
|
||||
return MOO_IS_EDIT_OPS (obj) ||
|
||||
GTK_IS_TEXT_VIEW (obj) ||
|
||||
GTK_IS_ENTRY (obj);
|
||||
}
|
||||
|
||||
void
|
||||
_moo_edit_ops_iface_install (void)
|
||||
{
|
||||
static gboolean been_here;
|
||||
|
||||
if (!been_here)
|
||||
{
|
||||
g_signal_new ("moo-edit-ops-can-do-op-changed",
|
||||
GTK_TYPE_TEXT_VIEW,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
_moo_marshal_VOID__UINT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_UINT);
|
||||
g_signal_new ("moo-edit-ops-can-do-op-changed",
|
||||
GTK_TYPE_ENTRY,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
_moo_marshal_VOID__UINT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_UINT);
|
||||
been_here = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* MooUndoOps
|
||||
*/
|
||||
|
||||
static void
|
||||
moo_undo_ops_class_init (G_GNUC_UNUSED MooUndoOpsIface *iface)
|
||||
{
|
||||
g_signal_new ("moo-undo-ops-can-undo-changed",
|
||||
MOO_TYPE_EDIT_OPS,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
_moo_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
g_signal_new ("moo-undo-ops-can-redo-changed",
|
||||
MOO_TYPE_EDIT_OPS,
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0, NULL, NULL,
|
||||
_moo_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
GType
|
||||
moo_undo_ops_get_type (void)
|
||||
{
|
||||
static GType type;
|
||||
|
||||
if (G_UNLIKELY (!type))
|
||||
{
|
||||
GTypeInfo type_info = {
|
||||
sizeof (MooEditOpsIface), NULL, NULL,
|
||||
(GClassInitFunc) moo_undo_ops_class_init,
|
||||
NULL
|
||||
};
|
||||
|
||||
type = g_type_register_static (G_TYPE_INTERFACE, "MooUndoOps",
|
||||
&type_info, 0);
|
||||
|
||||
g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
moo_undo_ops_can_undo_changed (GObject *obj)
|
||||
{
|
||||
g_signal_emit_by_name (obj, "moo-edit-ops-can-undo-changed");
|
||||
}
|
||||
|
||||
void
|
||||
moo_undo_ops_can_redo_changed (GObject *obj)
|
||||
{
|
||||
g_signal_emit_by_name (obj, "moo-edit-ops-can-redo-changed");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_moo_undo_ops_undo (GObject *obj)
|
||||
{
|
||||
if (MOO_IS_UNDO_OPS (obj))
|
||||
{
|
||||
g_return_if_fail (MOO_UNDO_OPS_GET_IFACE (obj)->undo != NULL);
|
||||
MOO_UNDO_OPS_GET_IFACE (obj)->undo (MOO_UNDO_OPS (obj));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_moo_undo_ops_redo (GObject *obj)
|
||||
{
|
||||
if (MOO_IS_UNDO_OPS (obj))
|
||||
{
|
||||
g_return_if_fail (MOO_UNDO_OPS_GET_IFACE (obj)->redo != NULL);
|
||||
MOO_UNDO_OPS_GET_IFACE (obj)->redo (MOO_UNDO_OPS (obj));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_moo_undo_ops_can_undo (GObject *obj)
|
||||
{
|
||||
if (MOO_IS_UNDO_OPS (obj))
|
||||
{
|
||||
g_return_val_if_fail (MOO_UNDO_OPS_GET_IFACE (obj)->can_undo != NULL, FALSE);
|
||||
return MOO_UNDO_OPS_GET_IFACE (obj)->can_undo (MOO_UNDO_OPS (obj));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_moo_undo_ops_can_redo (GObject *obj)
|
||||
{
|
||||
if (MOO_IS_UNDO_OPS (obj))
|
||||
{
|
||||
g_return_val_if_fail (MOO_UNDO_OPS_GET_IFACE (obj)->can_redo != NULL, FALSE);
|
||||
return MOO_UNDO_OPS_GET_IFACE (obj)->can_redo (MOO_UNDO_OPS (obj));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_moo_undo_ops_check (GObject *obj)
|
||||
{
|
||||
return MOO_IS_UNDO_OPS (obj);
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* mooeditops.h
|
||||
*
|
||||
* Copyright (C) 2004-2008 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation.
|
||||
*
|
||||
* See COPYING file that comes with this distribution.
|
||||
*/
|
||||
|
||||
#ifndef MOO_EDIT_OPS_H
|
||||
#define MOO_EDIT_OPS_H
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
#define MOO_TYPE_EDIT_OPS (moo_edit_ops_get_type ())
|
||||
#define MOO_EDIT_OPS(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_EDIT_OPS, MooEditOps))
|
||||
#define MOO_IS_EDIT_OPS(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_EDIT_OPS))
|
||||
#define MOO_EDIT_OPS_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MOO_TYPE_EDIT_OPS, MooEditOpsIface))
|
||||
|
||||
#define MOO_TYPE_UNDO_OPS (moo_undo_ops_get_type ())
|
||||
#define MOO_UNDO_OPS(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_UNDO_OPS, MooUndoOps))
|
||||
#define MOO_IS_UNDO_OPS(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOO_TYPE_UNDO_OPS))
|
||||
#define MOO_UNDO_OPS_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MOO_TYPE_UNDO_OPS, MooUndoOpsIface))
|
||||
|
||||
typedef struct MooEditOps MooEditOps;
|
||||
typedef struct MooEditOpsIface MooEditOpsIface;
|
||||
typedef struct MooUndoOps MooUndoOps;
|
||||
typedef struct MooUndoOpsIface MooUndoOpsIface;
|
||||
|
||||
typedef enum {
|
||||
MOO_EDIT_OP_CUT,
|
||||
MOO_EDIT_OP_COPY,
|
||||
MOO_EDIT_OP_PASTE,
|
||||
MOO_EDIT_OP_DELETE,
|
||||
MOO_EDIT_OP_SELECT_ALL
|
||||
} MooEditOpType;
|
||||
|
||||
#define MOO_N_EDIT_OPS (MOO_EDIT_OP_SELECT_ALL+1)
|
||||
|
||||
struct MooEditOpsIface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
void (*do_op) (MooEditOps *obj,
|
||||
MooEditOpType type);
|
||||
gboolean (*can_do_op) (MooEditOps *obj,
|
||||
MooEditOpType type);
|
||||
};
|
||||
|
||||
struct MooUndoOpsIface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
void (*undo) (MooUndoOps *obj);
|
||||
void (*redo) (MooUndoOps *obj);
|
||||
gboolean (*can_undo) (MooUndoOps *obj);
|
||||
gboolean (*can_redo) (MooUndoOps *obj);
|
||||
};
|
||||
|
||||
GType moo_edit_ops_get_type (void) G_GNUC_CONST;
|
||||
GType moo_undo_ops_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void _moo_edit_ops_do_op (GObject *obj,
|
||||
MooEditOpType type);
|
||||
gboolean _moo_edit_ops_can_do_op (GObject *obj,
|
||||
MooEditOpType type);
|
||||
void moo_edit_ops_can_do_op_changed (GObject *obj,
|
||||
MooEditOpType type);
|
||||
|
||||
gboolean _moo_edit_ops_check (GObject *obj);
|
||||
void _moo_edit_ops_iface_install (void);
|
||||
void _moo_edit_ops_connect (GObject *obj);
|
||||
void _moo_edit_ops_disconnect (GObject *obj);
|
||||
|
||||
void _moo_undo_ops_undo (GObject *obj);
|
||||
void _moo_undo_ops_redo (GObject *obj);
|
||||
gboolean _moo_undo_ops_can_undo (GObject *obj);
|
||||
gboolean _moo_undo_ops_can_redo (GObject *obj);
|
||||
void moo_undo_ops_can_undo_changed (GObject *obj);
|
||||
void moo_undo_ops_can_redo_changed (GObject *obj);
|
||||
gboolean _moo_undo_ops_check (GObject *obj);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* MOO_EDIT_OPS_H */
|
|
@ -23,6 +23,7 @@
|
|||
#include "mooutils/mooi18n.h"
|
||||
#include "mooutils/mooutils-misc.h"
|
||||
#include "mooutils/mooutils-mem.h"
|
||||
#include "mooutils/mooeditops.h"
|
||||
#include <gtk/gtk.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
|
@ -56,6 +57,11 @@ struct _MooWindowPrivate {
|
|||
char *name;
|
||||
char *id;
|
||||
|
||||
GtkWidget *eo_widget;
|
||||
GtkWidget *default_eo_widget;
|
||||
GtkWidget *uo_widget;
|
||||
GtkWidget *default_uo_widget;
|
||||
|
||||
guint global_accels : 1;
|
||||
};
|
||||
|
||||
|
@ -125,6 +131,18 @@ static void moo_window_set_toolbar_visible (MooWindow *window,
|
|||
static GtkAction *create_toolbar_style_action (MooWindow *window,
|
||||
gpointer dummy);
|
||||
|
||||
static void moo_window_set_focus (GtkWindow *window,
|
||||
GtkWidget *widget);
|
||||
static void moo_window_disconnect_eo_widget (MooWindow *window);
|
||||
static void moo_window_disconnect_uo_widget (MooWindow *window);
|
||||
static void moo_window_action_cut (MooWindow *window);
|
||||
static void moo_window_action_copy (MooWindow *window);
|
||||
static void moo_window_action_paste (MooWindow *window);
|
||||
static void moo_window_action_delete (MooWindow *window);
|
||||
static void moo_window_action_select_all (MooWindow *window);
|
||||
static void moo_window_action_undo (MooWindow *window);
|
||||
static void moo_window_action_redo (MooWindow *window);
|
||||
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
@ -135,7 +153,16 @@ enum {
|
|||
PROP_UI_XML,
|
||||
PROP_ACTIONS,
|
||||
PROP_TOOLBAR_VISIBLE,
|
||||
PROP_MENUBAR_VISIBLE
|
||||
PROP_MENUBAR_VISIBLE,
|
||||
|
||||
PROP_MEO_CAN_CUT,
|
||||
PROP_MEO_CAN_COPY,
|
||||
PROP_MEO_CAN_PASTE,
|
||||
PROP_MEO_CAN_SELECT_ALL,
|
||||
PROP_MEO_CAN_DELETE,
|
||||
|
||||
PROP_MUO_CAN_UNDO,
|
||||
PROP_MUO_CAN_REDO
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -152,11 +179,16 @@ G_DEFINE_TYPE (MooWindow, moo_window, GTK_TYPE_WINDOW)
|
|||
static gpointer moo_window_grand_parent_class;
|
||||
|
||||
|
||||
#define INSTALL_PROP(prop_id,name) \
|
||||
g_object_class_install_property (gobject_class, prop_id, \
|
||||
g_param_spec_boolean (name, name, name, FALSE, G_PARAM_READABLE))
|
||||
|
||||
static void
|
||||
moo_window_class_init (MooWindowClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
||||
GtkWindowClass *window_class = GTK_WINDOW_CLASS (klass);
|
||||
|
||||
moo_window_grand_parent_class = g_type_class_peek_parent (moo_window_parent_class);
|
||||
|
||||
|
@ -167,9 +199,12 @@ moo_window_class_init (MooWindowClass *klass)
|
|||
|
||||
widget_class->delete_event = moo_window_delete_event;
|
||||
widget_class->key_press_event = moo_window_key_press_event;
|
||||
window_class->set_focus = moo_window_set_focus;
|
||||
|
||||
moo_window_class_set_id (klass, "MooWindow", "Window");
|
||||
|
||||
_moo_edit_ops_iface_install ();
|
||||
|
||||
moo_window_class_new_action (klass, "ConfigureShortcuts", NULL,
|
||||
"label", _("Configure _Shortcuts..."),
|
||||
"no-accel", TRUE,
|
||||
|
@ -195,6 +230,75 @@ moo_window_class_init (MooWindowClass *klass)
|
|||
create_toolbar_style_action,
|
||||
NULL, NULL);
|
||||
|
||||
moo_window_class_new_action (klass, "Cut", NULL,
|
||||
"display-name", GTK_STOCK_CUT,
|
||||
"label", GTK_STOCK_CUT,
|
||||
"tooltip", GTK_STOCK_CUT,
|
||||
"stock-id", GTK_STOCK_CUT,
|
||||
"accel", MOO_ACCEL_CUT,
|
||||
"closure-callback", moo_window_action_cut,
|
||||
"condition::sensitive", "can-cut",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (klass, "Copy", NULL,
|
||||
"display-name", GTK_STOCK_COPY,
|
||||
"label", GTK_STOCK_COPY,
|
||||
"tooltip", GTK_STOCK_COPY,
|
||||
"stock-id", GTK_STOCK_COPY,
|
||||
"accel", MOO_ACCEL_COPY,
|
||||
"closure-callback", moo_window_action_copy,
|
||||
"condition::sensitive", "can-copy",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (klass, "Paste", NULL,
|
||||
"display-name", GTK_STOCK_PASTE,
|
||||
"label", GTK_STOCK_PASTE,
|
||||
"tooltip", GTK_STOCK_PASTE,
|
||||
"stock-id", GTK_STOCK_PASTE,
|
||||
"accel", MOO_ACCEL_PASTE,
|
||||
"closure-callback", moo_window_action_paste,
|
||||
"condition::sensitive", "can-paste",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (klass, "Delete", NULL,
|
||||
"display-name", GTK_STOCK_DELETE,
|
||||
"label", GTK_STOCK_DELETE,
|
||||
"tooltip", GTK_STOCK_DELETE,
|
||||
"stock-id", GTK_STOCK_DELETE,
|
||||
"closure-callback", moo_window_action_delete,
|
||||
"condition::sensitive", "can-delete",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (klass, "SelectAll", NULL,
|
||||
"display-name", GTK_STOCK_SELECT_ALL,
|
||||
"label", GTK_STOCK_SELECT_ALL,
|
||||
"tooltip", GTK_STOCK_SELECT_ALL,
|
||||
"stock-id", GTK_STOCK_SELECT_ALL,
|
||||
"accel", MOO_ACCEL_SELECT_ALL,
|
||||
"closure-callback", moo_window_action_select_all,
|
||||
"condition::sensitive", "can-select-all",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (klass, "Undo", NULL,
|
||||
"display-name", GTK_STOCK_UNDO,
|
||||
"label", GTK_STOCK_UNDO,
|
||||
"tooltip", GTK_STOCK_UNDO,
|
||||
"stock-id", GTK_STOCK_UNDO,
|
||||
"accel", MOO_ACCEL_UNDO,
|
||||
"closure-callback", moo_window_action_undo,
|
||||
"condition::sensitive", "can-undo",
|
||||
NULL);
|
||||
|
||||
moo_window_class_new_action (klass, "Redo", NULL,
|
||||
"display-name", GTK_STOCK_REDO,
|
||||
"label", GTK_STOCK_REDO,
|
||||
"tooltip", GTK_STOCK_REDO,
|
||||
"stock-id", GTK_STOCK_REDO,
|
||||
"accel", MOO_ACCEL_REDO,
|
||||
"closure-callback", moo_window_action_redo,
|
||||
"condition::sensitive", "can-redo",
|
||||
NULL);
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ACCEL_GROUP,
|
||||
g_param_spec_object ("accel-group",
|
||||
|
@ -259,6 +363,15 @@ moo_window_class_init (MooWindowClass *klass)
|
|||
TRUE,
|
||||
G_PARAM_READWRITE));
|
||||
|
||||
INSTALL_PROP (PROP_MEO_CAN_COPY, "can-copy");
|
||||
INSTALL_PROP (PROP_MEO_CAN_CUT, "can-cut");
|
||||
INSTALL_PROP (PROP_MEO_CAN_PASTE, "can-paste");
|
||||
INSTALL_PROP (PROP_MEO_CAN_DELETE, "can-delete");
|
||||
INSTALL_PROP (PROP_MEO_CAN_SELECT_ALL, "can-select-all");
|
||||
|
||||
INSTALL_PROP (PROP_MUO_CAN_UNDO, "can-undo");
|
||||
INSTALL_PROP (PROP_MUO_CAN_REDO, "can-redo");
|
||||
|
||||
signals[CLOSE] =
|
||||
g_signal_new ("close",
|
||||
G_OBJECT_CLASS_TYPE (klass),
|
||||
|
@ -375,6 +488,12 @@ moo_window_dispose (GObject *object)
|
|||
|
||||
if (window->priv)
|
||||
{
|
||||
window->priv->default_eo_widget = NULL;
|
||||
moo_window_disconnect_eo_widget (window);
|
||||
|
||||
window->priv->default_uo_widget = NULL;
|
||||
moo_window_disconnect_uo_widget (window);
|
||||
|
||||
if (window->priv->ui_xml)
|
||||
g_object_unref (window->priv->ui_xml);
|
||||
|
||||
|
@ -579,6 +698,36 @@ moo_window_get_property (GObject *object,
|
|||
g_value_set_boolean (value, window->priv->menubar_visible);
|
||||
break;
|
||||
|
||||
case PROP_MEO_CAN_COPY:
|
||||
g_value_set_boolean (value, window->priv->eo_widget &&
|
||||
_moo_edit_ops_can_do_op (G_OBJECT (window->priv->eo_widget), MOO_EDIT_OP_COPY));
|
||||
break;
|
||||
case PROP_MEO_CAN_CUT:
|
||||
g_value_set_boolean (value, window->priv->eo_widget &&
|
||||
_moo_edit_ops_can_do_op (G_OBJECT (window->priv->eo_widget), MOO_EDIT_OP_CUT));
|
||||
break;
|
||||
case PROP_MEO_CAN_PASTE:
|
||||
g_value_set_boolean (value, window->priv->eo_widget &&
|
||||
_moo_edit_ops_can_do_op (G_OBJECT (window->priv->eo_widget), MOO_EDIT_OP_PASTE));
|
||||
break;
|
||||
case PROP_MEO_CAN_DELETE:
|
||||
g_value_set_boolean (value, window->priv->eo_widget &&
|
||||
_moo_edit_ops_can_do_op (G_OBJECT (window->priv->eo_widget), MOO_EDIT_OP_DELETE));
|
||||
break;
|
||||
case PROP_MEO_CAN_SELECT_ALL:
|
||||
g_value_set_boolean (value, window->priv->eo_widget &&
|
||||
_moo_edit_ops_can_do_op (G_OBJECT (window->priv->eo_widget), MOO_EDIT_OP_SELECT_ALL));
|
||||
break;
|
||||
|
||||
case PROP_MUO_CAN_UNDO:
|
||||
g_value_set_boolean (value, window->priv->uo_widget &&
|
||||
_moo_undo_ops_can_undo (G_OBJECT (window->priv->uo_widget)));
|
||||
break;
|
||||
case PROP_MUO_CAN_REDO:
|
||||
g_value_set_boolean (value, window->priv->uo_widget &&
|
||||
_moo_undo_ops_can_redo (G_OBJECT (window->priv->uo_widget)));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -1792,3 +1941,247 @@ _moo_window_class_new_action_callback (MooWindowClass *klass,
|
|||
g_object_unref (action_factory);
|
||||
g_strfreev (conditions);
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/* MooEditOps
|
||||
*/
|
||||
|
||||
static void
|
||||
moo_window_action_cut (MooWindow *window)
|
||||
{
|
||||
g_return_if_fail (window->priv->eo_widget != NULL);
|
||||
_moo_edit_ops_do_op (G_OBJECT (window->priv->eo_widget),
|
||||
MOO_EDIT_OP_CUT);
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_action_copy (MooWindow *window)
|
||||
{
|
||||
g_return_if_fail (window->priv->eo_widget != NULL);
|
||||
_moo_edit_ops_do_op (G_OBJECT (window->priv->eo_widget),
|
||||
MOO_EDIT_OP_COPY);
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_action_paste (MooWindow *window)
|
||||
{
|
||||
g_return_if_fail (window->priv->eo_widget != NULL);
|
||||
_moo_edit_ops_do_op (G_OBJECT (window->priv->eo_widget),
|
||||
MOO_EDIT_OP_PASTE);
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_action_delete (MooWindow *window)
|
||||
{
|
||||
g_return_if_fail (window->priv->eo_widget != NULL);
|
||||
_moo_edit_ops_do_op (G_OBJECT (window->priv->eo_widget),
|
||||
MOO_EDIT_OP_DELETE);
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_action_select_all (MooWindow *window)
|
||||
{
|
||||
g_return_if_fail (window->priv->eo_widget != NULL);
|
||||
_moo_edit_ops_do_op (G_OBJECT (window->priv->eo_widget),
|
||||
MOO_EDIT_OP_SELECT_ALL);
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_action_undo (MooWindow *window)
|
||||
{
|
||||
g_return_if_fail (window->priv->uo_widget != NULL);
|
||||
_moo_undo_ops_undo (G_OBJECT (window->priv->uo_widget));
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_action_redo (MooWindow *window)
|
||||
{
|
||||
g_return_if_fail (window->priv->uo_widget != NULL);
|
||||
_moo_undo_ops_redo (G_OBJECT (window->priv->uo_widget));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
emit_can_do_op_changed (MooWindow *window,
|
||||
MooEditOpType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MOO_EDIT_OP_CUT:
|
||||
g_object_notify (G_OBJECT (window), "can-cut");
|
||||
break;
|
||||
case MOO_EDIT_OP_COPY:
|
||||
g_object_notify (G_OBJECT (window), "can-copy");
|
||||
break;
|
||||
case MOO_EDIT_OP_PASTE:
|
||||
g_object_notify (G_OBJECT (window), "can-paste");
|
||||
break;
|
||||
case MOO_EDIT_OP_DELETE:
|
||||
g_object_notify (G_OBJECT (window), "can-delete");
|
||||
break;
|
||||
case MOO_EDIT_OP_SELECT_ALL:
|
||||
g_object_notify (G_OBJECT (window), "can-select-all");
|
||||
break;
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_connect_eo_widget (MooWindow *window,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
g_return_if_fail (_moo_edit_ops_check (G_OBJECT (widget)));
|
||||
|
||||
window->priv->eo_widget = g_object_ref (widget);
|
||||
|
||||
_moo_edit_ops_connect (G_OBJECT (widget));
|
||||
g_signal_connect_swapped (widget, "moo-edit-ops-can-do-op-changed",
|
||||
G_CALLBACK (emit_can_do_op_changed), window);
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_disconnect_eo_widget (MooWindow *window)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = window->priv->eo_widget;
|
||||
window->priv->eo_widget = NULL;
|
||||
|
||||
if (widget)
|
||||
{
|
||||
_moo_edit_ops_disconnect (G_OBJECT (widget));
|
||||
g_signal_handlers_disconnect_by_func (widget,
|
||||
(gpointer) emit_can_do_op_changed,
|
||||
window);
|
||||
g_object_unref (widget);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
find_widget_for_edit_ops (MooWindow *window)
|
||||
{
|
||||
GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));
|
||||
|
||||
while (widget)
|
||||
{
|
||||
if (_moo_edit_ops_check (G_OBJECT (widget)))
|
||||
return widget;
|
||||
widget = widget->parent;
|
||||
}
|
||||
|
||||
return window->priv ? window->priv->default_eo_widget : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
check_edit_ops_widget (MooWindow *window)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = find_widget_for_edit_ops (window);
|
||||
|
||||
if (window->priv && widget != window->priv->eo_widget)
|
||||
{
|
||||
int i;
|
||||
|
||||
moo_window_disconnect_eo_widget (window);
|
||||
|
||||
if (widget)
|
||||
moo_window_connect_eo_widget (window, widget);
|
||||
|
||||
for (i = 0; i < MOO_N_EDIT_OPS; i++)
|
||||
emit_can_do_op_changed (window, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
emit_can_undo_changed (MooWindow *window)
|
||||
{
|
||||
g_object_notify (G_OBJECT (window), "can-undo");
|
||||
}
|
||||
|
||||
static void
|
||||
emit_can_redo_changed (MooWindow *window)
|
||||
{
|
||||
g_object_notify (G_OBJECT (window), "can-redo");
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_connect_uo_widget (MooWindow *window,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
g_return_if_fail (_moo_undo_ops_check (G_OBJECT (widget)));
|
||||
|
||||
window->priv->uo_widget = g_object_ref (widget);
|
||||
|
||||
g_signal_connect_swapped (widget, "moo-undo-ops-can-undo-changed",
|
||||
G_CALLBACK (emit_can_undo_changed), window);
|
||||
g_signal_connect_swapped (widget, "moo-undo-ops-can-redo-changed",
|
||||
G_CALLBACK (emit_can_redo_changed), window);
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_disconnect_uo_widget (MooWindow *window)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = window->priv->uo_widget;
|
||||
window->priv->uo_widget = NULL;
|
||||
|
||||
if (widget)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (widget,
|
||||
(gpointer) emit_can_undo_changed,
|
||||
window);
|
||||
g_signal_handlers_disconnect_by_func (widget,
|
||||
(gpointer) emit_can_redo_changed,
|
||||
window);
|
||||
g_object_unref (widget);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
find_widget_for_undo_ops (MooWindow *window)
|
||||
{
|
||||
GtkWidget *widget = gtk_window_get_focus (GTK_WINDOW (window));
|
||||
|
||||
while (widget)
|
||||
{
|
||||
if (_moo_undo_ops_check (G_OBJECT (widget)))
|
||||
return widget;
|
||||
|
||||
widget = widget->parent;
|
||||
}
|
||||
|
||||
return window->priv ? window->priv->default_uo_widget : NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
check_undo_ops_widget (MooWindow *window)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
|
||||
widget = find_widget_for_undo_ops (window);
|
||||
|
||||
if (window->priv && widget != window->priv->uo_widget)
|
||||
{
|
||||
moo_window_disconnect_uo_widget (window);
|
||||
|
||||
if (widget)
|
||||
moo_window_connect_uo_widget (window, widget);
|
||||
|
||||
emit_can_undo_changed (window);
|
||||
emit_can_redo_changed (window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
moo_window_set_focus (GtkWindow *window,
|
||||
GtkWidget *widget)
|
||||
{
|
||||
GTK_WINDOW_CLASS (moo_window_parent_class)->set_focus (window, widget);
|
||||
check_edit_ops_widget (MOO_WINDOW (window));
|
||||
check_undo_ops_widget (MOO_WINDOW (window));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue