lazarus/components/ideintf/srceditorintf.pas
2024-09-28 09:46:24 +02:00

1012 lines
40 KiB
ObjectPascal

{
*****************************************************************************
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Abstract:
Defines interface to source editors.
}
unit SrcEditorIntf;
{$mode objfpc}{$H+}
interface
uses
Classes,
// LCL
LCLType, Forms, Controls, Graphics, ComCtrls,
// LazUtils
Laz2_XMLCfg, LazStringUtils,
// BuildIntf
ProjectIntf,
// IdeIntf
IDECommands;
type
TSourceMarklingType = (
smtHint, // something is unusual or awkward
smtNote, // something could be wrong or is not optimized
smtWarning, // something is probably wrong or likely to fail
smtError // something is definitely wrong
);
{ TSourceMarklingProducer }
TSourceMarklingProducer = class(TComponent)
public
procedure InvalidateAllFiles;
procedure InvalidateFile(aFilename: string);
function GetMarklings(aFilename: string;
out FreeList, FreeMarklings: boolean): TFPList; virtual; abstract;
end;
{ TSourceMarkling }
TSourceMarkling = class
private
FColumn: integer;
FProducer: TSourceMarklingProducer;
FId: integer;
FLine: integer;
fType: TSourceMarklingType;
public
constructor Create(aProducer: TSourceMarklingProducer;
TheID, aLine, aColumn: integer; aType: TSourceMarklingType);
property Producer: TSourceMarklingProducer read FProducer;
property Id: integer read FId;
property Line: integer read FLine;
property Column: integer read FColumn;
property TheType: TSourceMarklingType read fType;
end;
type
TSrcEditSearchOption = (
sesoMatchCase,
sesoWholeWord,
sesoBackwards,
sesoEntireScope,
sesoSelectedOnly,
sesoReplace,
sesoReplaceAll,
sesoPrompt,
sesoRegExpr,
sesoMultiLine
);
TSrcEditSearchOptions = set of TSrcEditSearchOption;
TSrcEditReplaceAction = (seraCancel, seraSkip, seraReplace, seraReplaceAll);
TSrcEditProjectUpdateNeeded = (sepuNewShared, sepuChangedHighlighter);
TSrcEditProjectUpdatesNeeded = set of TSrcEditProjectUpdateNeeded;
{ TSourceEditorInterface }
TSourceEditorInterface = class
protected
function GetBlockBegin: TPoint; virtual; abstract;
function GetBlockEnd: TPoint; virtual; abstract;
function GetCodeToolsBuffer: TObject; virtual; abstract;
function GetCursorScreenXY: TPoint; virtual; abstract;
function GetCursorTextXY: TPoint; virtual; abstract;
function GetEditorControl: TWinControl; virtual; abstract;
function GetFileName: string; virtual; abstract;
function GetLines: TStrings; virtual; abstract;
function GetLineText: string; virtual; abstract;
function GetLinesInWindow: Integer; virtual; abstract;
function GetModified: Boolean; virtual; abstract;
function GetPageCaption: string; virtual; abstract;
function GetPageName: string; virtual; abstract;
function GetReadOnly: Boolean; virtual; abstract;
function GetSelection: string; virtual; abstract;
function GetSelEnd: Integer; virtual; abstract;
function GetSelStart: Integer; virtual; abstract;
function GetSourceText: string; virtual; abstract;
function GetTopLine: Integer; virtual; abstract;
procedure SetBlockBegin(const AValue: TPoint); virtual; abstract;
procedure SetBlockEnd(const AValue: TPoint); virtual; abstract;
procedure SetCursorScreenXY(const AValue: TPoint); virtual; abstract;
procedure SetCursorTextXY(const AValue: TPoint); virtual; abstract;
procedure SetLines(const AValue: TStrings); virtual; abstract;
procedure SetLineText(const AValue: string); virtual; abstract;
procedure SetModified(const NewValue: Boolean); virtual; abstract;
procedure SetReadOnly(const AValue: Boolean); virtual; abstract;
procedure SetSelection(const AValue: string); virtual; abstract;
procedure SetSelEnd(const AValue: Integer); virtual; abstract;
procedure SetSelStart(const AValue: Integer); virtual; abstract;
procedure SetSourceText(const AValue: string); virtual; abstract;
procedure SetTopLine(const AValue: Integer); virtual; abstract;
public
// selections
function SelectionAvailable: boolean; virtual; abstract;
function GetText(OnlySelection: boolean): string; virtual; abstract;
procedure SelectText(LineNum, CharStart, LineNum2, CharEnd: Integer);
procedure SelectText(const StartPos, EndPos: TPoint); virtual; abstract;
procedure InsertLine(StartLine: Integer; const NewText: String; aKeepMarks: Boolean = False); virtual; abstract;
procedure ReplaceLines(StartLine, EndLine: integer; const NewText: string; aKeepMarks: Boolean = False); virtual; abstract;
procedure ReplaceText(const StartPos, EndPos: TPoint; const NewText: string);
procedure AskReplace(Sender: TObject; const ASearch, AReplace: string;
Line, Column: integer;
out Action: TSrcEditReplaceAction); virtual; abstract;
procedure CopyToClipboard; virtual; abstract;
procedure CutToClipboard; virtual; abstract;
function GetBookMark(BookMark: Integer; out X, Y: Integer): Boolean; virtual; abstract;
function GetBookMark(BookMark: Integer; out X, Y, ALeft, ATop: Integer): Boolean; virtual; abstract;
procedure SetBookMark(BookMark: Integer; X, Y: Integer; AnLeft: Integer = -1; AnTop: Integer = -1); virtual; abstract;
// screen and text position mapping
function LineCount: Integer; virtual; abstract;
function TextToScreenPosition(const Position: TPoint): TPoint; virtual; abstract; // aka byte to glyph
function ScreenToTextPosition(const Position: TPoint): TPoint; virtual; abstract; // aka glyph to byte
// characters and pixels
function WidthInChars: Integer; virtual; abstract;
function HeightInLines: Integer; virtual; abstract;
function CharWidth: integer; virtual; abstract;
function CursorInPixel: TPoint; virtual; abstract;
function ScreenToPixelPosition(const Position: TPoint): TPoint; virtual; abstract;// ScreenXY to pixel in EditorControl.
// To get the desktop pixel coords use:
// with SourceEditorWindow.ActiveEditor do
// DesktopXY:=EditorControl.ClientToScreen(ScreenToPixelPosition(ScreenXY));
// update
procedure BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}(ACaller: String = ''){$ENDIF}; virtual; abstract;
procedure EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}(ACaller: String = ''){$ENDIF}; virtual; abstract;
procedure BeginUpdate; virtual; abstract; // block painting
procedure EndUpdate; virtual; abstract;
procedure IncreaseIgnoreCodeBufferLock; virtual; abstract;
procedure DecreaseIgnoreCodeBufferLock; virtual; abstract;
procedure UpdateCodeBuffer; virtual; abstract;// copy the source from EditorComponent to the codetools
function NeedsUpdateCodeBuffer: boolean; virtual; abstract;// needs UpdateCodeBuffer
// search and replace
function SearchReplace(const ASearch, AReplace: string;
SearchOptions: TSrcEditSearchOptions): integer; virtual; abstract;
// context
function GetProjectFile: TLazProjectFile; virtual; abstract;
procedure UpdateProjectFile(AnUpdates: TSrcEditProjectUpdatesNeeded = []); virtual; abstract;
function GetDesigner(LoadForm: boolean): TIDesigner; virtual; abstract;
// editor commands
procedure DoEditorExecuteCommand(EditorCommand: word); virtual; abstract;
// move/copy to another SourceEditorWindow
procedure MoveToWindow(AWindowIndex: Integer); virtual; abstract;
procedure CopyToWindow(AWindowIndex: Integer); virtual; abstract;
//
function DebugToSourceLine(aLinePos: Integer): Integer; virtual; abstract;
public
property BlockBegin: TPoint read GetBlockBegin write SetBlockBegin;
property BlockEnd: TPoint read GetBlockEnd write SetBlockEnd;
property CodeToolsBuffer: TObject read GetCodeToolsBuffer;
property CursorScreenXY: TPoint read GetCursorScreenXY write SetCursorScreenXY; // glyph/character,line coord, both 1-based
property CursorTextXY: TPoint read GetCursorTextXY write SetCursorTextXY; // byte,line coord, both 1-based
property EditorControl: TWinControl read GetEditorControl;// normally TSynEdit
property FileName: string read GetFileName;
property Lines: TStrings read GetLines write SetLines;// the whole file
property CurrentLineText: string read GetLineText write SetLineText;// source of current line
property PageCaption: string read GetPageCaption;// the beatified unit name with modifiers ('*', '#') as it is shown in tab caption
property PageName: string read GetPageName;// the beatified unit name
property ReadOnly: Boolean read GetReadOnly write SetReadOnly;
property Selection: string read GetSelection write SetSelection; // setting selection is undoable
property SelEnd: Integer read GetSelEnd write SetSelEnd;
property SelStart: Integer read GetSelStart write SetSelStart;
property SourceText: string read GetSourceText write SetSourceText;// the whole file, raw format, writing clears undo list
property TopLine: Integer read GetTopLine write SetTopLine;// first visible line
property LinesInWindow: Integer read GetLinesInWindow;
property Modified: Boolean read GetModified write SetModified;
end;
{ TSourceEditorCompletionPlugin }
TSourceEditorCompletionPlugin = class(TComponent)
public
procedure Init(SrcEdit: TSourceEditorInterface; JumpToError: boolean;
var Handled, Abort: boolean; var Prefix: string;
var BoxX, BoxY: integer); virtual; abstract; // check if this plugin is responsible
function Collect(List: TStrings): boolean; virtual; abstract; // collect values
procedure Cancel; virtual; abstract; // completion was cancelled
procedure Complete(var Value: string; SourceValue: string;
var SourceStart, SourceEnd: TPoint;
KeyChar: TUTF8Char; Shift: TShiftState); virtual; abstract; // execute completion
procedure IndexChanged(Position: integer); virtual; abstract;
procedure PrefixChanged(const NewPrefix: string; var NewIndex: integer;
var s: TStrings); virtual; abstract;
procedure CompletePrefix(var Prefix: string); virtual; abstract;
function HasCustomPaint: boolean; virtual;
procedure PaintItem(const {%H-}AKey: string; {%H-}ACanvas: TCanvas;
{%H-}X, {%H-}Y: integer; {%H-}ItemSelected: boolean; {%H-}Index: integer); virtual;
function MeasureItem(const {%H-}AKey: string; {%H-}ACanvas: TCanvas;
{%H-}ItemSelected: boolean; {%H-}Index: integer): TPoint; virtual;
end;
TSourceEditorStatusPanelInterface = class;
TDrawSourceEditPanelEvent = procedure(APanel: TSourceEditorStatusPanelInterface;
ACanvas: TCanvas; const Rect: TRect) of object;
{ TSourceEditorStatusPanelInterface }
TSourceEditorStatusPanelInterface = class
private
FOnClick: TNotifyEvent;
FOnContextPopup: TContextPopupEvent;
FOnDoubleClick: TNotifyEvent;
FOnDrawPanel: TDrawSourceEditPanelEvent;
FOwner: TClass;
FTag: PtrUInt;
FOnDestroy: TNotifyEvent;
FOnResize: TNotifyEvent;
protected
function GetAlignment: TAlignment; virtual; abstract;
function GetBevel: TStatusPanelBevel; virtual; abstract;
function GetBidiMode: TBiDiMode; virtual; abstract;
function GetHeight: integer; virtual; abstract;
function GetScreenBounds: TRect;virtual; abstract;
function GetText: string; virtual; abstract;
function GetVisible: boolean; virtual; abstract;
function GetWidth: integer; virtual; abstract;
procedure SetAlignment(AValue: TAlignment); virtual; abstract;
procedure SetBevel(AValue: TStatusPanelBevel); virtual; abstract;
procedure SetBidiMode(AValue: TBiDiMode); virtual; abstract;
procedure SetText(AValue: string); virtual; abstract;
procedure SetOnDrawPanel(AValue: TDrawSourceEditPanelEvent); virtual;
procedure SetVisible(AValue: boolean); virtual; abstract;
public
constructor Create(AnOwner: TClass; ATag: PtrUInt);
property Owner: TClass read FOwner;
property Tag: PtrUInt read FTag;
property Alignment: TAlignment read GetAlignment write SetAlignment;
property Bevel: TStatusPanelBevel read GetBevel write SetBevel;
property BidiMode: TBiDiMode read GetBidiMode write SetBidiMode;
property Text: string read GetText write SetText;
property Visible: boolean read GetVisible write SetVisible;
function RequestWidth(AWidth: Integer): Integer; virtual; abstract;
property Height: integer read GetHeight;
property Width: integer read GetWidth;
property ScreenBounds: TRect read GetScreenBounds;
property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy;
property OnResize: TNotifyEvent read FOnResize write FOnResize;
property OnClick: TNotifyEvent read FOnClick write FOnClick;
property OnDoubleClick: TNotifyEvent read FOnDoubleClick write FOnDoubleClick;
property OnContextPopup: TContextPopupEvent read FOnContextPopup write FOnContextPopup;
property OnDrawPanel: TDrawSourceEditPanelEvent read FOnDrawPanel write SetOnDrawPanel; // change draw mode
end;
{ TSourceEditorWindowInterface }
TSourceEditorWindowInterface = class(TForm)
protected
function GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; virtual; abstract;
function GetActiveEditor: TSourceEditorInterface; virtual; abstract;
function GetBaseCaption: String; virtual; abstract;
function GetCompletionPlugins(Index: integer): TSourceEditorCompletionPlugin; virtual; abstract;
function GetItems(Index: integer): TSourceEditorInterface; virtual; abstract;
procedure SetActiveEditor(const AValue: TSourceEditorInterface); virtual; abstract;
procedure SetBaseCaption(AValue: String); virtual; abstract;
function GetWindowID: Integer; virtual; abstract;
function GetStatusPanel(AnOwner: TClass; AnIdx: integer): TSourceEditorStatusPanelInterface; virtual; abstract;
function GetStatusPanelTagged(AnOwner: TClass; ATag: PtrUInt; AnIdx: integer): TSourceEditorStatusPanelInterface; virtual; abstract;
public
procedure IncUpdateLock; virtual; abstract;
procedure DecUpdateLock; virtual; abstract;
function IndexOfEditorInShareWith(AnOtherEditor: TSourceEditorInterface): Integer; virtual; abstract;
function SourceEditorIntfWithFilename(const Filename: string): TSourceEditorInterface; virtual; abstract;
property ActiveEditor: TSourceEditorInterface read GetActiveEditor write SetActiveEditor;
function Count: integer; virtual; abstract;
property Items[Index: integer]: TSourceEditorInterface read GetItems; default;
property ActiveCompletionPlugin: TSourceEditorCompletionPlugin read GetActiveCompletionPlugin;
// The number in the Form.Caption minus 1 (0-based), if multiple Win are open
property WindowID: Integer read GetWindowID;
// Editor Page Caption update
procedure AddUpdateEditorPageCaptionHandler(AEvent: TNotifyEvent; const AsLast: Boolean = True); virtual; abstract;
procedure RemoveUpdateEditorPageCaptionHandler(AEvent: TNotifyEvent); virtual; abstract;
procedure AddControlToEditor(aSourceEditor : TSourceEditorInterface; aControl : TControl; aAlign : TAlign); virtual; abstract;
property BaseCaption: String read GetBaseCaption write SetBaseCaption;
function AddStatusPanel(AnOwner: TClass; ATag: PtrUInt = 0): TSourceEditorStatusPanelInterface; virtual; abstract;
function StatusPanelCount(AnOwner: TClass): integer; virtual; abstract;
function StatusPanelTaggedCount(AnOwner: TClass; ATag: PtrUInt): integer; virtual; abstract;
property StatusPanel[AnOwner: TClass; AnIdx: integer]: TSourceEditorStatusPanelInterface read GetStatusPanel;
property StatusPanelTagged[AnOwner: TClass; ATag: PtrUInt; AnIdx: integer]: TSourceEditorStatusPanelInterface read GetStatusPanelTagged;
end;
TSemChangeReason = (
semWindowCreate, // Called after creation of a Window
semWindowDestroy, // Called after removal of a Window
semWindowActivate, // Window is now ActiveSourceWindow (does not vave to be focused)
semWindowFocused, // The window became the active win of the application
semWindowShow, // Called after a Window is shown
semWindowHide, // Called after a Window is hidden
semEditorCreate, // Called after a new editor was created and added to list
semEditorDestroy, // Called when an Editor is destroyed / after it is removed fron the list of editors
semEditorOptsChanged, // Called when EditorOptions changed / called with TIDEEditorOptions as Sender
semEditorActivate, // Editor is ActiveEditor
semEditorStatus, // any status change of the editor (Caret, Selection, topline, ...)
semEditorMouseDown,
semEditorMouseUp,
semEditorMoved, // Called when moved to a new window
semEditorCloned, // Called when cloned to a new window.
semEditorReConfigured // Called when the configuration of an editor changes
);
TSemSelectionMode = (
semsmNormal,
semsmLine,
semsmColumn,
semsmCurrent);
TSemCopyPasteAction = (
semcaContinue, // normal paste with specials like folding
semcaPlainText, // paste as normal text, ignore folding and other specials
semcaAbort // cancel, use this if you handled the paste yourself
);
// ToDo: use the right clipboard
TSemCopyPasteEvent = procedure(Sender: TSourceEditorInterface;
var AText: String; var AMode: TSemSelectionMode; ALogStartPos: TPoint;
var AnAction: TSemCopyPasteAction) of object;
TSemBeautyFlag = (
sembfNotBreakDots
);
TSemBeautyFlags = set of TSemBeautyFlag;
{ TSourceEditorManagerInterface }
TSourceEditorManagerInterface = class(TComponent)
protected
function GetActiveSourceWindow: TSourceEditorWindowInterface; virtual; abstract;
procedure SetActiveSourceWindow(const AValue: TSourceEditorWindowInterface);
virtual; abstract;
function GetSourceWindows(Index: integer): TSourceEditorWindowInterface;
virtual; abstract;
function GetActiveEditor: TSourceEditorInterface; virtual; abstract;
procedure SetActiveEditor(const AValue: TSourceEditorInterface);
virtual; abstract;
function GetSourceEditors(Index: integer): TSourceEditorInterface;
virtual; abstract;
function GetUniqueSourceEditors(Index: integer): TSourceEditorInterface;
virtual; abstract;
function GetMarklingProducers(Index: integer): TSourceMarklingProducer;
virtual; abstract;
function GetShowTabs: Boolean; virtual; abstract;
procedure SetShowTabs(const AShowTabs: Boolean); virtual; abstract;
public
// List of SourceEditorWindows
function SourceWindowWithEditor(const AEditor: TSourceEditorInterface): TSourceEditorWindowInterface;
virtual; abstract;
function IndexOfSourceWindowWithID(const AnID: Integer): Integer; virtual; abstract;
procedure ShowActiveWindowOnTop(Focus: Boolean = False); virtual; abstract;
function SourceWindowCount: integer; virtual; abstract;
property SourceWindows[Index: integer]: TSourceEditorWindowInterface
read GetSourceWindows;
property ActiveSourceWindow: TSourceEditorWindowInterface
read GetActiveSourceWindow write SetActiveSourceWindow;
// List of SourceEditors (accross all Windows)
function SourceEditorIntfWithFilename(const Filename: string): TSourceEditorInterface;
virtual; abstract; // first hit, there might be more
function SourceEditorCount: integer; virtual; abstract;
property SourceEditors[Index: integer]: TSourceEditorInterface
read GetSourceEditors;
property ActiveEditor: TSourceEditorInterface
read GetActiveEditor write SetActiveEditor;
// List of unique SourceEditors (excluding DualView)
function UniqueSourceEditorCount: integer; virtual; abstract;
property UniqueSourceEditors[Index: integer]: TSourceEditorInterface
read GetUniqueSourceEditors;
// Editor Preferences
function GetEditorControlSettings(EditControl: TControl): boolean; virtual; abstract;
function GetHighlighterSettings(Highlighter: TObject): boolean; virtual; abstract;
// Messages
procedure ClearErrorLines; virtual; abstract;
// General source functions
function Beautify(const Src: string; const Flags: TSemBeautyFlags = []): string; virtual; abstract;
protected
// Completion Plugins
function GetActiveCompletionPlugin: TSourceEditorCompletionPlugin; virtual; abstract;
function GetCompletionBoxPosition: integer; virtual; abstract;
function GetCompletionPlugins(Index: integer): TSourceEditorCompletionPlugin; virtual; abstract;
function GetDefaultSynCompletionForm: TCustomForm; virtual; abstract;
function GetSynCompletionLinesInWindow: integer; virtual; abstract;
procedure SetSynCompletionLinesInWindow(LineCnt: integer); virtual; abstract;
public
// Completion Plugins
function CompletionPluginCount: integer; virtual; abstract;
property CompletionPlugins[Index: integer]: TSourceEditorCompletionPlugin
read GetCompletionPlugins;
property DefaultSynCompletionForm: TCustomForm read GetDefaultSynCompletionForm;
property SynCompletionLinesInWindow: integer read GetSynCompletionLinesInWindow
write SetSynCompletionLinesInWindow;
procedure DeactivateCompletionForm; virtual; abstract;
property ActiveCompletionPlugin: TSourceEditorCompletionPlugin read GetActiveCompletionPlugin;
property CompletionBoxPosition: integer read GetCompletionBoxPosition;
procedure RegisterCompletionPlugin(Plugin: TSourceEditorCompletionPlugin); virtual; abstract;
procedure UnregisterCompletionPlugin(Plugin: TSourceEditorCompletionPlugin); virtual; abstract;
public
procedure RegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); virtual; abstract;
procedure UnRegisterChangeEvent(AReason: TsemChangeReason; AHandler: TNotifyEvent); virtual; abstract;
procedure RegisterCopyPasteEvent(AHandler: TSemCopyPasteEvent); virtual; abstract;
procedure UnRegisterCopyPasteEvent(AHandler: TSemCopyPasteEvent); virtual; abstract;
public
// source marklings
function MarklingProducerCount: integer; virtual; abstract;
property MarklingProducers[Index: integer]: TSourceMarklingProducer read GetMarklingProducers;
procedure RegisterMarklingProducer(aProducer: TSourceMarklingProducer); virtual; abstract;
procedure UnregisterMarklingProducer(aProducer: TSourceMarklingProducer); virtual; abstract;
procedure InvalidateMarklingsOfAllFiles(aProducer: TSourceMarklingProducer); virtual; abstract;
procedure InvalidateMarklings(aProducer: TSourceMarklingProducer; aFilename: string); virtual; abstract;
property ShowTabs: Boolean read GetShowTabs write SetShowTabs;
end;
var
SourceEditorManagerIntf: TSourceEditorManagerInterface=nil; // set by the IDE
type
TEditorMacroState = (emStopped, emRecording, emPlaying, emRecPaused); // msPaused = paused recording
TEditorMacro = class;
{ TEditorMacroKeyBinding }
TEditorMacroKeyBinding = class
protected
FOwner: TEditorMacro;
function GetIdeCmd: TIDECommand; virtual;
public
constructor Create(AOwner: TEditorMacro); virtual;
procedure WriteToXmlConf(AConf: TXMLConfig; const APath: String); virtual; abstract;
procedure ReadFromXmlConf(AConf: TXMLConfig; const APath: String); virtual; abstract;
procedure MacroNameChanged; virtual; // must be called by sub-class of TEditorMacro
property IdeCmd: TIDECommand read GetIdeCmd; // TKeyCommandRelation
function ShortCutAsText: String; virtual;
end;
TEditorMacroKeyBindingClass = class of TEditorMacroKeyBinding;
{ TEditorMacro
"aEditor: TWinControl" must be TCustomSynEdit
}
TEditorMacro = class
private
FOnChange: TNotifyEvent;
FOnStateChange: TNotifyEvent;
procedure SetMacroNameFull(AValue: String);
procedure SetOnChange(AValue: TNotifyEvent);
protected
procedure DoChanged;
procedure DoStateChanged;
// (Un)setActivated: Must be called, whenever the state changes
procedure SetActivated;
procedure UnsetActivated;
function IsActivated: Boolean;
procedure CheckStateAndActivated;
function GetMacroName: String; virtual; abstract;
procedure SetMacroName(AValue: string); virtual; abstract;
function GetState: TEditorMacroState; virtual; abstract;
function GetErrorMsg: String; virtual;
function GetDefaultKeyBinding: TEditorMacroKeyBinding;
function GetKeyBinding: TEditorMacroKeyBinding; virtual; abstract;
procedure DoRecordMacro(aEditor: TWinControl); virtual; abstract;
procedure DoPlaybackMacro(aEditor: TWinControl); virtual; abstract;
procedure DoStop; virtual; abstract;
procedure DoPause; virtual; abstract;
procedure DoResume; virtual; abstract;
public
constructor Create(aOwner: TComponent); virtual; abstract;
procedure AssignEventsFrom(AMacroRecorder: TEditorMacro); virtual; abstract;
procedure WriteToXmlConf(AConf: TXMLConfig; const APath: String); virtual; abstract;
procedure ReadFromXmlConf(AConf: TXMLConfig; const APath: String); virtual; abstract;
function GetAsSource: String; virtual; abstract;
procedure SetFromSource(const AText: String); virtual; abstract;
procedure RecordMacro(aEditor: TWinControl);
procedure PlaybackMacro(aEditor: TWinControl);
procedure Stop;
procedure Pause;
procedure Resume;
procedure Clear; virtual; abstract;
function IsEmpty: Boolean; virtual; abstract;
function IsInvalid: Boolean; virtual; abstract;
function IsRecording(AnEditor: TWinControl): Boolean; virtual; abstract;
property MacroName: String read GetMacroName write SetMacroNameFull;
property State: TEditorMacroState read GetState;
property ErrorMsg: String read GetErrorMsg;
property OnStateChange: TNotifyEvent read FOnStateChange write FOnStateChange;
property OnChange: TNotifyEvent read FOnChange write FOnChange; // Name, body
property KeyBinding: TEditorMacroKeyBinding read GetKeyBinding;
end;
TEditorMacroClass = class of TEditorMacro;
var
// EditorMacroForRecording:
// Used to record new Macros. On Completion it will be assigned to a player-macro
EditorMacroForRecording: TEditorMacro = nil; // set by SourceEditor
// ActiveEditorMacro:
// Will be set whenever a macro is playing/recording. Ensures only one Macro is active
ActiveEditorMacro: TEditorMacro = nil;
DefaultBindingClass: TEditorMacroKeyBindingClass = nil;
EditorMacroPlayerClass: TEditorMacroClass = nil;
function GetMacroListViewerWarningText: String;
procedure SetMacroListViewerWarningText(AValue: String);
function GetMacroListViewerWarningChanged: TNotifyProcedure;
procedure SetMacroListViewerWarningChanged(AValue: TNotifyProcedure);
property MacroListViewerWarningText: string read GetMacroListViewerWarningText write SetMacroListViewerWarningText;
property MacroListViewerWarningChanged: TNotifyProcedure read GetMacroListViewerWarningChanged write SetMacroListViewerWarningChanged;
type
{ TIDEInteractiveStringValue }
TIDEInteractiveStringValue = class(TPersistent)
private
FValue: string;
published
property Value: string read FValue write FValue;
end;
{ TIDETemplateParser }
TIDETemplateParser = class
protected
function GetSrcPosition: Integer; virtual; abstract;
function GetDestPosition: Integer; virtual; abstract;
function GetDestPosX: Integer; virtual; abstract;
function GetDestPosY: Integer; virtual; abstract;
function GetSrcTemplate: String; virtual; abstract;
function GetDestTemplate: String; virtual; abstract;
public
property SrcTemplate: String read GetSrcTemplate;
property DestTemplate: String read GetDestTemplate;
property SrcPosition: Integer read GetSrcPosition;
property DestPosition: Integer read GetDestPosition;
property DestPosX: Integer read GetDestPosX; // logical, byte position
property DestPosY: Integer read GetDestPosY;
end;
{ TIDECodeMacro - templates for sources, invoked by Ctrl-j }
TIDECodeMacroGetValueProc = function(const Parameter: string;
InteractiveValue: TPersistent;
SrcEdit: TSourceEditorInterface;
var Value, ErrorMsg: string): boolean;
TIDECodeMacroGetValueMethod = function(const Parameter: string;
InteractiveValue: TPersistent;
SrcEdit: TSourceEditorInterface;
var Value, ErrorMsg: string): boolean of object;
TIDECodeMacroGetValueExProc = function(const Parameter: string;
InteractiveValue: TPersistent;
SrcEdit: TSourceEditorInterface;
var Value, ErrorMsg: string;
TemplateParser: TIDETemplateParser): boolean;
TIDECodeMacroGetValueExMethod = function(const Parameter: string;
InteractiveValue: TPersistent;
SrcEdit: TSourceEditorInterface;
var Value, ErrorMsg: string;
TemplateParser: TIDETemplateParser): boolean of object;
TIDECodeMacro = class
private
FInteractive: boolean;
FInteractiveValueClass: TPersistentClass;
FLongDescription: string;
FName: string;
FOnGetValueMethod: TIDECodeMacroGetValueMethod;
FOnGetValueProc: TIDECodeMacroGetValueProc;
FOnGetValueExMethod: TIDECodeMacroGetValueExMethod;
FOnGetValueExProc: TIDECodeMacroGetValueExProc;
FShortDescription: string;
protected
procedure Init; virtual;
public
constructor Create(const TheName: string);
property Name: string read FName;
property ShortDescription: string read FShortDescription write FShortDescription;
property LongDescription: string read FLongDescription write FLongDescription;
property OnGetValueProc: TIDECodeMacroGetValueProc read FOnGetValueProc
write FOnGetValueProc;
property OnGetValueMethod: TIDECodeMacroGetValueMethod read FOnGetValueMethod
write FOnGetValueMethod;
property OnGetValueExProc: TIDECodeMacroGetValueExProc read FOnGetValueExProc
write FOnGetValueExProc;
property OnGetValueExMethod: TIDECodeMacroGetValueExMethod read FOnGetValueExMethod
write FOnGetValueExMethod;
function GetValue(const Parameter: string; InteractiveValue: TPersistent;
SrcEdit: TSourceEditorInterface; out Value, ErrorMsg: string;
TemplateParser: TIDETemplateParser = nil): boolean; virtual;
property Interactive: boolean read FInteractive write FInteractive;
property InteractiveValueClass: TPersistentClass read FInteractiveValueClass
write FInteractiveValueClass;
end;
{ TIDECodeMacros }
TIDECodeMacros = class
protected
function GetItems(Index: integer): TIDECodeMacro; virtual; abstract;
public
property Items[Index: integer]: TIDECodeMacro read GetItems; default;
function Count: integer; virtual; abstract;
function Add(Macro: TIDECodeMacro): integer; virtual; abstract;
function FindByName(const AName: string): TIDECodeMacro; virtual; abstract;
function CreateUniqueName(const AName: string): string; virtual; abstract;
end;
var
IDECodeMacros: TIDECodeMacros = nil; // set by the IDE
function RegisterCodeMacro(const Name: string;
const ShortDescription, LongDescription: string;
OnGetValueProc: TIDECodeMacroGetValueProc;
OnGetValueMethod: TIDECodeMacroGetValueMethod): TIDECodeMacro;
function RegisterCodeMacroEx(const Name: string;
const ShortDescription, LongDescription: string;
OnGetValueProc: TIDECodeMacroGetValueExProc;
OnGetValueMethod: TIDECodeMacroGetValueExMethod): TIDECodeMacro;
{ SearchInFile to search in a file.
This can be interactively or without user interaction.
If the file is open in the source editor, changes will be added to the undo
history.
}
type
TIDESearchInTextAddMatch = procedure(const Filename: string;
const StartPos, EndPos: TPoint;
const Lines: string) of object;
{ TIDESearchInTextProgress }
TIDESearchInTextProgress = class
private
FAbort: boolean;
FOnAddMatch: TIDESearchInTextAddMatch;
protected
procedure SetAbort(const AValue: boolean); virtual;
public
property Abort: boolean read FAbort write SetAbort;
property OnAddMatch: TIDESearchInTextAddMatch read FOnAddMatch write FOnAddMatch;
end;
TIDESearchInTextFunction = function(const TheFileName: string;
var TheText: string;// if TheFileName='' then use TheText
SearchFor, ReplaceText: string; Flags: TSrcEditSearchOptions;
var Prompt: boolean; Progress: TIDESearchInTextProgress = nil): TModalResult;
TBookmarkNumRange = 0..9;
var
IDESearchInText: TIDESearchInTextFunction = nil;// set by the IDE
implementation
function RegisterCodeMacro(const Name: string; const ShortDescription,
LongDescription: string; OnGetValueProc: TIDECodeMacroGetValueProc;
OnGetValueMethod: TIDECodeMacroGetValueMethod): TIDECodeMacro;
var
NewName: String;
begin
NewName:=IDECodeMacros.CreateUniqueName(Name);
Result:=TIDECodeMacro.Create(NewName);
Result.ShortDescription:=LineBreaksToSystemLineBreaks(ShortDescription);
Result.LongDescription:=LineBreaksToSystemLineBreaks(LongDescription);
Result.OnGetValueProc:=OnGetValueProc;
Result.OnGetValueMethod:=OnGetValueMethod;
IDECodeMacros.Add(Result);
end;
function RegisterCodeMacroEx(const Name: string; const ShortDescription,
LongDescription: string; OnGetValueProc: TIDECodeMacroGetValueExProc;
OnGetValueMethod: TIDECodeMacroGetValueExMethod): TIDECodeMacro;
var
NewName: String;
begin
NewName:=IDECodeMacros.CreateUniqueName(Name);
Result:=TIDECodeMacro.Create(NewName);
Result.ShortDescription:=LineBreaksToSystemLineBreaks(ShortDescription);
Result.LongDescription:=LineBreaksToSystemLineBreaks(LongDescription);
Result.OnGetValueExProc:=OnGetValueProc;
Result.OnGetValueExMethod:=OnGetValueMethod;
IDECodeMacros.Add(Result);
end;
{ TEditorMacroKeyBinding }
function TEditorMacroKeyBinding.GetIdeCmd: TIDECommand;
begin
Result :=nil;
end;
procedure TEditorMacroKeyBinding.MacroNameChanged;
begin
//
end;
constructor TEditorMacroKeyBinding.Create(AOwner: TEditorMacro);
begin
FOwner := AOwner;
end;
function TEditorMacroKeyBinding.ShortCutAsText: String;
begin
Result := '';
end;
procedure TEditorMacro.CheckStateAndActivated;
begin
if (State = emStopped) then begin
if IsActivated then
UnsetActivated;
end
else
if not IsActivated then
SetActivated;
end;
function TEditorMacro.GetDefaultKeyBinding: TEditorMacroKeyBinding;
begin
Result := DefaultBindingClass.Create(Self);
end;
procedure TEditorMacro.SetMacroNameFull(AValue: String);
begin
SetMacroName(AValue);
if KeyBinding <> nil then
KeyBinding.MacroNameChanged;
end;
procedure TEditorMacro.SetOnChange(AValue: TNotifyEvent);
begin
if FOnChange=AValue then Exit;
FOnChange:=AValue;
end;
function TEditorMacro.GetErrorMsg: String;
begin
Result := '';
end;
procedure TEditorMacro.DoChanged;
begin
if Assigned(FOnChange) then
FOnChange(Self);
end;
procedure TEditorMacro.DoStateChanged;
begin
if Assigned(FOnStateChange) then
FOnStateChange(Self);
end;
procedure TEditorMacro.SetActivated;
begin
Assert(ActiveEditorMacro=nil, 'TEditorMacro.SetActivated: There already is an active Macro');
ActiveEditorMacro := self;
end;
procedure TEditorMacro.UnsetActivated;
begin
Assert(ActiveEditorMacro=self, 'TEditorMacro.SetActivated: This is not the active Macro');
ActiveEditorMacro := nil;
end;
function TEditorMacro.IsActivated: Boolean;
begin
Result := ActiveEditorMacro = self;
end;
procedure TEditorMacro.RecordMacro(aEditor: TWinControl);
begin
SetActivated;
DoRecordMacro(aEditor);
CheckStateAndActivated;
end;
procedure TEditorMacro.PlaybackMacro(aEditor: TWinControl);
begin
SetActivated;
DoPlaybackMacro(aEditor);
CheckStateAndActivated;
end;
procedure TEditorMacro.Stop;
begin
DoStop;
CheckStateAndActivated;
end;
procedure TEditorMacro.Pause;
begin
DoPause;
CheckStateAndActivated;
end;
procedure TEditorMacro.Resume;
begin
DoResume;
CheckStateAndActivated;
end;
var
FMacroListViewerWarningText: String;
FMacroListViewerWarningChanged: TNotifyProcedure;
function GetMacroListViewerWarningText: String;
begin
Result := FMacroListViewerWarningText;
end;
procedure SetMacroListViewerWarningText(AValue: String);
begin
FMacroListViewerWarningText := AValue;
if FMacroListViewerWarningChanged <> nil then
FMacroListViewerWarningChanged(nil);
end;
function GetMacroListViewerWarningChanged: TNotifyProcedure;
begin
Result := FMacroListViewerWarningChanged;
end;
procedure SetMacroListViewerWarningChanged(AValue: TNotifyProcedure);
begin
FMacroListViewerWarningChanged := AValue;
if (FMacroListViewerWarningChanged <> nil) and
(FMacroListViewerWarningText <> '')
then
FMacroListViewerWarningChanged(nil);
end;
{ TEditorMacro }
{ TSourceEditorInterface }
procedure TSourceEditorInterface.SelectText(LineNum, CharStart, LineNum2,
CharEnd: Integer);
begin
SelectText(Point(CharStart,LineNum),Point(CharEnd,LineNum2));
end;
procedure TSourceEditorInterface.ReplaceText(const StartPos, EndPos: TPoint;
const NewText: string);
begin
BeginUpdate;
BeginUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditorInterface.ReplaceText'){$ENDIF};
try
SelectText(StartPos,EndPos);
CursorTextXY:=StartPos;
Selection:=NewText;
finally
EndUndoBlock{$IFDEF SynUndoDebugBeginEnd}('TSourceEditorInterface.ReplaceText'){$ENDIF};
EndUpdate;
end;
end;
{ TIDECodeMacro }
procedure TIDECodeMacro.Init;
begin
FInteractiveValueClass:=TIDEInteractiveStringValue;
end;
constructor TIDECodeMacro.Create(const TheName: string);
begin
FName:=TheName;
FShortDescription:=FName;
FLongDescription:=FName;
end;
function TIDECodeMacro.GetValue(const Parameter: string;
InteractiveValue: TPersistent; SrcEdit: TSourceEditorInterface;
out Value, ErrorMsg: string; TemplateParser: TIDETemplateParser = nil): boolean;
begin
Value:=Parameter;
ErrorMsg:='';
if Assigned(OnGetValueProc) then
Result:=OnGetValueProc(Parameter,InteractiveValue,SrcEdit,Value,ErrorMsg)
else if Assigned(OnGetValueMethod) then
Result:=OnGetValueMethod(Parameter,InteractiveValue,SrcEdit,Value,ErrorMsg)
else if Assigned(OnGetValueExProc) then
Result:=OnGetValueExProc(Parameter,InteractiveValue,SrcEdit,Value,ErrorMsg,
TemplateParser)
else if Assigned(OnGetValueExMethod) then
Result:=OnGetValueExMethod(Parameter,InteractiveValue,SrcEdit,Value,ErrorMsg,
TemplateParser)
else
Result:=true;
end;
{ TIDESearchInTextProgress }
procedure TIDESearchInTextProgress.SetAbort(const AValue: boolean);
begin
if FAbort=AValue then exit;
fAbort:=AValue;
end;
{ TSourceEditorCompletionPlugin }
function TSourceEditorCompletionPlugin.HasCustomPaint: boolean;
begin
Result:=false;
end;
procedure TSourceEditorCompletionPlugin.PaintItem(const AKey: string;
ACanvas: TCanvas; X, Y: integer; ItemSelected: boolean; Index: integer);
begin
// this is called if HasCustomPaint returns true
end;
function TSourceEditorCompletionPlugin.MeasureItem(const AKey: string;
ACanvas: TCanvas; ItemSelected: boolean; Index: integer): TPoint;
begin
// this is called if HasCustomPaint returns true
Result:=Point(0,0);
end;
{ TSourceEditorStatusPanelInterface }
procedure TSourceEditorStatusPanelInterface.SetOnDrawPanel(
AValue: TDrawSourceEditPanelEvent);
begin
if FOnDrawPanel = AValue then Exit;
FOnDrawPanel := AValue;
end;
constructor TSourceEditorStatusPanelInterface.Create(AnOwner: TClass;
ATag: PtrUInt);
begin
FOwner := AnOwner;
FTag := ATag;
inherited Create;
end;
{ TSourceMarkling }
constructor TSourceMarkling.Create(aProducer: TSourceMarklingProducer; TheID,
aLine, aColumn: integer; aType: TSourceMarklingType);
begin
FProducer:=aProducer;
FLine:=aLine;
FColumn:=aColumn;
FId:=TheID;
fType:=aType;
end;
{ TSourceMarklingProducer }
procedure TSourceMarklingProducer.InvalidateAllFiles;
begin
SourceEditorManagerIntf.InvalidateMarklingsOfAllFiles(Self);
end;
procedure TSourceMarklingProducer.InvalidateFile(aFilename: string);
begin
SourceEditorManagerIntf.InvalidateMarklings(Self,aFilename);
end;
end.