Jump to content
Sign in to follow this  
jarto

Smart 2.9.9 [alpha] is here!

Recommended Posts

Here's a quick test, which worked. There was no sound in the embedded chrome, but the browser worked well.

 

mp:=TW3MediaPlayer.Create(Self);

mp.SetBounds(0,0,Width,Height);

mp.OnLoadedData:=procedure(Sender: TObject)

begin

Writeln('Loaded!');

mp.Play;

end;

mp.Load('res/pumpupkicks.mp3');

 

I also tested with a mp4-file and that worked in the browser too. I guess the big trick is to call Play only after OnLoadedData has been triggered.

Share this post


Link to post
Share on other sites

<p>

I can't get that to work in my Alpha release

 

Using you exact code, i tried both an MP3 and an MP4

 

procedure TForm1.InitializeObject;

begin

inherited;

{$I 'Form1:impl'}

mp:=TW3MediaPlayer.Create(Self);

mp.SetBounds(0,0,Width,Height);

mp.OnLoadedData:=procedure(Sender: TObject)

begin

Writeln('Loaded!');

mp.Play;

end;

mp.Load('res/test.mp4');

end;

</P>

Share this post


Link to post
Share on other sites

<p>

If I do that, i get errors

 

Uncaught TypeError: Cannot read property 'FHandle$3' of null [line #5362]

Uncaught TypeError: Cannot read property 'FHandle$3' of null [line #5362]

</p>

 

 

 

Put it in TForm1.InitializeForm

 

Share this post


Link to post
Share on other sites

There have been quite a few bug fixes over the last few weeks. Is there any chance of a incremental update of the alpha?

 

I know you guys are working on some bigger issues but the current bugs in the alpha are seriously holding up our development. We cannot continue until they have been addressed so it would be awesome if we could receive the updated units while you work on new features. Then we can see if the issues have been resolved.

Share this post


Link to post
Share on other sites
On 10/30/2017 at 2:06 AM, Czar said:

There have been quite a few bug fixes over the last few weeks. Is there any chance of a incremental update of the alpha?

 

I know you guys are working on some bigger issues but the current bugs in the alpha are seriously holding up our development. We cannot continue until they have been addressed so it would be awesome if we could receive the updated units while you work on new features. Then we can see if the issues have been resolved.

Almost there. Jon is finishing the Lollipop theme. If we are lucky, we can push it out today. This week anyway, for sure.

Share this post


Link to post
Share on other sites

Well, the CSS Margins and Borders and Padding opened quite a big can of worms. So I'm afraid that we'll not be able to update the RTL today. Let me tell you what's going on, so you guys understand. This is going to be a long post.

If you are familiar with the Javascript boxing model, you know that:

  • Margin is outside of the control
  • Then comes border
  • Then comes padding (which can be thought about margin inside the control)
  • Finally we have the area inside the control, where content should be put

Imagine that you do a SetBounds(100,100,200,150); Margins 10px and Padding 5px, Borders 1px

What the browser does, may surprise you: If the CSS has margins, it shifts that control right and down, but it does not reduce the size of the control. So visually, your control moves and actually leaks out of the area that you thought that it should occupy based on that SetBounds -command. This means, that the programmer has very little possibilities to react to changes in CSS. You make your program nice, change style to something else and wonder why in the world stuff looks weird.

Some variables:

  • ClientWidth returned Width - Borders = 198
  • ClientHeight returned Height - Borders = 148
  • ClientRect returned TRect(0,0,198,148)

So basically, all those did not reflect the padding at all.

Plan 1: Change ClientRect to return the usable area inside the control

  • ClientWidth still 198
  • ClientHeight still 148
  • ClientRect: TRect(5,5,188,138);

Pros and Cons:

  • + ClientRect actually reflects the usable area
  • - ClientRect.Width does not match ClientWidth any more
  • - Margins do still cause the control to leak out of its area

So, I spent some time this week fixing code that assumed that the usable area was the same as ClientWidth and ClientHeight. And when I had done that for long enough, everything started feeling really too complicated. Basically, ClientWidth and ClientHeight were completely unusable. I had to use ClientRect everywhere to get the left and top position, but basically all ClientWidths had to be changed to ClientRect.Width etc. And even then, the Margins do still wreck havoc. And believe me, all this really messed with your head.

Plan 2: How stuff should be IMHO (And please, do give feedback about this!) edit: except Plan3 is even better :-)

Lets consider the original example: SetBounds(100,100,200,150); Margins 10px and Padding 5px, Borders 1px

IMHO, the control including the margins needs to stay inside the 200x150 box. So, if there are margins, the size is reduced automatically. This way there is no leakage outside of the area, not matter what margins the stylesheet uses. Basically this means: If there is more air between controls in the style sheet, the control size is just reduced accordingly.

  • Width 200 results in the control being 180px wide inside the browser (10px margin on both sides) and height 150 becomes 130px in the browser.
  • GetWidth still returns the original 200 and GetHeight the original 150.
  • ClientWidth is 180 - 5 - 5 - 1 - 1 = 168 (5px of padding and 1px of border on both sides)
  • ClientRect is TRect(5,5,168,138)

So, Width and Height are the original "requested" values. That's the area that the control takes up visually including all margins, borders, padding etc. That's the area you reserve for whatever there is inside the box.

ClientWidth and ClientHeight gives you the size that you can fill inside the box. The area that you can use after all margins, borders and padding has been taken off.

ClientRect gives you the TRect that you can work with. So ClientRect.Left is the left coordinate where you should start positioning anything so, that you don't overwrite your padding.

Pros and Cons:

  • + ClientRect actually reflects the usable are
  • + ClientRect.Width matches ClientWidth, so ClientWidth is again usable!
  • + Margins automatically reduce control so it fits inside its box

I do have a proof of concept of this and to me it looks like it works nicely. But we still need to have a real hard talk within the developers to make sure that Plan 2 is the way to go. And we also have to be sure that BoundsRect and ScreenRect do also return proper values.

Plan3 below. Please read it!

 

Share this post


Link to post
Share on other sites

And after I had written that one, I came up with Plan 3, which is a beauty:

Still the original example: SetBounds(100,100,200,150); Margins 10px and Padding 5px, Borders 1px

These are the same as in Plan2:

  • Control Size is automatically reduced based on margins
  • ClientWidth and ClientHeight return the usable size inside the control after padding has been taken off

But then:

  • ClientRect returns TRect(0,0,ClientWidth,ClientHeight) just like in Delphi
  • SetBounds, SetLeft, SetTop, MoveTo automatically shift the control based on parent control's padding!

So basically, you don't have to care at all about margins or padding. The control is automatically reduced and when you place something at 0,0 inside a control, it automatically moves according to the padding.

And to make sure that none of this causes problems, we'll add a position mode for this:

  • pmAbsolute: Like before. Padding etc. is up to you to handle correctly
  • pmRelative: Relative positioning as before
  • pmSmart (or whatever we will call it) Absolute positioning, except the RTL adjusts to margins and padding automatically. (default)

Share this post


Link to post
Share on other sites

off the cuff reaction :

It is always difficult to reconcile different systems, in this case the positioning systems as implemented by SMS(Delphi) and by HTML(browser), and it is a bit of a philosophical question as well.

However my personal opinion is that its important to stay as much in sync with the browser as possible.

So for instance defining clientHeight in SMS as "the usable size inside the control after padding has been taken off" is IMHO not a good idea. ClientHeight in the browsers border-box terminology is height minus border minus scrollbar width (https://developer.mozilla.org/en-US/docs/Web/API/CSS_Object_Model/Determining_the_dimensions_of_elements). 

It would be very confusing to have to deal with the difference between <mycomponent>.clientHeight and <mycomponent>.handle.clientHeight returning different values.

As such, if positioning in sms needs to be redefined, I would suggest to

  • keep with the border-box model
  • keep SMS and browser positioning terminoloy as much the same as possible : same naming convention and typing
  • positioning rules are complicated and depend on may different parameters (HTML rules, CSS rules, platform dependencies), so use the browser to calculate positioning values when possible, rather than re-coding those rules in sms

Cheers

 

 

 

Share this post


Link to post
Share on other sites

Thank you for your feedback. Now that I've actually implemented and tested the new code, I can describe better the reasons for why we need to fix this.

Take any component and put it at a fixed position with fixed width. For example: TestBox.SetBounds(0,0,200,100). What the programmer expects, is that the box actually takes up the area starting from 0,0 with a width of 200 and height of 100. And most of the time it actually does it. But then comes the styling person, who thinks that it'd be nice for that TestBox to have a 5px margin. What happens in the JS world is, that TestBox will automatically move down and right 5px and that  box will occupy an area of 210 wide and 110 high.

The bad news is: You as a programmer have no control over that. You could have done a TestBox.SetBounds(0,0,ClientWidth,ClientHeight) and thought that all is good, but it will still leak out. The only way to prevent that is for you, as a programmer, to make sure to calculate the margins yourself while doing that SetBounds. In pseudo code: Something like: TestBox.SetBounds(0,0,ClientWidth-GetTheRightMarginFor(TestBox),ClientWidth-GetTheBottomMarginFor(TestBox)); And well, then it should be of the proper size.

Except, we have not thought about padding yet. We need to of course put that TestBox to the proper location based on parent's padding. So, it becomes something like TestBox.SetBounds(LeftPadding,TopPadding,ClientWidth-GetTheRightMarginFor(TestBox)-RightPadding,ClientHeight-GetTheBottommarginFor(TestBox)-BottomPadding); And at this point you get a head ache.

You can make it easier by having some helper functions to return and change ClientRect based on own margins and own pading, but the point is:

  • You need to always remember to do that.
  • You will definitely forget to do that everywhere. Especially if your controls tend to use 0 margins or 0 padding most of the time.
  • If you do it right, it makes no sense that you as a programmer need to worry about this when the RTL could worry about it.

You can of course also use a proper layout library that takes care of all that, but you'd then have to always use it. No SetBounds, SetLeft, Top, Width etc. unless you always remember to calculate paddings and margins.

You can also use pmRelative and let the browser calculate all. And nothing what I write here causes you trouble when you use pmRelative. It will work as before.

So, I strongly think that this is the way to go when you work in Smart Mobile Studio:

  • You, the progammer do not decide what the margin, border and padding of a control is. They can be anything under the sun and they depend on the style sheet.
  • You decide where your control is and how big an area it will occupy.
  • The RTL will make sure that the control will be inside that area and not let it leak out.
  • You can read ClientWidth and ClientHeight to know how big an area you have inside the control to work with. Anything you put inside a control needs to be inside ClientRect, which is TRect(0,0,ClientWidth,ClientHeight)
  • The size of ClientWidth, ClientHeight and ClientRect depends on the style sheet - The styling guy is in charge.
  • When you put anything inside ClientRect, the RTL will make sure that it does not overlap the control's padding. So if you do a Move(0,0), the RTL will automatically put your control to the proper location at the top left corner. And if you do a SetBounds(0,0,ClientWidth,30), you can be sure that your control is on the top, as wide as it can be and respects padding.

You may ask: "Why should I worry about padding and margins as I myself write the style sheet? I know what the values are!"

Well, in the future we want to be able to let you change the style sheet during runtime. So you'd be able to ship your program with many style sheets. When it's run on Android, that style sheet is chosen. When you run it on iOS, that one goes. And on desktop a third one. And when we get to that point, it's logical that SMS maintains styles for the normal controls and you maintain styles for your own controls. And at that point you will not control any more, what the margins and paddings and borders for all the controls are any more.

Share this post


Link to post
Share on other sites

I've read your reply and admire the way of thinking.

Just to check, the following code in the present alpha returns 0, 100, 98, 98 respectively

Quote

procedure TForm1.InitializeObject;
begin
  inherited;
  {$I 'Form1:impl'}
  W3Panel1.SetBounds(40,40,200,100);
  showmessage(inttostr(w3panel1.height));
  w3Panel1.handle.ReadyExecute (procedure()
  begin
    showmessage(inttostr(w3panel1.height));
    showmessage(inttostr(w3panel1.clientheight));
    showmessage(w3panel1.handle.clientHeight);
  end);
end;

How would these values differ in the new code base ?

Share this post


Link to post
Share on other sites
11 hours ago, markus_ja said:

How would the code look like, if you want to put a second control under the first control,  considering padding and margin)?

secondControl.SetTop(firstControl.ClientHeight + ???)

If  you want to do it in the current code base: secondControl.SetTop(firstControl.Top + firstControl.Height + firstControl_bottom_margin_height)

And when we update the Alpha, it's as it should be: Simply secondControl.SetTop(firstControl.Top+firstControl.Height)

Share this post


Link to post
Share on other sites
4 hours ago, lynkfs@gmail.com said:

I've read your reply and admire the way of thinking.

Just to check, the following code in the present alpha returns 0, 100, 98, 98 respectively

How would these values differ in the new code base ?

In the present version you get 98 as clientheight and clientwidth as there's a 1px border.

With the new version and style sheet I have now, you get: 100,100,94,98. That difference between 98 and 94 are due to padding. So the usable are I have inside the panel is 94px high.

I guess it'd be best for us to have two ClientHeight-functions:

ClientHeightJS: Returns the old value regardless of padding
ClientHeight: Returns the new value aka the height of the area you can use inside the control.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×