midio_ui/gui/dsl

This file contains macros and templates that make up a dsl for creating GUIs.

Examples:

stack(width: 100, height: 100):
draggable text("hello there")
rectangle(margin: 10 10 10 20, color: "red"):
text("Some more text")
Goes from 'foo="bar", baz="123"'', to (("foo", "bar"), ("baz", 123)) Creates data-bindings for 'foo<-bar', if bar is an Observable If item is an element type, it becomes a child.

Types

Align = enum
  Left, Right, Top, Bottom, Center, TopLeft, TopRight, BottomLeft, BottomRight
NoProps = ref object
Used for element types that don't have their own props type, as a filler type.

Procs

proc align=(props: ElemProps; value: Align): void {...}{.raises: [], tags: [].}
proc toNimNode(self: Attribute): NimNode {...}{.raises: [], tags: [].}
proc toNimNode(self: seq[Attribute]): NimNode {...}{.raises: [], tags: [].}
proc toNimNode(self: Binding): NimNode {...}{.raises: [], tags: [].}
proc toNimNode(self: seq[Binding]): NimNode {...}{.raises: [], tags: [].}
proc toNimNode(self: seq[ChildOrBehavior]): NimNode {...}{.raises: [], tags: [].}
proc toNimNodeList(self: seq[NimNode]): NimNode {...}{.raises: [], tags: [].}
proc expandNiceAttributeSyntax(attributesAndChildren: NimNode): ExpandedNiceSyntax {...}{.
    raises: [ValueError], tags: [].}
proc bindChildCollection(self: Element; item: Subject[Element]): void {...}{.
    raises: [Exception, UnpackError], tags: [RootEffect].}
TODO: handle subscription
proc bindChildCollection(self: Element; item: Subject[Option[Element]]): void {...}{.
    raises: [Exception, UnpackError], tags: [RootEffect].}
TODO: handle subscription
proc bindChildCollection(self: Element; items: seq[Element]): void {...}{.
    raises: [UnpackError, Exception], tags: [RootEffect].}
proc bindChildCollection(self: Element; subj: Subject[seq[Element]]): void {...}{.
    raises: [Exception, UnpackError], tags: [RootEffect].}
TODO: Keep the correct ordering of the children even with multiple child lists spread
proc bindChildCollection(self: Element; obs: Observable[seq[Element]]): void {...}{.
    raises: [Exception, UnpackError], tags: [RootEffect].}
TODO: If we are to bind an Observable of seq[Element], we need a way for the binding we make here to be able to only add the elements that are new, and remove those that are not there any more. The problem is that the child collection also has children that are not 'managed' by this observable and so, we need to not interfer with them!
proc bindChildCollection(self: Element; subj: CollectionSubject[Element]): void {...}{.
    raises: [UnpackError, Exception], tags: [RootEffect].}

Macros

macro extractProps(propType: typed; attributes: typed): untyped
macro extractBindings(element: untyped; targetProp: untyped; propType: typed;
                     attributes: typed): untyped
macro extractChildren(childrenOrBehaviors: typed; childrenIdent: untyped;
                     behaviorsIdent: untyped): untyped
macro rectangle(attributesAndChildren: varargs[untyped]): untyped
macro path(attributesAndChildren: varargs[untyped]): untyped
macro stack(attributesAndChildren: varargs[untyped]): untyped
macro panel(attributesAndChildren: varargs[untyped]): untyped
macro dock(attributesAndChildren: varargs[untyped]): untyped
An element with a docking layout:
dock:
  docking(DockDirection.Right):
    rectangle(color = "red", width = 50.0)
  docking(DockDirection.Top):
    rectangle(color = "blue", height = 50.0)
  rectangle(color = "green")
macro text(attributesAndChildren: varargs[untyped]): untyped
macro container(attributesAndChildren: varargs[untyped]): untyped
macro circle(attributesAndChildren: varargs[untyped]): untyped
macro textInput(attributesAndChildren: varargs[untyped]): untyped
macro component(head: untyped; body: untyped): untyped

Templates

template bindPropWithInvalidation[T](elem: Element; prop: typed;
                                    observable: Observable[T]): untyped
template rectangle_impl(attributes: untyped): untyped
template docking(dir: DockDirection; element: Element): untyped