Browse Source

add Tooltip

Ethosa 3 years ago
parent
commit
cfd23c8cf3

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2020 Ethosa
+Copyright (c) 2021 Ethosa
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

+ 8 - 8
examples/readme.md

@@ -1,24 +1,24 @@
 # Examples
 
-## [Hello world](https://github.com/Ethosa/nodesnim/blob/master/examples/hello_world)
+## [Hello world](https://github.com/Ethosa/nodesnim/blob/nightly/examples/hello_world)
 ![Hello world](https://github.com/Ethosa/nodesnim/blob/nightly/screenshots/1.png)
 
-## [Calculator](https://github.com/Ethosa/nodesnim/blob/master/examples/calculator)
+## [Calculator](https://github.com/Ethosa/nodesnim/blob/nightly/examples/calculator)
 ![Calculator](https://github.com/Ethosa/nodesnim/blob/nightly/screenshots/2.png)
 
-## [Snake game](https://github.com/Ethosa/nodesnim/blob/master/examples/snake)
+## [Snake game](https://github.com/Ethosa/nodesnim/blob/nightly/examples/snake)
 ![Snake game](https://github.com/Ethosa/nodesnim/blob/nightly/screenshots/3.png)
 
-## [Screen saver](https://github.com/Ethosa/nodesnim/blob/master/examples/screensaver)
+## [Screen saver](https://github.com/Ethosa/nodesnim/blob/nightly/examples/screensaver)
 ![Screen saver](https://github.com/Ethosa/nodesnim/blob/nightly/screenshots/4.png)
 
-## [Novel](https://github.com/Ethosa/nodesnim/blob/master/examples/novel)
+## [Novel](https://github.com/Ethosa/nodesnim/blob/nightly/examples/novel)
 ![Novel](https://github.com/Ethosa/nodesnim/blob/nightly/screenshots/5.png)
 
-## [Roguelike](https://github.com/Ethosa/nodesnim/blob/master/examples/roguelike)
+## [Roguelike](https://github.com/Ethosa/nodesnim/blob/nightly/examples/roguelike)
 ![Roguelike](https://github.com/Ethosa/nodesnim/blob/nightly/screenshots/6.png)
 
-## [Sample messenger](https://github.com/Ethosa/nodesnim/blob/master/examples/sample_messenger)
+## [Sample messenger](https://github.com/Ethosa/nodesnim/blob/nightly/examples/sample_messenger)
 ![Sample messenger](https://github.com/Ethosa/nodesnim/blob/nightly/screenshots/7.png)
 
-## [Builder features](https://github.com/Ethosa/nodesnim/blob/master/examples/builder_features)
+## [Builder features](https://github.com/Ethosa/nodesnim/blob/nightly/examples/builder_features)

+ 27 - 28
src/nodesnim/core/scene_builder.nim

@@ -6,37 +6,36 @@ proc addNode(level: var seq[NimNode], code: NimNode): NimNode {.compileTime.} =
   result = newStmtList()
   if code.kind in [nnkStmtList, nnkObjConstr, nnkCall]:
     for line in code.children():
-      if line.kind == nnkPrefix:
-        if line[0].kind == nnkIdent and line[1].kind == nnkCommand:
-          # - Node name:
-          if $line[0] == "-":
-            case line[1][1].kind
-            of nnkIdent:  # - Node name:
-              result.add(newVarStmt(line[1][1], newCall($line[1][0], newStrLitNode($line[1][1]))))
-            of nnkObjConstr:  # - Node name(a: .., b: ...)
-              result.add(newVarStmt(line[1][1][0], newCall($line[1][0], newStrLitNode($line[1][1][0]))))
-            of nnkPar:  # Node (name):
-              result.add(newVarStmt(postfix(line[1][1][0], "*"), newCall($line[1][0], newStrLitNode($line[1][1][0]))))
-            of nnkCall:  # Node name(call smth()):
-              result.add(newVarStmt(line[1][1][0], newCall($line[1][0], newStrLitNode($line[1][1][0]))))
+      if line.kind == nnkPrefix and line[0].kind == nnkIdent and line[1].kind == nnkCommand:
+        # - Node name:
+        if $line[0] == "-":
+          case line[1][1].kind
+          of nnkIdent:  # - Node name:
+            result.add(newVarStmt(line[1][1], newCall($line[1][0], newStrLitNode($line[1][1]))))
+          of nnkObjConstr:  # - Node name(a: .., b: ...)
+            result.add(newVarStmt(line[1][1][0], newCall($line[1][0], newStrLitNode($line[1][1][0]))))
+          of nnkPar:  # Node (name):
+            result.add(newVarStmt(postfix(line[1][1][0], "*"), newCall($line[1][0], newStrLitNode($line[1][1][0]))))
+          of nnkCall:  # Node name(call smth()):
+            result.add(newVarStmt(line[1][1][0], newCall($line[1][0], newStrLitNode($line[1][1][0]))))
+          else:
+            discard
+
+          if level.len() > 0:
+            case line[1][1].kind:
+            of nnkIdent:
+              result.add(newCall("addChild", level[^1], line[1][1]))
+            of nnkPar, nnkObjConstr, nnkCall:
+              result.add(newCall("addChild", level[^1], line[1][1][0]))
             else:
               discard
 
-            if level.len() > 0:
-              case line[1][1].kind:
-              of nnkIdent:
-                result.add(newCall("addChild", level[^1], line[1][1]))
-              of nnkPar, nnkObjConstr, nnkCall:
-                result.add(newCall("addChild", level[^1], line[1][1][0]))
-              else:
-                discard
-
-            if line[1][1].kind == nnkObjConstr:  # - Node node(...)
-              level.add(line[1][1][0])
-              let nodes = addNode(level, line[1][1])
-              for i in nodes.children():
-                result.add(i)
-      # call  hodName(arg1, arg2) -> currentNode.methodName(arg1, arg2)
+          if line[1][1].kind == nnkObjConstr:  # - Node node(...)
+            level.add(line[1][1][0])
+            let nodes = addNode(level, line[1][1])
+            for i in nodes.children():
+              result.add(i)
+      # call methodName(arg1, arg2) -> currentNode.methodName(arg1, arg2)
       elif line.kind == nnkCommand and $line[0] == "call" and level.len > 0:
         line[1].insert(1, level[^1])
         result.add(line[1])

+ 17 - 0
src/nodesnim/nodes/canvas.nim

@@ -132,6 +132,23 @@ method move*(self: CanvasRef, x, y: float) {.base, inline.} =
   self.position += Vector2(x, y)
   self.anchor.clear()
 
+method moveTo*(self: CanvasRef, x, y: float) {.base, inline.} =
+  ## Change node position.
+  ##
+  ## Arguments:
+  ## - `x`: how much to add to the position on the X axis.
+  ## - `y`: how much to add to the position on the Y axis.
+  self.position = Vector2(x, y)
+  self.anchor.clear()
+
+method moveTo*(self: CanvasRef, vec2: Vector2Obj) {.base, inline.} =
+  ## Change node position.
+  ##
+  ## Arguments:
+  ## - `vec2`: how much to add to the position on the X,Y axes.
+  self.position = vec2
+  self.anchor.clear()
+
 method resize*(self: CanvasRef, w, h: GLfloat, save_anchor: bool = false) {.base.} =
   ## Resizes canvas.
   ##

+ 3 - 2
src/nodesnim/nodescontrol.nim

@@ -18,10 +18,11 @@ import
   nodescontrol/counter,
   nodescontrol/switch,
   nodescontrol/subwindow,
-  nodescontrol/checkbox
+  nodescontrol/checkbox,
+  nodescontrol/tooltip
 
 export
   control, color_rect, texture_rect, label, button,
   box, hbox, vbox, grid_box, edittext, scroll, progress_bar,
   slider, popup, texture_button, texture_progress_bar,
-  counter, switch, subwindow, checkbox
+  counter, switch, subwindow, checkbox, tooltip

+ 76 - 0
src/nodesnim/nodescontrol/tooltip.nim

@@ -0,0 +1,76 @@
+# author: Ethosa
+import
+  ../thirdparty/opengl,
+
+  ../core/vector2,
+  ../core/font,
+  ../core/enums,
+  ../core/color,
+  ../core/anchor,
+
+  ../nodes/node,
+  ../nodes/canvas,
+
+  ../graphics/drawable,
+
+  ../window,
+
+  control
+
+
+type
+  ToolTipObj* = object of ControlObj
+    text*: StyleText
+  ToolTipRef* = ref ToolTipObj
+
+const TOOLTIP_SPACE: float = 32f
+
+
+proc ToolTip*(name: string = "ToolTip",
+             tooltip: string = "Tooltip"): ToolTipRef =
+  nodepattern(ToolTipRef)
+  controlpattern()
+  result.text = stext(tooltip)
+  result.background.setColor(Color("#444"))
+  result.background.setBorderColor(Color("#555"))
+  result.background.setBorderWidth(0.5)
+  result.background.setCornerRadius(8)
+  result.background.setCornerDetail(8)
+  result.background.enableShadow(true)
+  result.background.setShadowOffset(Vector2(0, 5))
+  result.mousemode = MOUSEMODE_IGNORE
+  result.hide()
+
+
+method draw*(self: ToolTipRef, w, h: GLfloat) =
+  procCall self.ControlRef.draw(w, h)
+  let
+    x = -w/2 + self.global_position.x
+    y = h/2 - self.global_position.y
+
+  self.text.renderTo(Vector2(x, y), self.rect_size, Anchor(0, 0, 0, 0))
+
+method showAt*(self: ToolTipRef, x, y: float) {.base.} =
+  self.moveTo(x, y)
+  self.rect_min_size = self.text.getTextSize()
+  self.resize(self.rect_size.x, self.rect_size.y, true)
+  self.show()
+
+method showAtMouse*(self: ToolTipRef) {.base.} =
+  let
+    pos = self.getGlobalMousePosition()
+    textsize = self.text.getTextSize()
+    windowsize = getWindowSize()
+  self.moveTo(pos)
+
+  if pos.x + TOOLTIP_SPACE + textsize.x > windowsize.x:
+    self.move(-TOOLTIP_SPACE - textsize.x, 0)
+
+  if pos.y - TOOLTIP_SPACE - textsize.y < 0:
+    self.move(0, TOOLTIP_SPACE)
+  else:
+    self.move(0, -TOOLTIP_SPACE)
+
+  self.rect_min_size = self.text.getTextSize()
+  self.resize(self.rect_size.x, self.rect_size.y, true)
+  self.show()

+ 5 - 1
src/nodesnim/window.nim

@@ -8,6 +8,7 @@ import
   core/color,
   core/input,
   core/exceptions,
+  core/vector2,
 
   nodes/node,
   nodes/scene,
@@ -219,6 +220,9 @@ proc getSceneByName*(name: string): SceneRef =
     if scene.name == name:
       return scene
 
+proc getWindowSize*(): Vector2Obj =
+  Vector2(width.float, height.float)
+
 proc resizeWindow*(x, y: cint) =
   width = x
   height = y
@@ -255,7 +259,7 @@ proc Window*(title: cstring, w: cint = 640, h: cint = 360) {.cdecl.} =
   ## - `title` - window title.
   # Set up window.
   once:
-    when not defined(android) and not defined(ios):
+    when not defined(android) and not defined(ios) and not defined(useGlew):
       loadExtensions()  # Load OpenGL extensions.
       discard captureMouse(True32)
   windowptr = createWindow(

+ 8 - 0
tests/test3.nim

@@ -324,6 +324,14 @@ suite "Work with Control nodes.":
         call move(600, 310)
     getSceneByName("main").addChildren(slider1, slider2)
 
+  test "ToolTip test":
+    build:
+      - ToolTip tooltip:
+        call showAtMouse()
+        @onProcess():
+          tooltip.showAtMouse()
+    getSceneByName("main").addChild(tooltip)
+
 
   test "Launch window":
     windowLaunch()