Smart mobile studio introduces a few minor differences to an otherwise “VCL like” RTL. Just like Delphi you can create visual and non-visual controls, you have the same methods to work with (like resize) and you can move and size your child controls with left, top, width and height properties.
One important issue however, is that reading and writing non pascal properties (left, top, width and height being prime examples) relies on your control’s HTML to be visible to the DOM. In short, reading properties in the constructor can cause the browser to report NaN (not a number) as a result. This has nothing to do with our RTL but rather how the browser realizes cascading styles.
Modern HTML5 actually have 3 sets of styles:
- A style “class” applied to an element from a style sheet (see “styleClass” property in TW3CustomControl)
- Inline styles, which overrides whatever is set in the style sheet
- Calculated styles, which is the combined style the browser has compiled from the above. This is why it’s call “cascading” style-sheets, because they flow into each other resulting in a final style.
Since we want our components to reflect “real” values, our component model reads values from the calculated style. If we did not do this – things like margins defined in a css style would be invisible to your controls (and thus size calculations would be wrong).
[sourcecode language=”delphi”]
Procedure TForm1.InitializeObject;
Begin
inherited;
FLabel:=TW3Label.Create(self);
FLabel.left:=10;
FLabel.top:=10;
FLabel.width:=Self.Width – 20;
//Self.Width will return NaN, it should be moved to Resize
End;
[/sourcecode]
So to sum up:
- Positions (etc) are written as in-line styles but read from calculated styles
- Calculated styles are only available “post” creation of a control, which means reading position values in the constructor is not the correct way of doing things
Use resize
The proper way of handling a good layout under Smart is to deal with positions under the resize method. This doesn’t require any more code than usual – you just have to put your layout code under resize rather than in the constructor. This is how most languages deal with it (the C# object model is particularly strict about these things).
[sourcecode language=”delphi”]
Procedure TForm1.InitializeObject;
Begin
inherited;
FLabel:=TW3Label.Create(self);
End;
Procedure TForm1.Resize;
Begin
inherited;
FLabel.left:=10;
FLabel.top:=10;
FLabel.width:=Self.Width – 20;
End;
[/sourcecode]