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

📄 editunit.pas.svn-base

📁 支持自定义语法高亮显示的编辑器控件
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
unit editunit;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls,
  EasyEditor, EasyControls, EasyClasses, EasyParser, EasyEditSource, EasyKeyMap,
  EasyEditorSettings, EasySettings,
  Menus, TypInfo, StdCtrls, ImgList, ComCtrls;

type
  TEditForm = class(TForm)
    EasyEdit: TEasyEdit;
    JScrParser: TEasyEditorParser;
    HtmlParser: TEasyEditorParser;
    ChangeTimer: TTimer;
    ImageList1: TImageList;
    procedure FormActivate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure FormDestroy(Sender: TObject);
    procedure ChangeTimerTimer(Sender: TObject);
    procedure EasyEditSourceChanged(Sender: TObject;
      State: TEasyEditSourceStates);
    procedure EasyEditMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure EasyEditGetDrawStyle(Sender: TObject; Line, Char: Integer;
      var Style: Word);
    procedure EasyEditMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure EasyEditKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure EasyEditSelectionChanged(Sender: TObject);
    procedure EasyEditKeyPress(Sender: TObject; var Key: Char);
    procedure EasyEditDisplayHint(Sender: TObject; var s: String;
      AKey: Char; var AllowPopup: Boolean);
    procedure EasyEditAutoComplete(Sender: TObject; Strings: TStrings;
      AKey: Char; var AllowPopup: Boolean);
    procedure EasyEditBeforeInsertPopup(Sender: TObject; var s: String);
    procedure EasyEditFindStringInPopup(Sender: TObject; Strings: TStrings;
      const s: String; var Index: Integer; var Handled: Boolean);
  private
    FGotoDefinition : boolean;
    FDefPt          : TPoint;
    FGotoPt         : TPoint;
    FDefLen         : integer;
    FFunctionIndex  : integer;

    function GetParamIndex : integer;
    function IsMethod(var s : string; var Pt : TPoint) : boolean;

    procedure GetPlainString(var s : string; var IsFunction : boolean);
    procedure GetPlainText(AStrings : TStrings);
    procedure UpdateUrl;
    procedure ClearUrl;
    procedure CheckCtrlSpace;
    procedure CheckCtrlShiftSpace;
    procedure ShowMethodHint(const s : string; APoint : TPoint; CheckBold : boolean; AKeepHint : boolean = false);
    procedure CheckMethodParams;
    procedure FillCodeCompletion(Strings : TStrings);
    procedure FillStrings(Strings : TStrings; AClass : TClass);
    procedure DoPopupClosed(Sender: TObject);
    procedure UpdateStatusBar(StatusBar : TStatusBar; State : TEasyEditSourceStates);

  public
    procedure AfterCreate;
    property FunctionIndex : integer read FFunctionIndex write FFunctionIndex;
    { Public declarations }
  end;

var
  EditForm: TEditForm;

implementation

uses main, expl, jparser;

{$R *.DFM}
const
  sJsExt = '.js';
  sSaveChanges = 'Save changes to %s ?';
  cUrlTextStyle = 8;

  sColorTable = '{\rtf{\colortbl\red0\green0\blue0;\red0\green128\blue128;\red128\green0\blue0;\red128\green128\blue0;\red0\green0\blue255;}';
  sPropStr = '\cf1 Property \cf0 | %s | \b %s}';
  sVarStr = '\cf2 Var \cf0 \b | %s';
  sParamStr = '\cf3 Param \cf0 \b | %s';
  sConstStr = '\cf2 Const \cf0 \b | %s';
  sFuncStr = '\cf4 Function \cf0 \b | %s \b0 %s';
  sNoParams = '\b *No parameters expected*';

  cVarImage = 0;
  cPropImage = 3;
  cParamImage = 3;
  cConstImage = 1;
  cFunctionImage = 2;

type
  TMEdit = class(TCustomEasyEdit);
  TMEasyPopupWindow = class(TEasyPopupWindow);

function GetFunctionInfo(AEdit : TCustomEasyEdit) : TFunctionInfo;
var
  i      : integer;
  s      : string;
  pLeft  : integer;
  pRight : integer;
begin
  result := nil;
  s := Copy(AEdit.EditSource.Strings.GetStr(AEdit.CurrentPosition.Y), 1, AEdit.CurrentPosition.X);
  pLeft := Pos('(', s);
  pRight := Pos(')', s);

  s := '';
  if (pLeft > 0) and ((pRight = 0) or ((pRight > 0) and (pRight > pLeft) and (pRight > AEdit.CurrentPosition.X))) then
    s := AEdit.EditSource.GetTextAt(Point(pLeft - 2, AEdit.CurrentPosition.Y),true);

  i := UnitInfo.Functions.IndexOf(s);
  if i >= 0 then
    result := TFunctionInfo(UnitInfo.Functions.Objects[i]);
end;

procedure FillInfo(Strings : TStrings; Info: TFunctionInfo);
var
  i     : integer;
  AInfo : TFunctionInfo;

  procedure AddColoredString(const s : string; ImageIndex : integer);
  begin
    if Strings.Count = 0 then
      Strings.AddObject(sColorTable + s, Pointer(ImageIndex))
    else
      Strings.AddObject(s, Pointer(ImageIndex));
  end;

begin
  Strings.Clear;
  if Info = nil then
    exit;
  for i := 0 to info.LocalVars.Count - 1 do
    AddColoredString(Format(sVarStr, [info.LocalVars[i]]), cVarImage);
  for i := 0 to info.Params.Count - 1 do
    AddColoredString(Format(sParamStr, [info.Params[i]]), cParamImage);
  for i := 0 to UnitInfo.Variables.Count - 1 do
    AddColoredString(Format(sVarStr, [UnitInfo.Variables[i]]), cVarImage);
  for i := 0 to UnitInfo.Constants.Count - 1 do
    AddColoredString(Format(sConstStr, [UnitInfo.Constants[i]]), cConstImage);
  for i := 0 to UnitInfo.Functions.Count - 1 do
    begin
      AInfo := TFunctionInfo(UnitInfo.Functions.Objects[i]);
      if AInfo <> nil then
        AddColoredString(Format(sFuncStr, [AInfo.Name, AInfo.ParamText]), cFunctionImage);
    end;
end;

procedure TEditForm.AfterCreate;
begin
  if CompareText(ExtractFileExt(Caption), sJsExt) = 0 then
    EasyEdit.Parser := JScrParser
  else
    EasyEdit.Parser := HtmlParser;
  ExplorerFrm.UpdateExplorer(Caption);
  FFunctionIndex := -1;
  EasyEdit.OnPopupClosed := DoPopupClosed;
end;

procedure TEditForm.FormActivate(Sender: TObject);
begin
  MainForm.ActivateTab(Self);
  ExplorerFrm.UpdateExplorer(Caption);
end;

procedure TEditForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
  ExplorerFrm.UpdateExplorer('');
end;

procedure TEditForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if MainForm.InDestroying or not EasyEdit.Modified then
    Exit;
  case MessageDlg(Format(sSaveChanges, [Caption]), mtConfirmation, [mbYes, mbNo, mbCancel], 0) of
    mrYes:
      CanClose := MainForm.SaveEditor(Self, true);
    mrNo:
      CanClose := true;
    mrCancel:
      CanClose := false;
  end;
end;

procedure TEditForm.FormDestroy(Sender: TObject);
begin
  if not (csDestroying in MainForm.ComponentState) then
    MainForm.RemoveTab(Self);
end;

procedure TEditForm.ChangeTimerTimer(Sender: TObject);
begin
  ChangeTimer.Enabled := false;
  ExplorerFrm.UpdateExplorer(Caption);
end;

procedure TEditForm.UpdateStatusBar(StatusBar : TStatusBar; State : TEasyEditSourceStates);
var
  AText : string;
begin
  with StatusBar, EasyEdit do
  begin
    If (Panels.Count > 0) and (csPositionChanged in State) then
      Panels[0].Text := Format('Line: %d, Char: %d', [CurrentPosition.Y + 1, CurrentPosition.X + 1]);

    if (Panels.Count > 2) and (csInsModeChanged in State) then
      if OverWrite then
        Panels[2].Text := 'Overwrite'
      else
        Panels[2].Text := '';

    if (Panels.Count > 1) then
    begin
      AText := '' ;
      if ReadOnly then
        AText := 'ReadOnly';
      if Modified and (AText = '') then
        AText := 'Modified';
      if Panels[1].Text <> AText then
        Panels[1].Text := AText;
    end;
  end;
end;


procedure TEditForm.EasyEditSourceChanged(Sender: TObject;
  State: TEasyEditSourceStates);
begin
  if csEdit in State then
  begin
    ChangeTimer.Enabled := false;
    ChangeTimer.Enabled := true;
  end;
  UpdateStatusBar(MainForm.StatusBar1, State);
end;

procedure TEditForm.UpdateUrl;
var
  R : TRect;
begin
  if FDefPt.Y < 0 then
    exit;
  with TMEdit(EasyEdit), TextToPixelPoint(FDefPt, false) do
  begin
    R := Rect(X, Y, X + Painter.GetDefaultCharWidth * FDefLen, Y + Painter.GetDefaultLineHeight);
    InvalidateRect(Handle, @R, false);
  end;
end;

procedure TEditForm.ClearUrl;
begin
  UpdateUrl;
  FDefPt := Point(-1, -1);
  FDefLen := 0;
  EasyEdit.Cursor := crIBeam;
  FGotoDefinition := false;
end;


procedure TEditForm.EasyEditMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  s      : string;
  Info   : TElementInfo;
  Pt     : TPoint;
  ALeft  : integer;
  ARight : integer;
begin
  if (ssCtrl in Shift) then
    with EasyEdit, EditSource do
    begin
      Pt := PixelToTextPoint(Point(X, Y), false);
      s := GetTextAt(Pt, true);
      Info := UnitInfo.IndexOf(s);
      if Info <> nil then
      begin
        Cursor := crHandPoint;
        FGotoPt := Point(0, Info.LineNo);
        FGotoDefinition := true;
        UpdateUrl;
        GetWord(Pt, ALeft, ARight, wsWord);
        FDefPt := Point(ALeft - 1, Pt.Y);
        FDefLen := ARight - ALeft + 1;
        UpdateUrl;
      end
      else
        ClearUrl;
    end
  else
    ClearUrl;
end;

procedure TEditForm.EasyEditGetDrawStyle(Sender: TObject; Line,
  Char: Integer; var Style: Word);
begin
  if FGotoDefinition and (Line = FDefPt.Y) and (Char > FDefPt.X) and (Char <= FDefPt.X + FDefLen) then
    Style := cUrlTextStyle;
end;

procedure TEditForm.EasyEditMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if (FGotoDefinition) and (ssCtrl in Shift) then
  begin
    ClearUrl;
    with EasyEdit do
    begin
      CurrentPosition := FGotoPt;
      SelType := slNone;
      Navigate(cCenterLine);
    end;
  end;

end;

procedure TEditForm.EasyEditKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if (Key = VK_SPACE) and (ssCtrl in Shift) and (ssShift in Shift) then
  begin
    CheckCtrlShiftSpace;
    Key := 0;
  end;
end;

procedure TEditForm.CheckCtrlShiftSpace;
var
  s  : string;
  Pt : TPoint;
begin
  if IsMethod(s,Pt) then
    ShowMethodHint(s, Pt, true);

⌨️ 快捷键说明

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