diff --git a/moo/mooedit/mooeditinput.c b/moo/mooedit/mooeditinput.c index 79d5e380..66bb7a5b 100644 --- a/moo/mooedit/mooeditinput.c +++ b/moo/mooedit/mooeditinput.c @@ -1,6 +1,5 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4; coding: utf-8 -*- - * - * mooeditcursor.c +/* + * mooeditinput.c * * Copyright (C) 2004-2006 by Yevgen Muntyan * @@ -1086,23 +1085,47 @@ set_invisible_cursor (GdkWindow *window) } +static void +move_focus (GtkWidget *widget, + GtkDirectionType direction) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (widget); + g_signal_emit_by_name (toplevel, "move-focus", direction); +} + static gboolean -handle_tab (MooTextView *view, - G_GNUC_UNUSED GdkEventKey *event) +handle_tab (MooTextView *view, + GdkEventKey *event) { GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); GtkTextIter insert, bound, start, end; gboolean starts_line, insert_last, has_selection; int first_line, last_line; - if (!view->priv->indenter || !view->priv->tab_indents) + switch (view->priv->tab_key_action) + { + case MOO_TEXT_TAB_KEY_DO_NOTHING: + move_focus (GTK_WIDGET (view), + event->state & GDK_SHIFT_MASK ? + GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD); + return TRUE; + + case MOO_TEXT_TAB_KEY_FIND_PLACEHOLDER: + if (event->state & GDK_SHIFT_MASK) + moo_text_view_prev_placeholder (view); + else + moo_text_view_next_placeholder (view); + return TRUE; + + case MOO_TEXT_TAB_KEY_INDENT: + break; + } + + if (!view->priv->indenter) return FALSE; has_selection = gtk_text_buffer_get_selection_bounds (buffer, &start, &end); - if (!has_selection && !view->priv->tab_indents && !view->priv->tab_inserts_indent_chars) - return FALSE; - gtk_text_buffer_begin_user_action (buffer); if (has_selection) @@ -1275,6 +1298,7 @@ handle_ctrl_up (MooTextView *view, GtkTextView *text_view; GtkAdjustment *adjustment; double value; + int line_height; if (!view->priv->ctrl_up_down_scrolls) return FALSE; @@ -1285,21 +1309,25 @@ handle_ctrl_up (MooTextView *view, if (!adjustment) return FALSE; + line_height = _moo_text_view_get_line_height (view); + if (up) { - value = adjustment->value - adjustment->step_increment; + value = adjustment->value - line_height; + if (value < adjustment->lower) value = adjustment->lower; - gtk_adjustment_set_value (adjustment, value); } else { - value = adjustment->value + adjustment->step_increment; + value = adjustment->value + line_height; + if (value > adjustment->upper - adjustment->page_size) value = adjustment->upper - adjustment->page_size; - gtk_adjustment_set_value (adjustment, value); } + gtk_adjustment_set_value (adjustment, value); + return TRUE; } diff --git a/moo/mooedit/mootextview-private.h b/moo/mooedit/mootextview-private.h index afba4207..7ddd8016 100644 --- a/moo/mooedit/mootextview-private.h +++ b/moo/mooedit/mootextview-private.h @@ -57,6 +57,7 @@ int _moo_text_view_extend_selection (MooTextView *view, void _moo_text_view_check_char_inserted (MooTextView *view); void _moo_text_view_pend_cursor_blink (MooTextView *view); +int _moo_text_view_get_line_height (MooTextView *view); typedef enum { @@ -129,6 +130,7 @@ struct _MooTextViewPrivate { gboolean shift_tab_unindents; gboolean backspace_indents; gboolean enter_indents; + MooTextTabKeyAction tab_key_action; /***********************************************************************/ /* Keyboard diff --git a/moo/mooedit/mootextview.c b/moo/mooedit/mootextview.c index 8a478065..a772ed93 100644 --- a/moo/mooedit/mootextview.c +++ b/moo/mooedit/mootextview.c @@ -203,7 +203,8 @@ enum { PROP_SHOW_LINE_MARKS, PROP_ENABLE_FOLDING, PROP_ENABLE_QUICK_SEARCH, - PROP_QUICK_SEARCH_FLAGS + PROP_QUICK_SEARCH_FLAGS, + PROP_TAB_KEY_ACTION }; @@ -440,6 +441,15 @@ static void moo_text_view_class_init (MooTextViewClass *klass) MOO_TEXT_SEARCH_CASELESS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (gobject_class, + PROP_TAB_KEY_ACTION, + g_param_spec_enum ("tab-key-action", + "tab-key-action", + "tab-key-action", + MOO_TYPE_TEXT_TAB_KEY_ACTION, + MOO_TEXT_TAB_KEY_INDENT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + gtk_widget_class_install_style_property (widget_class, g_param_spec_int ("expander-size", "Expander Size", @@ -1037,6 +1047,10 @@ moo_text_view_set_property (GObject *object, g_object_notify (object, "quick-search-flags"); break; + case PROP_TAB_KEY_ACTION: + moo_text_view_set_tab_key_action (view, g_value_get_enum (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1139,6 +1153,10 @@ moo_text_view_get_property (GObject *object, g_value_set_flags (value, view->priv->qs.flags); break; + case PROP_TAB_KEY_ACTION: + g_value_set_enum (value, view->priv->tab_key_action); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1159,6 +1177,7 @@ moo_text_selection_type_get_type (void) { MOO_TEXT_SELECT_LINES, (char*)"MOO_TEXT_SELECT_LINES", (char*)"select-lines" }, { 0, NULL, NULL } }; + type = g_enum_register_static ("MooTextSelectionType", values); } @@ -1166,6 +1185,27 @@ moo_text_selection_type_get_type (void) } +GType +moo_text_tab_key_action_get_type (void) +{ + static GType type = 0; + + if (!type) + { + static const GEnumValue values[] = { + { MOO_TEXT_TAB_KEY_DO_NOTHING, (char*)"MOO_TEXT_TAB_KEY_DO_NOTHING", (char*)"do-nothing" }, + { MOO_TEXT_TAB_KEY_INDENT, (char*)"MOO_TEXT_TAB_KEY_INDENT", (char*)"indent" }, + { MOO_TEXT_TAB_KEY_FIND_PLACEHOLDER, (char*)"MOO_TEXT_TAB_KEY_FIND_PLACEHOLDER", (char*)"find-placeholder" }, + { 0, NULL, NULL } + }; + + type = g_enum_register_static ("MooTextTabKeyAction", values); + } + + return type; +} + + char* moo_text_view_get_selection (MooTextView *view) { @@ -2626,6 +2666,44 @@ _moo_text_view_pend_cursor_blink (MooTextView *view) } +void +moo_text_view_set_tab_key_action (MooTextView *view, + MooTextTabKeyAction action) +{ + g_return_if_fail (MOO_IS_TEXT_VIEW (view)); + + if (view->priv->tab_key_action != action) + { + view->priv->tab_key_action = action; + g_object_notify (G_OBJECT (view), "tab-key-action"); + } +} + + +int +_moo_text_view_get_line_height (MooTextView *view) +{ + PangoContext *ctx; + PangoLayout *layout; + PangoRectangle rect; + int height; + + g_return_val_if_fail (MOO_IS_TEXT_VIEW (view), 10); + + ctx = gtk_widget_get_pango_context (GTK_WIDGET (view)); + g_return_val_if_fail (ctx != NULL, 10); + + layout = pango_layout_new (ctx); + pango_layout_set_text (layout, "AA", -1); + + pango_layout_get_extents (layout, NULL, &rect); + height = rect.height / PANGO_SCALE; + + g_object_unref (layout); + return height; +} + + /*****************************************************************************/ /* Left margin */ @@ -4170,6 +4248,7 @@ moo_text_view_next_placeholder (MooTextView *view) if (moo_text_view_has_placeholder_at_iter (view, &match_start)) { gtk_text_buffer_select_range (buffer, &match_end, &match_start); + scroll_selection_onscreen (GTK_TEXT_VIEW (view)); return TRUE; } else @@ -4206,6 +4285,7 @@ moo_text_view_prev_placeholder (MooTextView *view) if (moo_text_view_has_placeholder_at_iter (view, &match_start)) { gtk_text_buffer_select_range (buffer, &match_start, &match_end); + scroll_selection_onscreen (GTK_TEXT_VIEW (view)); return TRUE; } else diff --git a/moo/mooedit/mootextview.h b/moo/mooedit/mootextview.h index 9f9dd312..a2b97c61 100644 --- a/moo/mooedit/mootextview.h +++ b/moo/mooedit/mootextview.h @@ -24,6 +24,7 @@ G_BEGIN_DECLS #define MOO_TYPE_TEXT_SELECTION_TYPE (moo_text_selection_type_get_type ()) +#define MOO_TYPE_TEXT_TAB_KEY_ACTION (moo_text_tab_key_action_get_type ()) #define MOO_TYPE_TEXT_VIEW (moo_text_view_get_type ()) #define MOO_TEXT_VIEW(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOO_TYPE_TEXT_VIEW, MooTextView)) @@ -43,6 +44,12 @@ typedef enum { MOO_TEXT_SELECT_LINES } MooTextSelectionType; +typedef enum { + MOO_TEXT_TAB_KEY_DO_NOTHING, + MOO_TEXT_TAB_KEY_INDENT, + MOO_TEXT_TAB_KEY_FIND_PLACEHOLDER +} MooTextTabKeyAction; + struct _MooTextView { GtkTextView parent; @@ -88,6 +95,7 @@ struct _MooTextViewClass GType moo_text_view_get_type (void) G_GNUC_CONST; GType moo_text_selection_type_get_type (void) G_GNUC_CONST; +GType moo_text_tab_key_action_get_type (void) G_GNUC_CONST; GtkWidget *moo_text_view_new (void); @@ -158,6 +166,9 @@ void moo_text_view_add_child_in_border (MooTextView *view, GtkWidget *child, GtkTextWindowType which_border); +void moo_text_view_set_tab_key_action (MooTextView *view, + MooTextTabKeyAction action); + void moo_text_view_insert_placeholder (MooTextView *view, GtkTextIter *iter); gboolean moo_text_view_next_placeholder (MooTextView *view);