Sign in Join

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

Mailing lists / lazarus / 2015-02

Column ruler above a synedit

7 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

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

Mark Morgan Lloyd

Is there a preferred way of putting a column ruler above the text in a synedit, either (two lines) marking columns or (one line) marking tab positions?

I've previously done this for a file viewer oriented towards large files with columnar text (e.g. database query output) by having two synedits on the same form, but since the ruler doesn't really want line numbers keeping the two lined up was not entirely reliable.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Martin Frb
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 9 lines
Is there a preferred way of putting a column ruler above the text in a synedit, either (two lines) marking columns or (one line) marking tab positions? I've previously done this for a file viewer oriented towards large files with columnar text (e.g. database query output) by having two synedits on the same form, but since the ruler doesn't really want line numbers keeping the two lined up was not entirely reliable.

Look at ide/SourceSynEditor.pp

constructor TIDESynEditor.Create(AOwner: TComponent);
....
   FPaintArea := TSourceLazSynSurfaceManager.Create(Self, FPaintArea);

It wraps the original paint area object, and reduces its size, then placing a new paintarea for its own purpose on top.

In this example the size is variable. For your case it would be fixed, so it should be easier.

Reply by email

Mark Morgan Lloyd
to Martin Frb
Martin Frb wrote 22 lines
On 10/02/2015 19:12, Mark Morgan Lloyd wrote: > Is there a preferred way of putting a column ruler above the text in a > synedit, either (two lines) marking columns or (one line) marking tab > positions? > > I've previously done this for a file viewer oriented towards large > files with columnar text (e.g. database query output) by having two > synedits on the same form, but since the ruler doesn't really want > line numbers keeping the two lined up was not entirely reliable. > Look at ide/SourceSynEditor.pp constructor TIDESynEditor.Create(AOwner: TComponent); .... FPaintArea := TSourceLazSynSurfaceManager.Create(Self, FPaintArea); It wraps the original paint area object, and reduces its size, then placing a new paintarea for its own purpose on top. In this example the size is variable. For your case it would be fixed, so it should be easier.

Thanks Martin, I'll investigate.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Martin Frb
to Mark Morgan Lloyd

You should be able to copy the entire class TSourceLazSynSurfaceManager = class(TLazSynSurfaceManager)
(It is in the IDE, but check the svn logs / blame, if no one else but me changed it then consider it lgpl+except)

TopLineCount sets how much space you get on top.

TSourceLazSynSurfaceManager(FPaintArea).ExtraManager.DisplayView

set a source for the text you want to paint. If you do NOT forward to the textbuffer, then it will not come via the highlighter, and be highlightfree. But you can add your own.

Mark Morgan Lloyd wrote 26 lines
Martin Frb wrote: > On 10/02/2015 19:12, Mark Morgan Lloyd wrote: >> Is there a preferred way of putting a column ruler above the text in >> a synedit, either (two lines) marking columns or (one line) marking >> tab positions? >> >> I've previously done this for a file viewer oriented towards large >> files with columnar text (e.g. database query output) by having two >> synedits on the same form, but since the ruler doesn't really want >> line numbers keeping the two lined up was not entirely reliable. >> > > Look at ide/SourceSynEditor.pp > > constructor TIDESynEditor.Create(AOwner: TComponent); > .... > FPaintArea := TSourceLazSynSurfaceManager.Create(Self, FPaintArea); > > It wraps the original paint area object, and reduces its size, then > placing a new paintarea for its own purpose on top. > > In this example the size is variable. For your case it would be > fixed, so it should be easier. Thanks Martin, I'll investigate.

Reply by email

Mark Morgan Lloyd
to Martin Frb
Martin Frb wrote 12 lines
You should be able to copy the entire class TSourceLazSynSurfaceManager = class(TLazSynSurfaceManager) (It is in the IDE, but check the svn logs / blame, if no one else but me changed it then consider it lgpl+except) TopLineCount sets how much space you get on top. TSourceLazSynSurfaceManager(FPaintArea).ExtraManager.DisplayView set a source for the text you want to paint. If you do NOT forward to the textbuffer, then it will not come via the highlighter, and be highlightfree. But you can add your own.

Is my understanding of what you're saying correct that there would be dead space to the left of the extra top line stuff if line numbers were displayed (which is what I want)?

I'll take a look at the logs presently to work out what went in when. My older code, relying on stacked synedits, is good for the GTKv1 era.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Martin Frb
to Mark Morgan Lloyd
Mark Morgan Lloyd wrote 21 lines
Martin Frb wrote: > You should be able to copy the entire class > TSourceLazSynSurfaceManager = class(TLazSynSurfaceManager) > (It is in the IDE, but check the svn logs / blame, if no one else but > me changed it then consider it lgpl+except) > > TopLineCount sets how much space you get on top. > > TSourceLazSynSurfaceManager(FPaintArea).ExtraManager.DisplayView > > set a source for the text you want to paint. If you do NOT forward > to the textbuffer, then it will not come via the highlighter, and be > highlightfree. But you can add your own. Is my understanding of what you're saying correct that there would be dead space to the left of the extra top line stuff if line numbers were displayed (which is what I want)? I'll take a look at the logs presently to work out what went in when. My older code, relying on stacked synedits, is good for the GTKv1 era.

Same as for the top-hint in the ide.
Yes the gutter stays empty. At least it can, and work like that in the IDE. All the code should be in SourceSynEditor.
See image

SynEdit delegates all painting to the TextArea, which also returns how much space it can offer.

Normal SynEdit:

   FTextArea := TLazSynTextArea.Create

TLazSynTextArea splits the space 3 ways (see the creator of SyNedit and/or TSourceLazSynSurfaceManager
Left/Right Gutter and Text

TSourceLazSynSurfaceManager splits it 2 ways: upper/lower
- The lower is known to SynEdit, and contains and provides SynEdit with info on the boundaries.
- The upper is in your control. It also has 2 gutter, but unless you feed them they stay empty (in the IDE even changes to the gutter setting appear to be forwarded, not sure how)

 From SourceSynEditor
   TSourceLazSynSurfaceManager(FPaintArea).ExtraManager.DisplayView :=
FTopInfoDisplay;

FTopInfoDisplay provides the info what to paint. You need to do your own From my memory....

procedure InitHighlighterTokens(AHighlighter: TSynCustomHighlighter); virtual;

nothing

procedure SetHighlighterTokensLine(ALine: TLineIdx; out ARealLine: TLineIdx); virtual;

will be called with 0, and gives "out" 0 // sets the line (index) that needs to be painted.
Since your area is the height of 1 line, and GetLinesCount retunrs 1 there is no scrolling (Also nothing (except you) will change the topline for this)

procedure FinishHighlighterTokens; virtual;

nothing

function GetNextHighlighterToken(out ATokenInfo: TLazSynDisplayTokenInfo): Boolean; virtual;
  your text
     TokenStart: PChar;
     TokenLength: integer;
     TokenAttr: TSynHighlighterAttributes;
you may need a TSynHighlighterAttributes; (color)  but try nil, or
create an empty one
function GetLinesCount: Integer; virtual;

always ONE (1)

function GetDrawDividerInfo: TSynDividerDrawConfigSetting; virtual;
     Result.Color := clNone;
function TextToViewIndex(AIndex: TLineIdx): TLineRange; virtual; function ViewToTextIndex(AIndex: TLineIdx): TLineIdx; virtual;

return same as input // used by folding

In your case to prevent the gutter
- Inherit TLazSynGutterArea
- in TSourceLazSynSurfaceManager.Create use your class for the gutter
- in YOUR_TLazSynGutterArea.DoPaint(ACanvas: TCanvas; AClip: TRect); call

   FGutter.Paint(ACanvas, Self, AClip, 0, -1);

that should keep it empty

For your case you need to add handling of LeftChar for horizontal scroll.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20150211/06e1734b/attachment-0001.html> -------------- next part --------------
A non-text attachment was scrubbed...
Name: idhddbgc.png
Type: image/png
Size: 14225 bytes
Desc: not available
URL: <http://lists.lazarus.freepascal.org/pipermail/lazarus/attachments/20150211/06e1734b/attachment-0001.png>

Reply by email