From 97785557020d5b726ae91cdf659aa9e64dce4cde Mon Sep 17 00:00:00 2001 From: default0 Date: Mon, 1 Feb 2016 21:22:32 +0100 Subject: [PATCH] Change Textbox Behaviour Textboxes have slightly altered behaviour: Shift-clicking to move the cursor creates a selection from the previous cursor position to the new position. Tabbing into an EditLine selects all its contents, tabbing out of an EditLine deselects everything. --- src/dlangui/core/types.d | 2 ++ src/dlangui/platforms/common/platform.d | 9 ++++++--- src/dlangui/widgets/editors.d | 18 ++++++++++++++++-- src/dlangui/widgets/lists.d | 2 +- src/dlangui/widgets/menu.d | 2 +- src/dlangui/widgets/widget.d | 17 +++++++++++------ 6 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/dlangui/core/types.d b/src/dlangui/core/types.d index e59dd503..8e0195d7 100644 --- a/src/dlangui/core/types.d +++ b/src/dlangui/core/types.d @@ -467,6 +467,8 @@ enum State : uint { WindowFocused = 256, /// widget is default control for form (should be focused when window gains focus first time) Default = 512, // widget is default for form (e.g. default button will be focused on show) + /// widget has been focused by keyboard navigation + KeyboardFocused = 1024, /// return state of parent instead of widget's state when requested Parent = 0x10000, // use parent's state } diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index 5f2885fd..2cf2b8ef 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -523,19 +523,22 @@ class Window : CustomEventTarget { } /// change focus to widget - Widget setFocus(Widget newFocus) { + Widget setFocus(Widget newFocus, FocusReason reason = FocusReason.Unspecified) { if (!isChild(_focusedWidget)) _focusedWidget = null; Widget oldFocus = _focusedWidget; + auto targetState = State.Focused; + if(reason == FocusReason.TabFocus) + targetState = State.Focused | State.KeyboardFocused; if (oldFocus is newFocus) return oldFocus; if (oldFocus !is null) - oldFocus.resetState(State.Focused); + oldFocus.resetState(targetState); if (newFocus is null || isChild(newFocus)) { if (newFocus !is null) { // when calling, setState(focused), window.focusedWidget is still previously focused widget debug(DebugFocus) Log.d("new focus: ", newFocus.id); - newFocus.setState(State.Focused); + newFocus.setState(targetState); } _focusedWidget = newFocus; // after focus change, ask for actions update automatically diff --git a/src/dlangui/widgets/editors.d b/src/dlangui/widgets/editors.d index 14076cea..e2888a6a 100644 --- a/src/dlangui/widgets/editors.d +++ b/src/dlangui/widgets/editors.d @@ -241,6 +241,9 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction protected int _iconsWidth = 0; protected int _foldingWidth = 0; + protected bool _selectAllWhenFocusedWithTab = false; + protected bool _deselectAllWhenUnfocused = false; + protected bool _replaceMode; // TODO: move to styles @@ -920,13 +923,20 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction } /// override to handle focus changes - override protected void handleFocusChange(bool focused) { + override protected void handleFocusChange(bool focused, bool receivedFocusFromKeyboard = false) { if (focused) startCaretBlinking(); else { stopCaretBlinking(); cancelHoverTimer(); + + if(_deselectAllWhenUnfocused) { + _selectionRange.start = _caretPos; + _selectionRange.end = _caretPos; + } } + if(focused && _selectAllWhenFocusedWithTab && receivedFocusFromKeyboard) + handleAction(ACTION_EDITOR_SELECT_ALL); super.handleFocusChange(focused); } @@ -1643,7 +1653,9 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction if (event.doubleClick) { selectWordByMouse(event.x - _clientRect.left, event.y - _clientRect.top); } else { - updateCaretPositionByMouse(event.x - _clientRect.left, event.y - _clientRect.top, false); + auto doSelect = cast(bool)(event.keyFlags & MouseFlag.Shift); + updateCaretPositionByMouse(event.x - _clientRect.left, event.y - _clientRect.top, doSelect); + if (event.keyFlags == MouseFlag.Control) onControlClick(); } @@ -1730,6 +1742,8 @@ class EditLine : EditWidgetBase { super(ID, ScrollBarMode.Invisible, ScrollBarMode.Invisible); _content = new EditableContent(false); _content.contentChanged = this; + _selectAllWhenFocusedWithTab = true; + _deselectAllWhenUnfocused = true; wantTabs = false; styleId = STYLE_EDIT_LINE; text = initialContent; diff --git a/src/dlangui/widgets/lists.d b/src/dlangui/widgets/lists.d index 055ee8f6..cfa0b1dd 100644 --- a/src/dlangui/widgets/lists.d +++ b/src/dlangui/widgets/lists.d @@ -732,7 +732,7 @@ class ListWidget : WidgetGroup, OnScrollHandler, OnAdapterChangeHandler { } /// override to handle focus changes - override protected void handleFocusChange(bool focused) { + override protected void handleFocusChange(bool focused, bool receivedFocusFromKeyboard = false) { updateSelectedItemFocus(); } diff --git a/src/dlangui/widgets/menu.d b/src/dlangui/widgets/menu.d index 5ea633de..a3f3a3c9 100644 --- a/src/dlangui/widgets/menu.d +++ b/src/dlangui/widgets/menu.d @@ -887,7 +887,7 @@ class MainMenu : MenuWidgetBase { } /// override to handle focus changes - override protected void handleFocusChange(bool focused) { + override protected void handleFocusChange(bool focused, bool receivedFocusFromKeyboard = false) { debug(DebugMenus) Log.d("menu ", id, "handling focus change to ", focused); if (focused && _openedPopup is null) { // activating! diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index 831ce44a..42e3379b 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -71,6 +71,11 @@ enum Orientation : ubyte { Horizontal } +enum FocusReason : ubyte { + TabFocus, + Unspecified +} + /// interface - slot for onClick interface OnClickHandler { bool onClick(Widget source); @@ -280,7 +285,7 @@ public: return _state | State.WindowFocused; // TODO: } /// override to handle focus changes - protected void handleFocusChange(bool focused) { + protected void handleFocusChange(bool focused, bool receivedFocusFromKeyboard = false) { invalidate(); focusChange(this, focused); } @@ -300,7 +305,7 @@ public: if ((oldState & State.Focused) && !(newState & State.Focused)) handleFocusChange(false); else if (!(oldState & State.Focused) && (newState & State.Focused)) - handleFocusChange(true); + handleFocusChange(true, cast(bool)(newState & State.KeyboardFocused)); // notify checked changes if ((oldState & State.Checked) && !(newState & State.Checked)) handleCheckChange(false); @@ -990,7 +995,7 @@ public: Widget nextWidget = findNextFocusWidget(direction); if (!nextWidget) return false; - nextWidget.setFocus(); + nextWidget.setFocus(FocusReason.TabFocus); return true; } @@ -1009,7 +1014,7 @@ public: } /// sets focus to this widget or suitable focusable child, returns previously focused widget - Widget setFocus() { + Widget setFocus(FocusReason reason = FocusReason.Unspecified) { if (window is null) return null; if (!visible) @@ -1020,11 +1025,11 @@ public: if (!w) w = findFocusableChild(false); if (w) - return window.setFocus(w); + return window.setFocus(w, reason); // try to find focusable child return window.focusedWidget; } - return window.setFocus(this); + return window.setFocus(this, reason); } /// searches children for first focusable item, returns null if not found Widget findFocusableChild(bool defaultOnly) {