⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 syneditcodefolding.pas

📁 SynEditStudio delphi 代码编辑器
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{
Mystix Text Editor
Copyright (C) 2005 Piotr Jura

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

You can contact with me by e-mail: pjura@o2.pl
}
unit SynEditCodeFolding;

interface

uses
	Graphics, Types, Classes, SysUtils;

type
	TSynEditFoldRange = class;
  TSynEditAllFoldRanges = class;
  TFoldRegions = class;

  TSkipRegionItemType = (itString, itMultiLineComment, itSingleLineComment);

  TSkipRegionItem = class(TCollectionItem)
  private
    fClose: PChar;
    fOpen: PChar;
    fEscape: PChar;
    fType: TSkipRegionItemType;
    procedure SetClose(const Value: PChar);
    procedure SetOpen(const Value: PChar);
    procedure SetEscape(const Value: PChar);
  public
    destructor Destroy(); override; //#mod memory leak
  	property Open: PChar read fOpen write SetOpen;
    property Close: PChar read fClose write SetClose;
    property Escape: PChar read fEscape write SetEscape;
    property RegionType: TSkipRegionItemType read fType write fType;
  end;

  TSkipRegions = class(TCollection)
  private
    function GetSkipRegionItem(Index: Integer): TSkipRegionItem;
  public
  	function Add(const aOpen, aClose, aEscape: String;
      aType: TSkipRegionItemType): TSkipRegionItem;
    
  	property SkipRegions[Index: Integer]: TSkipRegionItem
    	read GetSkipRegionItem; default;
  end;

	TFoldRegionType = (rtChar, rtKeyWord);

	TFoldRegionItem = class(TCollectionItem)
  private
		fType: TFoldRegionType;
		fAddEnding: Boolean;
		fNoSubFoldRegions: Boolean;
		fSubFoldRegions: TFoldRegions;
    fOpen: PChar;
    fClose: PChar;
    fParentRegion: TFoldRegionItem;
    fWholeWords: Boolean;
    fRegExpUseOpen: Boolean;
    fRegExpOpen: PChar;
    fRegExpUseClose: Boolean;
    fRegExpClose: PChar;
    fName: String;

    procedure SetClose(const Value: PChar);
    procedure SetOpen(const Value: PChar);
    procedure SetRegExpClose(const Value: PChar);
    procedure SetRegExpOpen(const Value: PChar);
  public
  	constructor Create(Collection: TCollection); override;
    destructor Destroy; override;

    property FoldRegionType: TFoldRegionType read fType write fType;
    property AddEnding: Boolean read fAddEnding write fAddEnding;
    property NoSubFoldRegions: Boolean read fNoSubFoldRegions
    	write fNoSubFoldRegions;
    property SubFoldRegions: TFoldRegions read fSubFoldRegions;
    property Open: PChar read fOpen write SetOpen;
    property Close: PChar read fClose write SetClose;
    property ParentRegion: TFoldRegionItem read fParentRegion
    	write fParentRegion;
    property WholeWords: Boolean read fWholeWords write fWholeWords;
    property RegExpOpen: PChar read fRegExpOpen write SetRegExpOpen;
    property RegExpClose: PChar read fRegExpClose write SetRegExpClose;
    property RegExpUseOpen: Boolean read fRegExpUseOpen write fRegExpUseOpen;
    property RegExpUseClose: Boolean read fRegExpUseClose
    	write fRegExpUseClose;
    property Name: String read fName write fName;
	end;

  TFoldRegions = class(TCollection)
  private
  	fSkipRegions: TSkipRegions;

    function GetItem(Index: Integer): TFoldRegionItem;
  public
  	constructor Create(ItemClass: TCollectionItemClass);
    destructor Destroy; override;
    function Add(AType: TFoldRegionType; AAddEnding, ANoSubFoldRegions,
    	AWholeWords: Boolean; AOpen, AClose: PChar;
    	AParentRegion: TFoldRegionItem = nil): TFoldRegionItem;
      
  	property Items[Index: Integer]: TFoldRegionItem read GetItem; default;
    property SkipRegions: TSkipRegions read fSkipRegions;
  end;

	TSynEditFoldRanges = class(TPersistent)
  private
  	fRanges: TList;
    function GetSynEditFoldRange(Index: Integer): TSynEditFoldRange;
    function GetCount: Integer;
  public
  	constructor Create;
    destructor Destroy; override;

    function Add(AAllFold: TSynEditAllFoldRanges; AFromLine,
			ALevel, ARealLevel: Integer; AFoldRegion: TFoldRegionItem;
  		AToLine: Integer = 0): TSynEditFoldRange;
    procedure AddF(FoldRange: TSynEditFoldRange);
    procedure Clear;

    property Count: Integer read GetCount;
    property FoldRanges[Index: Integer]: TSynEditFoldRange
    	read GetSynEditFoldRange; default;
    property Ranges: TList read fRanges;
  end;

  TSynEditAllFoldRanges = class(TSynEditFoldRanges)
  private
  	fAllRanges: TList;
    function GetAllCount: Integer;
    function GetAllFoldRange(Index: Integer): TSynEditFoldRange;
  public
  	constructor Create;
    destructor Destroy; override;

    procedure ClearAll;
    procedure Delete(Index: Integer);
    procedure AddFold(FoldRange: TSynEditFoldRange);
    procedure Assign(Source: TPersistent); override;

    property AllCount: Integer read GetAllCount;
    property AllFoldRanges[Index: Integer]: TSynEditFoldRange
    	read GetAllFoldRange; default;
    property AllRanges: TList read fAllRanges;
  end;

	TSynEditFoldRange = class
  private
  	fFromLine, // Beginning line
    fToLine, // End line
    fLevel, // Indent level (physcial)
    fLinesCollapsed, // Number of collapsed lines
    fCollapsedBy: Integer; // Parent fold range index
    fRealLevel: Integer; // Fold range level
  	fSubFoldRanges: TSynEditFoldRanges; // Sub fold ranges
    fCollapsed, // Is collapsed?
    fParentCollapsed: Boolean; // Is collapsed together with it's parent?
    fCollapsedLines: TStringList; // Collapsed lines
    fAllFoldRanges: TSynEditAllFoldRanges; // TAllFoldRanges pointer
    fFoldRegion: TFoldRegionItem; // FoldRegion pointer
    fHintMarkLeft: Integer;
    procedure SetRealLevel(const Value: Integer);
  public
  	constructor Create;
    destructor Destroy; override;

    procedure SetPCOfSubFoldRanges(AParentCollapsed: Boolean;
    	ACollapsedBy: Integer);
    function RealLinesCollapsed: Integer;
    procedure MoveBy(LineCount: Integer);
    procedure MoveChildren(By: Integer);
    procedure Widen(LineCount: Integer);
    function Collapsable: Boolean;

    property RealLevel: Integer read fRealLevel write SetRealLevel;
    property SubFoldRanges: TSynEditFoldRanges read fSubFoldRanges;
    property FromLine: Integer read fFromLine write fFromLine;
    property ToLine: Integer read fToLine write fToLine;
    property Level: Integer read fLevel write fLevel;
    property LinesCollapsed: Integer read fLinesCollapsed write fLinesCollapsed;
    property CollapsedBy: Integer read fCollapsedBy write fCollapsedBy;
    property Collapsed: Boolean read fCollapsed write fCollapsed;
    property ParentCollapsed: Boolean read fParentCollapsed
    	write fParentCollapsed;
    property CollapsedLines: TStringList read fCollapsedLines;
    property FoldRegion: TFoldRegionItem read fFoldRegion write fFoldRegion;
    property HintMarkLeft: Integer read fHintMarkLeft write fHintMarkLeft;
  end;

  TNode = class
	private
		fValue:      Pointer;
		fChildNode:  TNode;
		fParentNode: TNode;
	public
		constructor Create(AValue: Pointer);

    property ChildNode: TNode read fChildNode;
    property ParentNode: TNode read fParentNode;
		property Value: Pointer read fValue;
	end;

	TStack = class
	private
		fFirstNode: TNode;
	public
		constructor Create;
		destructor Destroy; override;

		function IsEmpty: Boolean;
		function Peak: Pointer;
		function Pop: Pointer;
		procedure Push(Value: Pointer);
	end;

  THSLColor = record
  	Hue,
    Saturation,
    Luminace: Integer;
  end;

function RGB2HSL(Color: TColor): THSLColor;
function HSL2RGB(Color: THSLColor): TColor;
function RoundUp(Number: Single): Integer;

implementation

function RoundUp(Number: Single): Integer;
begin
	if Number - Trunc(Number) > 0 then
  	Result := Trunc(Number) + 1
  else
  	Result := Trunc(Number);
end;

function RGB2HSL(Color: TColor): THSLColor;
var
	R, G, B, Max, Min, Diff, RGB, Sum: Integer;
  q: Single;
begin
  RGB := ColorToRGB(Color);
  R := RGB and $0000FF;
  G := (RGB and $00FF00) shr 8;
  B := (RGB and $FF0000) shr 16;

  if R > G then begin
  	Max := R;
    Min := G;
  end else begin
  	Max := G;
    Min := R;
  end;

  if B > Max then
  	Max := B
  else if B < Min then
  	Min := B;

  Sum := Max + Min;
  Diff := Max - Min;

  Result.Hue := 0;
  Result.Saturation := 0;
  Result.Luminace := (100 * Sum) div 510;

  if Diff > 0 then begin
  	if Result.Luminace <= 50 then
  		Result.Saturation := 100 * Diff div Sum
    else
      Result.Saturation := 100 * Diff div (510 - Sum);

    q := 60 / Diff;

    if Max = R then begin
    	if G < B then
        Result.Hue := Round(360 + q * (G - B))
    	else
        Result.Hue := Round(q * (G - B));
    end
    else if Max = G then
      Result.Hue := Round(q * (B - R) + 120)
    else if Max = B then
      Result.Hue := Round(q * (R - G) + 240);
  end;
end;

function HSL2RGB(Color: THSLColor): TColor;
var
	R, G, B, H, S, L, Min, Max, Diff: Single;
begin
	if Color.Saturation = 0 then
 		Result := (Round(2.55 * Color.Luminace) shl 16)
    or (Round(2.55 * Color.Luminace) shl 8) or (Round(2.55 * Color.Luminace))
  else begin
  	H := Color.Hue / 60;
    S := Color.Saturation / 100;
    L := Color.Luminace / 100;

    if L <= 0.5 then
    	Min := L * (1 - S)
    else
    	Min := L - S * (1 - L);
      
    Max := 2 * L - Min;
    Diff := Max - Min;

    case (Color.Hue div 60) of
    	0:
      begin
      	R := Max;
        B := Min;
        G := H * Diff + Min;
      end;
      1:
      begin
      	G := Max;
        B := Min;
        R := Min - (H - 2) * Diff;
      end;
      2:
      begin
      	G := Max;
        R := Min;
        B := (H - 2) * Diff + Min;
			end;
      3:
      begin
      	B := Max;
        R := Min;
        G := Min - (H - 4) * Diff;
      end;
      4:
      begin
      	B := Max;
        G := Min;
        R := (H - 4) * Diff + Min;
      end;
    else
    	R := Max;
      G := Min;
      B := Min - (H - 6) * Diff;
    end;

    Result := (RoundUp(B * 255) shl 16) + (RoundUp(G * 255) shl 8) + RoundUp(R * 255);
  end;
end;

{ TSynEditAllFoldRanges }

procedure TSynEditAllFoldRanges.AddFold(FoldRange: TSynEditFoldRange);
begin
	fAllRanges.Add(FoldRange);
end;

procedure TSynEditAllFoldRanges.Assign(Source: TPersistent);
var
	Src: TSynEditAllFoldRanges;

	procedure AuxProc(FoldRanges, SrcFoldRanges: TSynEditFoldRanges);
  var
  	i: Integer;
    FoldRange: TSynEditFoldRange;
  begin
  	for i := 0 to SrcFoldRanges.Count - 1 do
    begin
    	with SrcFoldRanges[i] do
      //if (assigned(fCollapsedLines))and(fCollapsedLines.Count<>0) then
      begin
      	FoldRange := FoldRanges.Add(Self, fFromLine, fLevel, fRealLevel, fFoldRegion, fToLine);
        FoldRange.fLinesCollapsed := fLinesCollapsed;
        FoldRange.fCollapsedBy := fCollapsedBy;
        FoldRange.fCollapsed := fCollapsed;
        FoldRange.fParentCollapsed := fParentCollapsed;
        FoldRange.fCollapsedLines.Assign(fCollapsedLines);
        FoldRange.fFoldRegion := fFoldRegion;
      end;

    	AuxProc(FoldRange.SubFoldRanges, SrcFoldRanges[i].SubFoldRanges);
    end;
  end;
begin
  Src := TSynEditAllFoldRanges(Source);
	AuxProc(Self, Src);
end;

procedure TSynEditAllFoldRanges.ClearAll;
var i: Integer;                                             //###mod memory leak

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -