We've had something like this for years in the VCF! And the predecessor to XAML dates back even further than that, to Delphi's form files, NeXT's NIB files, and so on. So, I thought I'd post what the format for a Visual Form File (VFF) looks like, in Backus-Naur format:
component-decl ::= "object" component-id component-properties
*(component-decl) [component-delegates] "end"
component-id ::= component-name component-class ["," component-classid]
component-name ::= id
id ::= ALPHA *(ALPHA | DIGIT | '_' )
component-class ::= ALPHA *(ALPHA | DIGIT | '_' | "::" )
component-classid ::= ''' 1*(ALPHA | DIGIT | '-' ) '''
component-properties ::= 1*component-property
component-property ::= property-name '=' property-value
property-name ::= id | property-object-name | property-collection-name
property-object-name ::= id '.' property-name
property-collection-name ::= id '[' property-collection-key ']'
property-collection-key ::= property-number | property-string
property-value ::= property-string | property-number |
property-component-ref | property-enum |
property-enum-mask | property-binary | property-bool
property-string ::= ''' *(ALPHA | DIGIT | 'any printable unicode char' ) '''
property-number ::= 1*DIGIT ['.' 1*(DIGIT) ]
property-component-ref ::= ('@' component-name) | "null"
property-enum ::= id
property-enum-mask ::= '[' property-enum *[',' property-enum] ']'
property-binary ::= '{' binary-data '}'
binary-data ::= 1*(binary-byte)
binary-byte ::= (DIGIT | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' )
(DIGIT | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' )
property-bool ::= "true" | "false"
component-delegates ::= "delegates" *(component-delegate-decl) "end"
component-delegate-decl ::= delegate-name '=' delegate-array
delegate-name ::= id
delegate-array ::= '[' 1*(event-handler-ref) ']'
event-handler-ref ::= component-instance '@' component-callback-method
component-instance ::= id
component-callback-method ::= component-classname "::" component-methodname
component-classname ::= id
component-methodname ::= id
A simple example:
object window1 : VCF::Window
top = 500
left = 500
width = 400
height = 300
end
Note that the class name must be a fully qualified C++ class name, including the namespace the class belongs to.
A more complex example might look like this:
object Form1 : Window, 'ED88C0A1-26AB-11d4-B539-00C04F0196DA'
alignment = AlignNone
anchor = 0
bottom = 555.00000
color.blue = 0.78431
color.green = 0.81569
color.red = 0.83137
height = 537.00000
left = 234.00000
name = 'Form1'
top = 70.00000
visible = true
width = 565.00000
object label1 : VCF::Label, 'ED88C09F-26AB-11d4-B539-00C04F0196DA'
anchor = [AnchorLeft,AnchorRight]
bottom = 100.00000
caption = 'This is a label!'
color.blue = 0.50000
color.green = 1.00000
color.red = 0.00000
height = 45.00000
left = 20.00000
name = 'label1'
textAlignment = taTextLeft
top = 55.00000
verticalAlignment = tvaTextCenter
visible = true
width = 300.00000
wordWrap = false
delegates
end
end
delegates
end
end
This is what we use to load up components dynamically at runtime. So a form can be stored in format, and then loaded at runtime, dynamically no less (!), like so:
Window* window = Frame::createWindow( classid(VisualFormFilesWindow) );
So no one thinks we're using some new fangled version of C++, "classid" is simply a macro that gets the VCF Class instance from a given C++ class type.
When you call Frame::createWindow(), you get a new instance of your window class (called VisualFormFilesWindow), with all the controls and components as you've defined them in your VFF file! Voila!
There's more information on the VFF format here:
Visual Form File format
Something to note - in the latest version, we now support collection properties that can be specified via the RTTI macros, and can also be modified via the VFF format, for example:
object myObj : MyObjectWithItems
items[0] = 10
items[1] = 123
end
1 comment:
I think it would be much helpfull if there was an GUI designer. Like Interface Builder for example.
Post a Comment