Skip to content

Commit

Permalink
add/change: request redraw when object property was changed, everywhe…
Browse files Browse the repository at this point in the history
…re (no more need to call redraw manually)
  • Loading branch information
levovix0 committed Feb 11, 2024
1 parent f547468 commit a5d3506
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 41 deletions.
3 changes: 1 addition & 2 deletions src/sigui/animations.nim
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import times, strutils
import siwin
import ./uibase
import ./events {.all.}
export times
Expand Down Expand Up @@ -98,7 +97,6 @@ proc addChild*[T](obj: Uiobj, a: Animation[T]) =
proc act =
if a.enabled[] and a.action != nil and a.duration != DurationZero:
a.action(a.currentValue)
redraw obj

proc tick(deltaTime: Duration) =
if a.enabled[] and a.running[]:
Expand Down Expand Up @@ -173,6 +171,7 @@ template transition*[T](prop: var AnyProperty[T], dur: Duration): Animation[T] =


when isMainModule:
import siwin
import ./globalShortcut

let animator = newOpenglWindow(size = ivec2(300, 40)).newUiWindow
Expand Down
3 changes: 3 additions & 0 deletions src/sigui/mouseArea.nim
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ type
pressedPos: IVec2
grabStarted: bool

proc initRedrawWhenPropertyChanged_ignore(t: type MouseArea, name: string): bool =
true # MouseArea doesn't draw anything

registerComponent MouseArea


Expand Down
22 changes: 8 additions & 14 deletions src/sigui/textArea.nim
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ method recieve*(this: TextArea, signal: Signal) =


method init*(this: TextArea) =
if this.initialized: return
procCall this.super.init()

this.cursorPos = CustomProperty[int](
Expand Down Expand Up @@ -240,13 +239,13 @@ method init*(this: TextArea) =
this.binding x: root.offset[]

root.textObj --- newUiText():
this.centerY = parent.center
centerY = parent.center
this.binding text: root.text[]
this.x[] = 1
x = 1

root.cursorObj --- newUiRect().UiObj:
this.fillVertical parent
this.w[] = 2
w = 2
this.binding visibility:
if root.active[]:
if root.blinking.enabled[]:
Expand All @@ -256,11 +255,6 @@ method init*(this: TextArea) =
Visibility.hiddenTree
else: Visibility.visible
else: Visibility.hiddenTree
do: discard
do: false # redraw

this.visibility.changed.connectTo this:
redraw this

this.binding x: root.cursorX[]
root.binding cursorX:
Expand Down Expand Up @@ -293,12 +287,12 @@ when isMainModule:
preview(clearColor = color(1, 1, 1), margin = 20,
withWindow = proc: Uiobj =
let this = TextArea()
init this
this.text[] = "start text"
this.textObj[].font[] = typeface.withSize(24)
this.w[] = 400
this.h[] = this.textObj[].h[]
this.makeLayout:
text = "start text"
this.textObj[].font[] = typeface.withSize(24)
w = 400
h = this.textObj[].h[]

- UiRectBorder():
this.fill(parent, -1)
this
Expand Down
115 changes: 91 additions & 24 deletions src/sigui/uibase.nim
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,35 @@ method recieve*(obj: Uiobj, signal: Signal) {.base.} =
x.recieve(signal)


proc initRedrawWhenPropertyChangedStatic[T: UiObj](this: T) =
{.push, warning[Deprecated]: off.}
for name, x in this[].fieldPairs:
when name == "visibility":
x.changed.connectTo this: redraw this

elif name == "globalX" or name == "globalY":
discard # will anyway be handled in parent

elif x is Property or x is CustomProperty:
when compiles(initRedrawWhenPropertyChanged_ignore(T, name)):
when not initRedrawWhenPropertyChanged_ignore(T, name):
x.changed.connectTo this:
if this.visibility[] == visible:
redraw this
else:
x.changed.connectTo this:
if this.visibility[] == visible:
redraw this
{.pop.}


method initRedrawWhenPropertyChanged*(obj: Uiobj) {.base.} =
initRedrawWhenPropertyChangedStatic(obj)


method init*(obj: Uiobj) {.base.} =
initRedrawWhenPropertyChanged(obj)

obj.visibility.changed.connectTo obj:
obj.recieve(VisibilityChanged(sender: obj, visibility: obj.visibility))

Expand Down Expand Up @@ -754,9 +782,8 @@ proc deteachStatic[T: UiObj](this: T) =

{.push, warning[Deprecated]: off.}
for x in this[].fields:
when x is Property[T] or x is CustomProperty[T]:
when x is Property or x is CustomProperty:
disconnect x.changed
else: discard
{.pop.}


Expand Down Expand Up @@ -1754,7 +1781,7 @@ macro makeLayout*(obj: Uiobj, body: untyped) =
impl(nnkDotExpr.newTree(ident "root", ident "parent"), ident "root", if body.kind == nnkStmtList: body else: newStmtList(body))


proc bindingImpl*(obj: NimNode, target: NimNode, body: NimNode, afterUpdate: NimNode, redraw: bool, init: bool, kind: BindingKind): NimNode =
proc bindingImpl*(obj: NimNode, target: NimNode, body: NimNode, afterUpdate: NimNode, init: bool, kind: BindingKind): NimNode =
## connects update proc to every `x[]` property changed, and invokes update proc instantly
##
## .. code-block:: nim
Expand Down Expand Up @@ -1830,42 +1857,53 @@ proc bindingImpl*(obj: NimNode, target: NimNode, body: NimNode, afterUpdate: Nim
case afterUpdate
of Call[Sym(strVal: "newStmtList"), HiddenStdConv[Empty(), Bracket()]]: discard
else: afterUpdate

if redraw and kind != bindProperty: call bindSym "redraw", thisInProc

var stmts: seq[NimNode]
(impl(stmts, body))
for x in stmts: x

if redraw and kind == bindProperty:
call:
ident "connectTo"
dotExpr(dotExpr(objCursor, target), ident "changed")
objCursor
call bindSym "redraw", objCursor

if init:
call updateProc, objCursor


macro binding*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool = true, init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, redraw, init, bindProperty)
macro binding*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, init, bindProperty)

macro bindingValue*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool = true, init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, redraw, init, bindValue)
macro bindingValue*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, init, bindValue)

macro bindingProc*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool = true, init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, redraw, init, bindProc)
macro bindingProc*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, init, bindProc)


macro binding*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool = true, init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, redraw, init, bindProperty)
macro binding*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, init, bindProperty)

macro bindingValue*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool = true, init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, redraw, init, bindValue)
macro bindingValue*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, init, bindValue)

macro bindingProc*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool = true, init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, redraw, init, bindProc)
macro bindingProc*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), init: static bool = true): untyped =
bindingImpl(obj, target, body, afterUpdate, init, bindProc)


macro binding*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool, init: static bool = true): untyped {.deprecated: "there is no more need to manually call redraw".} =
bindingImpl(obj, target, body, afterUpdate, init, bindProperty)

macro bindingValue*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool, init: static bool = true): untyped {.deprecated: "there is no more need to manually call redraw".} =
bindingImpl(obj, target, body, afterUpdate, init, bindValue)

macro bindingProc*(obj: EventHandler, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool, init: static bool = true): untyped {.deprecated: "there is no more need to manually call redraw".} =
bindingImpl(obj, target, body, afterUpdate, init, bindProc)


macro binding*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool, init: static bool = true): untyped {.deprecated: "there is no more need to manually call redraw".} =
bindingImpl(obj, target, body, afterUpdate, init, bindProperty)

macro bindingValue*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool, init: static bool = true): untyped {.deprecated: "there is no more need to manually call redraw".} =
bindingImpl(obj, target, body, afterUpdate, init, bindValue)

macro bindingProc*[T: HasEventHandler](obj: T, target: untyped, body: typed, afterUpdate: typed = newStmtList(), redraw: static bool, init: static bool = true): untyped {.deprecated: "there is no more need to manually call redraw".} =
bindingImpl(obj, target, body, afterUpdate, init, bindProc)


proc withSize*(typeface: Typeface, size: float): Font =
Expand Down Expand Up @@ -1974,6 +2012,35 @@ macro generateDeteachMethod(t: typed) =
registerReflection generateDeteachMethod, T is Uiobj and t != "Uiobj"


macro generateInitRedrawWhenPropertyChangedMethod(t: typed) =
nnkMethodDef.newTree(
nnkPostfix.newTree(
ident("*"),
ident("initRedrawWhenPropertyChanged")
),
newEmptyNode(),
newEmptyNode(),
nnkFormalParams.newTree(
newEmptyNode(),
nnkIdentDefs.newTree(
ident("this"),
t,
newEmptyNode()
)
),
newEmptyNode(),
newEmptyNode(),
nnkStmtList.newTree(
nnkCall.newTree(
bindSym("initRedrawWhenPropertyChangedStatic"),
ident("this")
)
)
)

registerReflection generateInitRedrawWhenPropertyChangedMethod, T is Uiobj and t != "Uiobj"


converter toColor*(s: string{lit}): chroma.Color =
case s.len
of 3:
Expand Down
1 change: 0 additions & 1 deletion tests/t_todoapp.nim
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ test "todo app":

parent.scrolled.connectTo this, delta:
targetY[] = (targetY[] - delta.y * 56).min(0).max(-(app.layout[].h[] - 56).max(0))
redraw this

app.layout --- Layout():
this.binding w: parent.w[]
Expand Down

0 comments on commit a5d3506

Please sign in to comment.