Recent

Author Topic: inheriting a standard component  (Read 7633 times)

codifies

  • Jr. Member
  • **
  • Posts: 98
    • bedroomcoders
inheriting a standard component
« on: August 12, 2021, 06:16:25 pm »
is there away to inherit a standard component, so I can override just one procedure ?

ideally I'd like something like a unit in a project, rather than having to make a new component and recompile the whole IDE
Lazarus 2.3.0 r3945f73 FPC 3.2.0 x86_64-linux-gtk2

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1570
    • Lebeau Software
Re: inheriting a standard component
« Reply #1 on: August 12, 2021, 07:03:07 pm »
is there away to inherit a standard component, so I can override just one procedure ?

ideally I'd like something like a unit in a project, rather than having to make a new component and recompile the whole IDE

Have you tried using an interposer class?  Not sure if this works in FreePascal, but in Delphi, you can do the following:

Code: Pascal  [Select][+][-]
  1. unit MyForm;
  2.  
  3. interface
  4.  
  5. uses
  6.   ..., StdCtrls;
  7.  
  8. type
  9.   TButton = class(StdCtrls.TButton)
  10.     ...
  11.   end;
  12.  
  13.   TForm1 = class(TForm)
  14.     Button1: TButton;
  15.     ...
  16.   end;
  17.  
  18. implementation
  19.  
  20. ...
  21.  
  22. end.
  23.  

Alternatively:

Code: Pascal  [Select][+][-]
  1. unit MyButton;
  2.  
  3. interface
  4.  
  5. uses
  6.   ..., StdCtrls;
  7.  
  8. type
  9.   TButton = class(StdCtrls.TButton)
  10.     ...
  11.   end;
  12.  
  13. implementation
  14.  
  15. ...
  16.  
  17. end.
  18.  
Code: Pascal  [Select][+][-]
  1. unit MyForm;
  2.  
  3. interface
  4.  
  5. uses
  6.   ..., StdCtrls, MyButton; // <-- make sure MyButton is AFTER StdCtrls!
  7.  
  8. type
  9.   TForm1 = class(TForm)
  10.     Button1: TButton;
  11.     ...
  12.   end;
  13.  
  14. implementation
  15.  
  16. ...
  17.  
  18. end.
  19.  

Either way, every TButton on the Form would then be your derived class.
« Last Edit: August 12, 2021, 07:08:39 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: inheriting a standard component
« Reply #2 on: August 12, 2021, 07:25:13 pm »
Have you tried using an interposer class?  Not sure if this works in FreePascal, but in Delphi, you can do the following:
[... etc ...]

It works in Free Pascal exactly as in Delphi (from the programmer's p.o.v.). The issue at hand here (IMHO, and also for the interposer which is, after all, just a "normal" derived class) is rather whether the "new" method is an override (possible if the method in the base class is virtual), an overload (same name but different signature, almost always possible though not usually recommended) or a sustitution (same signature, non-virtual base method).

In this last case the new method must almost always (re)implement at least part(s) of the base method, e.g. those dealing with interfacing with the widgetset or the IDE, if any, and similar.

These kind of things can be easily dealt with in the other two cases (in the first by using inherited and in the second by calling the base one) but in the last one the base is thoroughly hidden (and the compiler warns about this fact) so parts of it have usually to be copied over and adapted.

Not that it can't be done, but it's definitively not something for the faint of heart ;D
« Last Edit: August 12, 2021, 07:28:22 pm by lucamar »
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.

codifies

  • Jr. Member
  • **
  • Posts: 98
    • bedroomcoders
Re: inheriting a standard component
« Reply #3 on: August 12, 2021, 07:32:59 pm »
I tried making a new component and somehow hosed lazarus so that option is out for now, just too easy to mess things up...

Not sure I follow interposer classes, what would happen on the designer?

To be honest I think I'll just leave Lazarus for another few years, redesigning data controls to show actual database text fields as text not (MEMO) just shouldn't be required...
Lazarus 2.3.0 r3945f73 FPC 3.2.0 x86_64-linux-gtk2

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1570
    • Lebeau Software
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: inheriting a standard component
« Reply #5 on: August 12, 2021, 11:50:32 pm »
Not sure I follow interposer classes, what would happen on the designer?

You can use the standard control in the designer; only you will not have access in the object inspector to any new published properties you might have.

For example, in one of my own programs I use an interposed TMemo (which now resides in its own unit) and the mainform contains just a TMemo declaration. Only, my MemoEx unit is added after StdCtrls (where the standard TMemo resides), so whenever there is a "TMemo" declaration in the source it refers to my TMemo, not the one in StdCtrls.

However, the IDE knows nothing at all about this, since my unit doesn't register nor exposes my TMemo to the IDE in any way, other than as any other normal source, so for design purposes the IDE creates and uses a normal, standard TMemo ;)
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.

codifies

  • Jr. Member
  • **
  • Posts: 98
    • bedroomcoders
Re: inheriting a standard component
« Reply #6 on: August 13, 2021, 04:00:51 am »
thanks for those links made it much clearer! especially the complete example...

certainly a lot less risky than potentially hosing the ide!

why on earth the whole IDE needs to be recompiled just for a component is beyond me, components should be in their own little libraries - with a standard api all nice and plugin like !
Lazarus 2.3.0 r3945f73 FPC 3.2.0 x86_64-linux-gtk2

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: inheriting a standard component
« Reply #7 on: August 13, 2021, 07:32:45 am »
why on earth the whole IDE needs to be recompiled just for a component is beyond me, components should be in their own little libraries - with a standard api all nice and plugin like !

Very, very basically the IDE needs to be able to create controls/components on-the-fly and for that it has to have their code accessible at run-time. Of course, that can be done by having packages be akin to a DLL which can be loaded when needed, as does Delphi. Problem is that Lazarus needs a homogeneous cross-platform way to do it, which is not as easy as it sounds, so instead it recompiles itself to include the needed code inside its own.

However, work on dynamic packages has been (slowly) in progress for quite some time now and one of this days we'll have them, just as Delphi users have from day one and we'll be able to forget about recompiling the IDE each time we want a new design-time package installed :)
« Last Edit: August 13, 2021, 07:34:32 am by lucamar »
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.

PascalDragon

  • Hero Member
  • *****
  • Posts: 6267
  • Compiler Developer
Re: inheriting a standard component
« Reply #8 on: August 13, 2021, 08:59:07 am »
why on earth the whole IDE needs to be recompiled just for a component is beyond me, components should be in their own little libraries - with a standard api all nice and plugin like !

You simply can't just use libraries as each library would have their own "instance" of the RTL and other shared classes and those would be considered incompatible then. As lucamar said the solution for this is dynamic packages (essentially libraries plus a whole load of compiler magic), but it's a work in progress as it's complex to get right especially with multi platform support.

egsuh

  • Hero Member
  • *****
  • Posts: 1729
Re: inheriting a standard component
« Reply #9 on: August 13, 2021, 09:11:54 am »
If you need to change only one procedure, think helpers. I'm trying a few Interposers --- they are fine as well.

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: inheriting a standard component
« Reply #10 on: August 13, 2021, 01:32:48 pm »
If you need to change only one procedure, think helpers. I'm trying a few Interposers --- they are fine as well.

Yeah, for relatively "simple" things a helper should be preferred and not just for the "coolness" factor (which, let's be honest, it is there ;)) but because they're lighter-weighted compared to a child (not by much, mind, but enough) and you code it as an extension of the base class. Which is all class helpers really are, after all.

But as soon as you start doing even mildly "heavy" modifications to the behaviour of the base class (like, say, adding a new field) a child class (whether interposed or not) is the way to go.

Of course, it need not be instalable from a package, registable with the IDE and requiring recompilation of this last. Only when your new class is a component/control which must be insertable and modifiable at design-time (i.e. appearing in the O.I. and writable/readable to/from the form resource) it needs be so; otherwise just creating a package, opening it in the IDE and compiling it is enough for the IDE to remember where it is and you can add the package to a project's requisites, declare and use instances of the class, etc.

If anyone is interested I can make a write-up explaining the process through which I went to end up with my TMemo interposer. It's mildly interesting and entertaining and would allow anyone to understand how and why one decides between helper functions, full helpers or (interposed) child classes. Not that I'm a guru or anything like that, though ... just a little experience :-[ 
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.

codifies

  • Jr. Member
  • **
  • Posts: 98
    • bedroomcoders
Re: inheriting a standard component
« Reply #11 on: August 14, 2021, 09:26:45 am »
... each library would have their own "instance" of the RTL and other shared classes and those would be considered incompatible

Can you expand on this? in what way would they be "incompatible" I'm guessing pascal and C at this level must be working in quite a different way!
Lazarus 2.3.0 r3945f73 FPC 3.2.0 x86_64-linux-gtk2

jamie

  • Hero Member
  • *****
  • Posts: 7488
Re: inheriting a standard component
« Reply #12 on: August 14, 2021, 03:01:33 pm »
Please detail the method you wish to intercept and what you would like to do with this said method?

I am sure if you could reveal that little tidbit someone here could offer up a solution, most likely a simple one.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018