Przeglądaj źródła

add RichLabel node.

SakiKawasaki 5 lat temu
rodzic
commit
68d3347810

+ 6 - 3
src/nodesnim.nim

@@ -13,6 +13,7 @@ import
   nodesnim/core/exceptions,
   nodesnim/core/input,
   nodesnim/core/image,
+  nodesnim/core/color_text,
 
   nodesnim/nodes/node,
   nodesnim/nodes/scene,
@@ -27,11 +28,13 @@ import
   nodesnim/nodescontrol/hbox,
   nodesnim/nodescontrol/vbox,
   nodesnim/nodescontrol/grid_box,
-  nodesnim/nodescontrol/edittext
+  nodesnim/nodescontrol/edittext,
+  nodesnim/nodescontrol/rich_label
 
 export
   opengl, glut,
   window, environment,
-  vector2, rect2, enums, anchor, color, exceptions, input, image,
+  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
+  control, color_rect, texture_rect, label, button, box, hbox, vbox, grid_box, edittext,
+  rich_label

+ 3 - 0
src/nodesnim/core/color.nim

@@ -174,3 +174,6 @@ proc lerp*(r1, g1, b1, a1, r2, g2, b2, a2: uint32, lerpv: float): uint32 =
 
 proc `$`*(color: ColorRef): string =
   "Color(" & $color.r & ", " & $color.g & ", " & $color.b & ", " & $color.a & ")"
+
+proc `==`*(x, y: ColorRef): bool =
+  x.r == y.r and x.g == y.g and x.b == y.b and x.a == y.a

+ 117 - 0
src/nodesnim/core/color_text.nim

@@ -0,0 +1,117 @@
+# author: Ethosa
+import color
+
+
+type
+  ColorCharRef* = ref object
+    c*: char
+    color*: ColorRef
+  ColorTextRef* = ref object
+    chars*: seq[ColorCharRef]
+
+
+func clrtext*(text: string, color: ColorRef = Color(1f, 1f, 1f)): ColorTextRef =
+  ## Creates a new ColorText ref object.
+  runnableExamples:
+    import color
+    var
+      text = clrtext"hello"
+      text1 = clrtext("hello", Color(1, 0.6, 1))
+  var chars: seq[ColorCharRef] = @[]
+  for c in text:
+    chars.add(ColorCharRef(c: c, color: color))
+  result = ColorTextRef(chars: chars)
+
+
+func clrchar*(c: char, color: ColorRef = Color(1f, 1f, 1f)): ColorCharRef =
+  ## Creates a new ColorChar ref object.
+  runnableExamples:
+    import color
+    var
+      c = clrchar's'
+      c1 = clrchar('s', Color(1f, 1f, 1f))
+  result = ColorCharRef(c: c, color: color)
+
+
+proc setColor*(self: ColorTextRef, fromc, toc: int, value: ColorRef) =
+  runnableExamples:
+    import color
+    var
+      text = clrtext"hello world"
+      clr = Color(1, 0.6, 1)
+    text.setColor(5, text.chars.len()-1, clr)
+  for i in fromc..toc:
+    self.chars[i].color = value
+
+
+proc setColor*(self: ColorTextRef, index: int, value: ColorRef) =
+  runnableExamples:
+    import color
+    var
+      text = clrtext"hello world"
+      clr = Color(1, 0.6, 1)
+    text.setColor(0, clr)
+  self.chars[index].color = value
+
+# --- Operators --- #
+proc `$`*(text: ColorTextRef): string =
+  result = ""
+  for c in text.chars:
+    result &= $c.c
+
+proc `$`*(c: ColorCharRef): string =
+  result = $c.c
+
+proc `==`*(x, y: ColorTextRef): bool =
+  result = true
+  if x.chars.len() == y.chars.len():
+    for i in 0..x.chars.high:
+      if x.chars[i].c != y.chars[i].c and x.chars[i].color != y.chars[i].color:
+        result = false
+  else:
+    result = false
+
+proc `&`*(x, y: ColorCharRef): ColorTextRef =
+  runnableExamples:
+    var
+      a = clrchar'a'
+      b = clrchar'b'
+    assert a & b == clrtext"ab"
+  result = clrtext("")
+  result.chars.add(x)
+  result.chars.add(y)
+
+proc `&`*(x: ColorTextRef, y: ColorCharRef): ColorTextRef =
+  result = x
+  result.chars.add(y)
+
+proc `&`*(x, y: ColorTextRef): ColorTextRef =
+  result = x
+  for c in y.chars:
+    result.chars.add(c)
+
+proc contains*(x: ColorTextRef, y: ColorCharRef): bool =
+  runnableExamples:
+    var
+      text = clrtext"hello"
+      c = clrchar'o'
+    assert c in text
+  for c in x.chars:
+    if c.c == y.c and c.color == y.color:
+      return true
+
+converter char*(x: ColorCharRef): char =
+  x.c
+
+proc len*(x: ColorTextRef): int =
+  x.chars.len()
+
+proc splitLines*(x: ColorTextRef): seq[ColorTextRef] =
+  result = @[clrtext""]
+  for c in x.chars:
+    if c.c != '\n':
+      result[^1].chars.add(c)
+    else:
+      result.add(clrtext"")
+  if result[^1].len() == 0:
+    discard result.pop()

+ 11 - 0
src/nodesnim/nodes/node.nim

@@ -35,6 +35,7 @@ type
 
 
 template nodepattern*(nodetype: untyped): untyped =
+  ## This used in childs of the NodeObj.
   variable = `nodetype`(
     name: name, position: Vector2(), children: @[],
     global_position: Vector2(),
@@ -189,6 +190,7 @@ method hasNode*(self: NodePtr, other: NodePtr): bool {.base.} =
   self.getChildIndex(other) != -1
 
 method hasParent*(self: NodePtr): bool {.base, inline.} =
+  ## Returns true, when node has parent.
   self.parent != nil
 
 method move*(self: NodePtr, x, y: float) {.base, inline.} =
@@ -226,10 +228,19 @@ method removeChild*(self: NodePtr, other: NodePtr) {.base.} =
     self.removeChild(index)
 
 method setAnchor*(self: NodePtr, anchor: AnchorRef) {.base.} =
+  ## Changes node anchor.
+  ##
+  ## Arguments:
+  ## - `anchor` - AnchorRef object.
   self.anchor = anchor
   self.can_use_anchor = true
 
 method setAnchor*(self: NodePtr, x1, y1, x2, y2: float) {.base.} =
+  ## Changes node anchor.
+  ##
+  ## Arguments:
+  ## - `x1` and `y1` - anchor relative to the parent node.
+  ## - `x2` and `y2` - anchor relative to this node.
   self.anchor = Anchor(x1, y1, x2, y2)
   self.can_use_anchor = true
 

+ 80 - 0
src/nodesnim/nodescontrol/rich_label.nim

@@ -0,0 +1,80 @@
+# 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
+  RichLabelObj* = object of ControlPtr
+    font*: pointer          ## Glut font data.
+    spacing*: float         ## Font spacing.
+    size*: float            ## Font size.
+    text*: ColorTextRef     ## RichLabel text.
+    text_align*: AnchorRef  ## Text align.
+  RichLabelPtr* = ptr RichLabelObj
+
+
+proc RichLabel*(name: string, variable: var RichLabelObj): RichLabelPtr =
+  nodepattern(RichLabelObj)
+  controlpattern()
+  variable.rect_size.x = 40
+  variable.rect_size.y = 40
+  variable.text = clrtext""
+  variable.font = GLUT_BITMAP_HELVETICA_12
+  variable.size = 12
+  variable.spacing = 2
+  variable.text_align = Anchor(0, 0, 0, 0)
+
+proc RichLabel*(obj: var RichLabelObj): RichLabelPtr {.inline.} =
+  RichLabel("RichLabel", obj)
+
+
+method draw*(self: RichLabelPtr, w, h: GLfloat) =
+  self.calcGlobalPosition()
+  let
+    x = -w/2 + self.global_position.x
+    y = h/2 - self.global_position.y
+
+  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
+
+  for line in self.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 self.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:
+      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
+      tx += self.font.glutBitmapWidth(c.c.int).float
+    ty -= self.spacing + self.size
+
+  # Press
+  if self.pressed:
+    self.press(last_event.x, last_event.y)
+
+method setTextAlign*(self: RichLabelPtr, align: AnchorRef) {.base.} =
+  self.text_align = align
+
+method setTextAlign*(self: RichLabelPtr, x1, y1, x2, y2: float) {.base.} =
+  self.text_align = Anchor(x1, y1, x2, y2)

+ 1 - 0
tests/README.md

@@ -16,3 +16,4 @@
 14. [Use VBox node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test14.nim)
 15. [Use GridBox node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test15.nim)
 16. [Use TextEdit node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test16.nim)
+17. [Use RichLabel node.](https://github.com/Ethosa/nodesnim/blob/master/tests/test17.nim)

+ 25 - 0
tests/test17.nim

@@ -0,0 +1,25 @@
+# --- Test 17. Use RichLabel node. --- #
+import nodesnim
+
+
+Window("hello world")
+
+var
+  mainobj: SceneObj
+  main = Scene("Main", mainobj)
+
+  labelobj: RichLabelObj
+  label = RichLabel(labelobj)
+
+main.addChild(label)
+
+label.text = clrtext("Hello, world!\nsecondline\nThis is a long sentence.")  # Change label text.
+label.setTextAlign(0.2, 0.5, 0.2, 0.5)  # try to change it ^^.
+label.setSizeAnchor(1, 1)
+label.text.setColor(0, 4, Color(1, 0.6, 1))
+label.text.setColor(8, 16, Color(0xffccaaff'u32))
+
+
+addScene(main)
+setMainScene("Main")
+windowLaunch()