synedit, ide: add TSynMark.Priority to order marks at the same line. Make CurrentLine mark priority bigger

git-svn-id: trunk@18948 -
This commit is contained in:
paul 2009-03-10 15:19:48 +00:00
parent 5d3aba4a89
commit c21cb3f74f
4 changed files with 113 additions and 70 deletions

View File

@ -14,33 +14,36 @@ const
type type
{ TSynEditMark }
TSynEditMark = class TSynEditMark = class
protected protected
fLine, fColumn, fImage: Integer; FLine, FColumn, FImage, FPriority: Integer;
FEdit: TSynEditBase; FEdit: TSynEditBase;
fVisible: boolean; FVisible: boolean;
fInternalImage: boolean; FInternalImage: boolean;
fBookmarkNum: integer; FBookmarkNum: integer;
function GetEdit: TSynEditBase; virtual; function GetEdit: TSynEditBase; virtual;
procedure SetColumn(const Value: Integer); virtual; procedure SetColumn(const Value: Integer); virtual;
procedure SetImage(const Value: Integer); virtual; procedure SetImage(const Value: Integer); virtual;
procedure SetLine(const Value: Integer); virtual; procedure SetLine(const Value: Integer); virtual;
procedure SetVisible(const Value: boolean); {$IFDEF SYN_LAZARUS}virtual;{$ENDIF} //MWE: Laz needs to know when a line gets visible, so the editor color can be updated procedure SetPriority(const AValue: integer); virtual;
procedure SetVisible(const Value: boolean); virtual; //MWE: Laz needs to know when a line gets visible, so the editor color can be updated
procedure SetInternalImage(const Value: boolean); procedure SetInternalImage(const Value: boolean);
function GetIsBookmark: boolean; function GetIsBookmark: boolean;
public public
constructor Create(AOwner: TSynEditBase); constructor Create(AOwner: TSynEditBase);
property Line: integer read fLine write SetLine; property Line: integer read FLine write SetLine;
property Column: integer read fColumn write SetColumn; property Column: integer read FColumn write SetColumn;
property ImageIndex: integer read fImage write SetImage; property Priority: integer read FPriority write SetPriority;
property BookmarkNumber: integer read fBookmarkNum write fBookmarkNum; property ImageIndex: integer read FImage write SetImage;
property Visible: boolean read fVisible write SetVisible; property BookmarkNumber: integer read FBookmarkNum write fBookmarkNum;
property InternalImage: boolean read fInternalImage write SetInternalImage; property Visible: boolean read FVisible write SetVisible;
property InternalImage: boolean read FInternalImage write SetInternalImage;
property IsBookmark: boolean read GetIsBookmark; property IsBookmark: boolean read GetIsBookmark;
end; end;
TPlaceMarkEvent = procedure(Sender: TObject; var Mark: TSynEditMark) TPlaceMarkEvent = procedure(Sender: TObject; var Mark: TSynEditMark) of object;
of object;
TSynEditMarks = array[1..maxMarks] of TSynEditMark; TSynEditMarks = array[1..maxMarks] of TSynEditMark;
@ -82,6 +85,11 @@ type // This is until InvalidateGutterLines, can be moved to an accessible plac
{ TSynEditMark } { TSynEditMark }
procedure TSynEditMark.SetPriority(const AValue: integer);
begin
FPriority := AValue;
end;
function TSynEditMark.GetEdit: TSynEditBase; function TSynEditMark.GetEdit: TSynEditBase;
begin begin
if FEdit <> nil then try if FEdit <> nil then try
@ -106,42 +114,45 @@ end;
procedure TSynEditMark.SetImage(const Value: Integer); procedure TSynEditMark.SetImage(const Value: Integer);
begin begin
FImage := Value; FImage := Value;
if fVisible and Assigned(fEdit) then if FVisible and Assigned(FEdit) then
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine); SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(FLine, FLine);
end; end;
procedure TSynEditMark.SetInternalImage(const Value: boolean); procedure TSynEditMark.SetInternalImage(const Value: boolean);
begin begin
fInternalImage := Value; FInternalImage := Value;
if fVisible and Assigned(fEdit) then if FVisible and Assigned(FEdit) then
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine); SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(FLine, FLine);
end; end;
procedure TSynEditMark.SetLine(const Value: Integer); procedure TSynEditMark.SetLine(const Value: Integer);
begin begin
if fVisible and Assigned(fEdit) then begin if FVisible and Assigned(FEdit) then
if fLine > 0 then begin
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine); if FLine > 0 then
fLine := Value; SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(FLine, FLine);
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine); FLine := Value;
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(FLine, FLine);
end else end else
fLine := Value; FLine := Value;
end; end;
procedure TSynEditMark.SetVisible(const Value: boolean); procedure TSynEditMark.SetVisible(const Value: boolean);
begin begin
if fVisible <> Value then begin if FVisible <> Value then
fVisible := Value; begin
if Assigned(fEdit) then FVisible := Value;
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(fLine, fLine); if Assigned(FEdit) then
SynEditAccess(Pointer(FEdit)).InvalidateGutterLines(FLine, FLine);
end; end;
end; end;
constructor TSynEditMark.Create(AOwner: TSynEditBase); constructor TSynEditMark.Create(AOwner: TSynEditBase);
begin begin
inherited Create; inherited Create;
fBookmarkNum := -1; FBookmarkNum := -1;
fEdit := AOwner; FEdit := AOwner;
FPriority := 0;
end; end;
{ TSynEditMarkList } { TSynEditMarkList }
@ -163,7 +174,7 @@ end;
constructor TSynEditMarkList.Create(AOwner: TSynEditBase); constructor TSynEditMarkList.Create(AOwner: TSynEditBase);
begin begin
inherited Create; inherited Create;
fEdit := AOwner; FEdit := AOwner;
end; end;
destructor TSynEditMarkList.Destroy; destructor TSynEditMarkList.Destroy;
@ -189,12 +200,12 @@ end;
function TSynEditMarkList.First: TSynEditMark; function TSynEditMarkList.First: TSynEditMark;
begin begin
result := TSynEditMark(inherited First); Result := TSynEditMark(inherited First);
end; end;
function TSynEditMarkList.Get(Index: Integer): TSynEditMark; function TSynEditMarkList.Get(Index: Integer): TSynEditMark;
begin begin
result := TSynEditMark(inherited Get(Index)); Result := TSynEditMark(inherited Get(Index));
end; end;
//Returns up to maxMarks book/gutter marks for a chosen line. //Returns up to maxMarks book/gutter marks for a chosen line.
@ -207,8 +218,10 @@ var
begin begin
FillChar(marks, SizeOf(marks), 0); FillChar(marks, SizeOf(marks), 0);
cnt := 0; cnt := 0;
for i := 0 to Count - 1 do begin for i := 0 to Count - 1 do
if Items[i].Line = line then begin begin
if Items[i].Line = line then
begin
Inc(cnt); Inc(cnt);
marks[cnt] := Items[i]; marks[cnt] := Items[i];
if cnt = maxMarks then break; if cnt = maxMarks then break;
@ -224,12 +237,12 @@ end;
function TSynEditMarkList.Last: TSynEditMark; function TSynEditMarkList.Last: TSynEditMark;
begin begin
result := TSynEditMark(inherited Last); Result := TSynEditMark(inherited Last);
end; end;
procedure TSynEditMarkList.Place(mark: TSynEditMark); procedure TSynEditMarkList.Place(mark: TSynEditMark);
begin begin
if assigned(fEdit) then if assigned(FEdit) then
if assigned(TSynEdit(FEdit).OnPlaceBookmark) then if assigned(TSynEdit(FEdit).OnPlaceBookmark) then
TSynEdit(FEdit).OnPlaceBookmark(TSynEdit(FEdit), mark); TSynEdit(FEdit).OnPlaceBookmark(TSynEdit(FEdit), mark);
if assigned(mark) then if assigned(mark) then

View File

@ -66,6 +66,48 @@ begin
Result := 0; Result := 0;
end; end;
function DoMarksCompareBookmarksFirst(Item1, Item2: Pointer): Integer;
var
Mark1: TSynEditMark absolute Item1;
Mark2: TSynEditMark absolute Item2;
begin
Result := 0;
if Mark1 = Mark2 then Exit;
if Mark1.IsBookmark then
Result := -1
else
if Mark2.IsBookmark then
Result := 1
else
if Mark1.Priority < Mark2.Priority then
Result := 1
else
if Mark1.Priority > Mark2.Priority then
Result := -1;
end;
function DoMarksCompareBookmarksLast(Item1, Item2: Pointer): Integer;
var
Mark1: TSynEditMark absolute Item1;
Mark2: TSynEditMark absolute Item2;
begin
Result := 0;
if Mark1 = Mark2 then Exit;
if Mark1.IsBookmark then
Result := 1
else
if Mark2.IsBookmark then
Result := -1
else
if Mark1.Priority < Mark2.Priority then
Result := 1
else
if Mark1.Priority > Mark2.Priority then
Result := -1;
end;
procedure TSynGutterMarks.Paint(Canvas : TCanvas; AClip : TRect; FirstLine, LastLine : integer); procedure TSynGutterMarks.Paint(Canvas : TCanvas; AClip : TRect; FirstLine, LastLine : integer);
var var
i: integer; i: integer;
@ -73,15 +115,14 @@ var
aGutterOffs: PIntArray; aGutterOffs: PIntArray;
dc: HDC; dc: HDC;
LineHeight: Integer; LineHeight: Integer;
LineMarks: TList;
procedure DrawMark(iMark: integer); procedure DrawMark(CurMark: TSynEditMark);
var var
iLine: integer; iLine: integer;
itop : Longint; itop : Longint;
CurMark: TSynEditMark;
begin begin
iTop := 0; iTop := 0;
CurMark := TSynEdit(SynEdit).Marks[iMark];
if (CurMark.Line<1) or (CurMark.Line > SynEdit.Lines.Count) then exit; if (CurMark.Line<1) or (CurMark.Line > SynEdit.Lines.Count) then exit;
if FFoldView.FoldedAtTextIndex[CurMark.Line-1] then exit; if FFoldView.FoldedAtTextIndex[CurMark.Line-1] then exit;
iLine := FFoldView.TextIndexToScreenLine(CurMark.Line-1); iLine := FFoldView.TextIndexToScreenLine(CurMark.Line-1);
@ -97,7 +138,7 @@ var
iTop := (LineHeight - fBookMarkOpt.BookmarkImages.Height) div 2; iTop := (LineHeight - fBookMarkOpt.BookmarkImages.Height) div 2;
with fBookMarkOpt do with fBookMarkOpt do
BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs^[iLine], BookmarkImages.Draw(Canvas, LeftMargin + aGutterOffs^[iLine],
iTop + iLine * LineHeight, CurMark.ImageIndex,true); iTop + iLine * LineHeight, CurMark.ImageIndex, true);
Inc(aGutterOffs^[iLine], fBookMarkOpt.BookmarkImages.Width); Inc(aGutterOffs^[iLine], fBookMarkOpt.BookmarkImages.Width);
end; end;
@ -131,37 +172,23 @@ begin
// now the gutter marks // now the gutter marks
if FBookMarkOpt.GlyphsVisible and (TSynEdit(SynEdit).Marks.Count > 0) if FBookMarkOpt.GlyphsVisible and (TSynEdit(SynEdit).Marks.Count > 0) and (LastLine >= FirstLine) then
and (LastLine >= FirstLine) begin
then begin
aGutterOffs := AllocMem((LastLine+1{$IFNDEF SYN_LAZARUS}-TopLine{$ENDIF}) * SizeOf(integer)); aGutterOffs := AllocMem((LastLine+1{$IFNDEF SYN_LAZARUS}-TopLine{$ENDIF}) * SizeOf(integer));
try try
// Instead of making a two pass loop we look while drawing the bookmarks LineMarks := TList.Create;
// whether there is any other mark to be drawn try
bHasOtherMarks := FALSE;
for i := 0 to TSynEdit(SynEdit).Marks.Count - 1 do with TSynEdit(SynEdit).Marks[i] do for i := 0 to TSynEdit(SynEdit).Marks.Count - 1 do with TSynEdit(SynEdit).Marks[i] do
{$IFDEF SYN_LAZARUS} if Visible and (Line >= FFoldView.TextIndex[FirstLine] + 1) and (Line <= FFoldView.TextIndex[LastLine] + 1) then
if Visible and (Line >= FFoldView.TextIndex[FirstLine]+1) and (Line <= FFoldView.TextIndex[LastLine]+1) then LineMarks.Add(TSynEdit(SynEdit).Marks[i]);
{$ELSE} if fBookMarkOpt.DrawBookmarksFirst then
if Visible and (Line >= FirstLine) and (Line <= LastLine) then LineMarks.Sort(@DoMarksCompareBookmarksFirst)
{$ENDIF}
begin
if IsBookmark <> fBookMarkOpt.DrawBookmarksFirst then //mh 2000-10-12
bHasOtherMarks := TRUE
else else
DrawMark(i); LineMarks.Sort(@DoMarksCompareBookmarksLast);
end; for i := 0 to LineMarks.Count - 1 do
if bHasOtherMarks then DrawMark(TSynEditMark(LineMarks[i]));
for i := 0 to TSynEdit(SynEdit).Marks.Count - 1 do with TSynEdit(SynEdit).Marks[i] do finally
begin LineMarks.Free;
if Visible and (IsBookmark <> FBookMarkOpt.DrawBookmarksFirst) //mh 2000-10-12
{$IFDEF SYN_LAZARUS}
and (Line >= FFoldView.TextIndex[FirstLine]+1) and (Line <= FFoldView.TextIndex[LastLine]+1)
{$ELSE}
and (Line >= FirstLine) and (Line <= LastLine)
{$ENDIF}
then
DrawMark(i);
end; end;
finally finally
FreeMem(aGutterOffs); FreeMem(aGutterOffs);

View File

@ -2187,6 +2187,7 @@ begin
EditorComponent.Marks.Add(FExecutionMark); EditorComponent.Marks.Add(FExecutionMark);
FExecutionMark.ImageIndex := SourceEditorMarks.CurrentLineImg; FExecutionMark.ImageIndex := SourceEditorMarks.CurrentLineImg;
FExecutionMark.LineColorAttrib := ahaExecutionPoint; FExecutionMark.LineColorAttrib := ahaExecutionPoint;
FExecutionMark.Priority := 1;
end; end;
if ExecutionLine <> -1 then if ExecutionLine <> -1 then

View File

@ -396,6 +396,8 @@ begin
if Result<>0 then exit; if Result<>0 then exit;
Result:=Column-OtherMark.Column; Result:=Column-OtherMark.Column;
if Result <> 0 then exit; if Result <> 0 then exit;
Result:=Priority-OtherMark.Priority;
if Result <> 0 then exit;
Result := PtrInt(Self) - PtrInt(OtherMark); Result := PtrInt(Self) - PtrInt(OtherMark);
end; end;