Recent

Author Topic: TSynEditMarkupCtrlMouseLink for Ctrl+Alt  (Read 19717 times)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #15 on: September 19, 2016, 08:48:19 pm »
Okay,

then i think it will be better to use Option2 for this purpose. So that the user can use Option for own MouseActions as used with emcMouseLink.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #16 on: September 19, 2016, 09:07:51 pm »
Okay,

then i think it will be better to use Option2 for this purpose. So that the user can use Option for own MouseActions as used with emcMouseLink.

I dont know what you want to use "option" for?

This use is already published, and it would break user apps (code and lfm) if its usage was changed.

Option2 is also used. Well depending on the command value, and the Option value itself. For example cmd=wheel scroll, opt=percent of page, opt2=128 (half page /128 of 255)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #17 on: September 19, 2016, 09:10:58 pm »
Ideally each command would have had its own (sub-)class, so that it could have proper typed and proper named option fields (and only fields it needs)

But the needed to be collection items, so the work in object inspector, and can be streamed.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #18 on: September 19, 2016, 10:03:22 pm »
Okay,

then i think it will be better to use Option2 for this purpose. So that the user can use Option for own MouseActions as used with emcMouseLink.

I dont know what you want to use "option" for?

This use is already published, and it would break user apps (code and lfm) if its usage was changed.

Option2 is also used. Well depending on the command value, and the Option value itself. For example cmd=wheel scroll, opt=percent of page, opt2=128 (half page /128 of 255)
I want to use it to store an editor command which will be send when the link is clicked so that i do not necessarily have to set an OnClickLink event.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #19 on: September 19, 2016, 11:26:41 pm »
There is something similar, but without the link: emcSynEditCommand

But searching the code for that, made me aware of something.

emcMouseLink is handled by the main SynEdit, and more important, it is in SynEdits MouseActionList.
So if you have multiple markups, it will be hard to distinguish which one was activated.

Problem is, that user apps when SynEdit is saved as lfm, may have that streamed in the lfm.
So that needs to keep working like it is.

Any extension must be backward compatible.

-------------------------------------------------
One possibility is that the markup has a setting, if it uses the main SynEdit mouse action, or if it uses its own.

Or maybe better, a base class, 2 subclasses.
the default is kept as is. And one subclass will have its own action (stored on the markup).

The action stored on the markup, can be any command, so you can use emcSynEditCommand (the markup just needs to return this, SYnEdit will handle it.)

--------------
There are other modules that add mouse actions (eg multicaret). Most add many actions, the markup would need/have only one action. (So in that case this subclass does not search for emcMouseLink, but uses its own one action


Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #20 on: September 20, 2016, 06:33:47 am »
Thats the way i implement it.

The new baseclass TSynEditMarkupMouseLink has a procedure to tell the markup on which MouseAction it should react:
Code: Pascal  [Select][+][-]
  1. procedure AddMouseActionCommand(ACommand: TSynEditorMouseCommand);

The compatibility class TSynEditMarkupCtrlMouseLink which is a subclass of the new base class does a call to
AddMouseActionCommand(emcMousLink) in it's constructor as it always and only reacts on emcMouseLink.

I will put a patch on mantis later so you can see what i did.

If I remember rightly Option2 of emcMouseLink isn't used at the moment, so we can use it for a SynEditCommad.
Or should we leave this extension as a user could have used Option2 for his own?


There is something similar, but without the link: emcSynEditCommand

But searching the code for that, made me aware of something.

emcMouseLink is handled by the main SynEdit, and more important, it is in SynEdits MouseActionList.
So if you have multiple markups, it will be hard to distinguish which one was activated.

Form there i got the idea to implement a SynEditCommand  :D

It is no problem to distinguish them as they react on different MouseActionCommand (with also different shift states).
I did a subclass of TCustomSynEdit with an additional markup as subclass of TSynEditMarkupMouseLink which handles
different links for Ctrl+Alt and Ctrl+Shift while the original one handles Ctrl through the old interface (OnIsLinkable
and OnMouseLink). We can make the old interface deprecated to make the users aware of the new interface to MouseLinks.

Problem is, that user apps when SynEdit is saved as lfm, may have that streamed in the lfm.
I never dug that deep into the properties of a SynEdit in object inspector. But is it generally possible to change the internal
MouseTextAction for emcMouseLink? Or will a new emcMousLink over write the internal one?
« Last Edit: September 20, 2016, 11:12:32 am by Pascal »
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #21 on: September 20, 2016, 01:17:45 pm »
The new baseclass TSynEditMarkupMouseLink has a procedure to tell the markup on which MouseAction it should react:
Code: Pascal  [Select][+][-]
  1. procedure AddMouseActionCommand(ACommand: TSynEditorMouseCommand);
Just thinking about how that would best be done.

Normally Markup are passive, so the "correct" way would be a SynEdit Plugin (like SyncroEdit), and the plugin installs a markup (but mouse action handled in the plugin).

On the other hand, it currently just works fine to have it all in the Markup...

Note: the action is still part of synedit itself. The Markup just get to know a copy of it, to detect the keys for underlining.


Except you probably cant select the desired action in the object inspector. (well markups are not currently designable at all, but even if they were)
A pluging would have its own action list, and the plugin would hook the detection of the action.
But the plugin could also inform the markup of the correct action....

Anyway, we can leave it......

Quote
The compatibility class TSynEditMarkupCtrlMouseLink which is a subclass of the new base class does a call to
AddMouseActionCommand(emcMousLink) in it's constructor as it always and only reacts on emcMouseLink.
That will depend on creation order. And also break if the actions are changed after the markup was created.
The markup needs to search at runtime.

Quote
If I remember rightly Option2 of emcMouseLink isn't used at the moment, so we can use it for a SynEditCommad.
Or should we leave this extension as a user could have used Option2 for his own?
Why not use the existing action for the command? (you loose the option to hide the underline, but that does not matter / you can change the markupcolor anyway (clnone))

Quote
We can make the old interface deprecated to make the users aware of the new interface to MouseLinks.
yes and no. that would require the markup to become active.
In that case I would write a plugin that makes use of the markup....
But currently I would leave the old code as it is.

Quote
Problem is, that user apps when SynEdit is saved as lfm, may have that streamed in the lfm.
I never dug that deep into the properties of a SynEdit in object inspector. But is it generally possible to change the internal
MouseTextAction for emcMouseLink? Or will a new emcMousLink over write the internal one?

The current markup needs emcMouseLink, as it uses this for the search.

Your new class does not need to search, so it can have any command you want.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #22 on: September 20, 2016, 02:31:39 pm »
The new baseclass TSynEditMarkupMouseLink has a procedure to tell the markup on which MouseAction it should react:
Code: Pascal  [Select][+][-]
  1. procedure AddMouseActionCommand(ACommand: TSynEditorMouseCommand);
Just thinking about how that would best be done.

Normally Markup are passive, so the "correct" way would be a SynEdit Plugin (like SyncroEdit), and the plugin installs a markup (but mouse action handled in the plugin).

On the other hand, it currently just works fine to have it all in the Markup...

Note: the action is still part of synedit itself. The Markup just get to know a copy of it, to detect the keys for underlining.
I do not use the MouseAction as ResetMouseActions rebuilds them without notice. I only use the MouseCommand of the MouseAction!

Quote
The compatibility class TSynEditMarkupCtrlMouseLink which is a subclass of the new base class does a call to
AddMouseActionCommand(emcMousLink) in it's constructor as it always and only reacts on emcMouseLink.
That will depend on creation order. And also break if the actions are changed after the markup was created.
The markup needs to search at runtime.
No search needed as i use the MouseActionCommand.

Quote
If I remember rightly Option2 of emcMouseLink isn't used at the moment, so we can use it for a SynEditCommad.
Or should we leave this extension as a user could have used Option2 for his own?
Why not use the existing action for the command? (you loose the option to hide the underline, but that does not matter / you can change the markupcolor anyway (clnone))
I use Option in the same way as with emcMouseLink. So i can also hide the line/markup.

Quote
Problem is, that user apps when SynEdit is saved as lfm, may have that streamed in the lfm.
I never dug that deep into the properties of a SynEdit in object inspector. But is it generally possible to change the internal
MouseTextAction for emcMouseLink? Or will a new emcMousLink over write the internal one?

The current markup needs emcMouseLink, as it uses this for the search.

Your new class does not need to search, so it can have any command you want.
It still uses emcMouseLink. In its constructor i do AddMouseActionCommand(emcMouseLink) so it reacts like before.

Perhaps i should build a little sample so you can test it and see how it behaves.

laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #23 on: September 20, 2016, 08:38:03 pm »
Here's the demo:

Left SynEdit: without MouseActions (Ctrl)
Middle SynEdit: with MouseActions and emcMouseLink as MouseTextAction (Ctrl)
Right SynEdit: with MouseActions and emcMouseLink as MouseTextAction (Ctrl)
+ new TSynEditMarkupMouseLink which handles two links (Ctrl+Alt) and (Ctrl+Shift)

Needs applied patch from Bugtracker http://bugs.freepascal.org/view.php?id=30620
« Last Edit: September 21, 2016, 06:03:05 am by Pascal »
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #24 on: September 23, 2016, 12:52:14 am »
I had a first glimpse at the patch. Lots of changes gonna take me some time....


One thing came to mind, even before:
    DoNotifyMarkupMouseLinkMouseOptionsChanged

Actually that is not needed.
The option should only affect the one buildin markup (the old one). Basically kept for compatibilty.

All the extra markups, can be enabled via their enabled property. They do not need to know that flag.


About the patch.
Only one thing I looked at sofar, because we spoke about it already.
   AddMouseActionCommand(emcMouseLink);
Yes that keeps the old one working as it was. good.

But it is insufficient for the new ones.
If you have 2 mouse-actions (on 2 new markups) with the same command, but different options (eg editorcommand), then you can not distinguish between them.

So instead the markup module needs a pointer to the mouseaction object (actualy it should have a TSynEditMouseActions list, because it may have to underline for more than one command).
That means all the relevant commands need to be copied on that list.
Then if any matches the modifier keys, it will highlight.

-----------------------------
Something, that I did not think off to begin with. (And therefore I will not make it a requirement)
From a design point it was wrong to move OnLinkClick to the markup. The markup is only for markup, not to take actions.
There should have been a TLazSynEditPlugin, that has the OnLinkClick
(the plugin would also be good for holding the mouse actions / the plugin would automatically install and controll the markup)

But since it is on the markup now, leave it there.... I may move it in the (far) future.

---------------
the rest of the patch I will have to go through later.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #25 on: September 23, 2016, 04:21:44 pm »
If you have 2 mouse-actions (on 2 new markups) with the same command, but different options (eg editorcommand), then you can not distinguish between them.

So instead the markup module needs a pointer to the mouseaction object (actualy it should have a TSynEditMouseActions list, because it may have to underline for more than one command).
That means all the relevant commands need to be copied on that list.
Then if any matches the modifier keys, it will highlight.

No, as i also have the qualifier (Shift state) to distinguish between them (see IsMouseLinkShiftState).
If a have two MouseActions with the same MouseActionCommand. The should have different qualifiers to be usefull.
Then i only have to do AddMouseActionCommand one time as the MouseActionCommand is the same for the two.
The callback events are called with the matched MouseAction (including Shift state).
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #26 on: September 23, 2016, 04:35:12 pm »
One thing came to mind, even before:
    DoNotifyMarkupMouseLinkMouseOptionsChanged

Actually that is not needed.
The option should only affect the one buildin markup (the old one). Basically kept for compatibilty.

All the extra markups, can be enabled via their enabled property. They do not need to know that flag.

You are right if the new class should only work with MouseActions (emUseMouseActions). So we can only keep TSynEditMarkupCtrlMouseLink to work without MouseActions.

Code: Pascal  [Select][+][-]
  1. function TSynEditMarkupMouseLink.IsMouseLinkShiftState(AShift: TShiftState;
  2.   OnlyShowLink: Boolean): Boolean;
  3.   ...
  4. begin
  5.   ...
  6.   if not (emUseMouseActions in TCustomSynEdit(SynEdit).MouseOptions) then begin
  7.     Result := (emShowCtrlMouseLinks in TCustomSynEdit(SynEdit).MouseOptions) and
  8.               (AShift * ([ssShift, ssCtrl, ssAlt] + FShiftStateForDisabledMouseActions) = FShiftStateForDisabledMouseActions);
  9.     // FShiftStateForDisabledMouseActions = [SYNEDIT_LINK_MODIFIER]
  10.     exit;
  11.   end;
  12.   ...
  13. end;

Then i can keep the notification as it was before.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #27 on: September 23, 2016, 04:54:05 pm »
If you have 2 mouse-actions (on 2 new markups) with the same command, but different options (eg editorcommand), then you can not distinguish between them.

No, as i also have the qualifier (Shift state) to distinguish between them (see IsMouseLinkShiftState).
If a have two MouseActions with the same MouseActionCommand. The should have different qualifiers to be usefull.

If there are two actions with command emcMyLink1, one reacts to alt (alt only) and the other to ctrl (ctrl only).
And you want them to have different color underlines.

Then how to make it work? If I press alt (or ctrl), both markups will find a match.

Also keep in mind both could even have the same shift mask. One could be fallback to the other, if OnIsLinkable returns false for the first.
Actions have priorities and fallkack....

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #28 on: September 23, 2016, 05:02:18 pm »
If you have 2 mouse-actions (on 2 new markups) with the same command, but different options (eg editorcommand), then you can not distinguish between them.

No, as i also have the qualifier (Shift state) to distinguish between them (see IsMouseLinkShiftState).
If a have two MouseActions with the same MouseActionCommand. The should have different qualifiers to be usefull.

If there are two actions with command emcMyLink1, one reacts to alt (alt only) and the other to ctrl (ctrl only).
And you want them to have different color underlines.

Then how to make it work? If I press alt (or ctrl), both markups will find a match.

Code: Pascal  [Select][+][-]
  1. function TSynEditMarkupMouseLink.IsMouseLinkShiftState(AShift: TShiftState;
  2.   OnlyShowLink: Boolean): Boolean;
  3. var
  4.   act: TSynEditMouseAction;
  5.   i: Integer;
  6. begin
  7.   fMouseAction := nil;
  8.   Result := False;
  9.   ...
  10.   for i := 0 to TCustomSynEdit(SynEdit).MouseTextActions.Count - 1 do begin
  11.     act := TCustomSynEdit(SynEdit).MouseTextActions.Items[i];
  12.     if (FMouseActionCommandList.IndexOf(Pointer(act.Command)) >= 0) and      <--- Command match
  13.     ( (act.Option = emcoMouseLinkShow) or (not OnlyShowLink) ) and
  14.     act.IsMatchingShiftState(AShift)                                         <--- and Shift matches
  15.     then begin
  16.       fMouseAction := act;                                                   <--- this is the right MouseAction. It is used for the callback events. They set the MarkupInfo (var Parameter)
  17.       exit(True);
  18.     end;
  19.   end;
  20.   ...
  21. end;
  22.  
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9908
  • Debugger - SynEdit - and more
    • wiki
Re: TSynEditMarkupCtrlMouseLink for Ctrl+Alt
« Reply #29 on: September 23, 2016, 05:39:36 pm »
seen this.
Code: Pascal  [Select][+][-]
  1.    act := TCustomSynEdit(SynEdit).MouseTextActions.Items[i];
  2.     if (
  3.   FMouseActionCommandList.IndexOf(Pointer(act.Command)) >= 0) and      <--- Command match
  4.     ( (act.Option = emcoMouseLinkShow) or (not OnlyShowLink) ) and
  5.     act.IsMatchingShiftState(AShift)                                         <--- and Shift matches
  6.     then begin
  7.  

I am holding the alt key down.

2 markups perform the test. BOTH find the action with emcMyLink1 and alt.

Now I release alt, and hold ctrl

2 markups perform the test. BOTH find the action with emcMyLink1 and ctrl.

-------------
If both markup react to emcMyLink1,
how can one markup only find the action with alt, and the other only find the action with ctrl?

Try it.
In your demo, instead of changing the color in IsLinkable, add 2 markups, each configured with its own color.

-------------
Btw
Sender: TObject; // and NOT a specific subclass.
This allows the event (proc that will be assigned) to be in a unit, without dependencies.

----------
Just in case, I attached a draft for a plugin.
It would of course need some changes to the markup.
Such as
- being able to provide the markup with a pointer to FMouseActions
- Handling the IsLinkAble call
- exposing the markup, so user can change properties OR forwarding relevant properties (markupcolor / enable)









 

TinyPortal © 2005-2018