From f68cce12b14abba9c2faae6dcc490f0fbfab4e14 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 28 Jun 2016 15:47:34 +0300 Subject: [PATCH] triple mouse click support; select whole line on mouse triple click - close #193 --- src/dlangui/core/events.d | 22 +++++++++++++++++++++- src/dlangui/widgets/editors.d | 21 ++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/dlangui/core/events.d b/src/dlangui/core/events.d index d8be0cb2..f54f5bf0 100644 --- a/src/dlangui/core/events.d +++ b/src/dlangui/core/events.d @@ -722,6 +722,8 @@ __gshared long DOUBLE_CLICK_THRESHOLD_MS = 400; /// Mouse button state details for MouseEvent struct ButtonDetails { + /// Clock.currStdTime() for down event of this button (0 if button is up) set after double click to time when first click occured. + protected long _prevDownTs; /// Clock.currStdTime() for down event of this button (0 if button is up). protected long _downTs; /// Clock.currStdTime() for up event of this button (0 if button is still down). @@ -734,12 +736,19 @@ struct ButtonDetails { protected ushort _downFlags; /// true if button is made down shortly after up - valid if button is down protected bool _doubleClick; + /// true if button is made down twice shortly after up - valid if button is down + protected bool _tripleClick; /// Returns true if button is made down shortly after up @property bool doubleClick() { return _doubleClick; } + /// Returns true if button is made down twice shortly after up + @property bool tripleClick() { + return _tripleClick; + } + void reset() { @@ -759,14 +768,18 @@ struct ButtonDetails { _upTs = 0; _downTs = std.datetime.Clock.currStdTime; long downIntervalMs = (_downTs - oldDownTs) / 10000; + long prevDownIntervalMs = (_downTs - _prevDownTs) / 10000; //Log.d("Button down ", x, ",", y, " _downTs=", _downTs, " _upTs=", _upTs, " downInterval=", downIntervalMs); - _doubleClick = (oldDownTs && downIntervalMs < DOUBLE_CLICK_THRESHOLD_MS); + _tripleClick = (prevDownIntervalMs && prevDownIntervalMs < DOUBLE_CLICK_THRESHOLD_MS * 2); + _doubleClick = !_tripleClick && (oldDownTs && downIntervalMs < DOUBLE_CLICK_THRESHOLD_MS); + _prevDownTs = _doubleClick ? oldDownTs : 0; } /// update for button up void up(short x, short y, ushort flags) { static import std.datetime; //Log.d("Button up ", x, ",", y, " _downTs=", _downTs, " _upTs=", _upTs); _doubleClick = false; + _tripleClick = false; _upTs = std.datetime.Clock.currStdTime; } /// returns true if button is currently pressed @@ -860,6 +873,13 @@ class MouseEvent { return buttonDetails.doubleClick; } + /// Returns true for ButtonDown event when button is pressed third time in short interval after pressing first time + @property bool tripleClick() { + if (_action != MouseAction.ButtonDown) + return false; + return buttonDetails.tripleClick; + } + /// get event tracking widget to override @property Widget trackingWidget() { return _trackingWidget; } /// returns mouse button tracking flag diff --git a/src/dlangui/widgets/editors.d b/src/dlangui/widgets/editors.d index 1b9bc3f3..bd8c08cf 100644 --- a/src/dlangui/widgets/editors.d +++ b/src/dlangui/widgets/editors.d @@ -1116,6 +1116,23 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction } } + protected void selectLineByMouse(int x, int y, bool onSameLineOnly = true) { + TextPosition oldCaretPos = _caretPos; + TextPosition newPos = clientToTextPos(Point(x,y)); + if (onSameLineOnly && newPos.line != oldCaretPos.line) + return; // different lines + TextRange r = content.lineRange(newPos.line); + if (r.start < r.end) { + _selectionRange = r; + _caretPos = r.end; + invalidate(); + requestActionsUpdate(); + } else { + _caretPos = newPos; + updateSelectionAfterCursorMovement(oldCaretPos, false); + } + } + protected void updateCaretPositionByMouse(int x, int y, bool selecting) { TextPosition oldCaretPos = _caretPos; TextPosition newPos = clientToTextPos(Point(x,y)); @@ -1709,7 +1726,9 @@ class EditWidgetBase : ScrollWidgetBase, EditableContentListener, MenuItemAction setFocus(); startCaretBlinking(); cancelHoverTimer(); - if (event.doubleClick) { + if (event.tripleClick) { + selectLineByMouse(event.x - _clientRect.left, event.y - _clientRect.top); + } else if (event.doubleClick) { selectWordByMouse(event.x - _clientRect.left, event.y - _clientRect.top); } else { auto doSelect = cast(bool)(event.keyFlags & MouseFlag.Shift);