treeform / fidget

Figma based UI library for nim, with HTML and OpenGL backends.
MIT License
768 stars 33 forks source link

Counter-intuitive behaviour of event templates #112

Closed alt-tosc closed 3 years ago

alt-tosc commented 3 years ago

First thank you for this library! I'm new in the Nim world and in the "imperative UI style" world thanks to you :)

I played with the minimal.nim example and I noticed the behaviour is not the same for the following three pieces of code, which differ in the order of those statements: fill, onHover: fill and onClick: fill.

With this example onHover and onClick work as I expected:

## This minimal example shows 5 blue squares.

import fidget

proc drawMain() =
  frame "main":
    box 0, 0, 620, 140
    for i in 0 .. 4:
      group "block":
        box 20 + i * 120, 20, 100, 100
        fill "#2B9FEA"
        onHover:
          fill "#000"
        onClick:
          fill "#FFF"

startFidget(drawMain, w = 620, h = 140)

While with this example, onHover and onClick have no effect:

## This minimal example shows 5 blue squares.

import fidget

proc drawMain() =
  frame "main":
    box 0, 0, 620, 140
    for i in 0 .. 4:
      group "block":
        box 20 + i * 120, 20, 100, 100
        onClick:
          fill "#FFF"
        onHover:
          fill "#000"
        fill "#2B9FEA"

startFidget(drawMain, w = 620, h = 140)

Here, onHover works but not onClick:

import fidget

proc drawMain() =
  frame "main":
    box 0, 0, 620, 140
    for i in 0 .. 4:
      group "block":
        box 20 + i * 120, 20, 100, 100
        fill "#2B9FEA"
        onClick:
          fill "#FFF"
        onHover:
          fill "#000"

startFidget(drawMain, w = 620, h = 140)

I think it is at least surprising for a new user, because it differs from this other example: the observed behaviour is independent on the position of box 20 + i * 120, 20, 100, 100 statement inside the group "block".

Do you think that this is a "documentation issue" or that this behaviour is not expected?

Bahm commented 3 years ago

From the README (emphasis mine):

"Each UI frame is drawn completely from start to finish all in the code you control. Use of callbacks is discouraged. Think liner, think simple. After any event by the user, data or timer, the UI is redrawn. The UI is redrawn in an efficient way as to allow this. With HTML a modification cache is used to ensure only a minimal amount of DOM changes are needed. With OpenGL you redraw the whole screen using as few state transitions and batching everything into a texture atlas and single global vertex buffer."

Sounds like drawMain is called when an event is triggered, rather than just the code in onClick or onHover. I haven't taken a look at the internals yet though, so I might be wrong.

treeform commented 3 years ago

In your second example, it has no effect because as soon as you set fill color you override it next line.

In your third example same thing. onClick sets the fill, then you override it with hover.

Think of "onHover" as "if house is hovering:" and "onClick" as "if mouse is hovering and mouse button just pressed this frame:"

See code: https://github.com/treeform/fidget/blob/master/src/fidget.nim#L142

The code is working as expected. Closing for now. Feel free to ask more questions.

alt-tosc commented 3 years ago

Thank you for your both answers.

It was surprising for the me of six days ago (that guy was a very beginner ^^).

I thought "onHover" as a modifier which registers a fill property with a priority on the "default" one when mouse is hovering.

I have continued to play with fidget and it doesn't bother me anymore. It is consistent and obvious when looking at the code.

The non-working example could be used in a starter guide documentation.