Sign in Join

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

Mailing lists / lazarus / 2011-10

TControl.Click?

28 messages · 5 people ·

Reply by email Subscribe to this list Your subscription

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

Hans-Peter Diettrich

I don't understand the logic behind TControl.Click:

procedure TControl.Click;
begin
   //DebugLn(['TControl.Click ',DbgSName(Self)]);
   if (not (csDesigning in ComponentState)) and (ActionLink  nil) and
      ((Action=nil) or (@FOnClick  @Action.OnExecute) or
Assigned(FOnClick)) then
     ActionLink.Execute(Self)
   else
   if Assigned(FOnClick) then
     FOnClick(Self);
end;

This IMO will invoke ActionLink.Execute if (a different) FOnClick is assigned - so far okay. But FOnClick will *not* be invoked then (even if different), and it will be invoked *always* in design state.

Is it really okay to invoke an user-supplied OnClick handler in design state?

What about something like this:

   if (csDesigning in ComponentState) then
     exit; //nothing called in design state
   if (ActionLink  nil)
     and ((Action=nil) or (@FOnClick  @Action.OnExecute) then
     ActionLink.Execute(Self); //only if different from FOnClick
   if Assigned(FOnClick) then //eventually also: if not handled?
     FOnClick(Self); //always if assigned
end;

I also wonder what's the difference or relationship between Action and ActionLink - can somebody explain? Does ActionLink (when assigned) take precedence over Action?

DoDi

Reply by email

Mattias Gaertner
to Hans-Peter Diettrich
Show quoted text 20 lines
I don't understand the logic behind TControl.Click: procedure TControl.Click; begin //DebugLn(['TControl.Click ',DbgSName(Self)]); if (not (csDesigning in ComponentState)) and (ActionLink nil) and ((Action=nil) or (@FOnClick @Action.OnExecute) or Assigned(FOnClick)) then ActionLink.Execute(Self) else if Assigned(FOnClick) then FOnClick(Self); end; This IMO will invoke ActionLink.Execute if (a different) FOnClick is assigned - so far okay. But FOnClick will *not* be invoked then (even if different), and it will be invoked *always* in design state. Is it really okay to invoke an user-supplied OnClick handler in design state?

No.
User supplied OnClick handlers are fake methods and that's why "Assigned" is used instead of "FOnClicknil". Thus user handlers are *not* invoked.
Only real methods are invoked. That means custom component handlers are invoked.

Show quoted text 14 lines
What about something like this: if (csDesigning in ComponentState) then exit; //nothing called in design state if (ActionLink nil) and ((Action=nil) or (@FOnClick @Action.OnExecute) then ActionLink.Execute(Self); //only if different from FOnClick if Assigned(FOnClick) then //eventually also: if not handled? FOnClick(Self); //always if assigned end; I also wonder what's the difference or relationship between Action and ActionLink - can somebody explain? Does ActionLink (when assigned) take precedence over Action?

See TControl.GetAction.
Then lol.

Mattias

Reply by email

Zaher Dirkey
to Mattias Gaertner

On Sat, Oct 1, 2011 at 10:13 AM, Mattias Gaertner <

Show quoted text 22 lines
wrote: On Sat, 1 Oct 2011 10:08:59 +0300 Zaher Dirkey wrote: > Off your topic > On Sat, Oct 1, 2011 at 9:53 AM, Mattias Gaertner > wrote: > > > "Assigned" is used instead of "FOnClicknil" > > > What is different between check the Method fields ? > "Assigned(FOnClick)" and "FOnClicknil" http://wiki.lazarus.freepascal.org/IDE_tricks#Events_.28Method_properties.29_in_the_Object_Inspector Mattias

Thanks, but not understand it, but i will to check and correct my components code.

Best Regard

Zaher Dirkey
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20111001/16554c10/attachment.html>

Reply by email

Martin
to Mattias Gaertner: On Sat, 01 Oct 2011 03:04:56 +0200 No. User supplied OnClick handlers are fake methods…
Mattias Gaertner wrote 18 lines
On Sat, 01 Oct 2011 03:04:56 +0200 Hans-Peter Diettrich wrote: > I don't understand the logic behind TControl.Click: > > procedure TControl.Click; > begin > //DebugLn(['TControl.Click ',DbgSName(Self)]); > if (not (csDesigning in ComponentState)) and (ActionLink nil) and > ((Action=nil) or (@FOnClick @Action.OnExecute) or > Assigned(FOnClick)) then > ActionLink.Execute(Self) > else > if Assigned(FOnClick) then > FOnClick(Self); > end; > >

Maybe I overlook something, but
@FOnClick is the address of the variable holding the method reference (or nil)
so is @Action.OnExecute

So when can they ever be equal?

Should that maybe compare FOnClick Action.OnExecute ?

Also is that supposed to be a shortcut, saving the call, or is that indeed supposed to modify behaviour?
Even if the 2 callbacks are pointing to the same method, calling Action.OnExecute, will call the callback with Sender=TheAction, while FOnClick gets the current object.

Reply by email

Mattias Gaertner
to Martin
Show quoted text 26 lines
On 01/10/2011 07:53, Mattias Gaertner wrote: > On Sat, 01 Oct 2011 03:04:56 +0200 > Hans-Peter Diettrich wrote: > >> I don't understand the logic behind TControl.Click: >> >> procedure TControl.Click; >> begin >> //DebugLn(['TControl.Click ',DbgSName(Self)]); >> if (not (csDesigning in ComponentState)) and (ActionLink nil) and >> ((Action=nil) or (@FOnClick @Action.OnExecute) or >> Assigned(FOnClick)) then >> ActionLink.Execute(Self) >> else >> if Assigned(FOnClick) then >> FOnClick(Self); >> end; >> >> Maybe I overlook something, but @FOnClick is the address of the variable holding the method reference (or nil) so is @Action.OnExecute So when can they ever be equal?

You are right.

Should that maybe compare FOnClick Action.OnExecute ?

That would miss difference in Data.
I added a CompareMem.

Also is that supposed to be a shortcut, saving the call, or is that indeed supposed to modify behaviour?

Good question.
I guess it would be enough to check (not (csDesigning in ComponentState)) and (ActionLink nil).

Maybe the Delphi docs have an answer.

Even if the 2 callbacks are pointing to the same method, calling Action.OnExecute, will call the callback with Sender=TheAction, while FOnClick gets the current object.

Mattias

Reply by email

Mattias Gaertner
to Zaher Dirkey: On Sat, Oct 1, 2011 at 10:13 AM, Mattias Gaertner < Thanks, but not understand it, but i…
Show quoted text 25 lines
On Sat, Oct 1, 2011 at 10:13 AM, Mattias Gaertner < > wrote: > On Sat, 1 Oct 2011 10:08:59 +0300 > Zaher Dirkey wrote: > > > Off your topic > > On Sat, Oct 1, 2011 at 9:53 AM, Mattias Gaertner > > wrote: > > > > > "Assigned" is used instead of "FOnClicknil" > > > > > > What is different between check the Method fields ? > > "Assigned(FOnClick)" and "FOnClicknil" > > > http://wiki.lazarus.freepascal.org/IDE_tricks#Events_.28Method_properties.29_in_the_Object_Inspector > > > Mattias > > Thanks, but not understand it, but i will to check and correct my components code.

What do you don't understand?

Mattias

Reply by email

Martin
to Mattias Gaertner: On Sat, 1 Oct 2011 10:08:59 +0300 http://wiki.lazarus.freepascal.org/IDE_tricks#Events_.28…
Mattias Gaertner wrote 14 lines
On Sat, 1 Oct 2011 10:08:59 +0300 Zaher Dirkey wrote: > Off your topic > On Sat, Oct 1, 2011 at 9:53 AM, Mattias Gaertner > wrote: > >> "Assigned" is used instead of "FOnClicknil" > > What is different between check the Method fields ? > "Assigned(FOnClick)" and "FOnClicknil" http://wiki.lazarus.freepascal.org/IDE_tricks#Events_.28Method_properties.29_in_the_Object_Inspector

Strange, on the page it says:

if OnMyEvent nil then OnMyEvent(...);// wrong, because it checks Data too if OnMyEvent = NewValuethen exit;// wrong, because it compares only Code

So I compiled (to assembler) 32 bit:

Comparison with nil (expect to check code + data, as told above) Comparison with other method (expect code only)

But in both cases it tests one long entry (testl or cmpll). so the same amount of data. It doesn't look that nil checks code+data?

# [33] if OnDeactivate nil then;
movl -8(%ebp),%eax
movl 980(%eax),%eax
testl %eax,%eax
.Lj6:
.Ll3:
# [34] if OnClose = nil then;
movl -8(%ebp),%eax
movl 956(%eax),%eax
testl %eax,%eax
.Lj8:
.Ll4:
# [35] if OnDeactivate = OnCreate then;
movl -8(%ebp),%eax
movl -8(%ebp),%edx
movl 980(%eax),%eax
cmpl 972(%edx),%eax

Reply by email

Zaher Dirkey
to Mattias Gaertner: On Sat, 1 Oct 2011 10:20:54 +0300 What do you don't understand? Mattias

On Sat, Oct 1, 2011 at 10:05 AM, Mattias Gaertner <

Show quoted text 37 lines
wrote: On Sat, 1 Oct 2011 10:20:54 +0300 Zaher Dirkey wrote: > On Sat, Oct 1, 2011 at 10:13 AM, Mattias Gaertner < > > wrote: > > > On Sat, 1 Oct 2011 10:08:59 +0300 > > Zaher Dirkey wrote: > > > > > Off your topic > > > On Sat, Oct 1, 2011 at 9:53 AM, Mattias Gaertner > > > wrote: > > > > > > > "Assigned" is used instead of "FOnClicknil" > > > > > > > > > What is different between check the Method fields ? > > > "Assigned(FOnClick)" and "FOnClicknil" > > > > > > http://wiki.lazarus.freepascal.org/IDE_tricks#Events_.28Method_properties.29_in_the_Object_Inspector > > > > > > Mattias > > > > > Thanks, but not understand it, but i will to check and correct my components > code. What do you don't understand?

In my knowledge, Mehtod of the object, is pointer to the Procedure and pointer to that Object, i do not know if that correct. Now in design time, the code not set, that is ok, but data set to fake pointer, what is it?.
Maybe if i want to understand i must follow the IDE designer and read it, or you can explain it to me :) .

Thanks
Zaher Dirkey
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20111001/4368ebeb/attachment-0001.html>

Reply by email

Mattias Gaertner
to Zaher Dirkey: On Sat, Oct 1, 2011 at 10:05 AM, Mattias Gaertner < In my knowledge, Mehtod of the…
[...] In my knowledge, Mehtod of the object, is pointer to the Procedure and pointer to that Object, i do not know if that correct.

Correct.

Now in design time, the code not set, that is ok, but data set to fake pointer, what is it?.

In case of Lazarus it is a TJITMethod.

Maybe if i want to understand i must follow the IDE designer and read it, or you can explain it to me :) .

see designer/jitforms.pp
TJITMethod stores the owner object and method name. At runtime this information is normally stored in the method data and the VMT of the class of the method owner.

Mattias

Reply by email

Mattias Gaertner
to cobines: 2011/10/1 Mattias Gaertner : There is also a function CompareMethods. cobines
Show quoted text 9 lines
2011/10/1 Mattias Gaertner : > On Sat, 01 Oct 2011 08:39:42 +0100 > Martin wrote: >> Should that maybe compare FOnClick Action.OnExecute ? > > That would miss difference in Data. > I added a CompareMem. There is also a function CompareMethods.

Yes. But it needs typecasts and does the same, so it does not matter which one is used.

Mattias

Reply by email

Mattias Gaertner
to Martin: Strange, on the page it says: So I compiled (to assembler) 32 bit: Comparison with nil…
Show quoted text 27 lines
On 01/10/2011 08:13, Mattias Gaertner wrote: > On Sat, 1 Oct 2011 10:08:59 +0300 > Zaher Dirkey wrote: > >> Off your topic >> On Sat, Oct 1, 2011 at 9:53 AM, Mattias Gaertner >> wrote: >> >>> "Assigned" is used instead of "FOnClicknil" >> >> What is different between check the Method fields ? >> "Assigned(FOnClick)" and "FOnClicknil" > http://wiki.lazarus.freepascal.org/IDE_tricks#Events_.28Method_properties.29_in_the_Object_Inspector > > Strange, on the page it says: > if OnMyEvent nil then OnMyEvent(...);// wrong, because it checks Data too > if OnMyEvent = NewValuethen exit;// wrong, because it compares only Code So I compiled (to assembler) 32 bit: Comparison with nil (expect to check code + data, as told above) Comparison with other method (expect code only) But in both cases it tests one long entry (testl or cmpll). so the same amount of data. It doesn't look that nil checks code+data?

You are right. It seems it was changed in the compiler. I will update the wiki.

Mattias

Reply by email

Mattias Gaertner
to Hans-Peter Diettrich: Then the question remains, why Action hides the OnClick handler, at runtime? Is this…
Show quoted text 29 lines
Mattias Gaertner schrieb: > On Sat, 01 Oct 2011 03:04:56 +0200 > Hans-Peter Diettrich wrote: > >> I don't understand the logic behind TControl.Click: >> >> procedure TControl.Click; >> begin >> //DebugLn(['TControl.Click ',DbgSName(Self)]); >> if (not (csDesigning in ComponentState)) and (ActionLink nil) and >> ((Action=nil) or (@FOnClick @Action.OnExecute) or >> Assigned(FOnClick)) then >> ActionLink.Execute(Self) >> else >> if Assigned(FOnClick) then >> FOnClick(Self); >> end; >> >> This IMO will invoke ActionLink.Execute if (a different) FOnClick is >> assigned - so far okay. But FOnClick will *not* be invoked then (even if >> different), and it will be invoked *always* in design state. >> >> Is it really okay to invoke an user-supplied OnClick handler in design >> state? > > No. Then the question remains, why Action hides the OnClick handler, at runtime? Is this required by Delphi compatibility?

Yes.

[...]

Mattias

Reply by email

Mattias Gaertner
to Hans-Peter Diettrich: The many "Do not ..." hints are not really helpful without understanding method pointers…
Show quoted text 24 lines
Mattias Gaertner schrieb: >>>>> "Assigned" is used instead of "FOnClicknil" >>>> >>>> What is different between check the Method fields ? >>>> "Assigned(FOnClick)" and "FOnClicknil" >>> >>> http://wiki.lazarus.freepascal.org/IDE_tricks#Events_.28Method_properties.29_in_the_Object_Inspector >> Thanks, but not understand it, but i will to check and correct my components >> code. > > What do you don't understand? The many "Do not ..." hints are not really helpful without understanding method pointers and Assigned(). In detail I supposed that FOnClicknil will never work properly, on no method pointer, because it only checks the first pointer (explanation in Delphi newsgroups). The documentation of Assigned() also is not really helpful, there's no explanation of the real difference vs. Pnil. There seem to exist more differences, e.g. with the "dummy" event handler value at design time?

This wiki page is not the documentation for methods in general. See the fpc docs for that.
The wiki page is more like an FAQ.

Mattias

Reply by email

Martin
to Mattias Gaertner: On Sat, 01 Oct 2011 08:39:42 +0100 You are right. That would miss difference in Data. I…
Mattias Gaertner wrote 29 lines
On Sat, 01 Oct 2011 08:39:42 +0100 Martin wrote: > On 01/10/2011 07:53, Mattias Gaertner wrote: >> On Sat, 01 Oct 2011 03:04:56 +0200 >> Hans-Peter Diettrich wrote: >> >>> I don't understand the logic behind TControl.Click: >>> >>> procedure TControl.Click; >>> begin >>> //DebugLn(['TControl.Click ',DbgSName(Self)]); >>> if (not (csDesigning in ComponentState)) and (ActionLink nil) and >>> ((Action=nil) or (@FOnClick @Action.OnExecute) or >>> Assigned(FOnClick)) then >>> ActionLink.Execute(Self) >>> else >>> if Assigned(FOnClick) then >>> FOnClick(Self); >>> end; >>> >>> > Maybe I overlook something, but > @FOnClick is the address of the variable holding the method reference > (or nil) > so is @Action.OnExecute > > So when can they ever be equal? You are right.

...

Show quoted text 9 lines
I added a CompareMem. > Also is that supposed to be a shortcut, saving the call, or is that > indeed supposed to modify behaviour? Good question. I guess it would be enough to check (not (csDesigning in ComponentState)) and (ActionLink nil). Maybe the Delphi docs have an answer.

further more:

ActionLink.Execute is virtual

So comparing with the OnExecute method pointer is at the very least insufficient.

If ActionLink.Execute is overridden, it could call/do anything.

I would suggest to drop that check entirely

SVN Blame shows that it's been there for a long time, and always had the @FOnClick => so it never triggered in the past, and there never was a bug, while it did not trigger.

Reply by email

Hans-Peter Diettrich
to Mattias Gaertner: On Sat, 01 Oct 2011 03:04:56 +0200 No. User supplied OnClick handlers are fake methods…
Show quoted text 25 lines
On Sat, 01 Oct 2011 03:04:56 +0200 Hans-Peter Diettrich wrote: > I don't understand the logic behind TControl.Click: > > procedure TControl.Click; > begin > //DebugLn(['TControl.Click ',DbgSName(Self)]); > if (not (csDesigning in ComponentState)) and (ActionLink nil) and > ((Action=nil) or (@FOnClick @Action.OnExecute) or > Assigned(FOnClick)) then > ActionLink.Execute(Self) > else > if Assigned(FOnClick) then > FOnClick(Self); > end; > > This IMO will invoke ActionLink.Execute if (a different) FOnClick is > assigned - so far okay. But FOnClick will *not* be invoked then (even if > different), and it will be invoked *always* in design state. > > Is it really okay to invoke an user-supplied OnClick handler in design > state? No.

Then the question remains, why Action hides the OnClick handler, at runtime? Is this required by Delphi compatibility?

Show quoted text 5 lines
> I also wonder what's the difference or relationship between Action and > ActionLink - can somebody explain? Does ActionLink (when assigned) take > precedence over Action? See TControl.GetAction.

Thanks for the hint :-)

DoDi

Reply by email

Mattias Gaertner
to Hans-Peter Diettrich: Really? AFAIK method pointers are handled differently in Delphi and FPC, where FPC…
Show quoted text 35 lines
Mattias Gaertner schrieb: > On Sat, 01 Oct 2011 08:39:42 +0100 > Martin wrote: > >> On 01/10/2011 07:53, Mattias Gaertner wrote: >>> On Sat, 01 Oct 2011 03:04:56 +0200 >>> Hans-Peter Diettrich wrote: >>> >>>> I don't understand the logic behind TControl.Click: >>>> >>>> procedure TControl.Click; >>>> begin >>>> //DebugLn(['TControl.Click ',DbgSName(Self)]); >>>> if (not (csDesigning in ComponentState)) and (ActionLink nil) and >>>> ((Action=nil) or (@FOnClick @Action.OnExecute) or >>>> Assigned(FOnClick)) then >>>> ActionLink.Execute(Self) >>>> else >>>> if Assigned(FOnClick) then >>>> FOnClick(Self); >>>> end; >>>> >>>> >> Maybe I overlook something, but >> @FOnClick is the address of the variable holding the method reference >> (or nil) >> so is @Action.OnExecute >> >> So when can they ever be equal? > > You are right. Really? AFAIK method pointers are handled differently in Delphi and FPC,

No.
You could say: Method pointers are handled differently in mode Delphi and mode ObjFPC.
And since the LCL uses mode objfpc the @event is unambiguous and therefore wrong as Martin wrote.

Show quoted text 14 lines
[...] >> Should that maybe compare FOnClick Action.OnExecute ? > > That would miss difference in Data. > I added a CompareMem. IMO the comparison worked as-is, as found in several places in the LCL. What about: function TControlActionLink.IsOnExecuteLinked: Boolean; begin Result := inherited IsOnExecuteLinked and (FClient.OnClick = Action.OnExecute);

Thanks for pointing out.
Fixed by using CompareMethods.

Show quoted text 13 lines
end; >> Also is that supposed to be a shortcut, saving the call, or is that >> indeed supposed to modify behaviour? > > Good question. > I guess it would be enough to check (not (csDesigning in > ComponentState)) and (ActionLink nil). > > Maybe the Delphi docs have an answer. No :-(

It seems Delphi calls OnClick when it is set and differs from the Action. I did that.

Show quoted text 5 lines
>> Even if the 2 callbacks are pointing to the same method, calling >> Action.OnExecute, will call the callback with Sender=TheAction, while >> FOnClick gets the current object. Looks as if Execute should be overridden in TControlActionLink!

Why? How?

Mattias

Reply by email

Hans-Peter Diettrich
to Mattias Gaertner: On Sat, 1 Oct 2011 10:20:54 +0300 What do you don't understand? Mattias
Show quoted text 11 lines
>>>> "Assigned" is used instead of "FOnClicknil" >>> >>> What is different between check the Method fields ? >>> "Assigned(FOnClick)" and "FOnClicknil" >> >> http://wiki.lazarus.freepascal.org/IDE_tricks#Events_.28Method_properties.29_in_the_Object_Inspector > Thanks, but not understand it, but i will to check and correct my components > code. What do you don't understand?

The many "Do not ..." hints are not really helpful without understanding method pointers and Assigned().

In detail I supposed that FOnClicknil will never work properly, on no method pointer, because it only checks the first pointer (explanation in Delphi newsgroups).

The documentation of Assigned() also is not really helpful, there's no explanation of the real difference vs. Pnil. There seem to exist more differences, e.g. with the "dummy" event handler value at design time?

DoDi

Reply by email

Mattias Gaertner
to Martin: ... further more: ActionLink.Execute is virtual So comparing with the OnExecute method…
Show quoted text 49 lines
On 01/10/2011 09:05, Mattias Gaertner wrote: > On Sat, 01 Oct 2011 08:39:42 +0100 > Martin wrote: > >> On 01/10/2011 07:53, Mattias Gaertner wrote: >>> On Sat, 01 Oct 2011 03:04:56 +0200 >>> Hans-Peter Diettrich wrote: >>> >>>> I don't understand the logic behind TControl.Click: >>>> >>>> procedure TControl.Click; >>>> begin >>>> //DebugLn(['TControl.Click ',DbgSName(Self)]); >>>> if (not (csDesigning in ComponentState)) and (ActionLink nil) and >>>> ((Action=nil) or (@FOnClick @Action.OnExecute) or >>>> Assigned(FOnClick)) then >>>> ActionLink.Execute(Self) >>>> else >>>> if Assigned(FOnClick) then >>>> FOnClick(Self); >>>> end; >>>> >>>> >> Maybe I overlook something, but >> @FOnClick is the address of the variable holding the method reference >> (or nil) >> so is @Action.OnExecute >> >> So when can they ever be equal? > You are right. ... > I added a CompareMem. >> Also is that supposed to be a shortcut, saving the call, or is that >> indeed supposed to modify behaviour? > Good question. > I guess it would be enough to check (not (csDesigning in > ComponentState)) and (ActionLink nil). > > Maybe the Delphi docs have an answer. > further more: ActionLink.Execute is virtual So comparing with the OnExecute method pointer is at the very least insufficient. If ActionLink.Execute is overridden, it could call/do anything.

True. But it seems Delphi does the same.

I would suggest to drop that check entirely

Why?
Do you have a real case where it hurts?

SVN Blame shows that it's been there for a long time, and always had the @FOnClick => so it never triggered in the past, and there never was a bug, while it did not trigger.

Well, this allows many conclusions. ;)

Mattias

Reply by email

Zaher Dirkey
to Mattias Gaertner
Mattias Gaertner wrote 5 lines
> I would suggest to drop that check entirely Why? Do you have a real case where it hurts?

To expand the execute of Action, So Action.Execute run before Button.OnClick.
And that done in the our application Forms, not break the compatibility with Delphi.

Zaher Dirkey
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20111001/bfdee6c1/attachment.html>

Reply by email

Hans-Peter Diettrich
to Mattias Gaertner: On Sat, 01 Oct 2011 08:39:42 +0100 You are right. That would miss difference in Data. I…
Show quoted text 30 lines
On Sat, 01 Oct 2011 08:39:42 +0100 Martin wrote: > On 01/10/2011 07:53, Mattias Gaertner wrote: >> On Sat, 01 Oct 2011 03:04:56 +0200 >> Hans-Peter Diettrich wrote: >> >>> I don't understand the logic behind TControl.Click: >>> >>> procedure TControl.Click; >>> begin >>> //DebugLn(['TControl.Click ',DbgSName(Self)]); >>> if (not (csDesigning in ComponentState)) and (ActionLink nil) and >>> ((Action=nil) or (@FOnClick @Action.OnExecute) or >>> Assigned(FOnClick)) then >>> ActionLink.Execute(Self) >>> else >>> if Assigned(FOnClick) then >>> FOnClick(Self); >>> end; >>> >>> > Maybe I overlook something, but > @FOnClick is the address of the variable holding the method reference > (or nil) > so is @Action.OnExecute > > So when can they ever be equal? You are right.

Really?

AFAIK method pointers are handled differently in Delphi and FPC, where FPC requires @FOnClick to get the value stored in FOnClick, where Delphi guesses whether FOnClick should invoke the method or return the value.

> Should that maybe compare FOnClick Action.OnExecute ? That would miss difference in Data. I added a CompareMem.

IMO the comparison worked as-is, as found in several places in the LCL.

What about:

function TControlActionLink.IsOnExecuteLinked: Boolean;
begin
   Result := inherited IsOnExecuteLinked
             and (FClient.OnClick = Action.OnExecute);
end;
Show quoted text 8 lines
> Also is that supposed to be a shortcut, saving the call, or is that > indeed supposed to modify behaviour? Good question. I guess it would be enough to check (not (csDesigning in ComponentState)) and (ActionLink nil). Maybe the Delphi docs have an answer.

No :-(

> Even if the 2 callbacks are pointing to the same method, calling > Action.OnExecute, will call the callback with Sender=TheAction, while > FOnClick gets the current object.

Looks as if Execute should be overridden in TControlActionLink!

DoDi

Reply by email

Mattias Gaertner
to Zaher Dirkey: On Sat, Oct 1, 2011 at 3:23 PM, Mattias Gaertner To expand the execute of Action, So…
Show quoted text 14 lines
On Sat, Oct 1, 2011 at 3:23 PM, Mattias Gaertner wrote: > > > I would suggest to drop that check entirely > > Why? > Do you have a real case where it hurts? To expand the execute of Action, So Action.Execute run before Button.OnClick. And that done in the our application Forms, not break the compatibility with Delphi.

Please test the LCL trunk version for compatibility.

Mattias

Reply by email

Hans-Peter Diettrich
to Mattias Gaertner: On Sat, 01 Oct 2011 15:43:34 +0200 No. You could say: Method pointers are handled…
Show quoted text 6 lines
>>> Even if the 2 callbacks are pointing to the same method, calling >>> Action.OnExecute, will call the callback with Sender=TheAction, while >>> FOnClick gets the current object. > Looks as if Execute should be overridden in TControlActionLink! Why? How?

To use the control as Sender, at least when it equals the control's OnClick.

At least everything would be more clear, when in the case of different control.OnClick and action.Execute the OnClick would take precedence. Then it can be assumed that the OnClick handler expects a control, while equal handlers more probably indicate and Execute handler, expecting an Action as Sender. Then Execute doesn't deserve an override.

DoDi

Reply by email

Mattias Gaertner
to Hans-Peter Diettrich
Show quoted text 13 lines
Mattias Gaertner schrieb: >>>> Even if the 2 callbacks are pointing to the same method, calling >>>> Action.OnExecute, will call the callback with Sender=TheAction, while >>>> FOnClick gets the current object. >> Looks as if Execute should be overridden in TControlActionLink! > > Why? How? To use the control as Sender, at least when it equals the control's OnClick. At least everything would be more clear, when in the case of different control.OnClick and action.Execute the OnClick would take precedence.

That is the case since revision 32583.

Then it can be assumed that the OnClick handler expects a control, while equal handlers more probably indicate and Execute handler, expecting an Action as Sender. Then Execute doesn't deserve an override.

Mattias

Reply by email

Hans-Peter Diettrich
to Martin: ... further more: ActionLink.Execute is virtual So comparing with the OnExecute method…
Show quoted text 10 lines
further more: ActionLink.Execute is virtual So comparing with the OnExecute method pointer is at the very least insufficient. If ActionLink.Execute is overridden, it could call/do anything. I would suggest to drop that check entirely

Delphi compares

   DelegatesEqual(@FClient.OnClick, @Action.OnExecute)));

what looks good, except that DelegatesEqual accepts two Pointers - what causes the well known comparison problems.

At least FOnClick is preferred over Execute:

procedure TControl.Click;
begin
{ Call OnClick if assigned and not equal to associated action's OnExecute.
If associated action's OnExecute assigned then call it, otherwise, call OnClick. }
if Assigned(FOnClick) and (Action nil) and not
DelegatesEqual(@FOnClick, @Action.OnExecute) then
FOnClick(Self)

   else if not (csDesigning in ComponentState) and (ActionLink  nil) then
     ActionLink.Execute(Self)
   else if Assigned(FOnClick) then
     FOnClick(Self);

end;

DoDi

Reply by email