Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2010-02

TPanel bevel and client size

15 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

cobines

Hi everyone,

If I set TPanel's border to bsSingle then the control's ClientSize is less than Size. This is what I expected.

If I set any of the bevels instead, the control's ClientSize remains the same as Size. I would expect the bevels be treated like borders and also reduce client size. Or is this how it's supposed to work?

Problem arises when using autosize on TPanel. The bevels are not accounted for when size is calculated, the panel's size is the same as the size of the control it contains and the bevels are not visible at all. If I turn on autosize for a TPanel with Border=bsSingle the border is drawn correctly.

Is this a bug?

cobines -------------- next part -------------- A non-text attachment was scrubbed... Name: screenshot.png Type: image/png Size: 31147 bytes Desc: not available URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100212/916d7af9/attachment-0001.png>

Reply by email

Paul Ishenin
to cobines
cobines wrote
If I set any of the bevels instead, the control's ClientSize remains the same as Size. I would expect the bevels be treated like borders and also reduce client size. Or is this how it's supposed to work?

Bevels reduce ClientRect by BevelSize value.

Problem arises when using autosize on TPanel. The bevels are not accounted for when size is calculated, the panel's size is the same as

BevelSize is used to calculate the ClientRect in
TCustomPanel.AdjustClientRect.

Is this a bug?

If it does not work then yes.

Best regards,
Paul Ishenin.

Reply by email

cobines
to Paul Ishenin

2010/2/12 Paul Ishenin :

Show quoted text 7 lines
12.02.2010 14:33, cobines wrote: > If I set any of the bevels instead, the control's ClientSize remains > the same as Size. I would expect the bevels be treated like borders > and also reduce client size. Or is this how it's supposed to work? Bevels reduce ClientRect by BevelSize value.

I thought so that they're supposed to do that, but if I put a TPanel on a form with a outer bevel set to Lowered , the panel's ClientHeight = Height.

Show quoted text 6 lines
> Problem arises when using autosize on TPanel. The bevels are not > accounted for when size is calculated, the panel's size is the same as BevelSize is used to calculate the ClientRect in TCustomPanel.AdjustClientRect.

Yes, that function recalculates the rectangle correctly, but it seems it's somehow not propagated to the auto size algorithm or to the stored client rectangle.

> Is this a bug? If it does not work then yes.

I'll post it to Mantis. Still don't know if it's LCL issue or widgetsets, but I observed it on LCLGTK2 and LCLQT so far.

cobines

Reply by email

Mattias Gärtner
to cobines

Zitat von cobines :

Show quoted text 12 lines
2010/2/12 Paul Ishenin : > 12.02.2010 14:33, cobines wrote: > >> If I set any of the bevels instead, the control's ClientSize remains >> the same as Size. I would expect the bevels be treated like borders >> and also reduce client size. Or is this how it's supposed to work? > > Bevels reduce ClientRect by BevelSize value. I thought so that they're supposed to do that, but if I put a TPanel on a form with a outer bevel set to Lowered , the panel's ClientHeight = Height.

Bevel reduces the AdjustClientRect, which is ClientRect minus the Bevels. ClientWidth is the client area width from the widgetset. The bevels are custom drawn by TPanel and therefore not in the ClientWidth of TPanel.

Show quoted text 10 lines
> >> Problem arises when using autosize on TPanel. The bevels are not >> accounted for when size is calculated, the panel's size is the same as > > BevelSize is used to calculate the ClientRect in > TCustomPanel.AdjustClientRect. Yes, that function recalculates the rectangle correctly, but it seems it's somehow not propagated to the auto size algorithm or to the stored client rectangle.

The autosize algorithm uses AdjustClientRect.

Show quoted text 6 lines
>> Is this a bug? > > If it does not work then yes. I'll post it to Mantis. Still don't know if it's LCL issue or widgetsets, but I observed it on LCLGTK2 and LCLQT so far.

Please add an example to demonstrate the problem.

Mattias

Reply by email

cobines
to Mattias Gärtner

2010/2/12 Mattias G?rtner :

Show quoted text 14 lines
Zitat von cobines : > 2010/2/12 Paul Ishenin : >> >> Bevels reduce ClientRect by BevelSize value. > > I thought so that they're supposed to do that, but if I put a TPanel > on a form with a outer bevel set to Lowered , the panel's ClientHeight > = Height. Bevel reduces the AdjustClientRect, which is ClientRect minus the Bevels. ClientWidth is the client area width from the widgetset. The bevels are custom drawn by TPanel and therefore not in the ClientWidth of TPanel.

Ok, that clears up why ClientWidth=Width. But why the bevels are included in ClientRect? I think child controls are not supposed to occupy the bevels' space. Can the ClientWidth, ClientHeight from the widgetset be adjusted to include bevels?

For example if I want to check how much space is in the Panel for a control, I do:

SpaceAvailable := Panel.ClientHeight;
if SpaceAvailable >= 100 then
ShowMyControl_of_size_100_or_more (because I'm sure it will fit) else
HideMyControl... (don't want to show it partially)

(The Panel size is controlled by the user.)

However, if TPanel contains bevels then the space available for the child control is ClientHeight - BevelSize * 2. I have to take it into account when calculating space. Otherwise, either my control will not be fully shown, or it will be drawn over the bevels. Is there some other property I can check that will include all borders, bevels, etc.?

Show quoted text 8 lines
>> BevelSize is used to calculate the ClientRect in >> TCustomPanel.AdjustClientRect. > > Yes, that function recalculates the rectangle correctly, but it seems > it's somehow not propagated to the auto size algorithm or to the > stored client rectangle. The autosize algorithm uses AdjustClientRect.

It still puts child controls over the bevels. I don't know, maybe I'm confusing it with aligning child controls. It is supposed to either make the child control smaller so that it doesn't overwrite the bevels, or make the TPanel bigger so that the child control fits in whole and there's still space left for the bevels.

Please add an example to demonstrate the problem.

I have found an already existing bug on this with a good example. But it said the problem is only for BevelWidth > 1 and only for GTK, GTK2. I confirmed this issue also on QT and with any bevel width. I'll check later on Win32.

Unfortunately Mantis died on me while I was reading it so I didn't get the bug number. Will try later.

cobines

Reply by email

Mattias Gärtner
to cobines

Zitat von cobines :

Show quoted text 20 lines
2010/2/12 Mattias G?rtner : > Zitat von cobines : > >> 2010/2/12 Paul Ishenin : >>> >>> Bevels reduce ClientRect by BevelSize value. >> >> I thought so that they're supposed to do that, but if I put a TPanel >> on a form with a outer bevel set to Lowered , the panel's ClientHeight >> = Height. > > Bevel reduces the AdjustClientRect, which is ClientRect minus the Bevels. > ClientWidth is the client area width from the widgetset. The bevels are > custom drawn by TPanel and therefore not in the ClientWidth of TPanel. > Ok, that clears up why ClientWidth=Width. But why the bevels are included in ClientRect? I think child controls are not supposed to occupy the bevels' space. Can the ClientWidth, ClientHeight from the widgetset be adjusted to include bevels?

The widgetset values should only include the widgetset things.

Maybe you want new properties AdjustedClientWidth, AdjustedClientHeight. Changing ClientWidth/ClientHeight would be a big change and some third party controls rely on that. Note: The LCL ClientWidth/Height are not compatible to the VCL, so Delphi compatibility is irrelevant here.

Show quoted text 17 lines
For example if I want to check how much space is in the Panel for a control, I do: SpaceAvailable := Panel.ClientHeight; if SpaceAvailable >= 100 then ShowMyControl_of_size_100_or_more (because I'm sure it will fit) else HideMyControl... (don't want to show it partially) (The Panel size is controlled by the user.) However, if TPanel contains bevels then the space available for the child control is ClientHeight - BevelSize * 2. I have to take it into account when calculating space. Otherwise, either my control will not be fully shown, or it will be drawn over the bevels. Is there some other property I can check that will include all borders, bevels, etc.?
r:=ClientRect;
AdjustClientRect(r);
SpaceAvailable:=r.Right-r.Left;
Did you know, that you can anchor controls:
MyControl.AnchorParallel(akLeft,0,MyControl.Parent);
MyControl.AnchorParallel(akRight,0,MyControl.Parent);

This will expand MyControl to the full client area width, excluding the bevels.

Show quoted text 14 lines
>>> BevelSize is used to calculate the ClientRect in >>> TCustomPanel.AdjustClientRect. >> >> Yes, that function recalculates the rectangle correctly, but it seems >> it's somehow not propagated to the auto size algorithm or to the >> stored client rectangle. > > The autosize algorithm uses AdjustClientRect. It still puts child controls over the bevels. I don't know, maybe I'm confusing it with aligning child controls. It is supposed to either make the child control smaller so that it doesn't overwrite the bevels, or make the TPanel bigger so that the child control fits in whole and there's still space left for the bevels.

It works here on a simple example. Child controls are not on the bevels but within the bevels with autosize=true on gtk2.

Show quoted text 9 lines
> Please add an example to demonstrate the problem. I have found an already existing bug on this with a good example. But it said the problem is only for BevelWidth > 1 and only for GTK, GTK2. I confirmed this issue also on QT and with any bevel width. I'll check later on Win32. Unfortunately Mantis died on me while I was reading it so I didn't get the bug number. Will try later.

Thanks.

Mattias

Reply by email

cobines
to Mattias Gärtner

2010/2/12 Mattias G?rtner :

Show quoted text 31 lines
Zitat von cobines : > 2010/2/12 Mattias G?rtner : >> >> Zitat von cobines : >> >>> 2010/2/12 Paul Ishenin : >>>> >>>> Bevels reduce ClientRect by BevelSize value. >>> >>> I thought so that they're supposed to do that, but if I put a TPanel >>> on a form with a outer bevel set to Lowered , the panel's ClientHeight >>> = Height. >> >> Bevel reduces the AdjustClientRect, which is ClientRect minus the Bevels. >> ClientWidth is the client area width from the widgetset. The bevels are >> custom drawn by TPanel and therefore not in the ClientWidth of TPanel. >> > > Ok, that clears up why ClientWidth=Width. But why the bevels are > included in ClientRect? I think child controls are not supposed to > occupy the bevels' space. Can the ClientWidth, ClientHeight from the > widgetset be adjusted to include bevels? The widgetset values should only include the widgetset things. Maybe you want new properties AdjustedClientWidth, AdjustedClientHeight. Changing ClientWidth/ClientHeight would be a big change and some third party controls rely on that. Note: The LCL ClientWidth/Height are not compatible to the VCL, so Delphi compatibility is irrelevant here.

OK, I misunderstood what ClientWidth/Height represent.

Show quoted text 21 lines
> For example if I want to check how much space is in the Panel for a > control, I do: > > SpaceAvailable := Panel.ClientHeight; > if SpaceAvailable >= 100 then > ?ShowMyControl_of_size_100_or_more (because I'm sure it will fit) > else > ?HideMyControl... (don't want to show it partially) > > (The Panel size is controlled by the user.) > > However, if TPanel contains bevels then the space available for the > child control is ClientHeight - BevelSize * 2. I have to take it into > account when calculating space. Otherwise, either my control will not > be fully shown, or it will be drawn over the bevels. Is there some > other property I can check that will include all borders, bevels, > etc.? r:=ClientRect; AdjustClientRect(r); SpaceAvailable:=r.Right-r.Left;

Thanks, this might help.

Show quoted text 6 lines
Did you know, that you can anchor controls: MyControl.AnchorParallel(akLeft,0,MyControl.Parent); MyControl.AnchorParallel(akRight,0,MyControl.Parent); This will expand MyControl to the full client area width, excluding the bevels.

Yes this works. A child control with Align=alClient does not overwrite bevels.

Show quoted text 17 lines
>>>> BevelSize is used to calculate the ClientRect in >>>> TCustomPanel.AdjustClientRect. >>> >>> Yes, that function recalculates the rectangle correctly, but it seems >>> it's somehow not propagated to the auto size algorithm or to the >>> stored client rectangle. >> >> The autosize algorithm uses AdjustClientRect. > > It still puts child controls over the bevels. I don't know, maybe I'm > confusing it with aligning child controls. It is supposed to either > make the child control smaller so that it doesn't overwrite the > bevels, or make the TPanel bigger so that the child control fits in > whole and there's still space left for the bevels. It works here on a simple example. Child controls are not on the bevels but within the bevels with autosize=true on gtk2.

This is what doesn't work for me.

Take a look at attached example.

Panel1 has a bevel and is autosized. It includes a panel with no borders. For me both are invisible, but Panel1 bevels should be visible.

Panel3 has a bevel and is not autosized. It includes a panel with no borders that has Align=alClient. Bevels of Panel3 are visible.

Same thing on QT.

cobines -------------- next part -------------- A non-text attachment was scrubbed... Name: panel_bevel.tar.bz2 Type: application/x-bzip2 Size: 1816 bytes Desc: not available URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20100212/13cdd190/attachment-0001.bin>

Reply by email

cobines
to cobines

2010/2/12 cobines :

Panel3 has a bevel and is not autosized. It includes a panel with no borders that has Align=alClient. Bevels of Panel3 are visible.

Sorry, the last sentence was supposed to be:

Bevels of Panel1 are visible.

cobines

Reply by email

Hans-Peter Diettrich
to Mattias Gärtner: Zitat von cobines : The widgetset values should only include the widgetset things. Maybe…
Show quoted text 18 lines
>> Bevel reduces the AdjustClientRect, which is ClientRect minus the >> Bevels. >> ClientWidth is the client area width from the widgetset. The bevels are >> custom drawn by TPanel and therefore not in the ClientWidth of TPanel. >> > > Ok, that clears up why ClientWidth=Width. But why the bevels are > included in ClientRect? I think child controls are not supposed to > occupy the bevels' space. Can the ClientWidth, ClientHeight from the > widgetset be adjusted to include bevels? The widgetset values should only include the widgetset things. Maybe you want new properties AdjustedClientWidth, AdjustedClientHeight. Changing ClientWidth/ClientHeight would be a big change and some third party controls rely on that. Note: The LCL ClientWidth/Height are not compatible to the VCL, so Delphi compatibility is irrelevant here.

I came across the various client sizes in my attempt to better document the LCL. IMO we have the following related areas:

- raw client area (0,0,Width,Height)
- usable client area (excluding bevels...)
- logical client area (in scrolling containers)
- visible client area (visible part of logical area)
- BaseBounds (undocumented???)

IMO beveled controls should report the usable client area to the outer world, by adjusting ClientRect etc. accordingly. Internally they use the inherited methods/properties, to get the full client area for painting bevels etc.

What about drop down controls (combo boxes)?

r:=ClientRect; AdjustClientRect(r);

This IMO should be what [Get]ClientRect returns.

SpaceAvailable:=r.Right-r.Left;

This should be what [Get]ClientWidth returns.

Show quoted text 6 lines
Did you know, that you can anchor controls: MyControl.AnchorParallel(akLeft,0,MyControl.Parent); MyControl.AnchorParallel(akRight,0,MyControl.Parent); This will expand MyControl to the full client area width, excluding the bevels.

???

BTW, the determination of a control on a given screen coordinate also could be more straight forward. In the related code I found the beforementioned different areas, but the handling looks quite crappy to me. Did you ever test this with nested scrolling controls?

I also have to test the docking manager code, with beveled or scrolling dock sites. IMO no changes should be required, the specialized (beveled, scrolling) controls should encapsulate and hide their special treatment of client coordinates from *every* user code.

DoDi

Reply by email

Mattias Gaertner
to Hans-Peter Diettrich: I came across the various client sizes in my attempt to better document the LCL. IMO we…
Show quoted text 41 lines
Mattias G?rtner schrieb: >>> Bevel reduces the AdjustClientRect, which is ClientRect minus the >>> Bevels. >>> ClientWidth is the client area width from the widgetset. The bevels are >>> custom drawn by TPanel and therefore not in the ClientWidth of TPanel. >>> >> >> Ok, that clears up why ClientWidth=Width. But why the bevels are >> included in ClientRect? I think child controls are not supposed to >> occupy the bevels' space. Can the ClientWidth, ClientHeight from the >> widgetset be adjusted to include bevels? > > The widgetset values should only include the widgetset things. > > Maybe you want new properties AdjustedClientWidth, AdjustedClientHeight. > Changing ClientWidth/ClientHeight would be a big change and some third > party controls rely on that. > Note: The LCL ClientWidth/Height are not compatible to the VCL, so > Delphi compatibility is irrelevant here. I came across the various client sizes in my attempt to better document the LCL. IMO we have the following related areas: - raw client area (0,0,Width,Height) - usable client area (excluding bevels...) - logical client area (in scrolling containers) - visible client area (visible part of logical area) - BaseBounds (undocumented???) IMO beveled controls should report the usable client area to the outer world, by adjusting ClientRect etc. accordingly. Internally they use the inherited methods/properties, to get the full client area for painting bevels etc. What about drop down controls (combo boxes)? > r:=ClientRect; > AdjustClientRect(r); This IMO should be what [Get]ClientRect returns.

I agree, but that would be Delphi incompatible.

> SpaceAvailable:=r.Right-r.Left; This should be what [Get]ClientWidth returns.

dito

Show quoted text 8 lines
> Did you know, that you can anchor controls: > MyControl.AnchorParallel(akLeft,0,MyControl.Parent); > MyControl.AnchorParallel(akRight,0,MyControl.Parent); > > This will expand MyControl to the full client area width, excluding the > bevels. ???

In other words:
If you want to position a child control to fill the complete width of its parent, use the above. (or use Align=alTop,alBottom,alClient). This will exclude the bevels.

BTW, the determination of a control on a given screen coordinate also could be more straight forward. In the related code I found the beforementioned different areas, but the handling looks quite crappy to me. Did you ever test this with nested scrolling controls?

When Panel.AutoSize=true, then the LCL will expand the Panel, so that no scrolling is needed.
About nesting: The current algorithm is better than the VCL algorithm, but still not perfect. The new algorithm supports infinite nesting, but requires some improvements in the widgetsets before it will be enabled.

I also have to test the docking manager code, with beveled or scrolling dock sites. IMO no changes should be required, the specialized (beveled, scrolling) controls should encapsulate and hide their special treatment of client coordinates from *every* user code.

Mattias

Reply by email

waldo kitty
to Mattias Gaertner
Mattias Gaertner wrote
In other words: If you want to position a child control to fill the complete width of its parent, use the above. (or use Align=alTop,alBottom,alClient). This will exclude the bevels.

:shock: :!: :!: you can list multiple alignment options by comma separating them?? i've never seen this documented and it was one thing i searched for for quite a few days before giving up in frustration :sigh:

Reply by email

Mattias Gaertner
to waldo kitty
Show quoted text 9 lines
On 2/13/2010 05:23, Mattias Gaertner wrote: > In other words: > If you want to position a child control to fill the complete width of > its parent, use the above. (or use Align=alTop,alBottom,alClient). > This will exclude the bevels. :shock: :!: :!: you can list multiple alignment options by comma separating them?? i've never seen this documented and it was one thing i searched for for quite a few days before giving up in frustration :sigh:

Yes, english text mails have a very flexible format.

If you are speaking about pascal:
Align can only be one value. And more does not make sense, as each align value is a set of anchors.

Mattias

Reply by email

waldo kitty
to Mattias Gaertner
Mattias Gaertner wrote 18 lines
On Sat, 13 Feb 2010 06:03:27 -0500 waldo kitty wrote: > On 2/13/2010 05:23, Mattias Gaertner wrote: >> In other words: >> If you want to position a child control to fill the complete width of >> its parent, use the above. (or use Align=alTop,alBottom,alClient). >> This will exclude the bevels. > > :shock: :!: :!: you can list multiple alignment options by comma separating > them?? i've never seen this documented and it was one thing i searched for for > quite a few days before giving up in frustration :sigh: Yes, english text mails have a very flexible format. If you are speaking about pascal: Align can only be one value. And more does not make sense, as each align value is a set of anchors.

ahhh... so i misread the above?? it cannot be Align=alTop,alBottom,alClient but only Align=alTop or Align=alBottom or Align=alClient ??

Reply by email

Mattias Gaertner
to waldo kitty
Show quoted text 22 lines
On 2/13/2010 06:12, Mattias Gaertner wrote: > On Sat, 13 Feb 2010 06:03:27 -0500 > waldo kitty wrote: > >> On 2/13/2010 05:23, Mattias Gaertner wrote: >>> In other words: >>> If you want to position a child control to fill the complete width of >>> its parent, use the above. (or use Align=alTop,alBottom,alClient). >>> This will exclude the bevels. >> >> :shock: :!: :!: you can list multiple alignment options by comma separating >> them?? i've never seen this documented and it was one thing i searched for for >> quite a few days before giving up in frustration :sigh: > > Yes, english text mails have a very flexible format. > > If you are speaking about pascal: > Align can only be one value. And more does not make sense, as each align > value is a set of anchors. ahhh... so i misread the above?? it cannot be Align=alTop,alBottom,alClient but only Align=alTop or Align=alBottom or Align=alClient ??

Yes.
Align=alTop means Anchors=[akLeft,akTop,akRight] and filling the client space.

To anchor only the control's top side, use Anchors:=Anchors+[akTop]

Mattias

Reply by email