Jump to content
Sign in to follow this  
DavidRM

Size of Components at Runtime

Recommended Posts

I'm arranging controls at runtime. But I can't seem to puzzle out what the actual size of a control is. I can find what it *says* it is (read the Height property for instance), but that seems to be only a guess or something.

So what am I doing wrong here?

procedure TShowMessageForm.UpdateUI;
var
  tMetrics: TW3TextMetric;
  padding, border: integer;
  panelWidth, panelHeight, numButtons, buttonWidth, buttonLeft, buttonTotal: integer;
begin
  var CSSHandle := TW3CustomBrowserAPI.GetComputedStylesFor(FMessagePanel.Handle);
  if (CSSHandle) then
  begin
    padding := w3_getPropertyAsInt(CSSHandle, 'paddingLeft');
    border := w3_getPropertyAsInt(CSSHandle, 'borderLeft');
  end
  else
  begin
    padding := 2;
    border := 2;
  end;
  FMessageLabel.Caption := FMessageText;
  tMetrics := FMessageLabel.MeasureText(FMessageText + 'XXX');
  FMessageLabel.SetSize(border + padding + tMetrics.tmWidth + padding + border,
    border + padding + tMetrics.tmHeight + padding + border);
  FMessageLabel.Top := 0;
  FMessageLabel.Left := 0;
  panelWidth := (border + padding) + FMessageLabel.Width + (padding + border);
  panelHeight := (border + padding) + FMessageLabel.Height + (padding + border);
  if ButtonsVisible then
  begin
    numButtons := ButtonCount;
    buttonWidth := SizeButtons;
    buttonTotal := (buttonWidth * numButtons) + (padding * (numButtons - 1));
    panelWidth := Max(panelWidth, (padding + border) + buttonTotal + (padding + border));
    buttonLeft := (panelWidth - buttonTotal) div 2;
    if FMessageOKButton.Visible then
    begin
      FMessageOKButton.Left := buttonLeft;
      FMessageOKButton.Top := panelHeight + padding;
      Inc(buttonLeft, FMessageOKButton.Width + padding);
    end;
    if FMessageCancelButton.Visible then
    begin
      FMessageCancelButton.Left := buttonLeft;
      FMessageCancelButton.Top := panelHeight + padding;
      Inc(buttonLeft, FMessageCancelButton.Width + padding);
    end;
    panelHeight += FMessageOKButton.Height + padding;
  end;
  FMessagePanel.Width := panelWidth;
  FMessagePanel.Height := panelHeight;
end;

I'm guessing I'm going about adding in the padding and border widths wrong.

The buttons are the worst offenders. Just because they *say* their X wide doesn't mean they are. They are *really* X+(some-random-effing-N).

I appreciate any assistance.

-David

Share this post


Link to post
Share on other sites

Wouldn't that boil down to css?

 

I open sms drop down a tw3button at 128x32. If I leave the border then seems a bit bigger - if I remove border then 128x32

Share this post


Link to post
Share on other sites

@DavidRM Your code seems to have a lot of calculations about padding. Smart Mobile Studio uses  positionmode pmSmart as default, which means that the RTL takes care of margins and paddings. I made a post about it here:

https://forums.smartmobilestudio.com/topic/4423-smart-299-alpha-is-here/?do=findComment&comment=22250

Edit: Also added a new page to documentation about this: https://smartmobilestudio.com/documentation/getting-started/smart-mobile-studio-box-model-positionmode-margin-border-padding-etc/

 

I'll be happy to help if you have any questions.

Share this post


Link to post
Share on other sites

@jarto OK. How do I set the ClientWidth and ClientHeight without calculating all the padding and margins?

For example: I need the ClientWidth of the panel to be wide enough to fit the text of the label. I need the ClientHeight of the panel to be tall enough to fit the label and a row of buttons. And, yes, I would like the current stylesheet to provide the margins and padding between the components.

Thanks.

-David

Share this post


Link to post
Share on other sites

@DavidRM

  var Btn1:=TW3Button.Create(ParentPanel); Btn1.Caption:='Ok';
  var Btn2:=TW3Button.Create(ParentPanel); Btn2.Caption:='Cancel';
  //Create label but don't give it a size
  var Lab2:=TW3Label.Create(ParentPanel);
  Lab2.MoveTo(0,0);
  Lab2.AutoSize:=True;
  //OnResize will be triggered when we set the label text.
  Lab2.OnResize:=procedure(Sender: TObject)
    begin
      //Resize based on label size and add 40 px for button row
      var PHeight:=Lab2.Height+40+ParentPanel.Height-ParentPanel.ClientHeight;
      var PWidth:=Lab2.Width+ParentPanel.Width-ParentPanel.ClientWidth;
      ParentPanel.SetSize(PWidth,PHeight);
      //Resize the buttons
      var BtnWidth:=ParentPanel.ClientWidth div 2;
      Btn1.SetBounds(0,Lab2.Height,BtnWidth,40);
      Btn2.SetBounds(BtnWidth,Lab2.Height,BtnWidth,40);
    end;
  Lab2.Caption:='A quick brown fox jumped over the lazy dog!';

So, basically we let the label autosize itself and react to it in OnResize.

Label's Width and Height returns how much space it takes.

When we resize the panel, Width-ClientWidth  (and Height-ClientHeight) returns how much space the padding, margin and border takes.

Share this post


Link to post
Share on other sites
9 hours ago, DavidRM said:

OK. So even with "smart" positioning, the "spaces between" have to be calculated and accounted for.

Thanks.

-David

This could be made a bit simpler by also making ClientWidth and ClientHeight writable.

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  

×