Ethosa преди 5 години
родител
ревизия
c1a2b38933
променени са 5 файла, в които са добавени 226 реда и са изтрити 7 реда
  1. 3 2
      src/nodesnim.nim
  2. 34 4
      src/nodesnim/core/color_text.nim
  3. 0 1
      src/nodesnim/nodescontrol/button.nim
  4. 158 0
      src/nodesnim/nodescontrol/rich_edit_text.nim
  5. 31 0
      tests/test19.nim

+ 3 - 2
src/nodesnim.nim

@@ -29,7 +29,8 @@ import
   nodesnim/nodescontrol/vbox,
   nodesnim/nodescontrol/grid_box,
   nodesnim/nodescontrol/edittext,
-  nodesnim/nodescontrol/rich_label
+  nodesnim/nodescontrol/rich_label,
+  nodesnim/nodescontrol/rich_edit_text
 
 export
   opengl, glut,
@@ -37,4 +38,4 @@ export
   vector2, rect2, enums, anchor, color, exceptions, input, image, color_text,
   node, scene, canvas,
   control, color_rect, texture_rect, label, button, box, hbox, vbox, grid_box, edittext,
-  rich_label
+  rich_label, rich_edit_text

+ 34 - 4
src/nodesnim/core/color_text.nim

@@ -44,6 +44,17 @@ proc setColor*(self: ColorTextRef, fromc, toc: int, value: ColorRef) =
     self.chars[i].color = value
 
 
+proc setColor*(self: ColorTextRef, value: ColorRef) =
+  runnableExamples:
+    import color
+    var
+      text = clrtext"hello world"
+      clr = Color(1, 0.6, 0.8)
+    text.setColor(clr)
+  for i in 0..self.chars.high:
+    self.chars[i].color = value
+
+
 proc setColor*(self: ColorTextRef, index: int, value: ColorRef) =
   runnableExamples:
     import color
@@ -85,6 +96,10 @@ proc `&`*(x: ColorTextRef, y: ColorCharRef): ColorTextRef =
   result = x
   result.chars.add(y)
 
+proc `&`*(x: ColorCharRef, y: ColorTextRef): ColorTextRef =
+  result = y
+  result.chars.add(x)
+
 proc `&`*(x, y: ColorTextRef): ColorTextRef =
   result = x
   for c in y.chars:
@@ -100,18 +115,33 @@ proc contains*(x: ColorTextRef, y: ColorCharRef): bool =
     if c.c == y.c and c.color == y.color:
       return true
 
-converter char*(x: ColorCharRef): char =
+converter toChar*(x: ColorCharRef): char =
   x.c
 
 proc len*(x: ColorTextRef): int =
   x.chars.len()
 
 proc splitLines*(x: ColorTextRef): seq[ColorTextRef] =
-  result = @[clrtext""]
+  result = @[clrtext("")]
   for c in x.chars:
-    if c.c != '\n':
+    if c.c.int != 13:
       result[^1].chars.add(c)
     else:
-      result.add(clrtext"")
+      result.add(clrtext(""))
   if result[^1].len() == 0:
     discard result.pop()
+
+proc `[]`*[U, V](self: ColorTextRef, i: HSlice[U, V]): ColorTextRef =
+  ColorTextRef(chars: self.chars[i])
+
+proc `[]`*(self: ColorTextRef, i: BackwardsIndex): ColorCharRef =
+  self.chars[i]
+
+proc `[]`*(self: ColorTextRef, i: int): ColorCharRef =
+  self.chars[i]
+
+proc add*(self: var ColorTextRef, other: ColorTextRef) =
+  self = self & other
+
+proc add*(self: var ColorTextRef, other: ColorCharRef) =
+  self = self & other

+ 0 - 1
src/nodesnim/nodescontrol/button.nim

@@ -84,7 +84,6 @@ method dublicate*(self: ButtonPtr, obj: var ButtonObj): ButtonPtr {.base.} =
   obj = self[]
   obj.addr
 
-
 method handle*(self: ButtonPtr, event: InputEvent, mouse_on: var NodePtr) =
   procCall self.ControlPtr.handle(event, mouse_on)
 

+ 158 - 0
src/nodesnim/nodescontrol/rich_edit_text.nim

@@ -0,0 +1,158 @@
+# author: Ethosa
+import
+  ../thirdparty/opengl,
+  ../thirdparty/opengl/glut,
+
+  ../core/vector2,
+  ../core/rect2,
+  ../core/anchor,
+  ../core/input,
+  ../core/enums,
+  ../core/color,
+  ../core/color_text,
+
+  ../nodes/node,
+  control
+
+
+type
+  RichEditTextObj* = object of ControlPtr
+    blit_caret*: bool
+    blit_speed*: float
+    blit_time*: float
+    caret_position*: int
+    font*: pointer          ## Glut font data.
+    spacing*: float         ## Font spacing.
+    size*: float            ## Font size.
+    text*: ColorTextRef
+    hint_text*: ColorTextRef
+    caret_color*: ColorRef
+    text_align*: AnchorRef  ## Text align.
+  RichEditTextPtr* = ptr RichEditTextObj
+
+
+proc RichEditText*(name: string, variable: var RichEditTextObj): RichEditTextPtr =
+  nodepattern(RichEditTextObj)
+  controlpattern()
+  variable.rect_size.x = 64
+  variable.rect_size.y = 32
+  variable.text = clrtext""
+  variable.font = GLUT_BITMAP_HELVETICA_12
+  variable.size = 12
+  variable.spacing = 2
+  variable.text_align = Anchor(0, 0, 0, 0)
+  variable.hint_text = clrtext("Edit text ...", Color(0.8, 0.8, 0.8))
+  variable.caret_position = 0
+  variable.blit_caret = true
+  variable.caret_color = Color(1f, 1f, 1f, 0.5)
+  variable.blit_speed = 0.002
+  variable.blit_time = 0f
+
+proc RichEditText*(obj: var RichEditTextObj): RichEditTextPtr {.inline.} =
+  RichEditText("RichEditText", obj)
+
+
+method draw*(self: RichEditTextPtr, w, h: GLfloat) =
+  self.calcGlobalPosition()
+  let
+    x = -w/2 + self.global_position.x
+    y = h/2 - self.global_position.y
+    text =
+      if self.text.len() > 0:
+        self.text
+      else:
+        self.hint_text
+
+  glColor4f(self.background_color.r, self.background_color.g, self.background_color.b, self.background_color.a)
+  glRectf(x, y, x+self.rect_size.x, y-self.rect_size.y)
+  var
+    th = 0f
+    char_num = 0
+
+  for line in text.splitLines():  # get text height
+    th += self.spacing + self.size
+  if th != 0:
+    th -= self.spacing
+  var ty = y - self.rect_size.y*self.text_align.y1 + th*self.text_align.y2 - self.size
+
+  for line in text.splitLines():
+    var tw = self.font.glutBitmapLength($line).float
+    # Draw text:
+    var tx = x + self.rect_size.x*self.text_align.x1 - tw * self.text_align.x2
+    for c in line.chars:
+      let
+        cw = self.font.glutBitmapWidth(c.c.int).float
+        right =
+          if self.text_align.x2 > 0.9 and self.text_align.x1 > 0.9:
+            1f
+          else:
+            0f
+        bottom =
+          if self.text_align.y2 > 0.9 and self.text_align.y1 > 0.9:
+            1f
+          else:
+            0f
+      if tx >= x and tx < x + self.rect_size.x+right and ty <= y and ty > y - self.rect_size.y+bottom:
+        glColor4f(c.color.r, c.color.g, c.color.b, c.color.a)
+        glRasterPos2f(tx, ty)  # set char position
+        self.font.glutBitmapCharacter(c.c.int)  # render char
+
+        inc char_num
+        if char_num == self.caret_position and self.blit_caret and self.blit_time > 1f:
+          glColor4f(self.caret_color.r, self.caret_color.g, self.caret_color.b, self.caret_color.a)
+          glRectf(tx+cw, ty, tx+cw+2, ty+self.size)
+          if self.blit_time > 2f:
+            self.blit_time = 0f
+      tx += cw
+    inc char_num
+    ty -= self.spacing + self.size
+
+  self.blit_time += self.blit_speed
+
+  # Press
+  if self.pressed:
+    self.press(last_event.x, last_event.y)
+
+method dublicate*(self: RichEditTextPtr, obj: var RichEditTextObj): RichEditTextPtr {.base.} =
+  obj = self[]
+  obj.addr
+
+
+method handle*(self: RichEditTextPtr, event: InputEvent, mouse_on: var NodePtr) =
+  procCall self.ControlPtr.handle(event, mouse_on)
+
+  if self.focused:
+    if event.kind == KEYBOARD:
+      if event.key_cint in pressed_keys_cints:  # Special chars
+        if event.key_cint == K_LEFT and self.caret_position > 0:
+          self.caret_position -= 1
+        elif event.key_cint == K_RIGHT and self.caret_position < self.text.len():
+          self.caret_position += 1
+      elif event.key in pressed_keys:  # Normal chars
+        if event.key_int == 8:  # Backspace
+          if self.caret_position > 1 and self.caret_position < self.text.len():
+            self.text = self.text[0..self.caret_position-2] & self.text[self.caret_position..^1]
+            self.caret_position -= 1
+          elif self.caret_position == self.text.len() and self.caret_position > 0:
+            self.text = self.text[0..^2]
+            self.caret_position -= 1
+          elif self.caret_position == 1:
+            self.text = self.text[1..^1]
+            self.caret_position -= 1
+        elif self.caret_position > 0 and self.caret_position < self.text.len():
+          self.text = self.text[0..self.caret_position-1] & clrtext(event.key) & self.text[self.caret_position..^1]
+          self.caret_position += 1
+        elif self.caret_position == 0:
+          self.text = clrtext(event.key) & self.text
+          self.caret_position += 1
+        elif self.caret_position == self.text.len():
+          self.text &= clrtext(event.key)
+          self.caret_position += 1
+
+method setTextAlign*(self: RichEditTextPtr, align: AnchorRef) {.base.} =
+  ## Changes text align.
+  self.text_align = align
+
+method setTextAlign*(self: RichEditTextPtr, x1, y1, x2, y2: float) {.base.} =
+  ## Changes text align.
+  self.text_align = Anchor(x1, y1, x2, y2)

+ 31 - 0
tests/test19.nim

@@ -0,0 +1,31 @@
+# --- Test 19. Use RichEditText node. --- #
+import
+  strutils,
+  nodesnim
+
+
+Window("hello world")
+
+var
+  mainobj: SceneObj
+  main = Scene("Main", mainobj)
+
+  labelobj: RichEditTextObj
+  label = RichEditText(labelobj)
+
+main.addChild(label)
+
+label.setSizeAnchor(1, 1)
+
+label.process =
+  proc() =
+    label.text.setColor(Color(1f, 1f, 1f))
+    var start_position = ($label.text).find("Nim")
+    while start_position > -1:
+      label.text.setColor(start_position, start_position+2, Color(0xaa99ffff'u32))
+      start_position = ($label.text).find("Nim", start_position+2)
+
+
+addScene(main)
+setMainScene("Main")
+windowLaunch()