|
@@ -2,6 +2,7 @@
|
|
|
import
|
|
|
../thirdparty/opengl,
|
|
|
../thirdparty/sdl2,
|
|
|
+ ../thirdparty/sdl2/ttf,
|
|
|
|
|
|
../core/font,
|
|
|
../core/color,
|
|
@@ -21,12 +22,12 @@ import
|
|
|
|
|
|
type
|
|
|
EditTextRef* = ref object of LabelObj
|
|
|
- hint*: StyleText
|
|
|
- caret_color: ColorRef
|
|
|
- caret_pos: uint32
|
|
|
+ is_blink, is_select: bool
|
|
|
+ caret*, selectable: bool
|
|
|
blink_time: uint8
|
|
|
- is_blink: bool
|
|
|
- caret*: bool
|
|
|
+ caret_color: ColorRef
|
|
|
+ hint*: StyleText
|
|
|
+ caret_pos: array[2, uint32]
|
|
|
on_edit*: proc(pressed_key: string): void ## This called when user press any key.
|
|
|
|
|
|
const
|
|
@@ -36,10 +37,12 @@ const
|
|
|
proc EditText*(name: string = "EditText", hint: string = "Edit text ..."): EditTextRef =
|
|
|
nodepattern(EditTextRef)
|
|
|
controlpattern()
|
|
|
+ result.is_blink = false
|
|
|
+ result.is_select = false
|
|
|
result.caret = true
|
|
|
- result.caret_pos = 0
|
|
|
+ result.selectable = true
|
|
|
+ result.caret_pos = [0u32, 0u32]
|
|
|
result.caret_color = Color("#ffccddaa")
|
|
|
- result.is_blink = false
|
|
|
result.blink_time = BLINK_TIME
|
|
|
result.text = stext("")
|
|
|
result.hint = stext(hint)
|
|
@@ -61,9 +64,15 @@ method draw*(self: EditTextRef, w, h: Glfloat) =
|
|
|
let
|
|
|
x = -w/2 + self.global_position.x
|
|
|
y = h/2 - self.global_position.y
|
|
|
- caret = self.text.getCaretPos(self.caret_pos)
|
|
|
xalign = x + self.rect_size.x*self.text_align.x1 - self.rect_min_size.x*self.text_align.x2
|
|
|
yalign = y - self.rect_size.y*self.text_align.y1 + self.rect_min_size.y*self.text_align.y2
|
|
|
+ var
|
|
|
+ lines = self.text.splitLines()
|
|
|
+ w: cint
|
|
|
+ h: cint
|
|
|
+ x1 = 0f
|
|
|
+ y1 = 0f
|
|
|
+ i = 0u32
|
|
|
|
|
|
dec self.blink_time
|
|
|
if self.blink_time == 0:
|
|
@@ -75,25 +84,35 @@ method draw*(self: EditTextRef, w, h: Glfloat) =
|
|
|
else:
|
|
|
self.text.renderTo(Vector2(x+self.padding.x1, y-self.padding.y1), self.rect_size, self.text_align)
|
|
|
|
|
|
- if self.is_blink:
|
|
|
- glColor4f(self.caret_color.r, self.caret_color.g, self.caret_color.b, self.caret_color.a)
|
|
|
- glBegin(GL_QUADS)
|
|
|
- glVertex2f(
|
|
|
- xalign + caret[0].x,
|
|
|
- yalign - caret[0].y)
|
|
|
- glVertex2f(
|
|
|
- xalign + caret[0].x - BLINK_WIDTH,
|
|
|
- yalign - caret[0].y)
|
|
|
- glVertex2f(
|
|
|
- xalign + caret[0].x - BLINK_WIDTH,
|
|
|
- yalign - caret[0].y - caret[1].float)
|
|
|
- glVertex2f(
|
|
|
- xalign + caret[0].x,
|
|
|
- yalign - caret[0].y - caret[1].float)
|
|
|
- glEnd()
|
|
|
-
|
|
|
-
|
|
|
-template changeText( self, `text`, `save_properties`, t: untyped): untyped =
|
|
|
+ for line in lines:
|
|
|
+ discard self.text.font.sizeUtf8(($line).cstring, addr w, addr h)
|
|
|
+ x1 = self.rect_min_size.x*self.text_align.x1 - w.Glfloat*self.text_align.x2
|
|
|
+ for c in line.chars:
|
|
|
+ discard self.text.font.sizeUtf8(($c).cstring, addr w, addr h)
|
|
|
+ if self.is_select and (i >= self.caret_pos[0] and i < self.caret_pos[1]) or (i >= self.caret_pos[1] and i < self.caret_pos[0]):
|
|
|
+ glColor4f(0.4, 0.4, 0.7, 0.5)
|
|
|
+ glBegin(GL_QUADS)
|
|
|
+ glVertex2f(xalign+x1, yalign-y1)
|
|
|
+ glVertex2f(xalign+x1+w.Glfloat, yalign-y1)
|
|
|
+ glVertex2f(xalign+x1+w.Glfloat, yalign-y1-h.Glfloat)
|
|
|
+ glVertex2f(xalign+x1, yalign-y1-h.Glfloat)
|
|
|
+ glEnd()
|
|
|
+ if self.is_blink and i == self.caret_pos[0]:
|
|
|
+ glColor4f(self.caret_color.r, self.caret_color.g, self.caret_color.b, self.caret_color.a)
|
|
|
+ glBegin(GL_QUADS)
|
|
|
+ glVertex2f(xalign+x1, yalign-y1)
|
|
|
+ glVertex2f(xalign+x1+BLINK_WIDTH, yalign-y1)
|
|
|
+ glVertex2f(xalign+x1+BLINK_WIDTH, yalign-y1-h.Glfloat)
|
|
|
+ glVertex2f(xalign+x1, yalign-y1-h.Glfloat)
|
|
|
+ glEnd()
|
|
|
+ x1 += w.float
|
|
|
+ inc i
|
|
|
+ y1 += self.text.spacing
|
|
|
+ y1 += h.float
|
|
|
+ inc i
|
|
|
+
|
|
|
+
|
|
|
+template changeText(self, `text`, `save_properties`, t: untyped): untyped =
|
|
|
var st = stext(`text`)
|
|
|
if `self`.`t`.font.isNil():
|
|
|
`self`.`t`.font = standard_font
|
|
@@ -109,6 +128,28 @@ template changeText( self, `text`, `save_properties`, t: untyped): untyped =
|
|
|
`self`.resize(`self`.rect_size.x, `self`.rect_size.y)
|
|
|
`self`.`t`.rendered = false
|
|
|
|
|
|
+method moveCursorBy*(self: EditTextRef, value: int) {.base.} =
|
|
|
+ if value > 0:
|
|
|
+ self.caret_pos[0] += value.uint32
|
|
|
+ else:
|
|
|
+ self.caret_pos[0] -= (-value).uint32
|
|
|
+ self.caret_pos[1] = self.caret_pos[0]
|
|
|
+
|
|
|
+method insert*(self: EditTextRef, position: uint32, value: string) {.base.} =
|
|
|
+ let strtext = $self.text
|
|
|
+ if position > 0 and position < self.text.len().uint32: # insert in caret pos
|
|
|
+ self.setText(strtext[0..position-1] & value & strtext[position..^1])
|
|
|
+ self.moveCursorBy(1)
|
|
|
+ self.on_edit(value)
|
|
|
+ elif position == 0: # insert in start of text.
|
|
|
+ self.setText(value & strtext)
|
|
|
+ self.moveCursorBy(1)
|
|
|
+ self.on_edit(value)
|
|
|
+ elif position == self.text.len().uint32: # insert in end of text.
|
|
|
+ self.setText(strtext & value)
|
|
|
+ self.moveCursorBy(1)
|
|
|
+ self.on_edit(value)
|
|
|
+
|
|
|
method setText*(self: EditTextRef, t: string, save_properties: bool = false) =
|
|
|
## Changes text.
|
|
|
##
|
|
@@ -124,7 +165,6 @@ method setHintColor*(self: EditTextRef, color: ColorRef) {.base.} =
|
|
|
self.hint.setColor(color)
|
|
|
self.hint.rendered = false
|
|
|
|
|
|
-
|
|
|
method handle*(self: EditTextRef, event: InputEvent, mouse_on: var NodeRef) =
|
|
|
## Handles user input. Thi uses in the `window.nim`.
|
|
|
procCall self.ControlRef.handle(event, mouse_on)
|
|
@@ -135,43 +175,40 @@ method handle*(self: EditTextRef, event: InputEvent, mouse_on: var NodeRef) =
|
|
|
else:
|
|
|
setCursor(createSystemCursor(SDL_SYSTEM_CURSOR_ARROW))
|
|
|
|
|
|
- if event.kind == MOUSE and event.pressed and self.hovered:
|
|
|
- self.caret_pos = self.text.getPosUnderPoint(
|
|
|
- self.getGlobalMousePosition(),
|
|
|
- self.global_position + self.rect_size/2 - self.text.getTextSize()/2)
|
|
|
+ if event.kind == MOUSE and self.hovered:
|
|
|
+ if event.pressed:
|
|
|
+ self.caret_pos[0] = self.text.getPosUnderPoint(
|
|
|
+ self.getGlobalMousePosition(),
|
|
|
+ self.global_position + self.rect_size/2 - self.text.getTextSize()/2, self.text_align)
|
|
|
+ if self.selectable:
|
|
|
+ self.is_select = true
|
|
|
+ self.caret_pos[1] = self.caret_pos[0]
|
|
|
+ elif event.kind == MOTION:
|
|
|
+ if self.is_select and event.pressed:
|
|
|
+ self.caret_pos[1] = self.text.getPosUnderPoint(
|
|
|
+ self.getGlobalMousePosition(),
|
|
|
+ self.global_position + self.rect_size/2 - self.text.getTextSize()/2, self.text_align)
|
|
|
|
|
|
if self.focused:
|
|
|
if event.kind == TEXT and not event.pressed:
|
|
|
# Other keys
|
|
|
- if self.caret_pos > 0 and self.caret_pos < self.text.len().uint32: # insert in caret pos
|
|
|
- self.setText(($self.text)[0..self.caret_pos-1] & event.key & ($self.text)[self.caret_pos..^1])
|
|
|
- self.caret_pos += 1
|
|
|
- self.on_edit(event.key)
|
|
|
- elif self.caret_pos == 0: # insert in start of text.
|
|
|
- self.setText(event.key & ($self.text))
|
|
|
- self.caret_pos += 1
|
|
|
- self.on_edit(event.key)
|
|
|
- elif self.caret_pos == self.text.len().uint32: # insert in end of text.
|
|
|
- self.setText(($self.text) & event.key)
|
|
|
- self.caret_pos += 1
|
|
|
- self.on_edit(event.key)
|
|
|
+ self.insert(self.caret_pos[0], event.key)
|
|
|
elif event.kind == KEYBOARD and event.key in pressed_keys:
|
|
|
# Arrows
|
|
|
- if event.key_int == K_LEFT and self.caret_pos > 0:
|
|
|
- self.caret_pos -= 1
|
|
|
- elif event.key_int == K_RIGHT and self.caret_pos < self.text.len().uint32:
|
|
|
- self.caret_pos += 1
|
|
|
+ if event.key_int == K_LEFT and self.caret_pos[0] > 0:
|
|
|
+ self.moveCursorBy(-1)
|
|
|
+ elif event.key_int == K_RIGHT and self.caret_pos[0] < self.text.len().uint32:
|
|
|
+ self.moveCursorBy(1)
|
|
|
|
|
|
elif event.key_int == 8: # Backspace
|
|
|
- if self.caret_pos > 1 and self.caret_pos < self.text.len().uint32:
|
|
|
- self.setText($self.text[0..self.caret_pos-2] & $self.text[self.caret_pos..^1])
|
|
|
- self.caret_pos -= 1
|
|
|
- elif self.caret_pos == self.text.len().uint32 and self.caret_pos > 0:
|
|
|
+ if self.caret_pos[0] > 1 and self.caret_pos[0] < self.text.len().uint32:
|
|
|
+ self.setText($self.text[0..self.caret_pos[0]-2] & $self.text[self.caret_pos[0]..^1])
|
|
|
+ self.moveCursorBy(-1)
|
|
|
+ elif self.caret_pos[0] == self.text.len().uint32 and self.caret_pos[0] > 0:
|
|
|
self.setText($self.text[0..^2])
|
|
|
- self.caret_pos -= 1
|
|
|
- elif self.caret_pos == 1:
|
|
|
+ self.moveCursorBy(-1)
|
|
|
+ elif self.caret_pos[0] == 1:
|
|
|
self.setText($self.text[1..^1])
|
|
|
- self.caret_pos -= 1
|
|
|
+ self.moveCursorBy(-1)
|
|
|
elif event.key_int == 13: # Next line
|
|
|
- self.setText($self.text[0..self.caret_pos-1] & "\n" & $self.text[self.caret_pos..^1])
|
|
|
- self.caret_pos += 1
|
|
|
+ self.insert(self.caret_pos[0], "\n")
|