-
Notifications
You must be signed in to change notification settings - Fork 75
Layout DSL
The layout DSL (Domain Specific Language) is designed to help with common use-case layout definitions. Here is an example:
import nimx / [ window, button, layout ]
let
w = newWindow(newRect(50,50,400,200))
margin = 5.0
w.makeLayout:
- Button:
leading == super.leading + margin
trailing == super.trailing - margin
top == super.top + margin
bottom == super.bottom - margin
title: "Hello"
onAction:
echo "Hello, world!"
The makeLayout
macro accepts the View
as a first argument. The view is where the layout should happen. The second argument is the body of the DSL. It has the following syntax:
DSL ::= ViewConfiguration
ViewConfiguration ::= ViewConfigurationStatement*
ViewConfigurationStatement ::=
"discard"
| SubviewDefinition
| PropertyDefinition
| ConstraintDefinition
SubviewDefinition ::= "-" ( ViewType | ViewCreationExpression ) ( "as" Identifier )? ":" ViewConfiguration
PropertyDefinition ::= PropertyName ":" PropertyValue
ConstraintDefinition ::= ConstraintExpression (ConstraintPriority)?
-
In the example above, the
- Button:
and everything that follows is theSubviewDefinition
.Button
is theViewType
. Note that the types have to be valid symbols in the scope of the layout definition, that's why the sample code importsbutton
. -
title: "Hello"
is the property definiton of the button. If the button was bound to a variablemyButton
, this would be equivalent tomyButton.title = "Hello"
. -
onAction: ...
is also a property, but with a special rule: Properties starting with "on" and with an uppercased third letter are treated as callback properties. So this would expand to roughlymyButton.onAction = proc() = echo "Hello, world!"
If your callback takes arguments or returns something, you can use the do-notation:
- MyControl: onSomeEvent do(e: EventData) -> EventDataResult: echo "hi"
-
leading == super + margin
is a constraint definition, consisting of constraint expression, and default priority. Constraint expression should always be one of the following comparison expressions:<=
,==
, or>=
. Constraint expressions can refer to the following "variables":width
,height
,left
,right
,x
,y
,top
,bottom
,leading
,trailing
,centerX
,centerY
,origin
,center
,size
.
-
mySubView
should completely fill themainView
:
mainView.makeLayout:
- View as mySubView:
center == super.center
width == 20
height == 20
-
mySubView
should be of size 20x20 and be centered within the mainView:
mainView.makeLayout:
- View as mySubView:
center == super.center
width == 20
height == 20
Note that there is a special word super
in the above examples. This is a placeholder designating the superview of the currently defined view. There are other placeholders:
-
self
- The currently defined view -
prev
- The previous sibiling of the currently defined view -
next
- The next sibining of the currently defined view
Note that the pattern of something == super.something
is pretty common, so there is a special case to make it shorter:
mainView.makeLayout:
- View:
center == super
This works because the left side of the constraint consists of exactly one identifier which is treated as the subject. When super
, self
, prev
, or next
are met in the expression and it is not within the dot-expression, it is treated as a dot expression within the subject.
If the left side of the expression is not a single identifier, then there is no subject and thus such a shortcut would not work:
mainView.makeLayout:
- View:
width + 20 == super # Will not compile
width + 20 == super.width # Will compile
width == super - 20 # Will compile