lazarus/components/synedit/synguttermarks.pp
2009-03-14 19:01:35 +00:00

194 lines
5.5 KiB
ObjectPascal

unit SynGutterMarks;
{$I synedit.inc}
interface
uses
Classes, SysUtils, Graphics, LCLType, LCLIntf, SynGutterBase,
SynEditMiscClasses, SynEditMiscProcs, SynEditFoldedView, SynEditMarks;
type
{ TSynGutterMarks }
TSynGutterMarks = class(TSynGutterPartBase)
private
FDebugMarksImageIndex: Integer;
FFoldView: TSynEditFoldedView;
FBookMarkOpt: TSynBookMarkOpt;
FInternalImage: TSynInternalImage;
protected
procedure DoChange(Sender: TObject); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Paint(Canvas: TCanvas; AClip: TRect; FirstLine, LastLine: integer); override;
function RealGutterWidth(CharWidth: integer): integer; override;
property DebugMarksImageIndex: Integer read FDebugMarksImageIndex write FDebugMarksImageIndex;
end;
implementation
uses
SynEdit;
{ TSynGutterMarks }
procedure TSynGutterMarks.DoChange(Sender: TObject);
begin
if AutoSize then
FWidth := RealGutterWidth(0);
inherited DoChange(Sender);
end;
constructor TSynGutterMarks.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FFoldView := Gutter.FoldView;
FBookMarkOpt := TSynEdit(SynEdit).BookMarkOptions;
FInternalImage := nil;
FDebugMarksImageIndex := -1;
FWidth := 23;
end;
destructor TSynGutterMarks.Destroy;
begin
FreeAndNil(FInternalImage);
inherited Destroy;
end;
function TSynGutterMarks.RealGutterWidth(CharWidth: integer) : integer;
begin
if Visible then
Result := 22 + FBookMarkOpt.LeftMargin
else
Result := 0;
end;
procedure TSynGutterMarks.Paint(Canvas : TCanvas; AClip : TRect; FirstLine, LastLine : integer);
var
i, j, iLine: integer;
aGutterOffs: PIntArray;
dc: HDC;
LineHeight: Integer;
Marks: TSynEditMarks;
HasAnyMark: Boolean;
procedure DrawMark(CurMark: TSynEditMark);
var
iLine: integer;
itop : Longint;
begin
iTop := 0;
if (CurMark.Line<1) or (CurMark.Line > SynEdit.Lines.Count) then exit;
if FFoldView.FoldedAtTextIndex[CurMark.Line-1] then exit;
iLine := FFoldView.TextIndexToScreenLine(CurMark.Line-1);
if iLine < 0 then Exit;
if Assigned(FBookMarkOpt.BookmarkImages) and not CurMark.InternalImage then
begin
if (CurMark.ImageIndex <= FBookMarkOpt.BookmarkImages.Count) and
(CurMark.ImageIndex >= 0) then
begin
if CurMark.IsBookmark = FBookMarkOpt.DrawBookmarksFirst then
aGutterOffs^[iLine] := AClip.Left
else
if aGutterOffs^[iLine] = 0 then
aGutterOffs^[iLine] := FBookMarkOpt.BookmarkImages.Width + AClip.Left;
if LineHeight > FBookMarkOpt.BookmarkImages.Height then
iTop := (LineHeight - FBookMarkOpt.BookmarkImages.Height) div 2;
with FBookMarkOpt do
BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs^[iLine],
iTop + iLine * LineHeight, CurMark.ImageIndex, True);
Inc(aGutterOffs^[iLine], FBookMarkOpt.BookmarkImages.Width);
end;
end
else
begin
if CurMark.ImageIndex in [0..9] then
begin
if not Assigned(FInternalImage) then
FInternalImage := TSynInternalImage.Create('SynEditInternalImages',10);
if aGutterOffs^[iLine] = 0 then
aGutterOffs^[iLine] := AClip.Left;
FInternalImage.DrawMark(Canvas, CurMark.ImageIndex,
FBookMarkOpt.LeftMargin + aGutterOffs^[iLine], iLine * LineHeight,
LineHeight);
Inc(aGutterOffs^[iLine], FBookMarkOpt.Xoffset);
end;
end;
end;
procedure DrawDebugMark(Line: Integer);
var
itop : Longint;
begin
iTop := 0;
if Line < 0 then Exit;
if Assigned(FBookMarkOpt.BookmarkImages) and
(DebugMarksImageIndex <= FBookMarkOpt.BookmarkImages.Count) and
(DebugMarksImageIndex >= 0) then
begin
if not FBookMarkOpt.DrawBookmarksFirst then
aGutterOffs^[Line] := AClip.Left
else
if aGutterOffs^[Line] = 0 then
aGutterOffs^[Line] := FBookMarkOpt.BookmarkImages.Width + AClip.Left;
if LineHeight > FBookMarkOpt.BookmarkImages.Height then
iTop := (LineHeight - FBookMarkOpt.BookmarkImages.Height) div 2;
with FBookMarkOpt do
BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs^[Line],
iTop + Line * LineHeight, DebugMarksImageIndex, True);
Inc(aGutterOffs^[Line], FBookMarkOpt.BookmarkImages.Width);
end
end;
begin
if not Visible then exit;
LineHeight := TSynEdit(SynEdit).LineHeight;
if MarkupInfo.Background <> clNone then
Canvas.Brush.Color := MarkupInfo.Background
else
Canvas.Brush.Color := Gutter.Color;
dc := Canvas.Handle;
{$IFDEF SYN_LAZARUS}
LCLIntf.SetBkColor(dc,Canvas.Brush.Color);
{$ENDIF}
// now the gutter marks
if FBookMarkOpt.GlyphsVisible and (LastLine >= FirstLine) then
begin
aGutterOffs := AllocMem((LastLine + 1) * SizeOf(integer));
try
for i := FirstLine to LastLine do
begin
iLine := FFoldView.TextIndex[i] + 1;
TSynEdit(SynEdit).Marks.GetMarksForLine(iLine, Marks);
HasAnyMark := False;
for j := Low(Marks) to High(Marks) do
begin
if Marks[j] = nil then
break;
if not Marks[j].Visible then
continue;
DrawMark(Marks[j]);
HasAnyMark := HasAnyMark or not Marks[j].IsBookmark;
end;
if not HasAnyMark and TSynEdit(SynEdit).HasDebugMark(iLine) then
DrawDebugMark(i);
end;
finally
FreeMem(aGutterOffs);
end;
end;
end;
end.