Recent

Author Topic: Add Controls to Sub-Control of Custom Control at Design Time  (Read 4145 times)

LazProgger

  • Full Member
  • ***
  • Posts: 110
Add Controls to Sub-Control of Custom Control at Design Time
« on: August 01, 2019, 05:11:03 pm »
I want to create a custom control that contains several "panels" as sub-controls. It should be possible to add other controls such as buttons to those sub-control-panels.

So far, I have the following code:

Code: Pascal  [Select][+][-]
  1. unit ContainerTest;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs;
  9.  
  10. type
  11.  
  12.   TContainerTestSide = class(TCustomControl)
  13.   public
  14.     constructor Create(TheOwner: TComponent); override;
  15.     destructor Destroy; override;
  16.   end;
  17.  
  18.  
  19.   TContainerTest = class(TCustomControl)
  20.   private
  21.     FSideA, FSideB: TContainerTestSide;
  22.   public
  23.     constructor Create(TheOwner: TComponent); override;
  24.     destructor Destroy; override;
  25.   published
  26.     property Anchors;
  27.     property AutoSize;
  28.     property Align default alNone;
  29.     property BorderSpacing;
  30.     property Visible;
  31.     property Constraints;
  32.     property OnMouseWheel;
  33.     property OnResize;
  34.   end;
  35.  
  36. procedure Register;
  37.  
  38. implementation
  39.  
  40.  
  41. { TContainerTestSide }
  42.  
  43. constructor TContainerTestSide.Create(TheOwner: TComponent);
  44. begin
  45.   inherited Create(TheOwner);
  46.  
  47.   ControlStyle := ControlStyle + [csAcceptsControls];
  48.  
  49.   self.Color := clRed;
  50.  
  51.   self.Width  := 100;
  52.   self.Height := 200;
  53. end;
  54.  
  55. destructor TContainerTestSide.Destroy;
  56. begin
  57.   inherited Destroy;
  58. end;
  59.  
  60.  
  61.  
  62. { TContainerTest }
  63.  
  64. constructor TContainerTest.Create(TheOwner: TComponent);
  65. begin
  66.   inherited Create(TheOwner);
  67.  
  68.   ControlStyle := ControlStyle - [csAcceptsControls];
  69.  
  70.   self.Width  := 200;
  71.   self.Height := 200;
  72.  
  73.   self.FSideA := TContainerTestSide.Create(self);
  74.   self.FSideA.Align := alLeft;
  75.   self.FSideA.SetSubComponent(true);
  76.   self.FSideA.Parent := self;
  77.  
  78.   self.FSideB := TContainerTestSide.Create(self);
  79.   self.FSideB.Align := alRight;
  80.   self.FSideB.SetSubComponent(true);
  81.   self.FSideB.Parent := self;
  82. end;
  83.  
  84. destructor TContainerTest.Destroy;
  85. begin
  86.   self.FSideA.Free;
  87.   self.FSideB.Free;
  88.  
  89.   inherited Destroy;
  90. end;
  91.  
  92. procedure Register;
  93. begin
  94.   {$I containertest_icon.lrs}
  95.   RegisterComponents('TestControls',[TContainerTest]);
  96.   RegisterNoIcon([TContainerTestSide]);
  97. end;
  98.  
  99.  
  100. end.
  101.  

This code compiles well, the sub panels (FSideA and FSideB) are displayed at design time (I made them red to see that) and I can add controls to the sub panels at run-time.

However, the sub panels are not displayed in the object inspector and I can not add controls to them at design time.

How can I do that? Probably it's just some kind of flag or property I have to set (ControlStyle or so?). But I don't know. Can someone help me? Lazarus' TPairSplitter is behaving in a way, I want to have here, so there must be a way. But I could not figure out how it is done there when analyzing its code.

« Last Edit: August 01, 2019, 05:13:10 pm by LazProgger »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #1 on: August 01, 2019, 05:55:20 pm »
You need to write a property editor, so the object inspector knows how to handle and edit the sub-property class you have introduced.

See here

kupferstecher

  • Hero Member
  • *****
  • Posts: 604
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #2 on: August 01, 2019, 07:26:28 pm »
An simple way could be to publish the relevant properties of the sub panels in the custom control itself (TContainerTestSide in your example).
But that wouldn't solve the problem of adding controls at design time.

LazProgger

  • Full Member
  • ***
  • Posts: 110
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #3 on: August 01, 2019, 10:00:01 pm »
You need to write a property editor

Isn't there a simpler way than using the property editor? That seems to be an overkill for this simple task, because I don't need those possibilities to edit custom properties and so on, I just want to add controls at design time. I hoped that's just a flag to set or a call of a register function or something like that.

An simple way could be to publish the relevant properties of the sub panels in the custom control itself (TContainerTestSide in your example).
But that wouldn't solve the problem of adding controls at design time.

One of my first approaches was to publish the sub panels in the control:

Code: Pascal  [Select][+][-]
  1.   published
  2.     ...
  3.     property SideA: TContainerTestSide read FSideA write FSideA;
  4.     property SideB: TContainerTestSide read FSideB write FSideB;
  5.   end;  
  6.  

With this, the properties of the sub panels where editable via the object inspector but they were displayed in the list of properties of the control itself, not as own control (like Lazarus' LabeledEdit control). And it was also not possible to add controls to the sub panels. So this was no solution.

LazProgger

  • Full Member
  • ***
  • Posts: 110
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #4 on: August 02, 2019, 09:35:01 pm »
You need to write a property editor, so the object inspector knows how to handle and edit the sub-property class you have introduced.

See here

I have searched the web for how to use this property editor. But I have not found anything and I have no idea where to start.

Can someone give me a little advice?

And do I need the property editor for the base component or for the sub components?

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #5 on: August 02, 2019, 09:49:19 pm »
Do you need the container control? Because if not it might be easier to use a TFrame to contain the panels and that would allow you to treat them normally, as if they were embeded in a form. I use this "trick" when I've to implement a form with a complex layout.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

wp

  • Hero Member
  • *****
  • Posts: 13329
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #6 on: August 02, 2019, 09:54:09 pm »
You need to write a property editor, so the object inspector knows how to handle and edit the sub-property class you have introduced.

See here

I have searched the web for how to use this property editor. But I have not found anything and I have no idea where to start.

Can someone give me a little advice?
There's not much written beyond https://wiki.lazarus.freepascal.org/How_To_Write_Lazarus_Component#Integrating_the_component_with_the_IDE. You must study the source code of the IDE. The important things are in (lazarus)/components/ideintf/propedits.pas and componenteditors.pas (with much included documentation). It's hard stuff, though... I would try to find out which one of the standard components comes close to what you have in mind, then search the component editor for it and  try to learn as much of its code as possible.
« Last Edit: August 02, 2019, 10:05:18 pm by wp »

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12012
  • Debugger - SynEdit - and more
    • wiki
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #7 on: August 02, 2019, 09:59:13 pm »
I am not sure you need prop-editors.

Have you played with SetInline(True); ? (for the outer control)

wp

  • Hero Member
  • *****
  • Posts: 13329
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #8 on: August 02, 2019, 10:08:08 pm »
I want to create a custom control that contains several "panels" as sub-controls. It should be possible to add other controls such as buttons to those sub-control-panels.
[...]
the sub panels (FSideA and FSideB)...
Have you considered using a TPairSplitter? From what I understood when reading your 1st post, this is what gets very close to what you may want.

LazProgger

  • Full Member
  • ***
  • Posts: 110
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #9 on: August 02, 2019, 10:24:18 pm »
Have you considered using a TPairSplitter? From what I understood when reading your 1st post, this is what gets very close to what you may want.

Yes, it comes close. However, I want to do something else, but I have reduced my example code to only show the basics with which I am playing at the moment, also to learn something more about the IDE internals.

LazProgger

  • Full Member
  • ***
  • Posts: 110
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #10 on: August 02, 2019, 10:30:44 pm »
I am not sure you need prop-editors.

Have you played with SetInline(True); ? (for the outer control)

Very good! In my first test, this made the sub panels visible in the object inspector! :)

That's the first step in the right direction. However, it was not possible to add controls at design time to the panels. :/

Although I have used ControlStyle := ControlStyle + [csAcceptsControls] for the sub panels it is not possible to drag a button or something else on it (neither via the object  inspector nor via the form designer). The object inspector is showing the not-accept-cursor and in the designer the added control is added to the form behind.
« Last Edit: August 02, 2019, 10:39:26 pm by LazProgger »

LazProgger

  • Full Member
  • ***
  • Posts: 110
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #11 on: August 02, 2019, 10:51:42 pm »
Very good! In my first test, this made the sub panels visible in the object inspector! :)

Perhaps the problem is that the sides do not have a name in the object inspector...

Is there something to set to give the sub components a name?
« Last Edit: August 02, 2019, 11:14:29 pm by LazProgger »

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #12 on: August 03, 2019, 02:25:34 pm »
Their Name property?

LazProgger

  • Full Member
  • ***
  • Posts: 110
Re: Add Controls to Sub-Control of Custom Control at Design Time
« Reply #13 on: August 03, 2019, 02:55:24 pm »
Their Name property?

Yes. Normally, you have something like "Button1: TButton" in the object inspector, I had ": TContainerTestSide" instead of "ContrainerTestSide1:TContainerTestSide" there and also the name property was empty.

I have searched the code of other controls and have found that they are using CreateUniqueComponentName for that.
So, I wrote the following:

Code: Pascal  [Select][+][-]
  1.   if csDesigning in self.ComponentState then begin
  2.      self.FSideA.Name := FormEditingHook.CreateUniqueComponentName(self.FSideA.ClassName, self);
  3.   end;            
  4.  

Now, the sub panels get a proper name but it is still not possible to add controls at design time to them :/

 

TinyPortal © 2005-2018