SynEdit: Added markup module for source highlight from gutter-marks

git-svn-id: trunk@27893 -
This commit is contained in:
martin 2010-10-27 00:49:34 +00:00
parent bbebbdd3cd
commit 05da6877b9
6 changed files with 205 additions and 10 deletions

1
.gitattributes vendored
View File

@ -2121,6 +2121,7 @@ components/synedit/syneditmarks.pp svneol=native#text/plain
components/synedit/syneditmarkup.pp svneol=native#text/plain
components/synedit/syneditmarkupbracket.pp svneol=native#text/plain
components/synedit/syneditmarkupctrlmouselink.pp svneol=native#text/plain
components/synedit/syneditmarkupguttermark.pp svneol=native#text/pascal
components/synedit/syneditmarkuphighall.pp svneol=native#text/plain
components/synedit/syneditmarkupselection.pp svneol=native#text/plain
components/synedit/syneditmarkupspecialline.pp svneol=native#text/plain

View File

@ -39,7 +39,8 @@ implicitunits=synbeautifier syncompletion syndesignstringconstants \
synedit syneditautocomplete syneditexport syneditfoldedview synedithighlighter \
synedithighlighterfoldbase synedithighlighterxmlbase syneditkeycmds \
syneditlazdsgn syneditlines syneditmarks \
syneditmarkup syneditmarkupbracket syneditmarkupctrlmouselink syneditmarkuphighall \
syneditmarkup syneditmarkupbracket syneditmarkupctrlmouselink \
syneditmarkuphighall syneditmarkupguttermark\
syneditmarkupselection syneditmarkupspecialline syneditmarkupwordgroup \
syneditmiscclasses syneditmiscprocs syneditmousecmds syneditplugins \
syneditpointclasses syneditregexsearch syneditsearch syneditstrconst synedittextbase \

View File

@ -43,6 +43,9 @@ uses
SynHighlighterDiff,
SynGutter, SynGutterChanges, SynGutterCodeFolding, SynGutterLineNumber,
SynGutterMarks, SynGutterLineOverview,
SynEditMarkup, SynEditMarkupBracket, SynEditMarkupCtrlMouseLink,
SynEditMarkupHighAll, SynEditMarkupSelection, SynEditMarkupSpecialLine,
SynEditMarkupWordGroup, SynEditMarkupGutterMark,
SynPropertyEditObjectList, SynDesignStringConstants;
implementation

View File

@ -95,6 +95,7 @@ type
Procedure EndMarkup; virtual;
Function GetMarkupAttributeAtRowCol(const aRow, aCol : Integer) : TSynSelectedColor; virtual; abstract;
Function GetNextMarkupColAfterRowCol(const aRow, aCol : Integer) : Integer; virtual; abstract;
procedure MergeMarkupAttributeAtRowCol(const aRow, aCol, AEndCol : Integer; AMarkup: TSynSelectedColor); virtual;
// Notifications about Changes to the text
Procedure TextChanged(aFirstCodeLine, aLastCodeLine: Integer); virtual;
@ -148,9 +149,9 @@ type
Procedure PrepareMarkupForRow(aRow : Integer); override;
Procedure FinishMarkupForRow(aRow : Integer); override;
Procedure EndMarkup; override;
Function GetMarkupAttributeAtRowCol(const aRow, aCol : Integer) : TSynSelectedColor; override;
Function GetNextMarkupColAfterRowCol(const aRow, aCol : Integer) : Integer; override;
Procedure MergeMarkupAttributeAtRowCol(const aRow, aCol, AEndCol : Integer; AMarkup: TSynSelectedColor);
Function GetMarkupAttributeAtRowCol(const aRow, aCol : Integer) : TSynSelectedColor; override;
Function GetNextMarkupColAfterRowCol(const aRow, aCol : Integer) : Integer; override;
procedure MergeMarkupAttributeAtRowCol(const aRow, aCol, AEndCol : Integer; AMarkup: TSynSelectedColor); override;
// Notifications about Changes to the text
Procedure TextChanged(aFirstCodeLine, aLastCodeLine: Integer); override;
@ -358,6 +359,16 @@ procedure TSynEditMarkup.EndMarkup;
begin
end;
procedure TSynEditMarkup.MergeMarkupAttributeAtRowCol(const aRow, aCol, AEndCol: Integer;
AMarkup: TSynSelectedColor);
var
c: TSynSelectedColor;
begin
c := GetMarkupAttributeAtRowCol(aRow, aCol);
if assigned(c) then
AMarkup.Merge(c, aCol, AEndCol);
end;
procedure TSynEditMarkup.TextChanged(aFirstCodeLine, aLastCodeLine: Integer);
begin
DoTextChanged(aFirstCodeLine, aLastCodeLine);
@ -483,14 +494,11 @@ procedure TSynEditMarkupManager.MergeMarkupAttributeAtRowCol
(const aRow, aCol, AEndCol: Integer; AMarkup: TSynSelectedColor);
var
i : integer;
c : TSynSelectedColor;
begin
for i := 0 to fMarkUpList.Count-1 do begin
if not TSynEditMarkup(fMarkUpList[i]).Enabled then continue;
c := TSynEditMarkup(fMarkUpList[i]).GetMarkupAttributeAtRowCol(aRow, aCol);
if assigned(c) then begin
AMarkup.Merge(c, aCol, AEndCol);
end;
if TSynEditMarkup(fMarkUpList[i]).Enabled then
TSynEditMarkup(fMarkUpList[i]).MergeMarkupAttributeAtRowCol
(aRow, aCol, AEndCol, AMarkup);
end;
end;

View File

@ -0,0 +1,160 @@
{-------------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
the specific language governing rights and limitations under the License.
Alternatively, the contents of this file may be used under the terms of the
GNU General Public License Version 2 or later (the "GPL"), in which case
the provisions of the GPL are applicable instead of those above.
If you wish to allow use of your version of this file only under the terms
of the GPL and not to allow others to use your version of this file
under the MPL, indicate your decision by deleting the provisions above and
replace them with the notice and other provisions required by the GPL.
If you do not delete the provisions above, a recipient may use your version
of this file under either the MPL or the GPL.
-------------------------------------------------------------------------------}
unit SynEditMarkupGutterMark;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Graphics, Controls, LCLProc,
SynEditMarkup, SynEditMiscClasses, SynEditMarks;
type
TMarkSection = record
StartX, EndX: Integer; // Physical
Priority: Integer;
Markup: TSynSelectedColor;
end;
{ TSynEditMarkupMark }
TSynEditMarkupMark = class(TSynEditMark)
private
FSourceMarkup: TSynSelectedColor;
public
property SourceMarkup: TSynSelectedColor read FSourceMarkup write FSourceMarkup;
end;
{ TSynEditMarkupGutterMark }
TSynEditMarkupGutterMark = class(TSynEditMarkup)
// TODO: subscribe to mark changes for line invalidation => currently done by synedit itself
private
FRowData: Array of TMarkSection;
FWordBreaker: TSynWordBreaker;
protected
procedure DoMarkupChanged(AMarkup: TSynSelectedColor); override;
public
constructor Create(ASynEdit: TSynEditBase; AWordBreaker: TSynWordBreaker);
procedure PrepareMarkupForRow(ARow: Integer); override;
function GetMarkupAttributeAtRowCol(const ARow, ACol: Integer): TSynSelectedColor; override;
function GetNextMarkupColAfterRowCol(const ARow, ACol: Integer): Integer; override;
//procedure MergeMarkupAttributeAtRowCol(const aRow, aCol, AEndCol : Integer; AMarkup: TSynSelectedColor); override;
end;
implementation
uses
SynEdit;
{ TSynEditMarkupGutterMark }
procedure TSynEditMarkupGutterMark.DoMarkupChanged(AMarkup: TSynSelectedColor);
begin
inherited DoMarkupChanged(AMarkup);
SynEdit.Invalidate;
end;
constructor TSynEditMarkupGutterMark.Create(ASynEdit: TSynEditBase;
AWordBreaker: TSynWordBreaker);
begin
FWordBreaker := AWordBreaker;
inherited Create(ASynEdit);
end;
procedure TSynEditMarkupGutterMark.PrepareMarkupForRow(ARow: Integer);
var
MLine: TSynEditMarkLine;
i, j: Integer;
s: string;
begin
MLine := TSynEdit(SynEdit).Marks.Line[ARow];
if MLine = nil then begin
SetLength(FRowData, 0);
exit;
end;
SetLength(FRowData, MLine.Count);
j := 0;
for i := 0 to MLine.Count - 1 do begin
if not ( (MLine[i] is TSynEditMarkupMark) and
(TSynEditMarkupMark(MLine[i]).SourceMarkup <> nil) )
then
continue;
FRowData[i].Markup := TSynEditMarkupMark(MLine[i]).SourceMarkup;
FRowData[i].Priority := MLine[i].Priority;
s := Lines[MLine[i].Line - 1];
FRowData[i].StartX := LogicalToPhysicalPos
(Point(FWordBreaker.PrevBoundary(s, MLine[i].Column, True), MLine[i].Line)).x;
FRowData[i].EndX := LogicalToPhysicalPos
(Point(FWordBreaker.NextBoundary(s, MLine[i].Column), MLine[i].Line)).x;
if (FRowData[i].StartX > 0) and (FRowData[i].EndX > 0) then
inc(j);
end;
SetLength(FRowData, j);
end;
function TSynEditMarkupGutterMark.GetMarkupAttributeAtRowCol(const ARow,
ACol: Integer): TSynSelectedColor;
var
i, FoundPri: Integer;
begin
FoundPri := 0;
for i := 0 to length(FRowData) - 1 do begin
if (FRowData[i].StartX <= ACol) and (FRowData[i].EndX > ACol) and
( (FRowData[i].Priority < FoundPri) or (i = 0) )
then begin
Result := FRowData[i].Markup;
Result.StartX := FRowData[i].StartX;
Result.EndX := FRowData[i].EndX-1;
FoundPri := FRowData[i].Priority;
end;
end;
end;
function TSynEditMarkupGutterMark.GetNextMarkupColAfterRowCol(const ARow,
ACol: Integer): Integer;
var
i: Integer;
begin
Result := -1;
if length(FRowData) = 0 then
exit;
for i := 0 to length(FRowData) - 1 do begin
if FRowData[i].StartX < Result then
Result := FRowData[0].StartX;;
if FRowData[i].EndX < Result then
Result := FRowData[0].EndX;;
end;
end;
end.

View File

@ -68,6 +68,7 @@ type
procedure Reset;
// aX is the position between the chars (as in CaretX)
// 1 is in front of the first char
function IsInWord (aLine: String; aX: Integer
): Boolean;
function IsAtWordStart(aLine: String; aX: Integer): Boolean;
@ -82,6 +83,8 @@ type
aIncludeCurrent: Boolean = False): Integer;
function NextBoundary (aLine: String; aX: Integer): Integer;
function PrevBoundary (aLine: String; aX: Integer;
aIncludeCurrent: Boolean = False): Integer;
property IdentChars: TSynIdentChars read FIdentChars write SetIdentChars;
property WordChars: TSynIdentChars read FWordChars;
@ -1467,6 +1470,25 @@ begin
Result := aX;
end;
function TSynWordBreaker.PrevBoundary(aLine: String; aX: Integer;
aIncludeCurrent: Boolean): Integer;
var
len: Integer;
begin
len := Length(aLine);
if not aIncludeCurrent then dec(ax);
if (aX < 1) or (aX > len) then exit(-1);
if (aLine[aX] in FWordChars) then
while (aX > 1) and (aLine[aX] in FWordChars) do dec(ax)
else
if (aLine[aX] in FWordBreakChars) then
while (aX > 1) and (aLine[aX] in FWordBreakChars) do dec(ax)
else
while (aX > 1) and (aLine[aX] in FWhiteChars) do dec(ax);
Result := aX + 1;
end;
{ TSynMethodList }
function TSynMethodList.IndexToObjectIndex(const AnObject: TObject; AnIndex: Integer): integer;