View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0038370||Lazarus||Packages||public||2021-01-18 21:30||2021-01-28 20:35|
|Reporter||Domingo Galmés||Assigned To||Martin Friebe|
|Fixed in Version||2.2|
|Summary||0038370: [Patch] TSynEdit Change request in TSynGutterLineNumber component. Add event OnGetText.|
|Description||This patch adds an event to customize the line number text in the TSynedit gutter line number.|
The motivation for the change is to be used in a utility to compare files where the line numbers of the editor do not match the line numbers of the original file (there may be lines added or deleted).
This change allows the user of the TSynEdit component full control over the text of the editor line number part of the gutter.
Besides adding the OnGetText event I have changed the FormatLineNumber function from private to public to be able to use it in the event routine.
Example of using the proposed changes.
procedure TForm1.SynGutterLineNumber1GetText (Sender: TSynGutterLineNumber;
ALine: integer; var AText: string; AIsDot: boolean);
if aLine <= 3 then
AText: = '-'
AText: = Sender.FormatLineNumber (ALine - 3, AIsDot);
I hope you can apply these changes.
|Steps To Reproduce||The project1.zip contains a sample project to test the changes.|
|Tags||No tags attached.|
|Fixed in Revision||64426|
AddOnGetTextGutterLineText.patch (2,721 bytes)
From ab49c6df394351fd014af0a0257f96ced2b64acc Mon Sep 17 00:00:00 2001 From: DomingoGP <firstname.lastname@example.org> Date: Mon, 18 Jan 2021 20:55:43 +0100 Subject: [PATCH] Add event OnGetText to TSynGutterLineNumber. --- components/synedit/syngutterlinenumber.pp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/components/synedit/syngutterlinenumber.pp b/components/synedit/syngutterlinenumber.pp index a9270c5378..6f53eae7da 100644 --- a/components/synedit/syngutterlinenumber.pp +++ b/components/synedit/syngutterlinenumber.pp @@ -11,6 +11,9 @@ uses type + TSynGutterLineNumber = class; + TSynEditGetGutterLineTextEvent = procedure(Sender: TSynGutterLineNumber; ALine: integer; var AText: string; AIsDot: boolean) of object; + TSynEditMouseActionsLineNum = class(TSynEditMouseInternalActions) public // empty by default end; @@ -26,12 +29,12 @@ type FShowOnlyLineNumbersMultiplesOf: integer; FLeadingZeros: boolean; FZeroStart: boolean; + FOnGetText: TSynEditGetGutterLineTextEvent; procedure SetDigitCount(AValue : integer); procedure SetLeadingZeros(const AValue : boolean); procedure SetShowOnlyLineNumbersMultiplesOf(const AValue : integer); procedure SetZeroStart(const AValue : boolean); - function FormatLineNumber(Line: integer; IsDot: boolean): string; protected procedure Init; override; function PreferedWidthAtCurrentPPI: Integer; override; @@ -45,7 +48,7 @@ type constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Assign(Source: TPersistent); override; - + function FormatLineNumber(Line: integer; IsDot: boolean): string; procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); override; published @@ -55,6 +58,7 @@ type read FShowOnlyLineNumbersMultiplesOf write SetShowOnlyLineNumbersMultiplesOf; property ZeroStart: boolean read FZeroStart write SetZeroStart; property LeadingZeros: boolean read FLeadingZeros write SetLeadingZeros; + property OnGetText: TSynEditGetGutterLineTextEvent read FOnGetText write FOnGetText; end; implementation @@ -275,7 +279,13 @@ begin and (iLine <> TCustomSynEdit(SynEdit).CaretY) and (iLine <> 1) and (iLine <> SynEdit.Lines.Count); // Get the formatted line number or dot - s := FormatLineNumber(iLine, ShowDot); + if Assigned(FOnGetText) then + begin + s:=''; + FOnGetText(Self,iLine,s,ShowDot); + end + else + s := FormatLineNumber(iLine, ShowDot); Inc(rcLine.Bottom, LineHeight); if i <> IRange.Top then s := ''; -- 2.30.0.windows.1
AddOnGetTextGutterLineText.patch (2,721 bytes)
project1.zip (109,597 bytes)
Couple of notes / thoughts (I can change name/var-out when I apply the patch):
You may comment on those, if you wish. Otherwise I will adjust and apply. Hopefully in a few days / a week or so.
- OnGetText should be called OnFormatLineNumber
- AText should be an out param, not var) / that also remove "s:='';"
Reason for the name:
It should be clear that this is still a line number (and the same line number). And not arbitrary text.
Though of course nothing prevents to display arbitrary text, but doing so would count as abuse. For example, "line number hints" (eoShowScrollHint) when scrolling are not affected by this. And they will not ever be.
For general info / not about the patch:
Anything that goes beyond *formatting* for the text for the gutter would need to be outside the gutter. SynEdit has a concept of "views" which can (or will in future be able) to map and transform the content of the editor. However they are not user friendly for quick modification like this. So in this case adding an Event is ok.
Under those terms: Applying the patch would allow you to do what you need to do. It would however not be within the intended use of the event. (Since you actually map numbers, rather than formatting them).
Technically what you do, would require a custom written TSynEditStrings with a TLazSynDisplayView => this can map line numbers.
Though, this would be total overkill for what you want to do.
The result of formatting the line number does not affect the Gutters width. And I do not think it should. (That will be documented via comment in the code).
You could at any time set the width yourself. You do need to disable autosize.
If wanted, you could add an OnGutterWidthNeeded. Since the gutter believes width is related to the number of digits, this will be called when lines are added or removed (probably always, not just when the magnitude (digit count) changes).
This doesn't provide much functionality, since it is easy to set the value from other code. But if you want it, you can add it to the patch (that I will not add myself).
The proposed changes seem correct to me.
I don't will need the OnGutterWidthNeeded since i know the number of digits so i can disable autosize and set the width manually when filling the editor lines so I will not add them to the patch.
Applied, with a few more changes.
I made the last param to TSynEditGetGutterLineTextEvent a record.
- In addition to "ShowDot", I wanted to pass the LineRange info and ViewedLine too (more below)
- passing a record is forward compatible.
That is, if one day more params need to be passed, they can be added to the record, without breaking any existing code.
Adding them to the function directly would break its signature, and fail events that are set from lfm files (the compiler would not give any warning)
About LineRange / ViewedLine.
I recently added the most basic line wrapping to SynEdit (still needs a lot of polishing).
Then a single line in the text can occupy several lines on the screen.
Before going into details, this introduces new coordinate system in SynEdit.
There always was Logical/Physical: https://wiki.lazarus.freepascal.org/SynEdit#Logical.2FPhysical_caret_position
Now there also is "ViewedPos" (I have to check if the X is logical or physical [[physical is now a misnomer, it refers to the screen (screen=physical), but this is only for X, not for Y]])
The Y is mapped according to FOLDING and WRAPPING.
- I.e if you are in the 3rd line of text (text as it is in memory, in SynEdit.Lines), but the first line is folded and not visible, then on the screen this is the 2nd line.
- If you are in the 3rd line of text, but line are wrapped then you may be on the 4th or 5th line on the screen.
The params to the callback
- ALine => the phys/log line (line as in SynEdit.Lines)
- LineInfo.ViewLine => The viewed line
- LineInfo.LineRange => The first and last viewed line belonging to "ALine"
LineInfo.ViewLine = LineInfo.LineRange.Top
=> This is the first line (-part) of ALine.
Otherwise ALine is wrapped and this is a continuation line.
You only need this, if you add the wrap plugin.
SynEdit will never wrap on its own, you have to add the plugin
Thank you for applying the patch and for the extensive information provided.
Tested and works as expected.
|2021-01-18 21:30||Domingo Galmés||New Issue|
|2021-01-18 21:30||Domingo Galmés||File Added: AddOnGetTextGutterLineText.patch|
|2021-01-18 21:30||Domingo Galmés||File Added: project1.zip|
|2021-01-18 21:30||Domingo Galmés||File Added: project1_image.png|
|2021-01-19 01:02||Martin Friebe||Assigned To||=> Martin Friebe|
|2021-01-19 01:02||Martin Friebe||Status||new => assigned|
|2021-01-19 01:48||Martin Friebe||Note Added: 0128403|
|2021-01-19 16:11||Domingo Galmés||Note Added: 0128423|
|2021-01-27 14:45||Martin Friebe||Status||assigned => resolved|
|2021-01-27 14:45||Martin Friebe||Resolution||open => fixed|
|2021-01-27 14:45||Martin Friebe||Fixed in Version||=> 2.2|
|2021-01-27 14:45||Martin Friebe||Fixed in Revision||=> 64426|
|2021-01-27 14:45||Martin Friebe||LazTarget||=> 2.2|
|2021-01-27 14:45||Martin Friebe||Note Added: 0128622|
|2021-01-28 20:35||Domingo Galmés||Status||resolved => closed|
|2021-01-28 20:35||Domingo Galmés||Note Added: 0128645|