* * *

Author Topic: Autosize mechanism  (Read 2227 times)

taazz

  • Hero Member
  • *****
  • Posts: 5336
Autosize mechanism
« on: July 06, 2018, 04:45:51 am »
What is the latest news on the autosize mechanism of lcl is it possible to be disabled in any of the newer versions (later than 1.4.4)? If not is there any plans to allow one to disable it or preferable remove the code completely from ones applications?
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3489
  • I like bugs.
Re: Autosize mechanism
« Reply #1 on: July 06, 2018, 08:46:07 am »
The Autosize property can be switched off. It was possible already in Lazarus 1.4.4 and still is.

taazz

  • Hero Member
  • *****
  • Posts: 5336
Re: Autosize mechanism
« Reply #2 on: July 06, 2018, 08:48:37 am »
not the property, the mechanism, you know the problematic call to parent.resize every time you set the size of control.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3489
  • I like bugs.
Re: Autosize mechanism
« Reply #3 on: July 06, 2018, 09:57:34 am »
not the property, the mechanism, you know the problematic call to parent.resize every time you set the size of control.
Yes but if you switch off Autosize for every control, the whole mechanism will effectively be disabled.
Doing that for a GUI form is relatively easy at both design time and run time.

taazz

  • Hero Member
  • *****
  • Posts: 5336
Re: Autosize mechanism
« Reply #4 on: July 06, 2018, 10:28:36 am »
no it will not be disabled, it will fall into an infinite loop regardless of the auto size property.

PS
It seems that my choice of words are bad, I'm not after the autosize behavior I just want to disable the resize mechanism that calls the parent resize, something that is needed in the visual designer of the ide, but as far as I know it is the only place that is needed, I personally have no use for it even on my own runtime visual designer. Sorry for the confusion.
« Last Edit: July 06, 2018, 10:34:23 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3489
  • I like bugs.
Re: Autosize mechanism
« Reply #5 on: July 06, 2018, 11:08:03 am »
no it will not be disabled, it will fall into an infinite loop regardless of the auto size property.
That means there is a bug in the LCL layout system. You should report it with an example.

Quote
It seems that my choice of words are bad, I'm not after the autosize behavior I just want to disable the resize mechanism that calls the parent resize, something that is needed in the visual designer of the ide, but as far as I know it is the only place that is needed, I personally have no use for it even on my own runtime visual designer. Sorry for the confusion.
AFAIK the same layout code that is used at runtime is also used by the visual designer.
That allows the WYSIWYG experience at design time.

taazz

  • Hero Member
  • *****
  • Posts: 5336
Re: Autosize mechanism
« Reply #6 on: July 06, 2018, 11:20:31 am »
no it will not be disabled, it will fall into an infinite loop regardless of the auto size property.
That means there is a bug in the LCL layout system. You should report it with an example.
you assume I'm talking about standard controls, I'm not.
Quote
It seems that my choice of words are bad, I'm not after the autosize behavior I just want to disable the resize mechanism that calls the parent resize, something that is needed in the visual designer of the ide, but as far as I know it is the only place that is needed, I personally have no use for it even on my own runtime visual designer. Sorry for the confusion.
AFAIK the same layout code that is used at runtime is also used by the visual designer.
That allows the WYSIWYG experience at design time.
The resize infinite loop is only used during design time to auto size a container (when autosize is true) when a contained control is sized outside its boundaries. That is the only thing that makes sense to call the parent.resize method. Its a good idea poorly designed and badly implemented. On top of that there is no escape mechanism in place to avoid using the "layout mechanism" or change it to a more suitable behavior. In any way I guess I have my answer. Thank you for your time.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3489
  • I like bugs.
Re: Autosize mechanism
« Reply #7 on: July 06, 2018, 12:46:58 pm »
you assume I'm talking about standard controls, I'm not.
Ok, it is your own custom control. In that case you should override procedure GetPreferredSize(), defined in TControl which also has other useful virtual methods.
More useful virtual methods can be found in TWinControl.
You may want to look at complex controls like TCustomCoolBar which overrides TWinControl.AlignControls() instead of TControl.GetPreferredSize().

Quote
The resize infinite loop is only used during design time to auto size a container (when autosize is true) when a contained control is sized outside its boundaries. That is the only thing that makes sense to call the parent.resize method.
Why is autosizing a container needed only at design time? How did you prevent the layout code being called at runtime?

Quote
Its a good idea poorly designed and badly implemented. On top of that there is no escape mechanism in place to avoid using the "layout mechanism" or change it to a more suitable behavior.
Yes there is, namely the virtual methods of TControl and TWinControl which you can override.
Can you please show a simple example code demostrating the problems you are facing?
« Last Edit: July 06, 2018, 12:54:45 pm by JuhaManninen »

taazz

  • Hero Member
  • *****
  • Posts: 5336
Re: Autosize mechanism
« Reply #8 on: July 06, 2018, 01:53:10 pm »
you assume I'm talking about standard controls, I'm not.
Ok, it is your own custom control. In that case you should override procedure GetPreferredSize(), defined in TControl which also has other useful virtual methods.
More useful virtual methods can be found in TWinControl.
You may want to look at complex controls like TCustomCoolBar which overrides TWinControl.AlignControls() instead of TControl.GetPreferredSize().
TCoolbar is not part of 1.4.4 as I said I'm stuck with 1.4.4 for the foreseeable future but hey I'm porting an sql server to lazarus that meens 1.8.2 or newer I guess I'll look it up there.
Quote
The resize infinite loop is only used during design time to auto size a container (when autosize is true) when a contained control is sized outside its boundaries. That is the only thing that makes sense to call the parent.resize method.
Why is autosizing a container needed only at design time? How did you prevent the layout code being called at runtime?

Quote
Its a good idea poorly designed and badly implemented. On top of that there is no escape mechanism in place to avoid using the "layout mechanism" or change it to a more suitable behavior.
Yes there is, namely the virtual methods of TControl and TWinControl which you can override.
Can you please show a simple example code demostrating the problems you are facing?
they are not important at this stage lazarus is no longer in my professional toolbox its used only at home, so when I get around it I'll try to find the control with the problem and see where I got stamped.two things from memory UpdateAlignIndex needs to be rewritten as soon as possible its unacceptable, If I rember correctly it goes on to create controls directly in some other controls private space or something along those lines.

The method that sets the size of the control is DoSetBounds (which, if I'm correct, comes 3rd in a long chain of methods) it calls parent.invalidate some size or something of that nature. Now this is virtual in 1.4.4, how can I set the FLeft, FRight etc fields of the control with out calling the inherited method and inadvertently calling parent.whatever?
Since I'm bitching publicly let me add a small annoyance in there too, just to get it out of my system. In Delphi there are 2 groups of methods the workers and event raisers. DoXXXXXXX are the methods that raise the event where XXXX is the worker method lazarus has it backwards but that's a preference as long as its always the same I can tolerate it.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3489
  • I like bugs.
Re: Autosize mechanism
« Reply #9 on: July 06, 2018, 03:13:31 pm »
TCoolbar is not part of 1.4.4 as I said I'm stuck with 1.4.4 for the foreseeable future but hey I'm porting an sql server to lazarus that meens 1.8.2 or newer I guess I'll look it up there.
Yes, you can look at more recent sources in any case.

Quote
they are not important at this stage lazarus is no longer in my professional toolbox its used only at home, ...
Hmmm... then why you still must use Lazarus 1.4.4?
Last time it was about Unicode issues but you refused to give details then. I still believe those issues could be solved easily.

Quote
... so when I get around it I'll try to find the control with the problem and see where I got stamped.two things from memory UpdateAlignIndex needs to be rewritten as soon as possible its unacceptable, If I rember correctly it goes on to create controls directly in some other controls private space or something along those lines.
Code: Pascal  [Select]
  1. procedure TControl.UpdateAlignIndex;
  2. var
  3.   i: Integer;
  4. begin
  5.   if Parent=nil then exit;
  6.   if Parent.FAlignOrder=nil then
  7.     Parent.FAlignOrder:=TFPList.Create;
  8.   i:=Parent.FAlignOrder.IndexOf(Self);
  9.   if i<0 then
  10.     Parent.FAlignOrder.Insert(0,Self)
  11.   else
  12.     Parent.FAlignOrder.Move(i,0);
  13. end;
TWinControl has:
Code: Pascal  [Select]
  1. FAlignOrder: TFPList; // list of TControl. Last moved (SetBounds) comes first. Used by AlignControls.
So, it does not create controls. It only creates FAlignOrder list which (I guess) is an optimization. The code is old and works well with other controls.

Quote
The method that sets the size of the control is DoSetBounds (which, if I'm correct, comes 3rd in a long chain of methods) it calls parent.invalidate some size or something of that nature. Now this is virtual in 1.4.4, how can I set the FLeft, FRight etc fields of the control with out calling the inherited method and inadvertently calling parent.whatever?
Hard to say without an example code. All other controls are able to do it without resize loops.

BTW, there is a bug related to TControl.ChangeBounds. Sometimes the values go outside Smallint limits. I have added debug code there but nobody has caught the fundamental cause yet.
This is not related to your issues though.

Quote
Since I'm bitching publicly let me add a small annoyance in there too, just to get it out of my system. In Delphi there are 2 groups of methods the workers and event raisers. DoXXXXXXX are the methods that raise the event where XXXX is the worker method lazarus has it backwards but that's a preference as long as its always the same I can tolerate it.
Yes, there are mixed naming styles. A patch to clean them would by accepted I believe. If it breaks the protected / public interface then the original method names must be retained as "deprecated" for some years.

taazz

  • Hero Member
  • *****
  • Posts: 5336
Re: Autosize mechanism
« Reply #10 on: July 06, 2018, 03:50:49 pm »
TCoolbar is not part of 1.4.4 as I said I'm stuck with 1.4.4 for the foreseeable future but hey I'm porting an sql server to lazarus that meens 1.8.2 or newer I guess I'll look it up there.
Yes, you can look at more recent sources in any case.

Quote
they are not important at this stage lazarus is no longer in my professional toolbox its used only at home, ...
Hmmm... then why you still must use Lazarus 1.4.4?
Last time it was about Unicode issues but you refused to give details then. I still believe those issues could be solved easily.
Yes, those issues where the excuse needed to move to C# at work. I'm using 1.4.4 to maintain a couple of utilities until a more permanent solution is found. thankfully we are not aggressively replacing everything yet.
Quote
... so when I get around it I'll try to find the control with the problem and see where I got stamped.two things from memory UpdateAlignIndex needs to be rewritten as soon as possible its unacceptable, If I rember correctly it goes on to create controls directly in some other controls private space or something along those lines.
Code: Pascal  [Select]
  1. procedure TControl.UpdateAlignIndex;
  2. var
  3.   i: Integer;
  4. begin
  5.   if Parent=nil then exit;
  6.   if Parent.FAlignOrder=nil then
  7.     Parent.FAlignOrder:=TFPList.Create;
  8.   i:=Parent.FAlignOrder.IndexOf(Self);
  9.   if i<0 then
  10.     Parent.FAlignOrder.Insert(0,Self)
  11.   else
  12.     Parent.FAlignOrder.Move(i,0);
  13. end;
TWinControl has:
Code: Pascal  [Select]
  1. FAlignOrder: TFPList; // list of TControl. Last moved (SetBounds) comes first. Used by AlignControls.
So, it does not create controls. It only creates FAlignOrder list which (I guess) is an optimization. The code is old and works well with other controls.
Yes I used control as a synonym for object my bad. I don't see the optimization sorry.
Quote
The method that sets the size of the control is DoSetBounds (which, if I'm correct, comes 3rd in a long chain of methods) it calls parent.invalidate some size or something of that nature. Now this is virtual in 1.4.4, how can I set the FLeft, FRight etc fields of the control with out calling the inherited method and inadvertently calling parent.whatever?
Hard to say without an example code. All other controls are able to do it without resize loops.
As far as I remember the only thing I did was to call setbounds at the constructor or onload and the control raised the exception, but better try and find the code before I send you down the wrong path.
BTW, there is a bug related to TControl.ChangeBounds. Sometimes the values go outside Smallint limits. I have added debug code there but nobody has caught the fundamental cause yet.
This is not related to your issues though.
good to know for future reference if I stamble on it I'll give it a go. My guess is that it comes from the constraintresize.
Quote
Since I'm bitching publicly let me add a small annoyance in there too, just to get it out of my system. In Delphi there are 2 groups of methods the workers and event raisers. DoXXXXXXX are the methods that raise the event where XXXX is the worker method lazarus has it backwards but that's a preference as long as its always the same I can tolerate it.
Yes, there are mixed naming styles. A patch to clean them would by accepted I believe. If it breaks the protected / public interface then the original method names must be retained as "deprecated" for some years.
any sort of public guide lines I can consult for what it is expected? I could do a couple of bug reports but I need to know what I'm aiming for.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3489
  • I like bugs.
Re: Autosize mechanism
« Reply #11 on: July 06, 2018, 06:17:44 pm »
Yes, those issues where the excuse needed to move to C# at work. I'm using 1.4.4 to maintain a couple of utilities until a more permanent solution is found. thankfully we are not aggressively replacing everything yet.
So, it was an excuse and there were no real issues. Is that right?
Please switch to Lazarus 1.8.4 for those utilities. Did you even try to solve the Unicode issues? You may be positively surprised if you try.

Quote
Yes I used control as a synonym for object my bad. I don't see the optimization sorry.
I don't know the purpose of that code either. I did not study the code more. Actually this was the first time I noticed that method. It is likely made by Mattias a long time ago.
TControl and its derivatives create lots of private variables. What is the problem with this one particular TFPList?

Quote
As far as I remember the only thing I did was to call setbounds at the constructor or onload and the control raised the exception, but better try and find the code before I send you down the wrong path.
Don't do that! Instead override procedure GetPreferredSize() as I told earlier. Your bad again ... :)
For the record, the layout algorith in LCL is more advanced than in Delphi's VCL but it requires more careful coding in some situations.

Quote
any sort of public guide lines I can consult for what it is expected? I could do a couple of bug reports but I need to know what I'm aiming for.
You suggested Delphi's naming convention yourself which is OK. Otherwise there are no strict guidelines. The public and published interfaces of controls are more or less Delphi compatible. Protected method names may differ because the internals differ from Delphi.

taazz

  • Hero Member
  • *****
  • Posts: 5336
Re: Autosize mechanism
« Reply #12 on: July 06, 2018, 07:20:21 pm »
Yes, those issues where the excuse needed to move to C# at work. I'm using 1.4.4 to maintain a couple of utilities until a more permanent solution is found. thankfully we are not aggressively replacing everything yet.
So, it was an excuse and there were no real issues. Is that right?
Please switch to Lazarus 1.8.4 for those utilities. Did you even try to solve the Unicode issues? You may be positively surprised if you try.
There where issues, some technical, some marketing, but most of them had to do with hiring new people. The unicode issues were used to demonstrate what happens when you do not follow the main stream and how that affects the bottom line, no support for utf16 was used as an other "off the lines" example since most of the big players are utf16 etc. The technical reasons could be solved but the "off the main stream" taste was too prevalent to be of any help.
Quote
Yes I used control as a synonym for object my bad. I don't see the optimization sorry.
I don't know the purpose of that code either. I did not study the code more. Actually this was the first time I noticed that method. It is likely made by Mattias a long time ago.
TControl and its derivatives create lots of private variables. What is the problem with this one particular TFPList?
Its in the wrong place. You never access private variables of other objects, you create a method that will place the control on top of the order and call that, you are not supposed to know anything about the internals of other objects even objects of the same class it is "tight coupling" (sorry can't remember the term at the moment) which is 1) insecure 2) thread problematic (in case of multithreading) 3) hard to track and change in the future. It has so many red flags for me that has me stamped actually.
Quote
As far as I remember the only thing I did was to call setbounds at the constructor or onload and the control raised the exception, but better try and find the code before I send you down the wrong path.
Don't do that! Instead override procedure GetPreferredSize() as I told earlier. Your bad again ... :)
No that's YOUR bad, you mined the constructor with a bad design and even worst implementation, for a feature that is only useful to the IDE. Sorry but that is inappropriate for a library.

For the record, the layout algorith in LCL is more advanced than in Delphi's VCL but it requires more careful coding in some situations.
Quote
any sort of public guide lines I can consult for what it is expected? I could do a couple of bug reports but I need to know what I'm aiming for.
You suggested Delphi's naming convention yourself which is OK. Otherwise there are no strict guidelines. The public and published interfaces of controls are more or less Delphi compatible. Protected method names may differ because the internals differ from Delphi.
I suggested a clear line, delphi was an example, I was a bit annoyed with the reversed meaning mostly because I dived in blindly and fallen on my face, but that does not mean that there has to be a line let alone compatible with delphi. In any case I will post a request on the bug tracker for a couple of methods I came across and mark it as delphi compatibility and see where that takes us.
You could go with a number of interesting designs (a list of observers that react on the changes of the control) or standard ones (list of event handlers on the OnResize /onmove just like application handlers (Application.AddOnActivateHandler and friends) or even better have a controller reacting on the events that can be replaced for different layouts reducing the executed code to only the pieces needed by the application, you chose the worst, directly call the parent methods.
Any way, I'm off the gui programming for the time being and it will take me some time before I'll be able to spend some serious time on it again.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

JuhaManninen

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3489
  • I like bugs.
Re: Autosize mechanism
« Reply #13 on: July 06, 2018, 11:20:04 pm »
Its in the wrong place. You never access private variables of other objects, you create a method that will place the control on top of the order and call that, you are not supposed to know anything about the internals of other objects even objects of the same class it is "tight coupling" (sorry can't remember the term at the moment) which is 1) insecure 2) thread problematic (in case of multithreading) 3) hard to track and change in the future. It has so many red flags for me that has me stamped actually.
You have a valid point here. UpdateAlignIndex deals with a private variable of TWinControl so I moved it there in r58449.
You maybe exaccerated a little. It was secure, threading is not an issue here because the GUI layout code runs always in the main thread, and it was easy to change.

Quote
No that's YOUR bad, you mined the constructor with a bad design and even worst implementation, for a feature that is only useful to the IDE. Sorry but that is inappropriate for a library.
I didn't quite understand this one. What is the bad design in a constructor? I think constructors work well.
Anyway, the layout system can be improved with new features and events but only if they solve a real problem. It looks like your issues can be solved using the existing interface.

taazz

  • Hero Member
  • *****
  • Posts: 5336
Re: Autosize mechanism
« Reply #14 on: July 07, 2018, 03:39:34 am »
Its in the wrong place. You never access private variables of other objects, you create a method that will place the control on top of the order and call that, you are not supposed to know anything about the internals of other objects even objects of the same class it is "tight coupling" (sorry can't remember the term at the moment) which is 1) insecure 2) thread problematic (in case of multithreading) 3) hard to track and change in the future. It has so many red flags for me that has me stamped actually.
You have a valid point here. UpdateAlignIndex deals with a private variable of TWinControl so I moved it there in r58449.
You maybe exaccerated a little. It was secure, threading is not an issue here because the GUI layout code runs always in the main thread, and it was easy to change.
No its bad design to access the private fields of an other class for all the reasons above including insecure. Thing of it this way what if there was a law that made mandatory for any driver to change the lights of the car infront of them (when stopped on a light) if that car used the same light bulb as his car? Well, now that is a stretch of imagination but its similar situation. The reasons are valid, no exaggeration was used, they are simple more generic than use in the lcl.
Quote
No that's YOUR bad, you mined the constructor with a bad design and even worst implementation, for a feature that is only useful to the IDE. Sorry but that is inappropriate for a library.
I didn't quite understand this one. What is the bad design in a constructor? I think constructors work well.
Anyway, the layout system can be improved with new features and events but only if they solve a real problem. It looks like your issues can be solved using the existing interface.
You have introduced artifacts that made setting the size of a control an exercise in patience and analysis that is bad design, adding mechanisms to handle what it should not be there only adds to the confusion it does not make things easier, the more mechanisms you add, the harder it becomes to use the library, the less people will use it and you need people to use it.

as for the existing interface comment you haven't answer my original question, I want to change the size of a control and not inform anyone about that change how it is done? I do not want the parent to be updated I do not want the layout to be recalculated or changed in any way. I just want to change the control's size. Go show me how.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus