Skip to content

Commit 40d481b

Browse files
committed
add: selecting in TextArea by double/triple clicks
1 parent e2035c5 commit 40d481b

File tree

1 file changed

+65
-30
lines changed

1 file changed

+65
-30
lines changed

src/sigui/textArea.nim

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ type
2222

2323
selectingUsingMouse
2424
selectingUsingKeyboard
25-
# selectingWordsByDobleClick
26-
# selectingAllTextByDobleClick
27-
# selectingAllTextByTripleClick
25+
selectingWordsByDobleClick
26+
selectingAllTextByDobleClick
27+
selectingAllTextByTripleClick
2828
selectingAllTextByCtrlA
2929
# note: implement selecting all text on activation by yourself if you need it
3030

@@ -60,11 +60,16 @@ type
6060
selectionStartX*, selectionEndX*: Property[float32] # in pixels
6161
# note: provided in case if you want to animate them
6262

63-
allowedInteractions*: set[TextAreaInteraction] = {TextAreaInteraction.low..TextAreaInteraction.high}
63+
allowedInteractions*: set[TextAreaInteraction] =
64+
{TextAreaInteraction.low..TextAreaInteraction.high} -
65+
{TextAreaInteraction.selectingAllTextByDobleClick}
6466

6567
undoBuffer*: seq[tuple[text: string, cursorPos: int, selectionStart, selectionEnd: int]]
6668
undoBufferLimit*: int = 200
6769
redoIndex*: int
70+
71+
doubleClick: bool
72+
lastDoubleClickTime: Time
6873

6974
m_cursorPos: int
7075
m_selectionStart, m_selectionEnd: int
@@ -162,28 +167,29 @@ template onKeyDown*(this: TextArea, expectedKey: Key, body: untyped) =
162167
if event.key == expectedKey: body
163168

164169

170+
proc findLeftCtrlWord(this: TextArea, inBorders: bool = false): int =
171+
var fondLetter = inBorders
172+
result = 0
173+
for i in countdown(this.cursorPos[].min(this.text[].runeLen) - 1, 0):
174+
if fondLetter and not this.text[].runeAtPos(i).isAlpha:
175+
result = i + 1
176+
break
177+
elif this.text[].runeAtPos(i).isAlpha:
178+
fondLetter = true
179+
180+
proc findRightCtrlWord(this: TextArea, inBorders: bool = false): int =
181+
var fondLetter = inBorders
182+
result = this.text[].runeLen
183+
for i in countup(this.cursorPos[].max(0), this.text[].runeLen - 1):
184+
if fondLetter and not this.text[].runeAtPos(i).isAlpha:
185+
result = i
186+
break
187+
elif this.text[].runeAtPos(i).isAlpha:
188+
fondLetter = true
189+
190+
165191
method recieve*(this: TextArea, signal: Signal) =
166192
procCall this.super.recieve(signal)
167-
168-
proc findLeftCtrlWord(): int =
169-
var fondLetter = false
170-
result = 0
171-
for i in countdown(this.cursorPos[].min(this.text[].runeLen) - 1, 0):
172-
if fondLetter and not this.text[].runeAtPos(i).isAlpha:
173-
result = i + 1
174-
break
175-
elif this.text[].runeAtPos(i).isAlpha:
176-
fondLetter = true
177-
178-
proc findRightCtrlWord(): int =
179-
var fondLetter = false
180-
result = this.text[].runeLen
181-
for i in countup(this.cursorPos[].max(0), this.text[].runeLen - 1):
182-
if fondLetter and not this.text[].runeAtPos(i).isAlpha:
183-
result = i
184-
break
185-
elif this.text[].runeAtPos(i).isAlpha:
186-
fondLetter = true
187193

188194
case signal
189195
of of WindowEvent(event: @ea is of KeyEvent(), handled: false):
@@ -208,14 +214,14 @@ method recieve*(this: TextArea, signal: Signal) =
208214
case key
209215
of Key.left:
210216
if Key.lcontrol in window.keyboard.pressed or Key.rcontrol in window.keyboard.pressed:
211-
this.cursorPos[] = findLeftCtrlWord()
217+
this.cursorPos[] = this.findLeftCtrlWord()
212218
else:
213219
this.cursorPos[] = this.cursorPos[] - 1
214220
handleSelection()
215221

216222
of Key.right:
217223
if Key.lcontrol in window.keyboard.pressed or Key.rcontrol in window.keyboard.pressed:
218-
this.cursorPos[] = findRightCtrlWord()
224+
this.cursorPos[] = this.findRightCtrlWord()
219225
else:
220226
this.cursorPos[] = this.cursorPos[] + 1
221227
handleSelection()
@@ -300,7 +306,7 @@ method recieve*(this: TextArea, signal: Signal) =
300306
elif this.cursorPos[] > 0:
301307
if window.keyboard.pressed.containsControl():
302308
# delete whole word
303-
let i = findLeftCtrlWord()
309+
let i = this.findLeftCtrlWord()
304310
let offset = this.text[].runeOffset(i)
305311
let offset2 =
306312
if this.cursorPos[] == this.text[].runeLen:
@@ -329,7 +335,7 @@ method recieve*(this: TextArea, signal: Signal) =
329335
elif this.cursorPos[] < this.text[].runeLen:
330336
if window.keyboard.pressed.containsControl():
331337
# delete whole word
332-
let i = findRightCtrlWord()
338+
let i = this.findRightCtrlWord()
333339
let offset = this.text[].runeOffset(this.cursorPos[])
334340
let offset2 =
335341
if i == this.text[].runeLen:
@@ -440,10 +446,38 @@ method init*(this: TextArea) =
440446
let e = (ref MouseButtonEvent)ea
441447
if e.pressed: root.active[] = false
442448

449+
450+
this.clicked.connectTo root, e:
451+
if selectingWordsByDobleClick in root.allowedInteractions and e.double:
452+
root.selectionStart[] = root.findLeftCtrlWord(inBorders=true)
453+
root.selectionEnd[] = root.findRightCtrlWord(inBorders=true)
454+
root.cursorPos[] = root.selectionEnd[]
455+
root.doubleClick = true
456+
457+
if selectingAllTextByDobleClick in root.allowedInteractions and e.double:
458+
root.selectionStart[] = 0
459+
root.selectionEnd[] = root.text[].runeLen
460+
root.cursorPos[] = root.selectionEnd[]
461+
root.doubleClick = true
462+
463+
if getTime() - root.lastDoubleClickTime <= initDuration(milliseconds=300):
464+
if selectingAllTextByTripleClick in root.allowedInteractions:
465+
root.selectionStart[] = 0
466+
root.selectionEnd[] = root.text[].runeLen
467+
root.cursorPos[] = root.selectionEnd[]
468+
469+
if e.double:
470+
root.lastDoubleClickTime = getTime()
471+
472+
443473
this.pressed.changed.connectTo root, pressed:
474+
if not pressed:
475+
root.doubleClick = false
476+
444477
if activatingUsingMouse in root.allowedInteractions and pressed:
445478
root.active[] = true
446-
if navigationUsingMouse in root.allowedInteractions and pressed:
479+
480+
if navigationUsingMouse in root.allowedInteractions and pressed and (not root.doubleClick):
447481
root.cursorPos[] = characterAtPosition(root.textObj{}.arrangement[], this.mouseX[] - root.offset[])
448482

449483
if selectingUsingMouse in root.allowedInteractions:
@@ -452,7 +486,8 @@ method init*(this: TextArea) =
452486
else:
453487
root.selectionStart[] = root.cursorPos[]
454488
root.selectionEnd[] = root.cursorPos[]
455-
489+
490+
456491
this.mouseX.changed.connectTo root, mouseX:
457492
if navigationUsingMouse in root.allowedInteractions and this.pressed[]:
458493
root.cursorPos[] = characterAtPosition(root.textObj{}.arrangement[], this.mouseX[] - root.offset[])

0 commit comments

Comments
 (0)