Recent

Author Topic: Sizing the parent control depending on the children  (Read 1286 times)

kupferstecher

  • Hero Member
  • *****
  • Posts: 603
Sizing the parent control depending on the children
« on: January 17, 2024, 12:52:33 pm »
Hello all,

how would you implement a class of graphical items (controls) arranged as a list where items can have children and the size changes according the childrens size and the quantity. Its something like a tree view, where each item can have several subitems. Each subitem should be indented, so the parent's width should be extended. And the height of course, as well. Attached a sketch to make it more clear. The items are derived from a common class based on a TCustomControl.

I could do the calculations manually each time an item is added or if something is changed. But perhaps there is an easier way by using LCL mechanisms like utilizing the "Controls" property to keep track of the children, trigger resize from children or similar stuff.

So how would you guys do that?

Regards~

Joanna from IRC

  • Hero Member
  • *****
  • Posts: 1393
Re: Sizing the parent control depending on the children
« Reply #1 on: January 17, 2024, 01:16:00 pm »
I’m not a guy but I’ll try to answer your question..

I have done many things resizing controls.
First of all, What determines how large the child controls are?

The indentation effect can be achieved by anchoring controls on the left using the borderspacing.left property to indent them.

You can use constraints to make the parent fit the child controls.
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

kupferstecher

  • Hero Member
  • *****
  • Posts: 603
Re: Sizing the parent control depending on the children
« Reply #2 on: January 17, 2024, 03:25:36 pm »
Thanks for your reply!

About the size of the child controls, they take as much space as they need, i.e. they define it themselfes. So the size shuould propagate from bottom to the top, as the "upper" controls need more space if they have more or larger children.


In the meanwhile I played around a little and came up with a solution, I think. As said I have a base class derived from TCustomControl (for testing I just used TPanel instead), and there I override the Resize event. Also I define a (virtual) ChildResize/OnChildResize event (doesn't exist in LCL). In the Resize event I call the parent's ChildResize, so the parent can adjust its dimensions. It can do it by iterating its children and arranging them adequately. Arranging, i.e. setting Top and Left doesn't trigger Resize events, so there is no infinite loop. When the parent adjusts its dimension, its own Resize is automatically called, triggering the ChildResize of their parent and so on, until the then parent is not from the common base class any more.

There was an issue, that the Resize event is called several times and before the parent was even set. With OnResize it works, but I prefer to leave it empty for further eventual usage. So I mimik the filtering code in the TControl's Resize Procedure, which seems to work fine.

Code: Pascal  [Select][+][-]
  1. procedure TItem.Resize;
  2. begin
  3.   inherited Resize;
  4.  
  5.   //Filter to have only one Resize event per actual resizing
  6.   if ([csLoading,csDestroying]*ComponentState<>[]) then exit;
  7.   if AutoSizeDelayed then exit;
  8.  
  9.   if (Width=LastWidth) and (Height=LastHeight)
  10.   and (ClientWidth=LastClientWidth) and (ClientHeight=LastClientHeight) then EXIT;
  11.   LastWidth:= Width; LastHeight:= Height;
  12.   LastClientWidth:= ClientWidth; LastClientHeight:= ClientHeight;
  13.  
  14.   writeln('Resize:',PtrUInt(self));
  15.  
  16.   //Notify the parent
  17.   if Parent is TItem
  18.   then TItem(Parent).ChildResize(self);
  19.  
  20. end;
  21.  
  22. Procedure TItem.ChildResize(Sender:TObject);
  23. var
  24.   ii,pp: Integer;
  25. begin
  26.   writeln('ChildResize:',PtrUInt(self));
  27.  
  28.   //Adjust the Child positions
  29.   if self.ControlCount=0 then EXIT;
  30.   pp:= 40;
  31.   for ii:= 0 to self.ControlCount-1 do begin
  32.     self.Controls[ii].Top:= pp;
  33.     pp:= pp + self.Controls[ii].Height;
  34.   end;
  35.  
  36.   //Adjust the own size
  37.   self.Height:= pp+10;
  38.  
  39. end;

Joanna from IRC

  • Hero Member
  • *****
  • Posts: 1393
Re: Sizing the parent control depending on the children
« Reply #3 on: January 17, 2024, 04:38:31 pm »
I once tried to have a tedit that would get larger as text was typed into it.
 
Currently I determine how much space controls need and store it in the tag field until I actually constrain things. I no longer use any resize events except formresize which uses recursion to set the tag fields and then constrain everything.

 So I ended up with the top down approach rather than the bottom up approach. My controls are probably more nested/complicated than yours. I believe the reason I changed to top down is that the many onresize events were interfering with eachother. So if performance becomes sluggish it could be caused by that.

I use tflowpanel which naturally moves controls around to fill the space. It looks like your controls are statically anchored to the left so maybe you don’t need that.

Another issue I forgot to mention is what if the controls and parent get too large for someone who is using a small screen? Not all users have big monitors. You can’t really shrink parent if it’s width is dictated by child controls. Like what if you want to look at other things on your desktop while using program? Just some food for thought.. 8)
« Last Edit: January 17, 2024, 04:44:11 pm by Joanna »
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

kupferstecher

  • Hero Member
  • *****
  • Posts: 603
Re: Sizing the parent control depending on the children
« Reply #4 on: January 17, 2024, 05:44:13 pm »
I believe the reason I changed to top down is that the many onresize events were interfering with eachother. So if performance becomes sluggish it could be caused by that.
Yeah, that was my worry, too. The code I posted is very short, and seems like it doesn't have the issue of triggering other events, so seems OK by now.

Another issue I forgot to mention is what if the controls and parent get too large for someone who is using a small screen? Not all users have big monitors. You can’t really shrink parent if it’s width is dictated by child controls. [...] Just some food for thought..
It really is to be considered. My current solution is to put everything in a scrollbox, so the user at least can reach every place*. The more advanced would be to (additionally) allow zooming, but I've never done something like that. At least it shouldn't contradict the bottom-up approach.

*Performance could become an issue for larger lists, I'm not sure.

Joanna from IRC

  • Hero Member
  • *****
  • Posts: 1393
Re: Sizing the parent control depending on the children
« Reply #5 on: January 18, 2024, 01:14:29 am »
So the scrollbox inside of the form can get larger than the form that it’s  in? I guess that works if users don’t mind sometimes  being unable to see everything at once.

What I do is allow optional scaling of my font size depending upon form size to keep everything visible. It’s the text that usually determines how wide that controls need to be in my case. In other words controls can shrink or expand as form is resized as well as rearrange if the Form width is narrowed.
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

 

TinyPortal © 2005-2018