IdeIntf, IDE: Refactor command system. Separate menu and toolbar commands, update them in right place etc. Issue #28777, patch from Ondrej Pokorny.

git-svn-id: trunk@50026 -
This commit is contained in:
juha 2015-10-11 09:11:47 +00:00
parent e2a04877b0
commit 38878ad607
13 changed files with 1067 additions and 760 deletions

View File

@ -30,7 +30,8 @@ unit IDECommands;
interface
uses
Classes, SysUtils, LCLProc, Forms, LCLType, Menus, PropEdits;
Classes, SysUtils, LCLProc, Forms, LCLType, Menus, PropEdits, IDEImagesIntf,
ExtCtrls, LCLIntf;
const
{ editor commands constants. see syneditkeycmds.pp for more
@ -432,6 +433,8 @@ const
type
TIDECommand = class;
TIDECommandCategory = class;
TIDESpecialCommand = class;
TIDESpecialCommands = class;
TNotifyProcedure = procedure(Sender: TObject);
@ -512,6 +515,7 @@ type
destructor Destroy; override;
function ScopeIntersects(AScope: TIDECommandScope): boolean;
procedure WriteScopeDebugReport;
procedure DoOnUpdate;
public
property Name: string read FName;
property Description: string read FDescription write SetDescription;
@ -522,19 +526,25 @@ type
{ TIDECommand }
{ class for storing the keys of a single command
(shortcut-command relationship) }
{ class for storing the keys of a single command (shortcut-command relationship) }
TIDECommand = class
private
FCategory: TIDECommandCategory;
FCommand: word;
FLocalizedName: string;
FName: String;
FOnChange: TNotifyEvent;
FOnExecute: TNotifyEvent;
FOnExecuteProc: TNotifyProcedure;
FShortcutA: TIDEShortCut;
FShortcutB: TIDEShortCut;
FOnUpdateMethod: TNotifyEvent;
FOnUpdateProc: TNotifyProcedure;
FUsers: TIDESpecialCommands;
function GetUser(Index: Integer): TIDESpecialCommand;
function GetUserCount: Integer;
procedure SetOnExecute(const aOnExecute: TNotifyEvent);
procedure SetOnExecuteProc(const aOnExecuteProc: TNotifyProcedure);
protected
function GetLocalizedName: string; virtual;
procedure SetLocalizedName(const AValue: string); virtual;
@ -562,6 +572,10 @@ type
procedure ClearShortcutB;
function GetCategoryAndName: string;
function Execute(Sender: TObject): boolean;
procedure UserAdded(const aUser: TIDESpecialCommand);
procedure UserRemoved(const aUser: TIDESpecialCommand);
procedure DoOnUpdate; overload;
procedure DoOnUpdate(Sender: TObject); overload;
public
property Name: String read FName;
property Command: word read FCommand;// see the ecXXX constants above
@ -569,18 +583,30 @@ type
property Category: TIDECommandCategory read FCategory write SetCategory;
property ShortcutA: TIDEShortCut read FShortcutA write SetShortcutA;
property ShortcutB: TIDEShortCut read FShortcutB write SetShortcutB;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnExecute: TNotifyEvent read FOnExecute write FOnExecute;
property OnExecuteProc: TNotifyProcedure read FOnExecuteProc write FOnExecuteProc;
property OnExecute: TNotifyEvent read FOnExecute write SetOnExecute;
property OnExecuteProc: TNotifyProcedure read FOnExecuteProc write SetOnExecuteProc;
property OnUpdate: TNotifyEvent read FOnUpdateMethod write FOnUpdateMethod;
property OnUpdateProc: TNotifyProcedure read FOnUpdateProc write FOnUpdateProc;
property Users[Index: Integer]: TIDESpecialCommand read GetUser;
property UserCount: Integer read GetUserCount;
end;
{ TIDECommands }
TIDECommands = class
private
FCustomUpdateEvents: TMethodList;
FLateUpdateTimer: TTimer;
procedure FLateUpdateTimerTimer(Sender: TObject);
protected
function GetCategory(Index: integer): TIDECommandCategory; virtual; abstract;
public
constructor Create;
destructor Destroy; override;
function FindIDECommand(ACommand: word): TIDECommand; virtual; abstract;
function CreateCategory(Parent: TIDECommandCategory;
const Name, Description: string;
@ -596,10 +622,101 @@ type
function FindCommandsByShortCut(const ShortCutMask: TIDEShortCut;
IDEWindowClass: TCustomFormClass = nil): TFPList; virtual; abstract; // list of TIDECommand
function CategoryCount: integer; virtual; abstract;
public
procedure StartUpdateHandler;
procedure ExecuteUpdateEvents;
procedure LateExecuteUpdateEvents;
procedure AddCustomUpdateEvent(const aEvent: TNotifyEvent);
procedure RemoveCustomUpdateEvent(const aEvent: TNotifyEvent);
public
property Categories[Index: integer]: TIDECommandCategory read GetCategory;
end;
// MenuItem and ButtonCommand inherit from SpecialCommand.
TIDESpecialCommand = class(TPersistent)
private
FCommand: TIDECommand;
FName: string;
FCaption: string;
FEnabled: Boolean;
FChecked: Boolean;
FHint: string;
FImageIndex: Integer;
FOnClickMethod: TNotifyEvent;
FOnClickProc: TNotifyProcedure;
FVisible: Boolean;
protected
function GetCaption: string; virtual;
procedure SetCommand(const AValue: TIDECommand); virtual;
procedure SetName(const aName: string); virtual;
procedure SetCaption(aCaption: string); virtual;
procedure SetEnabled(const aEnabled: Boolean); virtual;
procedure SetChecked(const aChecked: Boolean); virtual;
procedure SetHint(const aHint: string); virtual;
procedure SetImageIndex(const aImageIndex: Integer); virtual;
procedure SetVisible(const aVisible: Boolean); virtual;
procedure SetOnClickMethod(const aOnClick: TNotifyEvent); virtual;
procedure SetOnClickProc(const aOnClickProc: TNotifyProcedure); virtual;
procedure SetResourceName(const aResourceName: string); virtual;
procedure ShortCutsUpdated(const {%H-}aShortCut, {%H-}aShortCutKey2: TShortCut); virtual;
public
constructor Create(const aName: string); virtual;
destructor Destroy; override;
public
procedure DoOnClick; overload;
procedure DoOnClick(Sender: TObject); virtual; overload;
public
function GetCaptionWithShortCut: String; virtual;
function GetHintOrCaptionWithShortCut: String; virtual;
function GetShortcut: String; virtual;
property Command: TIDECommand read FCommand write SetCommand;
property Name: string read FName write SetName;
property Caption: string read GetCaption write SetCaption;
property Hint: string read FHint write SetHint;
property Enabled: Boolean read FEnabled write SetEnabled;
property Checked: Boolean read FChecked write SetChecked;
property Visible: Boolean read FVisible write SetVisible;
property ImageIndex: Integer read FImageIndex write SetImageIndex;
property ResourceName: string write SetResourceName;
property OnClick: TNotifyEvent read FOnClickMethod write SetOnClickMethod;
property OnClickProc: TNotifyProcedure read FOnClickProc write SetOnClickProc;
end;
TIDESpecialCommandEnumerator = class
private
FList: TIDESpecialCommands;
FPosition: Integer;
public
constructor Create(AButtons: TIDESpecialCommands);
function GetCurrent: TIDESpecialCommand;
function MoveNext: Boolean;
property Current: TIDESpecialCommand read GetCurrent;
end;
TIDESpecialCommands = class
private
FList: TFPList;
function GetCount: Integer;
function GetItems(Index: Integer): TIDESpecialCommand;
public
constructor Create;
destructor Destroy; override;
public
function GetEnumerator: TIDESpecialCommandEnumerator;
procedure Add(const aUser: TIDESpecialCommand);
procedure Remove(const aUser: TIDESpecialCommand);
property Count: Integer read GetCount;
property Items[Index: Integer]: TIDESpecialCommand read GetItems; default;
end;
const
CleanIDEShortCut: TIDEShortCut =
(Key1: VK_UNKNOWN; Shift1: []; Key2: VK_UNKNOWN; Shift2: []);
@ -845,6 +962,70 @@ begin
IDECommandScopes.Add(Result);
end;
{ TIDECommands }
procedure TIDECommands.AddCustomUpdateEvent(const aEvent: TNotifyEvent);
begin
FCustomUpdateEvents.Add(TMethod(aEvent));
end;
constructor TIDECommands.Create;
begin
inherited Create;
FCustomUpdateEvents := TMethodList.Create;
//Updating the events needs a lot of CPU power, use TTimer for late updating
FLateUpdateTimer := TTimer.Create(nil);
FLateUpdateTimer.Interval := 800;
FLateUpdateTimer.OnTimer := @FLateUpdateTimerTimer;
FLateUpdateTimer.Enabled := False;
end;
destructor TIDECommands.Destroy;
begin
FLateUpdateTimer.Free;
FCustomUpdateEvents.Free;
inherited Destroy;
end;
procedure TIDECommands.ExecuteUpdateEvents;
var
i: Integer;
begin
if not Application.Active or
(ActivePopupMenu <> nil) or//no popup menus
(Application.ModalLevel > 0) or//no modal windows
not IsWindowEnabled(Application.MainForm.Handle)//main IDE must be enabled
then
Exit;
FCustomUpdateEvents.CallNotifyEvents(Self);
for i := 0 to CategoryCount-1 do
Categories[i].DoOnUpdate;
end;
procedure TIDECommands.FLateUpdateTimerTimer(Sender: TObject);
begin
ExecuteUpdateEvents;
end;
procedure TIDECommands.LateExecuteUpdateEvents;
begin
FLateUpdateTimer.Enabled := False;
FLateUpdateTimer.Enabled := True;
end;
procedure TIDECommands.RemoveCustomUpdateEvent(const aEvent: TNotifyEvent);
begin
FCustomUpdateEvents.Remove(TMethod(aEvent));
end;
procedure TIDECommands.StartUpdateHandler;
begin
FLateUpdateTimer.Enabled := True;
end;
{ TIDECommand }
procedure TIDECommand.SetShortcutA(const AValue: TIDEShortCut);
@ -863,9 +1044,25 @@ begin
Change;
end;
procedure TIDECommand.Change;
procedure TIDECommand.UserAdded(const aUser: TIDESpecialCommand);
begin
if Assigned(OnChange) then OnChange(Self);
FUsers.Add(aUser);
end;
procedure TIDECommand.UserRemoved(const aUser: TIDESpecialCommand);
begin
FUsers.Remove(aUser);
end;
procedure TIDECommand.Change;
var
xUser: TIDESpecialCommand;
begin
for xUser in FUsers do
begin
xUser.ShortCutsUpdated(KeyToShortCut(ShortcutA.Key1,ShortcutA.Shift1),
KeyToShortCut(ShortcutA.Key2,ShortcutA.Shift2));
end;
end;
procedure TIDECommand.Init;
@ -881,6 +1078,16 @@ begin
Result:=Name;
end;
function TIDECommand.GetUser(Index: Integer): TIDESpecialCommand;
begin
Result := FUsers[Index];
end;
function TIDECommand.GetUserCount: Integer;
begin
Result := FUsers.Count;
end;
procedure TIDECommand.SetLocalizedName(const AValue: string);
begin
if FLocalizedName=AValue then exit;
@ -889,6 +1096,26 @@ begin
Change;
end;
procedure TIDECommand.SetOnExecute(const aOnExecute: TNotifyEvent);
var
xUser: TIDESpecialCommand;
begin
if FOnExecute = aOnExecute then Exit;
FOnExecute := aOnExecute;
for xUser in FUsers do
xUser.OnClick := FOnExecute;
end;
procedure TIDECommand.SetOnExecuteProc(const aOnExecuteProc: TNotifyProcedure);
var
xUser: TIDESpecialCommand;
begin
if FOnExecuteProc = aOnExecuteProc then Exit;
FOnExecuteProc := aOnExecuteProc;
for xUser in FUsers do
xUser.OnClickProc := FOnExecuteProc;
end;
procedure TIDECommand.SetCategory(const AValue: TIDECommandCategory);
begin
if FCategory=AValue then exit;
@ -928,6 +1155,7 @@ constructor TIDECommand.Create(TheCategory: TIDECommandCategory;
const ExecuteMethod: TNotifyEvent;
const ExecuteProc: TNotifyProcedure);
begin
FUsers:=TIDESpecialCommands.Create;
fCommand:=TheCommand;
fName:=TheName;
FLocalizedName:=TheLocalizedName;
@ -951,21 +1179,29 @@ end;
constructor TIDECommand.Create(ACommand: TIDECommand; ACategory: TIDECommandCategory);
begin
fCommand:=ACommand.Command;
fName:=ACommand.Name;
FLocalizedName:=ACommand.LocalizedName;
fShortcutA:=ACommand.ShortcutA;
fShortcutB:=ACommand.ShortcutB;
DefaultShortcutA:=ACommand.ShortcutA;
DefaultShortcutB:=ACommand.ShortcutB;
Category:=ACategory;
Create(ACategory, ACommand.Name, ACommand.LocalizedName, ACommand.Command,
ACommand.ShortcutA, ACommand.ShortcutB, ACommand.OnExecute, ACommand.OnExecuteProc);
end;
destructor TIDECommand.Destroy;
begin
FUsers.Free;
inherited Destroy;
end;
procedure TIDECommand.DoOnUpdate(Sender: TObject);
begin
if Assigned(FOnUpdateProc) then
FOnUpdateProc(Sender);
if Assigned(FOnUpdateMethod) then
FOnUpdateMethod(Sender);
end;
procedure TIDECommand.DoOnUpdate;
begin
DoOnUpdate(Self);
end;
procedure TIDECommand.Assign(ACommand: TIDECommand);
begin
if IsEqual(ACommand) then exit;
@ -1011,6 +1247,268 @@ begin
end;
end;
{ TIDESpecialCommand }
constructor TIDESpecialCommand.Create(const aName: string);
begin
inherited Create;
FName := aName;
FEnabled:=true;
FVisible:=true;
FImageIndex:=-1;
end;
destructor TIDESpecialCommand.Destroy;
begin
if Assigned(FCommand) then
FCommand.UserRemoved(Self);
inherited Destroy;
end;
procedure TIDESpecialCommand.DoOnClick(Sender: TObject);
begin
if Assigned(FOnClickProc) then
FOnClickProc(Self)
else
if Assigned(FOnClickMethod) then
FOnClickMethod(Self);
end;
procedure TIDESpecialCommand.DoOnClick;
begin
DoOnClick(Self);
end;
function TIDESpecialCommand.GetCaption: string;
begin
if FCaption<>'' then
Result:=FCaption
else
Result:=FName;
end;
function TIDESpecialCommand.GetCaptionWithShortCut: String;
begin
Result := Caption;
DeleteAmpersands(Result);
Result := Result + GetShortcut;
end;
function TIDESpecialCommand.GetHintOrCaptionWithShortCut: String;
begin
if Hint <> '' then
Result := Hint
else
Result := Caption;
DeleteAmpersands(Result);
Result := Result + GetShortcut;
end;
function TIDESpecialCommand.GetShortcut: String;
begin
Result := '';
if Assigned(FCommand) then
Result := ShortCutToText(FCommand.AsShortCut);
if Result <> '' then
Result := ' (' + Result + ')';
end;
procedure TIDESpecialCommand.SetCaption(aCaption: string);
var
xUser: TIDESpecialCommand;
begin
if FCaption=aCaption then Exit;
FCaption := aCaption;
if FCommand<> nil then
for xUser in FCommand.FUsers do
if xUser <> Self then
xUser.Caption:=aCaption;
end;
procedure TIDESpecialCommand.SetChecked(const aChecked: Boolean);
var
xUser: TIDESpecialCommand;
begin
if FChecked=aChecked then Exit;
FChecked := aChecked;
if FCommand<> nil then
for xUser in FCommand.FUsers do
if xUser <> Self then
xUser.Checked:=aChecked;
end;
procedure TIDESpecialCommand.SetCommand(const AValue: TIDECommand);
begin
if FCommand = AValue then
Exit;
if FCommand <> nil then
begin
//DebugLn('TIDEMenuCommand.SetCommand OLD ',ShortCutToText(FCommand.AsShortCut),' FCommand.Name=',FCommand.Name,' Name=',Name,' FCommand=',dbgs(Pointer(FCommand)));
if FCommand.OnExecute=OnClick then
FCommand.OnExecute:=nil;
if FCommand.OnExecuteProc=OnClickProc then
FCommand.OnExecuteProc:=nil;
end;
FCommand := AValue;
if FCommand <> nil then
begin
if FCommand.OnExecute = nil then
FCommand.OnExecute := OnClick;
if FCommand.OnExecuteProc = nil then
FCommand.OnExecuteProc := OnClickProc;
//DebugLn('TIDEMenuCommand.SetCommand NEW ',ShortCutToText(FCommand.AsShortCut),' FCommand.Name=',FCommand.Name,' Name=',Name,' FCommand=',dbgs(Pointer(FCommand)));
FCommand.Change;
FCommand.UserAdded(Self);
end;
end;
procedure TIDESpecialCommand.SetEnabled(const aEnabled: Boolean);
var
xUser: TIDESpecialCommand;
begin
if FEnabled=aEnabled then Exit;
FEnabled := aEnabled;
if FCommand<> nil then
for xUser in FCommand.FUsers do
if xUser <> Self then
xUser.Enabled:=aEnabled;
end;
procedure TIDESpecialCommand.SetHint(const aHint: string);
var
xUser: TIDESpecialCommand;
begin
if FHint=aHint then Exit;
FHint := aHint;
if FCommand<> nil then
for xUser in FCommand.FUsers do
if xUser <> Self then
xUser.Hint:=aHint;
end;
procedure TIDESpecialCommand.SetImageIndex(const aImageIndex: Integer);
var
xUser: TIDESpecialCommand;
begin
if FImageIndex=aImageIndex then Exit;
FImageIndex := aImageIndex;
if FCommand<> nil then
for xUser in FCommand.FUsers do
if xUser <> Self then
xUser.ImageIndex:=aImageIndex;
end;
procedure TIDESpecialCommand.SetName(const aName: string);
begin
FName := aName;
end;
procedure TIDESpecialCommand.SetOnClickMethod(const aOnClick: TNotifyEvent);
begin
if FOnClickMethod = aOnClick then Exit;
FOnClickMethod := aOnClick;
if FCommand<> nil then
FCommand.OnExecute:=aOnClick;
end;
procedure TIDESpecialCommand.SetOnClickProc(const aOnClickProc: TNotifyProcedure);
begin
if FOnClickProc = aOnClickProc then Exit;
FOnClickProc := aOnClickProc;
if FCommand<> nil then
FCommand.OnExecuteProc:=aOnClickProc;
end;
procedure TIDESpecialCommand.SetResourceName(const aResourceName: string);
begin
if aResourceName <> '' then
ImageIndex := IDEImages.LoadImage(16, aResourceName)
else
ImageIndex := -1;
end;
procedure TIDESpecialCommand.ShortCutsUpdated(const aShortCut,
aShortCutKey2: TShortCut);
begin
//nothing here, override in descendants
end;
procedure TIDESpecialCommand.SetVisible(const aVisible: Boolean);
var
xUser: TIDESpecialCommand;
begin
if FVisible=aVisible then Exit;
FVisible := aVisible;
if FCommand<> nil then
for xUser in FCommand.FUsers do
if xUser <> Self then
xUser.Visible:=aVisible;
end;
{ TIDESpecialCommandEnumerator }
constructor TIDESpecialCommandEnumerator.Create(AButtons: TIDESpecialCommands);
begin
inherited Create;
FList := AButtons;
FPosition := -1;
end;
function TIDESpecialCommandEnumerator.GetCurrent: TIDESpecialCommand;
begin
Result := TIDESpecialCommand(FList[FPosition]);
end;
function TIDESpecialCommandEnumerator.MoveNext: Boolean;
begin
Inc(FPosition);
Result := FPosition < FList.Count;
end;
{ TIDESpecialCommands }
procedure TIDESpecialCommands.Add(const aUser: TIDESpecialCommand);
begin
FList.Add(aUser);
end;
constructor TIDESpecialCommands.Create;
begin
inherited Create;
FList := TFPList.Create;
end;
destructor TIDESpecialCommands.Destroy;
var
I: Integer;
begin
for I := 0 to Count-1 do
Items[I].FCommand := nil;
FList.Free;
inherited Destroy;
end;
function TIDESpecialCommands.GetCount: Integer;
begin
Result := FList.Count;
end;
function TIDESpecialCommands.GetEnumerator: TIDESpecialCommandEnumerator;
begin
Result := TIDESpecialCommandEnumerator.Create(Self);
end;
function TIDESpecialCommands.GetItems(Index: Integer): TIDESpecialCommand;
begin
Result := TIDESpecialCommand(FList[Index]);
end;
procedure TIDESpecialCommands.Remove(const aUser: TIDESpecialCommand);
begin
FList.Remove(aUser);
end;
{ TIDECommandScopes }
function TIDECommandScopes.GetItems(Index: integer): TIDECommandScope;
@ -1105,6 +1603,14 @@ begin
inherited Destroy;
end;
procedure TIDECommandCategory.DoOnUpdate;
var
i: Integer;
begin
for i := 0 to Count-1 do
TIDECommand(Items[i]).DoOnUpdate;
end;
function TIDECommandCategory.ScopeIntersects(AScope: TIDECommandScope): boolean;
begin
if (Scope=nil) or (AScope=nil) then

View File

@ -2,6 +2,7 @@
<CONFIG>
<Package Version="4">
<Name Value="IDEIntf"/>
<Type Value="RunAndDesignTime"/>
<Author Value="Lazarus"/>
<CompilerOptions>
<Version Value="11"/>
@ -19,7 +20,7 @@
<Description Value="IDEIntf - the interface units for the Lazarus IDE"/>
<License Value="Modified LPGL2"/>
<Version Major="1"/>
<Files Count="77">
<Files Count="78">
<Item1>
<Filename Value="actionseditor.pas"/>
<UnitName Value="ActionsEditor"/>
@ -243,7 +244,7 @@
</Item55>
<Item56>
<Filename Value="newfield.pas"/>
<UnitName Value="newfield"/>
<UnitName Value="NewField"/>
</Item56>
<Item57>
<Filename Value="newfield.lfm"/>
@ -323,19 +324,22 @@
</Item75>
<Item76>
<Filename Value="projpackintf.pas"/>
<UnitName Value="projpackintf"/>
<UnitName Value="ProjPackIntf"/>
</Item76>
<Item77>
<Filename Value="dbgridcolumnspropeditform.pas"/>
<UnitName Value="DBGridColumnsPropEditForm"/>
</Item77>
<Item78>
<Filename Value="toolbarintf.pas"/>
<UnitName Value="ToolBarIntf"/>
</Item78>
</Files>
<LazDoc Paths="docs"/>
<i18n>
<EnableI18N Value="True"/>
<OutDir Value="languages"/>
</i18n>
<Type Value="RunAndDesignTime"/>
<RequiredPkgs Count="1">
<Item1>
<PackageName Value="LazControls"/>

View File

@ -15,12 +15,12 @@ uses
IDECommands, IDEDialogs, IDEExternToolIntf, IDEHelpIntf, IDEImagesIntf,
IDEMsgIntf, IDEOptionsIntf, IDETextConverter, IDEUtils, IDEWindowIntf,
ImageListEditor, KeyValPropEditDlg, LazIDEIntf, LazStringGridEdit,
ListViewPropEdit, MacroDefIntf, MacroIntf, MaskPropEdit, MenuIntf, newfield,
ListViewPropEdit, MacroDefIntf, MacroIntf, MaskPropEdit, MenuIntf, NewField,
NewItemIntf, ObjectInspector, ObjInspStrConsts, OIFavoriteProperties,
PackageIntf, ProjectIntf, ProjectResourcesIntf, PropEdits, PropEditUtils,
SrcEditorIntf, StatusBarPropEdit, StringsPropEditDlg, TextTools,
TreeViewPropEdit, UnitResources, ProjPackIntf, DBGridColumnsPropEditForm,
LazarusPackageIntf;
ToolBarIntf, LazarusPackageIntf;
implementation

View File

@ -18,7 +18,7 @@ unit MenuIntf;
interface
uses
Classes, SysUtils, LCLType, LCLProc, Menus, ComCtrls, ImgList, Graphics,
Classes, SysUtils, LCLType, LCLProc, Menus, ImgList, Graphics,
IDECommands, IDEImagesIntf;
type
@ -36,49 +36,37 @@ type
{ TIDEMenuItem }
TIDEMenuItem = class(TPersistent)
TIDEMenuItem = class(TIDESpecialCommand)
private
FAutoFreeMenuItem: boolean;
FBitmap: TBitmap;
FCaption: string;
FEnabled: Boolean;
FHint: string;
FImageIndex: Integer;
FMenuItem: TMenuItem;
FMenuItemClass: TMenuItemClass;
FName: string;
FOnClickMethod: TNotifyEvent;
FOnClickProc: TNotifyProcedure;
FResourceName: String;
FSection: TIDEMenuSection;
FSectionIndex: Integer;
FSize: integer;
FTag: Integer;
FUserTag: PtrUInt;
FVisible: Boolean;
FLastVisibleActive: boolean;
procedure MenuItemDestroy(Sender: TObject);
procedure BitmapChange(Sender: TObject);
protected
procedure SetCommand(const AValue: TIDECommand); override;
procedure MenuItemClick(Sender: TObject); virtual;
function GetBitmap: TBitmap; virtual;
function GetCaption: string; virtual;
function GetHint: String; virtual;
procedure SetBitmap(const AValue: TBitmap); virtual;
procedure SetCaption(const AValue: string); virtual;
procedure SetEnabled(const AValue: Boolean); virtual;
procedure SetHint(const AValue: String); virtual;
procedure SetImageIndex(const AValue: Integer); virtual;
procedure SetCaption(AValue: string); override;
procedure SetEnabled(const AValue: Boolean); override;
procedure SetChecked(const AValue: Boolean); override;
procedure SetHint(const AValue: String); override;
procedure SetImageIndex(const AValue: Integer); override;
procedure SetMenuItem(const AValue: TMenuItem); virtual;
procedure SetName(const AValue: string); virtual;
procedure SetOnClickMethod(const AValue: TNotifyEvent); virtual;
procedure SetOnClickProc(const AValue: TNotifyProcedure); virtual;
procedure SetResourceName(const AValue: String); virtual;
procedure SetSection(const AValue: TIDEMenuSection); virtual;
procedure SetVisible(const AValue: Boolean); virtual;
procedure SetVisible(const AValue: Boolean); override;
procedure ClearMenuItems; virtual;
procedure ShortCutsUpdated(const aShortCut, aShortCutKey2: TShortCut); override;
public
constructor Create(const TheName: string); virtual;
constructor Create(const TheName: string); override;
destructor Destroy; override;
function GetImageList: TCustomImageList; virtual;
function HasBitmap: Boolean;
@ -93,41 +81,17 @@ type
procedure WriteDebugReport(const Prefix: string;
MenuItemDebugReport: boolean); virtual;
procedure ConsistencyCheck; virtual;
procedure TriggerClick;
public
property Name: string read FName write SetName;
property Bitmap: TBitmap read GetBitmap write SetBitmap;
property Hint: String read GetHint write SetHint;
property ImageIndex: Integer read FImageIndex write SetImageIndex;
property Visible: Boolean read FVisible write SetVisible;
property OnClick: TNotifyEvent read FOnClickMethod write SetOnClickMethod;
property OnClickProc: TNotifyProcedure read FOnClickProc write SetOnClickProc;
property Caption: string read GetCaption write SetCaption;
property Section: TIDEMenuSection read FSection write SetSection;
property Enabled: Boolean read FEnabled write SetEnabled;
property MenuItem: TMenuItem read FMenuItem write SetMenuItem;
property MenuItemClass: TMenuItemClass read FMenuItemClass write FMenuItemClass;
property SectionIndex: Integer read FSectionIndex;
property AutoFreeMenuItem: boolean read FAutoFreeMenuItem write FAutoFreeMenuItem;
property ResourceName: String read FResourceName write SetResourceName;
property Tag: Integer read FTag write FTag;
property UserTag: PtrUInt read FUserTag write FUserTag;
end;
TIDEMenuItemClass = class of TIDEMenuItem;
{ TIDEToolButton }
TIDEToolButton = class(TToolButton)
private
FMenuItem: TIDEMenuItem;
protected
procedure DoOnAdded; virtual;
public
procedure Click; override;
property IdeMenuItem: TIDEMenuItem read FMenuItem write FMenuItem;
end;
TIDEToolButtonClass = class of TIDEToolButton;
{ TIDEMenuSection
An TIDEMenuItem with children, either in a sub menu or separated with
@ -224,36 +188,6 @@ type
end;
TIDEMenuSectionClass = class of TIDEMenuSection;
TIDEMenuCommandButtons = class;
TIDEMenuCommandButtonsEnumerator = class
private
FList: TIDEMenuCommandButtons;
FPosition: Integer;
public
constructor Create(AButtons: TIDEMenuCommandButtons);
function GetCurrent: TIDEToolButton;
function MoveNext: Boolean;
property Current: TIDEToolButton read GetCurrent;
end;
TIDEMenuCommandButtons = class(TComponent)
private
FList: TFPList;
function GetCount: Integer;
function GetItems(Index: Integer): TIDEToolButton;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
public
function GetEnumerator: TIDEMenuCommandButtonsEnumerator;
procedure Add(const aBtn: TIDEToolButton);
property Count: Integer read GetCount;
property Items[Index: Integer]: TIDEToolButton read GetItems; default;
end;
{ TIDEMenuCommand
A leaf menu item. No children.
Hint: The shortcut is defined via the Command property.
@ -261,54 +195,30 @@ type
TIDEMenuCommand = class(TIDEMenuItem)
private
FAutoCheck: boolean;
FChecked: Boolean;
FCommand: TIDECommand;
FDefault: Boolean;
FGroupIndex: Byte;
FRadioItem: Boolean;
FRightJustify: boolean;
FShowAlwaysCheckable: boolean;
FToolButtonClass: TIDEToolButtonClass;
FToolButtons: TIDEMenuCommandButtons;
protected
procedure MenuItemClick(Sender: TObject); override;
procedure SetAutoCheck(const AValue: boolean); virtual;
procedure SetChecked(const AValue: Boolean); virtual;
procedure SetDefault(const AValue: Boolean); virtual;
procedure SetGroupIndex(const AValue: Byte); virtual;
procedure SetRadioItem(const AValue: Boolean); virtual;
procedure SetRightJustify(const AValue: boolean); virtual;
procedure SetShowAlwaysCheckable(const AValue: boolean); virtual;
procedure SetCommand(const AValue: TIDECommand); virtual;
procedure SetMenuItem(const AValue: TMenuItem); override;
procedure SetOnClickMethod(const AValue: TNotifyEvent); override;
procedure SetOnClickProc(const AValue: TNotifyProcedure); override;
procedure SetCaption(const AValue: string); override;
procedure SetEnabled(const AValue: Boolean); override;
procedure SetHint(const AValue: String); override;
procedure SetImageIndex(const AValue: Integer); override;
procedure SetResourceName(const AValue: String); override;
procedure SetVisible(const AValue: Boolean); override;
procedure CommandChanged(Sender: TObject);
public
constructor Create(const TheName: string); override;
destructor Destroy; override;
public
procedure ToolButtonAdded(const aBtn: TIDEToolButton);
public
property Command: TIDECommand read FCommand write SetCommand;
property AutoCheck: boolean read FAutoCheck write SetAutoCheck default False;
property Checked: Boolean read FChecked write SetChecked default False;
property Default: Boolean read FDefault write SetDefault default False;
property GroupIndex: Byte read FGroupIndex write SetGroupIndex default 0;
property RadioItem: Boolean read FRadioItem write SetRadioItem;
property RightJustify: boolean read FRightJustify write SetRightJustify;
property ShowAlwaysCheckable: boolean read FShowAlwaysCheckable
write SetShowAlwaysCheckable;
property ToolButtonClass: TIDEToolButtonClass read FToolButtonClass write FToolButtonClass;
property ToolButtons: TIDEMenuCommandButtons read FToolButtons;
end;
TIDEMenuCommandClass = class of TIDEMenuCommand;
@ -629,94 +539,6 @@ begin
OnClickMethod, OnClickProc, Command, ResourceName, UserTag);
end;
{ TIDEMenuCommandButtonsEnumerator }
constructor TIDEMenuCommandButtonsEnumerator.Create(
AButtons: TIDEMenuCommandButtons);
begin
inherited Create;
FList := AButtons;
FPosition := -1;
end;
function TIDEMenuCommandButtonsEnumerator.GetCurrent: TIDEToolButton;
begin
Result := FList[FPosition];
end;
function TIDEMenuCommandButtonsEnumerator.MoveNext: Boolean;
begin
Inc(FPosition);
Result := FPosition < FList.Count;
end;
{ TIDEMenuCommandButtons }
procedure TIDEMenuCommandButtons.Add(const aBtn: TIDEToolButton);
begin
FList.Add(aBtn);
aBtn.FreeNotification(Self);
end;
constructor TIDEMenuCommandButtons.Create(aOwner: TComponent);
begin
inherited Create(aOwner);
FList := TFPList.Create;
end;
destructor TIDEMenuCommandButtons.Destroy;
var
I: Integer;
begin
for I := 0 to Count-1 do
Items[I].RemoveFreeNotification(Self);
FList.Free;
inherited Destroy;
end;
function TIDEMenuCommandButtons.GetCount: Integer;
begin
Result := FList.Count;
end;
function TIDEMenuCommandButtons.GetEnumerator: TIDEMenuCommandButtonsEnumerator;
begin
Result := TIDEMenuCommandButtonsEnumerator.Create(Self);
end;
function TIDEMenuCommandButtons.GetItems(Index: Integer): TIDEToolButton;
begin
Result := TIDEToolButton(FList[Index]);
end;
procedure TIDEMenuCommandButtons.Notification(AComponent: TComponent;
Operation: TOperation);
var
xIndex: Integer;
begin
inherited Notification(AComponent, Operation);
if (Operation = opRemove) then
begin
xIndex := FList.IndexOf(AComponent);
if xIndex >= 0 then
FList.Delete(xIndex);
end;
end;
{ TIDEToolButton }
procedure TIDEToolButton.Click;
begin
inherited Click;
if assigned(FMenuItem) then
FMenuItem.TriggerClick;
end;
procedure TIDEToolButton.DoOnAdded;
begin
end;
{ TIDEMenuItem }
procedure TIDEMenuItem.MenuItemClick(Sender: TObject);
@ -736,31 +558,10 @@ begin
if MenuItem<>nil then MenuItem.Bitmap:=Bitmap;
end;
procedure TIDEMenuItem.SetOnClickProc(const AValue: TNotifyProcedure);
begin
FOnClickProc := AValue;
end;
procedure TIDEMenuItem.SetResourceName(const AValue: String);
begin
if FResourceName = AValue then exit;
FResourceName := AValue;
if MenuItem <> nil then
if AValue <> '' then
MenuItem.ImageIndex := IDEImages.LoadImage(16, FResourceName)
else
MenuItem.ImageIndex := -1;
end;
procedure TIDEMenuItem.SetOnClickMethod(const AValue: TNotifyEvent);
begin
FOnClickMethod := AValue;
end;
procedure TIDEMenuItem.SetEnabled(const AValue: Boolean);
begin
if FEnabled=AValue then exit;
FEnabled:=AValue;
if Enabled=AValue then exit;
inherited SetEnabled(AValue);
if MenuItem<>nil then
MenuItem.Enabled:=Enabled;
end;
@ -775,19 +576,6 @@ begin
Result:=FBitmap;
end;
function TIDEMenuItem.GetCaption: string;
begin
if FCaption<>'' then
Result:=FCaption
else
Result:=FName;
end;
function TIDEMenuItem.GetHint: String;
begin
Result:=FHint;
end;
procedure TIDEMenuItem.SetBitmap(const AValue: TBitmap);
begin
if FBitmap=AValue then exit;
@ -799,24 +587,53 @@ begin
MenuItem.Bitmap:=FBitmap;
end;
procedure TIDEMenuItem.SetCaption(const AValue: string);
procedure TIDEMenuItem.SetCaption(AValue: string);
begin
FCaption:=AValue;
if Caption=AValue then Exit;
inherited SetCaption(AValue);
if MenuItem<>nil then
MenuItem.Caption:=Caption;
end;
procedure TIDEMenuItem.SetChecked(const AValue: Boolean);
begin
if Checked=AValue then exit;
inherited SetChecked(AValue);
if MenuItem<>nil then
MenuItem.Checked:=Checked;
end;
procedure TIDEMenuItem.SetCommand(const AValue: TIDECommand);
var
I: Integer;
xUser: TIDESpecialCommand;
begin
inherited SetCommand(AValue);
//copy properties to other command users
if AValue<>nil then
for I := 0 to AValue.UserCount-1 do
if AValue.Users[I] <> Self then
begin
xUser:=AValue.Users[I];
xUser.Caption:=Caption;
xUser.Hint:=Hint;
xUser.ImageIndex:=ImageIndex;
xUser.Enabled:=Enabled;
end;
end;
procedure TIDEMenuItem.SetHint(const AValue: String);
begin
FHint:=AValue;
if Hint=AValue then Exit;
inherited SetHint(AValue);
if MenuItem<>nil then
MenuItem.Hint:=Hint;
end;
procedure TIDEMenuItem.SetImageIndex(const AValue: Integer);
begin
if FImageIndex=AValue then exit;
FImageIndex:=AValue;
if ImageIndex=AValue then exit;
inherited SetImageIndex(AValue);
if MenuItem<>nil then
MenuItem.ImageIndex:=ImageIndex;
end;
@ -837,18 +654,11 @@ begin
MenuItem.Visible := Visible;
MenuItem.Enabled := Enabled;
MenuItem.OnClick := @MenuItemClick;
if ResourceName <> '' then
MenuItem.ImageIndex := IDEImages.LoadImage(16, ResourceName);
MenuItem.ImageIndex := ImageIndex;
end else if Section<>nil then
Section.Invalidate(SectionIndex,SectionIndex);
end;
procedure TIDEMenuItem.SetName(const AValue: string);
begin
if FName=AValue then exit;
FName:=AValue;
end;
procedure TIDEMenuItem.SetSection(const AValue: TIDEMenuSection);
var
OldSection: TIDEMenuSection;
@ -867,15 +677,26 @@ procedure TIDEMenuItem.SetVisible(const AValue: Boolean);
var
OldVisibleActive: Boolean;
begin
if FVisible=AValue then exit;
if Visible=AValue then exit;
OldVisibleActive:=VisibleActive;
FVisible:=AValue;
inherited SetVisible(AValue);
if MenuItem<>nil then
MenuItem.Visible:=Visible;
if (VisibleActive<>OldVisibleActive) and (Section<>nil) then
Section.ItemVisibleActiveChanged(Self);
end;
procedure TIDEMenuItem.ShortCutsUpdated(const aShortCut,
aShortCutKey2: TShortCut);
begin
inherited ShortCutsUpdated(aShortCut, aShortCutKey2);
if MenuItem<>nil then
begin
MenuItem.ShortCut:=aShortCut;
MenuItem.ShortCutKey2:=aShortCutKey2;
end;
end;
procedure TIDEMenuItem.ClearMenuItems;
begin
if FMenuItem <> nil then begin
@ -893,14 +714,10 @@ end;
constructor TIDEMenuItem.Create(const TheName: string);
begin
inherited Create;
inherited Create(TheName);
FSize:=1;
FName:=TheName;
FEnabled:=true;
FVisible:=true;
FMenuItemClass:=TMenuItem;
FSectionIndex:=-1;
FImageIndex:=-1;
{$IFDEF VerboseMenuIntf}
//debugln('TIDEMenuItem.Create ',dbgsName(Self),' Name="',Name,'"');
{$ENDIF}
@ -1076,11 +893,6 @@ begin
end;
end;
procedure TIDEMenuItem.TriggerClick;
begin
MenuItemClick(Self);
end;
{ TIDEMenuSection }
procedure TIDEMenuSection.SetSubMenuImages(const AValue: TCustomImageList);
@ -1516,7 +1328,7 @@ end;
procedure TIDEMenuSection.Insert(Index: Integer; AnItem: TIDEMenuItem);
begin
AnItem.fName:=CreateUniqueName(AnItem.Name);
AnItem.Name:=CreateUniqueName(AnItem.Name);
FItems.Insert(Index,AnItem);
UpdateChildsIndex(Index);
UpdateSize(AnItem.Size);
@ -1781,33 +1593,6 @@ end;
{ TIDEMenuCommand }
procedure TIDEMenuCommand.CommandChanged(Sender: TObject);
begin
//DebugLn('TIDEMenuCommand.CommandChanged ',Name);
if MenuItem<>nil then
if FCommand<>nil then begin
MenuItem.ShortCut:=KeyToShortCut(FCommand.ShortcutA.Key1,FCommand.ShortcutA.Shift1);
MenuItem.ShortCutKey2:=KeyToShortCut(FCommand.ShortcutA.Key2,FCommand.ShortcutA.Shift2);
end
else begin
MenuItem.ShortCut:=0;
MenuItem.ShortCutKey2:=0;
end;
end;
constructor TIDEMenuCommand.Create(const TheName: string);
begin
inherited Create(TheName);
FToolButtonClass := TIDEToolButton;
FToolButtons := TIDEMenuCommandButtons.Create(nil);
end;
destructor TIDEMenuCommand.Destroy;
begin
FToolButtons.Free;
inherited Destroy;
end;
procedure TIDEMenuCommand.MenuItemClick(Sender: TObject);
begin
inherited MenuItemClick(Sender);
@ -1825,22 +1610,6 @@ begin
if MenuItem<>nil then MenuItem.AutoCheck:=AutoCheck;
end;
procedure TIDEMenuCommand.SetCaption(const AValue: string);
var
xBtn: TIDEToolButton;
begin
inherited SetCaption(AValue);
for xBtn in ToolButtons do
xBtn.Caption := AValue;
end;
procedure TIDEMenuCommand.SetChecked(const AValue: Boolean);
begin
if FChecked=AValue then exit;
FChecked:=AValue;
if MenuItem<>nil then MenuItem.Checked:=Checked;
end;
procedure TIDEMenuCommand.SetDefault(const AValue: Boolean);
begin
if FDefault=AValue then exit;
@ -1848,15 +1617,6 @@ begin
if MenuItem<>nil then MenuItem.Default:=Default;
end;
procedure TIDEMenuCommand.SetEnabled(const AValue: Boolean);
var
xBtn: TIDEToolButton;
begin
inherited SetEnabled(AValue);
for xBtn in ToolButtons do
xBtn.Enabled := AValue;
end;
procedure TIDEMenuCommand.SetGroupIndex(const AValue: Byte);
begin
if FGroupIndex=AValue then exit;
@ -1865,24 +1625,6 @@ begin
MenuItem.GroupIndex:=GroupIndex;
end;
procedure TIDEMenuCommand.SetHint(const AValue: String);
var
xBtn: TIDEToolButton;
begin
inherited SetHint(AValue);
for xBtn in ToolButtons do
xBtn.Hint := AValue;
end;
procedure TIDEMenuCommand.SetImageIndex(const AValue: Integer);
var
xBtn: TIDEToolButton;
begin
inherited SetImageIndex(AValue);
for xBtn in ToolButtons do
xBtn.ImageIndex := AValue;
end;
procedure TIDEMenuCommand.SetRadioItem(const AValue: Boolean);
begin
if FRadioItem=AValue then exit;
@ -1891,18 +1633,6 @@ begin
MenuItem.RadioItem:=RadioItem;
end;
procedure TIDEMenuCommand.SetResourceName(const AValue: String);
var
xBtn: TIDEToolButton;
begin
inherited SetResourceName(AValue);
for xBtn in ToolButtons do
if AValue <> '' then
xBtn.ImageIndex := IDEImages.LoadImage(16, FResourceName)
else
xBtn.ImageIndex := -1;
end;
procedure TIDEMenuCommand.SetRightJustify(const AValue: boolean);
begin
if FRightJustify=AValue then exit;
@ -1919,44 +1649,6 @@ begin
MenuItem.ShowAlwaysCheckable:=ShowAlwaysCheckable;
end;
procedure TIDEMenuCommand.SetVisible(const AValue: Boolean);
begin
inherited SetVisible(AValue);
//do not set visible for tool buttons, you usually only want to hide menu item and keep tool buttons visible
end;
procedure TIDEMenuCommand.ToolButtonAdded(const aBtn: TIDEToolButton);
begin
ToolButtons.Add(aBtn);
aBtn.DoOnAdded;
end;
procedure TIDEMenuCommand.SetCommand(const AValue: TIDECommand);
begin
if FCommand = AValue then
Exit;
if FCommand <> nil then
begin
//DebugLn('TIDEMenuCommand.SetCommand OLD ',ShortCutToText(FCommand.AsShortCut),' FCommand.Name=',FCommand.Name,' Name=',Name,' FCommand=',dbgs(Pointer(FCommand)));
FCommand.OnChange := nil;
if FCommand.OnExecute=OnClick then
FCommand.OnExecute:=nil;
if FCommand.OnExecuteProc=OnClickProc then
FCommand.OnExecuteProc:=nil;
end;
FCommand := AValue;
if FCommand <> nil then
begin
if FCommand.OnExecute = nil then
FCommand.OnExecute := OnClick;
if FCommand.OnExecuteProc = nil then
FCommand.OnExecuteProc := OnClickProc;
FCommand.OnChange := @CommandChanged;
//DebugLn('TIDEMenuCommand.SetCommand NEW ',ShortCutToText(FCommand.AsShortCut),' FCommand.Name=',FCommand.Name,' Name=',Name,' FCommand=',dbgs(Pointer(FCommand)));
end;
CommandChanged(nil);
end;
procedure TIDEMenuCommand.SetMenuItem(const AValue: TMenuItem);
begin
inherited SetMenuItem(AValue);
@ -1967,9 +1659,9 @@ begin
MenuItem.RadioItem:=RadioItem;
MenuItem.RightJustify:=RightJustify;
MenuItem.ShowAlwaysCheckable:=ShowAlwaysCheckable;
if FCommand<>nil then begin
MenuItem.ShortCut:=KeyToShortCut(FCommand.ShortcutA.Key1,FCommand.ShortcutA.Shift1);
MenuItem.ShortCutKey2:=KeyToShortCut(FCommand.ShortcutA.Key2,FCommand.ShortcutA.Shift2);
if Command<>nil then begin
MenuItem.ShortCut:=KeyToShortCut(Command.ShortcutA.Key1,Command.ShortcutA.Shift1);
MenuItem.ShortCutKey2:=KeyToShortCut(Command.ShortcutA.Key2,Command.ShortcutA.Shift2);
end
else begin
MenuItem.ShortCut:=0;
@ -2020,7 +1712,7 @@ end;
procedure TIDEMenuRoots.RegisterMenuRoot(Section: TIDEMenuSection);
begin
Section.FName:=CreateUniqueName(Section.Name);
Section.Name:=CreateUniqueName(Section.Name);
FItems.Add(Section);
end;

View File

@ -26,9 +26,9 @@ unit CodeToolsExample1;
interface
uses
Classes, SysUtils, MenuIntf, LazIDEIntf, Controls, SrcEditorIntf,
Classes, SysUtils, LazIDEIntf, Controls, SrcEditorIntf,
CodeToolManager, CodeTree, CodeCache, CustomCodeTool, IDECommands,
LCLType, Menus, ComCtrls;
ToolBarIntf, LCLType, Menus, ComCtrls;
type
TJumpToSectionDemoToolButton = class(TIDEToolButton)
@ -121,17 +121,16 @@ procedure Register;
var
Key: TIDEShortCut;
Cat: TIDECommandCategory;
CmdMyTool: TIDECommand;
xMenuCmd: TIDEMenuCommand;
xCmd: TIDECommand;
xBtnCmd: TIDEButtonCommand;
begin
// register IDE shortcut and menu item
// register IDE shortcut and tool button
Key := IDEShortCut(VK_UNKNOWN,[],VK_UNKNOWN,[]);
Cat:=IDECommandList.FindCategoryByName(CommandCategoryCodeTools);
CmdMyTool := RegisterIDECommand(Cat,'JumpToImplementationDemo', 'Jump to implementation keyword (demo)', Key, nil, @JumpIDEToImplementationKeyword);
xCmd := RegisterIDECommand(Cat,'JumpToImplementationDemo', 'Jump to implementation keyword (demo)', Key, nil, @JumpIDEToImplementationKeyword);
xMenuCmd := RegisterIDEMenuCommand(itmCodeToolSearches,'JumpToImplementationDemo',
'Jump to implementation keyword (demo)',nil,@JumpIDEToImplementationKeyword, CmdMyTool);
xMenuCmd.ToolButtonClass := TJumpToSectionDemoToolButton;
xBtnCmd := RegisterIDEButtonCommand(xCmd);
xBtnCmd.ToolButtonClass := TJumpToSectionDemoToolButton;
end;
{ TJumpToSectionDemoToolButton }

View File

@ -9,7 +9,7 @@ uses
Buttons, ButtonPanel, IDEImagesIntf,
LCLType, LazarusIDEStrConsts, LCLProc, EnvironmentOpts,
IDEWindowIntf, IDEOptionsIntf, IDEOptionDefs, Laz2_XMLCfg, InputHistory,
MenuIntf, Menus, ComCtrls, ActnList;
ToolBarIntf, Menus, ComCtrls, ActnList;
type

View File

@ -26,7 +26,8 @@ interface
uses
SysUtils, Classes, Forms, ComCtrls, Controls, ExtCtrls, fgl,
MenuIntf, IDEImagesIntf, SrcEditorIntf, BaseIDEIntf, LazIDEIntf,
LazarusIDEStrConsts, LazConfigStorage, Laz2_XMLCfg, LCLProc, ToolbarConfig;
LazarusIDEStrConsts, LazConfigStorage, Laz2_XMLCfg, LCLProc, ToolbarConfig,
ToolBarIntf;
type
@ -312,9 +313,9 @@ end;
procedure TEditorToolbar.CopyFromOptions(Options: TEditorToolBarOptions);
var
mi: TIDEMenuItem;
ButtonName: string;
i: Integer;
mi: TIDEButtonCommand;
begin
FToolBar.BeginUpdate;
try
@ -325,9 +326,9 @@ begin
AddDivider
else
begin
mi := IDEMenuRoots.FindByPath(ButtonName,false);
mi := IDEToolButtonCategories.FindItemByMenuPathOrName(ButtonName);
if Assigned(mi) then
AddButton(mi as TIDEMenuCommand);
AddButton(mi);
end;
end;
SetTbPos;

View File

@ -33,8 +33,8 @@ unit IdeCoolbarData;
interface
uses
Classes, SysUtils, LCLProc, ComCtrls, ExtCtrls, ToolWin, Controls, fgl,
MenuIntf, IDEImagesIntf, Laz2_XMLCfg, ToolbarConfig, LazIDEIntf;
Classes, SysUtils, LCLProc, ComCtrls, ToolWin, Controls, fgl,
ToolBarIntf, IDEImagesIntf, Laz2_XMLCfg, ToolbarConfig;
type
@ -427,8 +427,8 @@ end;
procedure TIDEToolBar.AddCustomItems(Index: Integer);
var
mi: TIDEMenuItem;
AName: string;
mi: TIDEButtonCommand;
begin
FToolBar.BeginUpdate;
try
@ -439,9 +439,9 @@ begin
AddDivider
else
begin
mi := IDEMenuRoots.FindByPath(AName, False);
mi := IDEToolButtonCategories.FindItemByMenuPathOrName(AName);
if Assigned(mi) then
AddButton(mi as TIDEMenuCommand);
AddButton(mi);
end;
end;
finally

View File

@ -75,13 +75,13 @@ uses
FileUtil, LazFileUtils, LazFileCache, LazUTF8, LazUTF8Classes, UTF8Process,
LConvEncoding, Laz2_XMLCfg, LazLogger,
// SynEdit
AllSynEdit, SynEditKeyCmds, SynEditMarks,
AllSynEdit, SynEditKeyCmds, SynEditMarks, SynEditHighlighter,
// IDE interface
IDEIntf, ObjectInspector, PropEdits, PropEditUtils,
MacroIntf, IDECommands, IDEWindowIntf, ComponentReg,
SrcEditorIntf, NewItemIntf, IDEExternToolIntf, IDEMsgIntf,
PackageIntf, ProjectIntf, CompOptsIntf, MenuIntf, LazIDEIntf, IDEDialogs,
IDEOptionsIntf, IDEImagesIntf, ComponentEditors,
IDEOptionsIntf, IDEImagesIntf, ComponentEditors, ToolBarIntf,
// protocol
IDEProtocol,
// compile
@ -380,17 +380,20 @@ type
// help menu
// see helpmanager.pas
// Handlers called when a menu opens. Can disable sub-items etc.
procedure mnuFileClicked(Sender: TObject); // file menu
procedure mnuEditClicked(Sender: TObject); // edit menu
procedure mnuSourceClicked(Sender: TObject); // source menu
procedure mnuProjectClicked(Sender: TObject); // project menu
procedure mnuRunClicked(Sender: TObject); // run menu
procedure mnuPackageClicked(Sender: TObject); // package menu
// Handlers to update commands. Can disable sub-items etc.
procedure UpdateMainIDECommands(Sender: TObject);
procedure UpdateFileMenu(Sender: TObject); // file menu
procedure UpdateEditMenu(Sender: TObject); // edit menu
procedure UpdateSourceMenu(Sender: TObject); // source menu
procedure UpdateProjectMenu(Sender: TObject); // project menu
procedure UpdateRunMenu(Sender: TObject); // run menu
procedure UpdatePackageMenu(Sender: TObject); // package menu
// see pkgmanager.pas
procedure mnuChgBuildModeClicked(Sender: TObject);
procedure ToolBarOptionsClick(Sender: TObject);
private
FLastUnitInfoFileName: string; // used in UpdateProjectMenu
private
fBuilder: TLazarusBuilder;
function DoBuildLazarusSub(Flags: TBuildLazarusFlags): TModalResult;
@ -1572,7 +1575,9 @@ begin
DoShowMessagesView(false); // reopen extra windows
fUserInputSinceLastIdle:=true; // Idle work gets done initially before user action.
MainIDEBar.ApplicationIsActivate:=true;
IDECommandList.AddCustomUpdateEvent(@UpdateMainIDECommands);
LazIDEInstances.StartListening(@LazInstancesStartNewInstance);
IDECommandList.StartUpdateHandler;
FIDEStarted:=true;
{$IFDEF IDE_MEM_CHECK}CheckHeapWrtMemCnt('TMainIDE.StartIDE END');{$ENDIF}
end;
@ -1580,6 +1585,9 @@ end;
destructor TMainIDE.Destroy;
begin
ToolStatus:=itExiting;
IDECommandList.RemoveCustomUpdateEvent(@UpdateMainIDECommands);
if Assigned(ExternalTools) then
ExternalTools.TerminateAll;
@ -1643,6 +1651,7 @@ begin
FreeThenNil(LazProjectDescriptors);
FreeThenNil(NewIDEItems);
FreeThenNil(IDEMenuRoots);
FreeThenNil(IDEToolButtonCategories);
// IDE options objects
FreeThenNil(CodeToolsOpts);
FreeThenNil(CodeExplorerOptions);
@ -2119,8 +2128,6 @@ begin
MainIDEBar.itmJumpToImplementation.OnClick := @SourceEditorManager.JumpToImplementationClicked;
MainIDEBar.itmJumpToImplementationUses.OnClick := @SourceEditorManager.JumpToImplementationUsesClicked;
MainIDEBar.itmJumpToInitialization.OnClick := @SourceEditorManager.JumpToInitializationClicked;
MainIDEBar.itmJumpToProcedureHeader.OnClick := @SourceEditorManager.JumpToProcedureHeaderClicked;
MainIDEBar.itmJumpToProcedureBegin.OnClick := @SourceEditorManager.JumpToProcedureBeginClicked;
MainIDEBar.itmFindBlockStart.OnClick:=@mnuSearchFindBlockStart;
MainIDEBar.itmFindBlockOtherEnd.OnClick:=@mnuSearchFindBlockOtherEnd;
MainIDEBar.itmFindDeclaration.OnClick:=@mnuSearchFindDeclaration;
@ -2449,6 +2456,8 @@ end;
procedure TMainIDE.SetupStandardIDEMenuItems;
begin
IDEMenuRoots:=TIDEMenuRoots.Create;
IDEToolButtonCategories:=TIDEToolButtonCategories.Create;
RegisterStandardSourceTabMenuItems;
RegisterStandardSourceEditorMenuItems;
RegisterStandardMessagesViewMenuItems;
@ -2487,7 +2496,7 @@ end;
procedure TMainIDE.SetupFileMenu;
begin
inherited SetupFileMenu;
mnuFile.OnClick:=@mnuFileClicked;
mnuFile.OnClick:=@UpdateFileMenu;
with MainIDEBar do begin
itmFileNewUnit.OnClick := @mnuNewUnitClicked;
itmFileNewForm.OnClick := @mnuNewFormClicked;
@ -2512,7 +2521,7 @@ end;
procedure TMainIDE.SetupEditMenu;
begin
inherited SetupEditMenu;
mnuEdit.OnClick:=@mnuEditClicked;
mnuEdit.OnClick:=@UpdateEditMenu;
with MainIDEBar do begin
itmEditUndo.OnClick:=@mnuEditUndoClicked;
itmEditRedo.OnClick:=@mnuEditRedoClicked;
@ -2578,7 +2587,7 @@ end;
procedure TMainIDE.SetupSourceMenu;
begin
inherited SetupSourceMenu;
mnuSource.OnClick:=@mnuSourceClicked;
mnuSource.OnClick:=@UpdateSourceMenu;
with MainIDEBar do begin
itmSourceCommentBlock.OnClick:=@mnuSourceCommentBlockClicked;
itmSourceUncommentBlock.OnClick:=@mnuSourceUncommentBlockClicked;
@ -2636,7 +2645,7 @@ end;
procedure TMainIDE.SetupProjectMenu;
begin
inherited SetupProjectMenu;
mnuProject.OnClick:=@mnuProjectClicked;
mnuProject.OnClick:=@UpdateProjectMenu;
with MainIDEBar do begin
itmProjectNew.OnClick := @mnuNewProjectClicked;
itmProjectNewFromFile.OnClick := @mnuNewProjectFromFileClicked;
@ -2660,7 +2669,7 @@ end;
procedure TMainIDE.SetupRunMenu;
begin
inherited SetupRunMenu;
mnuRun.OnClick:=@mnuRunClicked;
mnuRun.OnClick:=@UpdateRunMenu;
with MainIDEBar do begin
itmRunMenuCompile.OnClick := @mnuCompileProjectClicked;
itmRunMenuBuild.OnClick := @mnuBuildProjectClicked;
@ -2688,7 +2697,7 @@ end;
procedure TMainIDE.SetupPackageMenu;
begin
inherited SetupPackageMenu;
mnuPackage.OnClick:=@mnuPackageClicked;
mnuPackage.OnClick:=@UpdatePackageMenu;
end;
procedure TMainIDE.SetupToolsMenu;
@ -3551,7 +3560,7 @@ end;
{------------------------------------------------------------------------------}
procedure TMainIDE.mnuFileClicked(Sender: TObject);
procedure TMainIDE.UpdateFileMenu(Sender: TObject);
var
ASrcEdit: TSourceEditor;
AnUnitInfo: TUnitInfo;
@ -3563,7 +3572,17 @@ begin
end;
end;
procedure TMainIDE.mnuEditClicked(Sender: TObject);
procedure TMainIDE.UpdateMainIDECommands(Sender: TObject);
begin
UpdateFileMenu(Sender);
UpdateEditMenu(Sender);
UpdateSourceMenu(Sender);
UpdateProjectMenu(Sender);
UpdateRunMenu(Sender);
UpdatePackageMenu(Sender);
end;
procedure TMainIDE.UpdateEditMenu(Sender: TObject);
var
ASrcEdit: TSourceEditor;
AnUnitInfo: TUnitInfo;
@ -3613,38 +3632,29 @@ begin
end;
end;
procedure TMainIDE.mnuSourceClicked(Sender: TObject);
procedure TMainIDE.UpdateSourceMenu(Sender: TObject);
var
ASrcEdit: TSourceEditor;
AnUnitInfo: TUnitInfo;
Editable, SelEditable, SelAvail, IdentFound, StringFound: Boolean;
StartCode, EndCode: TCodeBuffer;
StartPos, EndPos: TPoint;
NewX, NewY, NewTopLine: integer;
CursorXY: TPoint;
xToken: string;
xAttr: TSynHighlighterAttributes;
begin
Editable:=False;
SelAvail:=False;
IdentFound:=False;
StringFound:=False;
ASrcEdit:=nil;
if BeginCodeTool(ASrcEdit,AnUnitInfo,[]) then begin
Assert(Assigned(ASrcEdit));
IdentFound:=False;
GetCurrentUnit(ASrcEdit,AnUnitInfo);
if ASrcEdit<>nil then
begin
Editable:=not ASrcEdit.ReadOnly;
SelAvail:=ASrcEdit.SelectionAvailable;
// Try to find main identifier declaration to enable rename feature.
CursorXY:=ASrcEdit.EditorComponent.LogicalCaretXY;
IdentFound:=CodeToolBoss.FindMainDeclaration(AnUnitInfo.Source,
CursorXY.X,CursorXY.Y,StartCode,NewX,NewY,NewTopLine);
// Calculate start and end of string expr to enable ResourceString feature.
if ASrcEdit.EditorComponent.SelAvail then
CursorXY:=ASrcEdit.EditorComponent.BlockBegin;
if CodeToolBoss.GetStringConstBounds(AnUnitInfo.Source,CursorXY.X,CursorXY.Y,
StartCode,StartPos.X,StartPos.Y,
EndCode,EndPos.X,EndPos.Y,true) then
StringFound:=(StartCode<>EndCode) or (CompareCaret(StartPos,EndPos)<>0);
//it is faster to get information from SynEdit than from CodeTools
if ASrcEdit.EditorComponent.GetHighlighterAttriAtRowCol(ASrcEdit.EditorComponent.CaretXY, xToken, xAttr) then
begin
StringFound := xAttr = ASrcEdit.EditorComponent.Highlighter.StringAttribute;
IdentFound := xAttr = ASrcEdit.EditorComponent.Highlighter.IdentifierAttribute;
end;
end;
SelEditable:=Editable and SelAvail;
with MainIDEBar do begin
@ -3691,7 +3701,7 @@ begin
end;
end;
procedure TMainIDE.mnuProjectClicked(Sender: TObject);
procedure TMainIDE.UpdateProjectMenu(Sender: TObject);
var
ASrcEdit: TSourceEditor;
AUnitInfo: TUnitInfo;
@ -3702,32 +3712,37 @@ begin
MainIDEBar.itmProjectAddTo.Enabled:=NotPartOfProj;
end;
procedure TMainIDE.mnuRunClicked(Sender: TObject);
procedure TMainIDE.UpdateRunMenu(Sender: TObject);
begin
with MainIDEBar do begin
itmRunMenuBuildManyModes.Enabled:=Project1.BuildModes.Count>1;
end;
end;
procedure TMainIDE.mnuPackageClicked(Sender: TObject);
procedure TMainIDE.UpdatePackageMenu(Sender: TObject);
var
ASrcEdit: TSourceEditor;
AUnitInfo: TUnitInfo;
PkgFile: TPkgFile;
CanOpenPkgOfFile, CanAddCurFile: Boolean;
begin
CanOpenPkgOfFile:=False;
CanAddCurFile:=False;
GetCurrentUnit(ASrcEdit,AUnitInfo);
if Assigned(ASrcEdit) then begin
if Assigned(AUnitInfo) and (AUnitInfo.Filename <> FLastUnitInfoFileName) then
begin
PkgFile:=PackageGraph.FindFileInAllPackages(AUnitInfo.Filename,true,
not AUnitInfo.IsPartOfProject);
not AUnitInfo.IsPartOfProject);
CanOpenPkgOfFile:=Assigned(PkgFile);
CanAddCurFile:=(not AUnitInfo.IsVirtual) and FileExistsUTF8(AUnitInfo.Filename)
and not AUnitInfo.IsPartOfProject;
MainIDEBar.itmPkgOpenPackageOfCurUnit.Enabled:=CanOpenPkgOfFile;
MainIDEBar.itmPkgAddCurFileToPkg.Enabled:=CanAddCurFile;
FLastUnitInfoFileName := AUnitInfo.Filename;
end else
begin
MainIDEBar.itmPkgOpenPackageOfCurUnit.Enabled:=False;
MainIDEBar.itmPkgAddCurFileToPkg.Enabled:=False;
FLastUnitInfoFileName := '';
end;
MainIDEBar.itmPkgOpenPackageOfCurUnit.Enabled:=CanOpenPkgOfFile;
MainIDEBar.itmPkgAddCurFileToPkg.Enabled:=CanAddCurFile;
end;
{------------------------------------------------------------------------------}

View File

@ -146,8 +146,6 @@ type
itmJumpToImplementation: TIDEMenuCommand;
itmJumpToImplementationUses: TIDEMenuCommand;
itmJumpToInitialization: TIDEMenuCommand;
itmJumpToProcedureHeader: TIDEMenuCommand;
itmJumpToProcedureBegin: TIDEMenuCommand;
//itmBookmarks: TIDEMenuSection;
itmSetFreeBookmark: TIDEMenuCommand;
itmJumpToNextBookmark: TIDEMenuCommand;

View File

@ -60,10 +60,10 @@ uses
CodeToolManager, AVL_Tree, SynEditKeyCmds, PackageIntf,
// IDEIntf
IDEImagesIntf, SrcEditorIntf, LazIDEIntf, MenuIntf, NewItemIntf,
IDECommands, IDEWindowIntf, ProjectIntf,
IDECommands, IDEWindowIntf, ProjectIntf, ToolBarIntf,
// IDE
LazConf, LazarusIDEStrConsts, ProjectDefs, Project, IDEDialogs,
TransferMacros, ObjectInspector, PropEdits, BuildManager, ToolbarConfig,
TransferMacros, ObjectInspector, PropEdits, BuildManager,
EnvironmentOpts, EditorOptions, CompilerOptions, KeyMapping, IDEProcs,
Debugger, IDEOptionDefs, Splash, Designer,
SourceEditor, FindInFilesDlg,
@ -326,7 +326,7 @@ var
i: Integer;
CurTemplate: TNewIDEItemTemplate;
TheIndex: Integer;
Item: TNewFormUnitMenuItem;
xItem: TNewFormUnitMenuItem;
begin
Category:=NewIDEItems.FindCategoryByPath(FileDescGroupName,true);
TemplateName:=FindDefaultTemplateName(Category);
@ -337,16 +337,16 @@ begin
CurTemplate:=Category[i];
if not CurTemplate.VisibleInNewDialog then continue;
if TheIndex<SetDefaultMenuItem.Count then
Item:=SetDefaultMenuItem[TheIndex] as TNewFormUnitMenuItem
xItem:=SetDefaultMenuItem[TheIndex] as TNewFormUnitMenuItem
else begin
Item:=TNewFormUnitMenuItem.Create(SetDefaultMenuItem);
SetDefaultMenuItem.Add(Item);
xItem:=TNewFormUnitMenuItem.Create(SetDefaultMenuItem);
SetDefaultMenuItem.Add(xItem);
end;
Item.OnClick:=@mnuSetFormUnitTemplate;
Item.Caption:=CurTemplate.LocalizedName;
Item.TemplateName:=CurTemplate.Name;
Item.ShowAlwaysCheckable:=true;
Item.Checked:=CompareText(TemplateName,CurTemplate.Name)=0;
xItem.OnClick:=@mnuSetFormUnitTemplate;
xItem.Caption:=CurTemplate.LocalizedName;
xItem.TemplateName:=CurTemplate.Name;
xItem.ShowAlwaysCheckable:=true;
xItem.Checked:=CompareText(TemplateName,CurTemplate.Name)=0;
inc(TheIndex);
end;
// remove unneeded items
@ -552,7 +552,7 @@ const
begin
if Assigned(Project1) then
MainIDEBar.itmProjectBuildMode.Hint :=
lisChangeBuildMode + GetShortcut(MainIDEBar.itmProjectBuildMode) + sLineBreak +
lisChangeBuildMode + MainIDEBar.itmProjectBuildMode.GetShortcut + sLineBreak +
Format(cActiveBuildMode, [Project1.ActiveBuildMode.GetCaption]);
end;
@ -1084,12 +1084,6 @@ begin
CreateMenuItem(ParentMI,itmJumpToImplementationUses,'itmJumpToImplementationUses',lisMenuJumpToImplementationUses, 'menu_jumpto_implementationuses');
CreateMenuItem(ParentMI,itmJumpToInitialization,'itmJumpToInitialization',lisMenuJumpToInitialization, 'menu_jumpto_initialization');
ParentMI:=itmJumpings;
CreateMenuItem(ParentMI,itmJumpToProcedureHeader,'itmJumpToProcedureHeader',lisMenuJumpToProcedureHeader, 'menu_jumpto_procedureheader');
CreateMenuItem(ParentMI,itmJumpToProcedureBegin,'itmJumpToProcedureBegin',lisMenuJumpToProcedureBegin, 'menu_jumpto_procedurebegin');
itmJumpToProcedureHeader.Visible := False;
itmJumpToProcedureBegin.Visible := False;
CreateMenuSeparatorSection(mnuSearch,itmBookmarks,'itmBookmarks');
ParentMI:=itmBookmarks;
@ -1471,21 +1465,40 @@ end;
procedure TMainIDEBase.LoadMenuShortCuts;
function GetCommand(ACommand: word): TIDECommand;
function GetCmdAndBtn(ACommand: word; out ToolButton: TIDEButtonCommand): TIDECommand;
begin
Result:=IDECommandList.FindIDECommand(ACommand);
if Result<>nil then
ToolButton := RegisterIDEButtonCommand(Result)
else
ToolButton := nil;
end;
function GetCommand(ACommand: word): TIDECommand;
var
ToolButton: TIDEButtonCommand;
begin
Result:=GetCmdAndBtn(ACommand, ToolButton);
end;
function GetCommand(ACommand: word; ToolButtonClass: TIDEToolButtonClass): TIDECommand;
var
ToolButton: TIDEButtonCommand;
begin
Result:=GetCmdAndBtn(ACommand, ToolButton);
if ToolButton<>nil then
ToolButton.ToolButtonClass := ToolButtonClass;
end;
var
xBtnItem: TIDEButtonCommand;
begin
with MainIDEBar do begin
// file menu
itmFileNewUnit.Command:=GetCommand(ecNewUnit);
itmFileNewUnit.ToolButtonClass:=TNewUnitToolButton;
itmFileNewForm.Command:=GetCommand(ecNewForm);
itmFileNewForm.ToolButtonClass:=TNewFormToolButton;
itmFileNewUnit.Command:=GetCommand(ecNewUnit, TNewUnitToolButton);
itmFileNewForm.Command:=GetCommand(ecNewForm, TNewFormToolButton);
itmFileNewOther.Command:=GetCommand(ecNew);
itmFileOpen.Command:=GetCommand(ecOpen);
itmFileOpen.ToolButtonClass:=TOpenFileToolButton;
itmFileOpen.Command:=GetCommand(ecOpen, TOpenFileToolButton);
itmFileRevert.Command:=GetCommand(ecRevert);
itmFileSave.Command:=GetCommand(ecSave);
itmFileSaveAs.Command:=GetCommand(ecSaveAs);
@ -1494,7 +1507,6 @@ begin
itmFileCloseAll.Command:=GetCommand(ecCloseAll);
itmFileCleanDirectory.Command:=GetCommand(ecCleanDirectory);
itmFileQuit.Command:=GetCommand(ecQuit);
itmFileQuit.Command:=GetCommand(ecQuit);
// edit menu
itmEditUndo.Command:=GetCommand(ecUndo);
@ -1538,18 +1550,17 @@ begin
itmSetFreeBookmark.Command:=GetCommand(ecSetFreeBookmark);
itmJumpToNextBookmark.Command:=GetCommand(ecNextBookmark);
itmJumpToPrevBookmark.Command:=GetCommand(ecPrevBookmark);
itmJumpToInterface.Command:=GetCommand(ecJumpToInterface);
itmJumpToInterface.ToolButtonClass:=TJumpToSectionToolButton;
itmJumpToInterfaceUses.Command:=GetCommand(ecJumpToInterfaceUses);
itmJumpToInterfaceUses.ToolButtonClass:=TJumpToSectionToolButton;
itmJumpToImplementation.Command:=GetCommand(ecJumpToImplementation);
itmJumpToImplementation.ToolButtonClass:=TJumpToSectionToolButton;
itmJumpToImplementationUses.Command:=GetCommand(ecJumpToImplementationUses);
itmJumpToImplementationUses.ToolButtonClass:=TJumpToSectionToolButton;
itmJumpToInitialization.Command:=GetCommand(ecJumpToInitialization);
itmJumpToInitialization.ToolButtonClass:=TJumpToSectionToolButton;
itmJumpToProcedureHeader.Command:=GetCommand(ecJumpToProcedureHeader);
itmJumpToProcedureBegin.Command:=GetCommand(ecJumpToProcedureBegin);
itmJumpToInterface.Command:=GetCommand(ecJumpToInterface, TJumpToSectionToolButton);
itmJumpToInterfaceUses.Command:=GetCommand(ecJumpToInterfaceUses, TJumpToSectionToolButton);
itmJumpToImplementation.Command:=GetCommand(ecJumpToImplementation, TJumpToSectionToolButton);
itmJumpToImplementationUses.Command:=GetCommand(ecJumpToImplementationUses, TJumpToSectionToolButton);
itmJumpToInitialization.Command:=GetCommand(ecJumpToInitialization, TJumpToSectionToolButton);
GetCmdAndBtn(ecJumpToProcedureHeader, xBtnItem);
xBtnItem.OnClick := @SourceEditorManager.JumpToProcedureHeaderClicked;
xBtnItem.ImageIndex := IDEImages.LoadImage(16, 'menu_jumpto_procedureheader');
GetCmdAndBtn(ecJumpToProcedureBegin, xBtnItem);
xBtnItem.ImageIndex := IDEImages.LoadImage(16, 'menu_jumpto_procedurebegin');
xBtnItem.OnClick := @SourceEditorManager.JumpToProcedureBeginClicked;
itmFindBlockOtherEnd.Command:=GetCommand(ecFindBlockOtherEnd);
itmFindBlockStart.Command:=GetCommand(ecFindBlockStart);
itmFindDeclaration.Command:=GetCommand(ecFindDeclaration);
@ -1642,8 +1653,7 @@ begin
itmProjectRemoveFrom.Command:=GetCommand(ecRemoveFromProj);
itmProjectViewUnits.Command:=GetCommand(ecViewProjectUnits);
itmProjectViewForms.Command:=GetCommand(ecViewProjectForms);
itmProjectViewSource.Command:=GetCommand(ecViewProjectSource);
itmProjectBuildMode.ToolButtonClass:=TSetBuildModeToolButton;
itmProjectViewSource.Command:=GetCommand(ecViewProjectSource,TSetBuildModeToolButton);
// run menu
itmRunMenuCompile.Command:=GetCommand(ecCompile);
@ -1689,8 +1699,7 @@ begin
itmToolConfigure.Command:=GetCommand(ecExtToolSettings);
itmToolManageDesktops.Command:=GetCommand(ecManageDesktops);
itmToolManageDesktops.ToolButtonClass:=TShowDesktopsToolButton;
itmToolManageDesktops.Command:=GetCommand(ecManageDesktops, TShowDesktopsToolButton);
itmToolManageExamples.Command:=GetCommand(ecManageExamples);
itmToolDiff.Command:=GetCommand(ecDiff);

View File

@ -60,7 +60,7 @@ uses
SynExportHTML, SynHighlighterPas, SynEditMarkup, SynEditMarkupIfDef,
// Intf
SrcEditorIntf, MenuIntf, LazIDEIntf, PackageIntf, IDEHelpIntf, IDEImagesIntf,
IDEWindowIntf, ProjectIntf, MacroDefIntf,
IDEWindowIntf, ProjectIntf, MacroDefIntf, ToolBarIntf,
// IDE units
IDECmdLine, IDEDialogs, LazarusIDEStrConsts, IDECommands,
EditorOptions, EnvironmentOpts, WordCompletion, FindReplaceDialog, IDEProcs,
@ -246,14 +246,18 @@ type
FOnMouseDown: TMouseEvent;
FOnMouseWheel : TMouseWheelEvent;
FOnKeyDown: TKeyEvent;
FOnKeyUp: TKeyEvent;
FSourceNoteBook: TSourceNotebook;
procedure EditorMouseMoved(Sender: TObject; Shift: TShiftState; X,Y:Integer);
procedure EditorMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X,Y: Integer);
procedure EditorMouseUp(Sender: TObject; {%H-}Button: TMouseButton;
{%H-}Shift: TShiftState; {%H-}X,{%H-}Y: Integer);
procedure EditorMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
procedure EditorKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure EditorKeyUp({%H-}Sender: TObject; var {%H-}Key: Word; {%H-}Shift: TShiftState);
procedure EditorStatusChanged(Sender: TObject; {%H-}Changes: TSynStatusChanges);
procedure EditorPaste(Sender: TObject; var AText: String;
var AMode: TSynSelectionMode; ALogStartPos: TPoint;
@ -511,6 +515,7 @@ type
property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
property OnMouseWheel: TMouseWheelEvent read FOnMouseWheel write FOnMouseWheel;
property OnKeyDown: TKeyEvent read FOnKeyDown write FOnKeyDown;
property OnKeyUp: TKeyEvent read FOnKeyUp write FOnKeyUp;
property Owner: TComponent read FAOwner;
property PageName: string read FPageName write SetPageName;
property PopupMenu: TPopupMenu read FPopUpMenu write SetPopUpMenu;
@ -607,10 +612,12 @@ type
procedure SrcEditMenuFindInWindowClicked(Sender: TObject);
procedure SrcEditMenuMoveToExistingWindowClicked(Sender: TObject);
procedure SrcPopUpMenuPopup(Sender: TObject);
procedure UpdateSrcPopUpMenu(SrcEdit: TSourceEditor);
procedure StatusBarClick(Sender: TObject);
procedure StatusBarDblClick(Sender: TObject);
procedure StatusBarDrawPanel({%H-}AStatusBar: TStatusBar; APanel: TStatusPanel;
const ARect: TRect);
procedure UpdateTabPopUpMenu(ASrcEdit: TSourceEditor);
procedure TabPopUpMenuPopup(Sender: TObject);
private
FNotebook: TExtendedNotebook;
@ -651,9 +658,9 @@ type
function GetPageIndex: Integer;
procedure SetPageIndex(AValue: Integer);
procedure UpdateHighlightMenuItems;
procedure UpdateLineEndingMenuItems;
procedure UpdateEncodingMenuItems;
procedure UpdateHighlightMenuItems(SrcEdit: TSourceEditor);
procedure UpdateLineEndingMenuItems(SrcEdit: TSourceEditor);
procedure UpdateEncodingMenuItems(SrcEdit: TSourceEditor);
procedure RemoveUserDefinedMenuItems;
function AddUserDefinedPopupMenuItem(const NewCaption: string;
const NewEnabled: boolean;
@ -707,6 +714,7 @@ type
Reason: TSynEditorCommand;
SetIndentProc: TSynBeautifierSetIndentProc): Boolean;
procedure EditorKeyDown(Sender: TObject; var {%H-}Key: Word; {%H-}Shift: TShiftState);
procedure EditorKeyUp(Sender: TObject; var {%H-}Key: Word; {%H-}Shift: TShiftState);
procedure EditorMouseWheel(Sender: TObject; {%H-}Shift: TShiftState;
{%H-}WheelDelta: Integer; {%H-}MousePos: TPoint; var {%H-}Handled: Boolean);
@ -996,6 +1004,8 @@ type
procedure SetActiveSourceNotebook(const AValue: TSourceNotebook);
function GetSourceNotebook(Index: integer): TSourceNotebook;
procedure SetActiveSrcEditor(const AValue: TSourceEditor);
procedure UpdatePopUpMenus(Sender: TObject);
public
// Windows
function SourceWindowWithEditor(const AEditor: TSourceEditorInterface): TSourceNotebook;
@ -1381,18 +1391,18 @@ var
r: Boolean;
begin
if SourceEditorManager = nil then exit;
if not (Sender is TIDEMenuCommand) then exit;
if TIDEMenuCommand(Sender).Command = nil then exit;
if not (Sender is TIDESpecialCommand) then exit;
if TIDESpecialCommand(Sender).Command = nil then exit;
ActEdit := SourceEditorManager.ActiveEditor;
if ActEdit = nil then exit;
r := TIDEMenuCommand(Sender).Command.OnExecuteProc = @ExecuteIdeMenuClick;
r := TIDESpecialCommand(Sender).Command.OnExecuteProc = @ExecuteIdeMenuClick;
if r then
TIDEMenuCommand(Sender).Command.OnExecuteProc := nil;
TIDESpecialCommand(Sender).Command.OnExecuteProc := nil;
// Commands may not work without focusing when anchordocking is installed
ActEdit.FocusEditor;
ActEdit.DoEditorExecuteCommand(TIDEMenuCommand(Sender).Command.Command);
ActEdit.DoEditorExecuteCommand(TIDESpecialCommand(Sender).Command.Command);
if r then
TIDEMenuCommand(Sender).Command.OnExecuteProc := @ExecuteIdeMenuClick;
TIDESpecialCommand(Sender).Command.OnExecuteProc := @ExecuteIdeMenuClick;
end;
procedure RegisterStandardSourceTabMenuItems;
@ -4792,9 +4802,11 @@ Begin
OnMouseMove := @EditorMouseMoved;
OnMouseWheel := @EditorMouseWheel;
OnMouseDown := @EditorMouseDown;
OnMouseUp := @EditorMouseUp;
OnClickLink := Manager.OnClickLink;
OnMouseLink := Manager.OnMouseLink;
OnKeyDown := @EditorKeyDown;
OnKeyUp := @EditorKeyUp;
OnPaste:=@EditorPaste;
OnEnter:=@EditorEnter;
OnPlaceBookmark := @EditorPlaceBookmark;
@ -5234,6 +5246,8 @@ begin
// Navigating with mousebuttons between editors (eg jump history on btn 4/5)
// can trigger the old editor to be refocused (while not visible)
end;
IDECommandList.LateExecuteUpdateEvents;
end;
procedure TSourceEditor.EditorActivateSyncro(Sender: TObject);
@ -5322,6 +5336,12 @@ begin
OnMouseMove(Self,Shift,X,Y);
end;
procedure TSourceEditor.EditorMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
IDECommandList.LateExecuteUpdateEvents;
end;
procedure TSourceEditor.EditorMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
@ -5345,6 +5365,18 @@ begin
CheckActiveWindow;
if Assigned(OnKeyDown) then
OnKeyDown(Sender, Key, Shift);
IDECommandList.LateExecuteUpdateEvents;
end;
procedure TSourceEditor.EditorKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
CheckActiveWindow;
if Assigned(OnKeyUp) then
OnKeyUp(Sender, Key, Shift);
IDECommandList.LateExecuteUpdateEvents;
end;
{-------------------------------------------------------------------------------
@ -5917,6 +5949,7 @@ begin
OnClickLink := nil;
OnMouseLink := nil;
OnKeyDown := nil;
OnKeyUp := nil;
OnEnter := nil;
OnPlaceBookmark := nil;
OnClearBookmark := nil;
@ -6269,7 +6302,6 @@ var
end;
var
NBAvail: Boolean;
PageCtrl: TPageControl;
PopM: TPopupMenu;
PageI: integer;
@ -6295,33 +6327,18 @@ begin
end;
ASrcEdit:=Editors[PageIndex];
UpdateTabPopUpMenu(ASrcEdit);
{$IFnDEF SingleSrcWindow}
SrcEditMenuEditorLock.Checked := ASrcEdit.IsLocked; // Editor locks
// Multi win
NBAvail := ToWindow(SrcEditMenuMoveToOtherWindowList, 'MoveToWindow',
ToWindow(SrcEditMenuMoveToOtherWindowList, 'MoveToWindow',
@SrcEditMenuMoveToExistingWindowClicked);
SrcEditMenuMoveToNewWindow.Visible := not NBAvail;
SrcEditMenuMoveToNewWindow.Enabled := PageCount > 1;
SrcEditMenuMoveToOtherWindow.Visible := NBAvail;
SrcEditMenuMoveToOtherWindowNew.Enabled := PageCount > 1;
NBAvail := ToWindow(SrcEditMenuCopyToOtherWindowList, 'CopyToWindow',
ToWindow(SrcEditMenuCopyToOtherWindowList, 'CopyToWindow',
@SrcEditMenuCopyToExistingWindowClicked);
SrcEditMenuCopyToNewWindow.Visible := not NBAvail;
SrcEditMenuCopyToOtherWindow.Visible := NBAvail;
NBAvail := ToWindow(SrcEditMenuFindInOtherWindowList, 'FindInWindow',
ToWindow(SrcEditMenuFindInOtherWindowList, 'FindInWindow',
@SrcEditMenuFindInWindowClicked, True);
SrcEditMenuFindInOtherWindow.Enabled := NBAvail;
{$ENDIF}
// editor layout
SrcEditMenuMoveEditorLeft.MenuItem.Enabled:= (PageCount>1);
SrcEditMenuMoveEditorRight.MenuItem.Enabled:= (PageCount>1);
SrcEditMenuMoveEditorFirst.MenuItem.Enabled:= (PageCount>1) and (PageIndex>0);
SrcEditMenuMoveEditorLast.MenuItem.Enabled:= (PageCount>1) and (PageIndex<(PageCount-1));
SrcEditMenuSectionEditors.Clear;
if Manager <> nil then begin
EdList := TStringList.Create;
@ -6426,24 +6443,13 @@ var
end;
var
se: TSourceEditor;
BookMarkID, BookMarkX, BookMarkY: integer;
MarkDesc, FPDocSrc, ShortFileName: String;
MarkMenuItem: TIDEMenuItem;
FPDocSrc, ShortFileName: String;
EditorComp: TSynEdit;
MainCodeBuf: TCodeBuffer;
AnOwner: TObject;
Marks: PSourceMark;
i, MarkCount: integer;
EditorPopupPoint, EditorCaret: TPoint;
SelAvail, SelAvailAndWritable, AtIdentifier: Boolean;
CurWordAtCursor: String;
CodeTool: TCodeTool;
CaretXY: TCodeXYPosition;
CleanPos: integer;
CodeNode: TCodeTreeNode;
ProcNode: TCodeTreeNode;
ProcName: String;
begin
SourceEditorMenuRoot.MenuItem:=SrcPopupMenu.Items;
SourceEditorMenuRoot.BeginUpdate;
@ -6453,52 +6459,20 @@ begin
ASrcEdit:=FindSourceEditorWithEditorComponent(TPopupMenu(Sender).PopupComponent);
Assert(Assigned(ASrcEdit), 'TSourceNotebook.SrcPopUpMenuPopup: ASrcEdit=nil');
Assert((ASrcEdit=GetActiveSE), 'TSourceNotebook.SrcPopUpMenuPopup: ASrcEdit<>GetActiveSE');
EditorComp:=ASrcEdit.EditorComponent;
// Clipboard section:
SrcEditMenuCut.Enabled := ASrcEdit.SelectionAvailable and not ASrcEdit.ReadOnly;
SrcEditMenuCopy.Enabled := ASrcEdit.SelectionAvailable;
SrcEditMenuPaste.Enabled := not ASrcEdit.ReadOnly;
SrcEditMenuSelectAll.Enabled:= ASrcEdit.SourceText<>'';
// Files section: Readonly, ShowLineNumbers
SrcEditMenuReadOnly.Checked:=ASrcEdit.ReadOnly;
SrcEditMenuShowLineNumbers.Checked := ASrcEdit.EditorComponent.Gutter.LineNumberPart.Visible;
SrcEditMenuDisableI18NForLFM.Visible:=false;
UpdateHighlightMenuItems;
UpdateEncodingMenuItems;
UpdateLineEndingMenuItems;
// add context specific menu items
CurFilename:=ASrcEdit.FileName;
ShortFileName:=ExtractFileName(CurFilename);
SelAvail:=ASrcEdit.EditorComponent.SelAvail;
SelAvailAndWritable:=SelAvail and (not ASrcEdit.ReadOnly);
CurWordAtCursor:=ASrcEdit.GetWordAtCurrentCaret;
AtIdentifier:=IsValidIdent(CurWordAtCursor);
UpdateSrcPopUpMenu(ASrcEdit);
// ask Codetools
CurFilename:=ASrcEdit.FileName;
ShortFileName:=ExtractFileName(CurFilename);
MainCodeBuf:=nil;
if FilenameIsPascalUnit(ShortFileName)
or (CompareFileExt(ShortFileName,'.inc',true)=0) then
MainCodeBuf:=CodeToolBoss.GetMainCode(ASrcEdit.CodeBuffer)
else if FilenameIsPascalSource(ShortFileName) then
MainCodeBuf:=ASrcEdit.CodeBuffer;
CodeTool:=nil;
CaretXY:=CleanCodeXYPosition;
CaretXY.Code:=ASrcEdit.CodeBuffer;
CaretXY.X:=ASrcEdit.CursorTextXY.X;
CaretXY.Y:=ASrcEdit.CursorTextXY.Y;
CodeNode:=nil;
if MainCodeBuf<>nil then begin
CodeToolBoss.Explore(MainCodeBuf,CodeTool,true);
if CodeTool<>nil then begin
CodeTool.CaretToCleanPos(CaretXY,CleanPos);
CodeNode:=CodeTool.FindDeepestNodeAtPos(CleanPos,false);
end;
end;
if (FilenameIsAbsolute(CurFilename)) then begin
if (MainCodeBuf<>nil) and (MainCodeBuf<>ASrcEdit.CodeBuffer)
@ -6537,66 +6511,8 @@ begin
true,@OnPopupMenuOpenFile);
end;
// bookmarks
for BookMarkID:=0 to 9 do begin
MarkDesc:=' '+IntToStr(BookMarkID);
SelAvail:=False;
i := 0;
while i < Manager.SourceEditorCount do begin
se:=Manager.SourceEditors[i];
BookMarkX:=0; BookMarkY:=0;
if se.EditorComponent.GetBookMark(BookMarkID,BookMarkX,BookMarkY) then
begin
MarkDesc:=MarkDesc+': '+se.PageName+' ('+IntToStr(BookMarkY)+','+IntToStr(BookMarkX)+')';
SelAvail:=True;
break;
end;
inc(i);
end;
// goto book mark item
MarkMenuItem:=SrcEditSubMenuGotoBookmarks[BookMarkID];
MarkMenuItem.Caption:=uemBookmarkN+MarkDesc;
MarkMenuItem.Enabled:=SelAvail;
// set book mark item
MarkMenuItem:=SrcEditSubMenuToggleBookmarks[BookMarkID];
MarkMenuItem.Caption:=uemToggleBookmark+MarkDesc;
end;
EditorPopupPoint:=EditorComp.ScreenToClient(SrcPopUpMenu.PopupPoint);
if EditorPopupPoint.X>EditorComp.Gutter.Width then begin
// user clicked on text
// enable search menu items
SrcEditMenuFindDeclaration.Enabled:=CurWordAtCursor<>'';
if CurWordAtCursor<>'' then
SrcEditMenuFindDeclaration.Caption:=Format(lisFindDeclarationOf, [
CurWordAtCursor])
else
SrcEditMenuFindDeclaration.Caption:=uemFindDeclaration;
SrcEditMenuFindIdentifierReferences.Enabled:=AtIdentifier;
SrcEditMenuFindUsedUnitReferences.Enabled:=AtIdentifier;
SrcEditMenuFindOverloads.Enabled:=AtIdentifier;
ProcName:='';
if CodeNode<>nil then begin
ProcNode:=CodeNode.GetNodeOfType(ctnProcedure);
if ProcNode<>nil then
ProcName:=CodeTool.ExtractProcName(ProcNode,[]);
end;
SrcEditMenuProcedureJump.Enabled:=(ProcName<>'');
if ProcName<>'' then
SrcEditMenuProcedureJump.Caption:=Format(lisJumpToProcedure, [ProcName])
else
SrcEditMenuProcedureJump.Caption:=uemProcedureJump;
// enable refactoring menu items
SrcEditMenuEncloseSelection.Enabled := SelAvailAndWritable;
SrcEditMenuEncloseInIFDEF.Enabled := SelAvailAndWritable;
SrcEditMenuExtractProc.Enabled := SelAvailAndWritable;
SrcEditMenuInvertAssignment.Enabled := SelAvailAndWritable;
SrcEditMenuRenameIdentifier.Enabled:=AtIdentifier and (not ASrcEdit.ReadOnly);
SrcEditMenuShowAbstractMethods.Enabled:=not ASrcEdit.ReadOnly;
SrcEditMenuShowEmptyMethods.Enabled:=not ASrcEdit.ReadOnly;
SrcEditMenuMakeResourceString.Enabled:=not ASrcEdit.ReadOnly;
end else
begin
if EditorPopupPoint.X<=EditorComp.Gutter.Width then begin
EditorCaret := EditorComp.PhysicalToLogicalPos(EditorComp.PixelsToRowColumn(EditorPopupPoint));
// user clicked on gutter
SourceEditorMarks.GetMarksForLine(ASrcEdit, EditorCaret.y, Marks, MarkCount);
@ -6734,17 +6650,15 @@ begin
DebugLnExit(SRCED_PAGES, ['<< TSourceNotebook.SetPageIndex ']);
end;
procedure TSourceNotebook.UpdateHighlightMenuItems;
procedure TSourceNotebook.UpdateHighlightMenuItems(SrcEdit: TSourceEditor);
var
h: TLazSyntaxHighlighter;
i: Integer;
CurName: String;
CurCaption: String;
IDEMenuItem: TIDEMenuItem;
SrcEdit: TSourceEditor;
begin
SrcEditSubMenuHighlighter.ChildsAsSubMenu:=true;
SrcEdit:=GetActiveSE;
i:=0;
for h:=Low(TLazSyntaxHighlighter) to High(TLazSyntaxHighlighter) do begin
CurName:='Highlighter'+IntToStr(i);
@ -6765,10 +6679,9 @@ begin
end;
end;
procedure TSourceNotebook.UpdateLineEndingMenuItems;
procedure TSourceNotebook.UpdateLineEndingMenuItems(SrcEdit: TSourceEditor);
var
le: TLineEnding;
SrcEdit: TSourceEditor;
FileEndings: String;
IDEMenuItem: TIDEMenuCommand;
const
@ -6779,7 +6692,6 @@ const
);
begin
SrcEditSubMenuLineEnding.ChildsAsSubMenu:=true;
SrcEdit:=GetActiveSE;
if (SrcEdit<>nil) and (SrcEdit.CodeBuffer<>nil) then
FileEndings:=SrcEdit.CodeBuffer.DiskLineEnding
else
@ -6827,11 +6739,136 @@ begin
Editors[i].UpdateProjectFile;
end;
procedure TSourceNotebook.UpdateEncodingMenuItems;
procedure TSourceNotebook.UpdateSrcPopUpMenu(SrcEdit: TSourceEditor);
var
se: TSourceEditor;
BookMarkID, BookMarkX, BookMarkY: integer;
MarkDesc, ShortFileName, CurFilename: String;
MarkMenuItem: TIDEMenuItem;
MainCodeBuf: TCodeBuffer;
i: integer;
SelAvail, SelAvailAndWritable, StringFound, IdentFound: Boolean;
CurWordAtCursor: String;
CodeTool: TCodeTool;
CaretXY: TCodeXYPosition;
CleanPos: integer;
CodeNode: TCodeTreeNode;
ProcNode: TCodeTreeNode;
ProcName, xToken: String;
xAttr: TSynHighlighterAttributes;
begin
// Clipboard section:
SrcEditMenuCut.Enabled := SrcEdit.SelectionAvailable and not SrcEdit.ReadOnly;
SrcEditMenuCopy.Enabled := SrcEdit.SelectionAvailable;
SrcEditMenuPaste.Enabled := not SrcEdit.ReadOnly;
SrcEditMenuSelectAll.Enabled:= SrcEdit.SourceText<>'';
// Files section: Readonly, ShowLineNumbers
SrcEditMenuReadOnly.Checked:=SrcEdit.ReadOnly;
SrcEditMenuShowLineNumbers.Checked := SrcEdit.EditorComponent.Gutter.LineNumberPart.Visible;
SrcEditMenuDisableI18NForLFM.Visible:=false;
UpdateHighlightMenuItems(SrcEdit);
UpdateEncodingMenuItems(SrcEdit);
UpdateLineEndingMenuItems(SrcEdit);
// add context specific menu items
CurFilename:=SrcEdit.FileName;
ShortFileName:=ExtractFileName(CurFilename);
SelAvail:=SrcEdit.EditorComponent.SelAvail;
SelAvailAndWritable:=SelAvail and (not SrcEdit.ReadOnly);
CurWordAtCursor:=SrcEdit.GetWordAtCurrentCaret;
// ask Codetools
MainCodeBuf:=nil;
if FilenameIsPascalUnit(ShortFileName)
or (CompareFileExt(ShortFileName,'.inc',true)=0) then
MainCodeBuf:=CodeToolBoss.GetMainCode(SrcEdit.CodeBuffer)
else if FilenameIsPascalSource(ShortFileName) then
MainCodeBuf:=SrcEdit.CodeBuffer;
CodeTool:=nil;
CaretXY:=CleanCodeXYPosition;
CaretXY.Code:=SrcEdit.CodeBuffer;
CaretXY.X:=SrcEdit.CursorTextXY.X;
CaretXY.Y:=SrcEdit.CursorTextXY.Y;
CodeNode:=nil;
if MainCodeBuf<>nil then begin
CodeToolBoss.Explore(MainCodeBuf,CodeTool,true);
if CodeTool<>nil then begin
CodeTool.CaretToCleanPos(CaretXY,CleanPos);
CodeNode:=CodeTool.FindDeepestNodeAtPos(CleanPos,false);
end;
end;
StringFound:=False;
IdentFound:=False;
//it is faster to get information from SynEdit than from CodeTools
if SrcEdit.EditorComponent.GetHighlighterAttriAtRowCol(SrcEdit.EditorComponent.CaretXY, xToken, xAttr) then
begin
StringFound := xAttr = SrcEdit.EditorComponent.Highlighter.StringAttribute;
IdentFound := xAttr = SrcEdit.EditorComponent.Highlighter.IdentifierAttribute;
end;
// bookmarks
for BookMarkID:=0 to 9 do begin
MarkDesc:=' '+IntToStr(BookMarkID);
SelAvail:=False;
i := 0;
while i < Manager.SourceEditorCount do begin
se:=Manager.SourceEditors[i];
BookMarkX:=0; BookMarkY:=0;
if se.EditorComponent.GetBookMark(BookMarkID,BookMarkX,BookMarkY) then
begin
MarkDesc:=MarkDesc+': '+se.PageName+' ('+IntToStr(BookMarkY)+','+IntToStr(BookMarkX)+')';
SelAvail:=True;
break;
end;
inc(i);
end;
// goto book mark item
MarkMenuItem:=SrcEditSubMenuGotoBookmarks[BookMarkID];
MarkMenuItem.Caption:=uemBookmarkN+MarkDesc;
MarkMenuItem.Enabled:=SelAvail;
// set book mark item
MarkMenuItem:=SrcEditSubMenuToggleBookmarks[BookMarkID];
MarkMenuItem.Caption:=uemToggleBookmark+MarkDesc;
end;
SrcEditMenuFindDeclaration.Enabled:=CurWordAtCursor<>'';
if CurWordAtCursor<>'' then
SrcEditMenuFindDeclaration.Caption:=Format(lisFindDeclarationOf, [
CurWordAtCursor])
else
SrcEditMenuFindDeclaration.Caption:=uemFindDeclaration;
SrcEditMenuFindIdentifierReferences.Enabled:=IdentFound;
SrcEditMenuFindUsedUnitReferences.Enabled:=IdentFound;
SrcEditMenuFindOverloads.Enabled:=IdentFound;
ProcName:='';
if CodeNode<>nil then begin
ProcNode:=CodeNode.GetNodeOfType(ctnProcedure);
if ProcNode<>nil then
ProcName:=CodeTool.ExtractProcName(ProcNode,[]);
end;
SrcEditMenuProcedureJump.Enabled:=(ProcName<>'');
if ProcName<>'' then
SrcEditMenuProcedureJump.Caption:=Format(lisJumpToProcedure, [ProcName])
else
SrcEditMenuProcedureJump.Caption:=uemProcedureJump;
// enable refactoring menu items
SrcEditMenuEncloseSelection.Enabled := SelAvailAndWritable;
SrcEditMenuEncloseInIFDEF.Enabled := SelAvailAndWritable;
SrcEditMenuExtractProc.Enabled := SelAvailAndWritable;
SrcEditMenuInvertAssignment.Enabled := SelAvailAndWritable;
SrcEditMenuRenameIdentifier.Enabled:=IdentFound and (not SrcEdit.ReadOnly);
SrcEditMenuShowAbstractMethods.Enabled:=not SrcEdit.ReadOnly;
SrcEditMenuShowEmptyMethods.Enabled:=not SrcEdit.ReadOnly;
SrcEditMenuMakeResourceString.Enabled:=not SrcEdit.ReadOnly and StringFound;
end;
procedure TSourceNotebook.UpdateEncodingMenuItems(SrcEdit: TSourceEditor);
var
List: TStringList;
i: Integer;
SrcEdit: TSourceEditor;
Encoding: String;
CurEncoding: string;
CurName: String;
@ -6840,7 +6877,6 @@ var
SysEncoding: String;
begin
SrcEditSubMenuEncoding.ChildsAsSubMenu:=true;
SrcEdit:=GetActiveSE;
Encoding:='';
if SrcEdit<>nil then begin
if SrcEdit.CodeBuffer<>nil then
@ -7038,6 +7074,7 @@ begin
AnEditor.OnMouseDown := @EditorMouseDown;
AnEditor.OnMouseWheel := @EditorMouseWheel;
AnEditor.OnKeyDown := @EditorKeyDown;
AnEditor.OnKeyUp := @EditorKeyUp;
AnEditor.EditorComponent.Beautifier.OnGetDesiredIndent := @EditorGetIndent;
AnEditor.EditorComponent.EndUpdate;
@ -8163,6 +8200,51 @@ begin
CheckCurrentCodeBufferChanged;
End;
procedure TSourceNotebook.UpdateTabPopUpMenu(ASrcEdit: TSourceEditor);
{$IFnDEF SingleSrcWindow}
function ToWindow(WinForFind: Boolean = False): Boolean;
var
i, ThisWin, SharedEditor: Integer;
nb: TSourceNotebook;
begin
Result := False;
ThisWin := Manager.IndexOfSourceWindow(self);
for i := 0 to Manager.SourceWindowCount - 1 do begin
nb:=Manager.SourceWindows[i];
SharedEditor:=nb.IndexOfEditorInShareWith(ASrcEdit);
if (i <> ThisWin) and ((SharedEditor < 0) <> WinForFind) then begin
Result := True;
Break;
end;
end;
end;
{$ENDIF}
var
NBAvail: Boolean;
begin
{$IFnDEF SingleSrcWindow}
SrcEditMenuEditorLock.Checked := ASrcEdit.IsLocked; // Editor locks
// Multi win
NBAvail := ToWindow();
SrcEditMenuMoveToNewWindow.Visible := not NBAvail;
SrcEditMenuMoveToNewWindow.Enabled := PageCount > 1;
SrcEditMenuMoveToOtherWindow.Visible := NBAvail;
SrcEditMenuMoveToOtherWindowNew.Enabled := PageCount > 1;
SrcEditMenuCopyToNewWindow.Visible := not NBAvail;
SrcEditMenuCopyToOtherWindow.Visible := NBAvail;
SrcEditMenuFindInOtherWindow.Enabled := NBAvail;
{$ENDIF}
// editor layout
SrcEditMenuMoveEditorLeft.Enabled:= (PageCount>1);
SrcEditMenuMoveEditorRight.Enabled:= (PageCount>1);
SrcEditMenuMoveEditorFirst.Enabled:= (PageCount>1) and (PageIndex>0);
SrcEditMenuMoveEditorLast.Enabled:= (PageCount>1) and (PageIndex<(PageCount-1));
end;
function TSourceNotebook.FindPageWithEditor(
ASourceEditor: TSourceEditor):integer;
var
@ -8636,6 +8718,12 @@ begin
end;
procedure TSourceNotebook.EditorKeyUp(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
end;
procedure TSourceNotebook.ShowSynEditHint(const MousePos: TPoint);
var
EditPos: TPoint;
@ -10130,9 +10218,20 @@ end;
procedure TSourceEditorManager.SetupShortCuts;
function GetCommand(ACommand: Word): TIDECommand; inline;
function GetCmdAndBtn(ACommand: word; out ToolButton: TIDEButtonCommand): TIDECommand;
begin
Result := IDECommandList.FindIDECommand(ACommand);
Result:=IDECommandList.FindIDECommand(ACommand);
if Result<>nil then
ToolButton := RegisterIDEButtonCommand(Result)
else
ToolButton := nil;
end;
function GetCommand(ACommand: word): TIDECommand;
var
ToolButton: TIDEButtonCommand;
begin
Result:=GetCmdAndBtn(ACommand, ToolButton);
end;
var
@ -10372,6 +10471,34 @@ begin
end;
end;
procedure TSourceEditorManager.UpdatePopUpMenus(Sender: TObject);
var
ASrcNB: TSourceNotebook;
I: Integer;
begin
if Screen.ActiveCustomForm is TSourceNotebook then
begin
ASrcNB:=TSourceNotebook(Screen.ActiveCustomForm);
end else
begin
ASrcNB:=nil;
for I := 0 to Screen.CustomFormZOrderCount-1 do
if Screen.CustomFormsZOrdered[I] is TSourceNotebook then
begin
ASrcNB:=TSourceNotebook(Screen.CustomFormsZOrdered[I]);
Break;
end;
end;
if (ASrcNB=nil) and (SourceWindowCount > 0) then
ASrcNB:=SourceWindows[0];
if (ASrcNB<>nil) and (ASrcNB.GetActiveSE<>nil) then
begin
ASrcNB.UpdateSrcPopUpMenu(ASrcNB.GetActiveSE);
ASrcNB.UpdateTabPopUpMenu(ASrcNB.GetActiveSE);
end;
end;
procedure TSourceEditorManager.BeginGlobalUpdate;
var
i: integer;
@ -10710,10 +10837,13 @@ begin
Application.AddOnIdleHandler(@OnIdle);
Application.AddOnUserInputHandler(@OnUserInput);
IDECommandList.AddCustomUpdateEvent(@UpdatePopUpMenus);
end;
destructor TSourceEditorManager.Destroy;
begin
IDECommandList.RemoveCustomUpdateEvent(@UpdatePopUpMenus);
FreeAndNil(FHints);
SourceEditorMarks.OnAction := nil;
Application.RemoveAllHandlersOfObject(Self);
@ -10817,12 +10947,12 @@ end;
procedure TSourceEditorManager.ToggleLineNumbersClicked(Sender: TObject);
var
MenuITem: TIDEMenuCommand;
MenuITem: TIDESpecialCommand;
ActEdit:TSourceEditor;
i: integer;
ShowLineNumbers: boolean;
begin
MenuItem := Sender as TIDEMenuCommand;
MenuItem := Sender as TIDESpecialCommand;
ActEdit:=ActiveEditor;
if ActEdit = nil then exit;

View File

@ -23,19 +23,19 @@ unit ToolbarConfig;
interface
uses
Classes, SysUtils, fgl,
Classes, SysUtils,
// LCL and LazControls
LCLProc, Forms, Graphics, Dialogs, ExtCtrls, Buttons, StdCtrls,
LCLProc, Forms, Graphics, ExtCtrls, Buttons, StdCtrls,
Controls, ComCtrls, Menus, ButtonPanel, TreeFilterEdit, LclIntf,
// IdeIntf
IDECommands, MenuIntf, IDEImagesIntf,
IDECommands, ToolBarIntf, IDEImagesIntf,
// IDE
LazarusIDEStrConsts;
type
{ TLvItem }
TLvItem = class (TObject)
Item: TIDEMenuItem;
Item: TIDEButtonCommand;
LvIndex: Integer;
end;
@ -93,10 +93,10 @@ type
procedure ExchangeMainListItem (Item1,Item2: TListItem);
procedure SetupCaptions;
procedure LoadCategories;
procedure AddMenuItem(ParentNode: TTreeNode; Item: TIDEMenuItem; Level: Integer);
function RootNodeCaption(Item: TIDEMenuItem): string;
procedure AddListItem(Item: TIDEMenuItem);
procedure AddToolBarItem(Item: TIDEMenuItem);
procedure AddMenuItem(ParentNode: TTreeNode; Item: TIDEButtonCommand);
function RootNodeCaption(Item: TIDEButtonCommand): string;
procedure AddListItem(Item: TIDEButtonCommand);
procedure AddToolBarItem(Item: TIDEButtonCommand);
procedure AddDivider;
procedure FillToolBar;
public
@ -104,15 +104,13 @@ type
procedure SaveSettings(SL: TStringList);
end;
TIDEMenuItemList = specialize TFPGList<TIDEMenuItem>;
{ TIDEToolbarBase }
TIDEToolbarBase = class(TComponent)
private
protected
FToolBar: TToolBar;
procedure AddButton(ACommand: TIDEMenuCommand);
procedure AddButton(ACommand: TIDEButtonCommand);
procedure AddDivider;
procedure PositionAtEnd(AToolBar: TToolBar; AButton: TToolButton);
public
@ -125,7 +123,6 @@ const
cIDEToolbarDivider = '---------------';
function ShowToolBarConfig(aNames: TStringList): TModalResult;
function GetShortcut(AMenuItem: TIDEMenuItem): string;
implementation
@ -148,23 +145,6 @@ begin
end;
end;
function GetShortcut(AMenuItem: TIDEMenuItem): string;
var
ACommand: TIDECommand;
AShortcut: string;
begin
Result := '';
AShortcut := '';
if AMenuItem is TIDEMenuCommand then
begin
ACommand := TIDEMenuCommand(AMenuItem).Command;
if Assigned(ACommand) then
AShortcut := ShortCutToText(ACommand.AsShortCut);
if AShortcut <> '' then
Result := ' (' + AShortcut + ')';
end;
end;
{ TToolBarConfig }
procedure TToolBarConfig.FormCreate(Sender: TObject);
@ -265,7 +245,7 @@ var
aMainListItem: TLvItem;
begin
aMainListItem := TLvItem.Create;
aMainListItem.Item := TIDEMenuItem(Item.Data);
aMainListItem.Item := TIDEButtonCommand(Item.Data);
aMainListItem.LvIndex := Item.Index;
if NextItem = Nil then
MainList.AddObject(Item.Caption,aMainListItem)
@ -320,7 +300,7 @@ begin
begin
btnAdd.Enabled := False;
anIndex:= lvToolbar.ItemIndex;
ACaption:= TIDEMenuItem(n.Data).Caption;
ACaption:= TIDEButtonCommand(n.Data).Caption;
DeleteAmpersands(ACaption);
if anIndex > -1 then
lvItem := lvToolbar.Items.Insert(lvToolbar.ItemIndex)
@ -355,7 +335,7 @@ end;
procedure TToolBarConfig.btnRemoveClick(Sender: TObject);
Var
mi: TIDEMenuItem;
mi: TIDEButtonCommand;
n: TTreeNode;
I: Integer;
lvItem: TListItem;
@ -363,7 +343,7 @@ begin
I := lvToolbar.ItemIndex;
if I > -1 then begin
lvItem := lvToolbar.Items[I];
mi := TIDEMenuItem(lvItem.Data);
mi := TIDEButtonCommand(lvItem.Data);
RemoveMainListItem(lvItem);
lvToolbar.Items.Delete(lvToolbar.ItemIndex);
if I < lvToolbar.Items.Count then
@ -371,7 +351,8 @@ begin
lbToolbarSelectionChange(lvToolbar);
if assigned(mi) then begin
n:= TV.Items.FindNodeWithData(mi);
n.Visible:= True;
if n<>nil then
n.Visible:= True;
end;
TVSelectionChanged(TV);
end;
@ -397,8 +378,8 @@ begin
if AItem.Caption = cIDEToolbarDivider then
ImageIndex := divImageIndex
else if Assigned(AItem.Data) and (TIDEMenuItem(AItem.Data).ImageIndex > -1) then
ImageIndex := TIDEMenuItem(AItem.Data).ImageIndex
else if Assigned(AItem.Data) and (TIDEButtonCommand(AItem.Data).ImageIndex > -1) then
ImageIndex := TIDEButtonCommand(AItem.Data).ImageIndex
else
ImageIndex := defImageIndex;
Image.Clear;
@ -486,62 +467,42 @@ end;
procedure TToolBarConfig.LoadCategories;
var
i: integer;
i, l: integer;
xCategory: TIDEToolButtonCategory;
xCaption: string;
n: TTreeNode;
begin
TV.Items.BeginUpdate;
try
TV.Items.Clear;
for i := 0 to IDEMenuRoots.Count-1 do
AddMenuItem(nil, IDEMenuRoots[i],0);
for i := 0 to IDEToolButtonCategories.Count-1 do
begin
xCategory := IDEToolButtonCategories[i];
xCaption := xCategory.Description;
DeleteAmpersands(xCaption);
n := TV.Items.AddChild(nil, Format('%s', [xCaption]));
for l := 0 to xCategory.ButtonCount-1 do
AddMenuItem(n, xCategory.Buttons[l]);
end;
finally
TV.Items.EndUpdate;
end;
end;
procedure TToolBarConfig.AddMenuItem(ParentNode: TTreeNode; Item: TIDEMenuItem; Level: Integer);
procedure TToolBarConfig.AddMenuItem(ParentNode: TTreeNode;
Item: TIDEButtonCommand);
var
n: TTreeNode;
i: integer;
sec: TIDEMenuSection;
ACaption: string;
hasCaption: boolean;
begin
if Item is TIDEMenuSection then
begin
if Item.Name <> Item.Caption then hasCaption:= true
else hasCaption:= false;
sec := (Item as TIDEMenuSection);
if sec.Count > 0 then begin // skip empty sections
if Level= 0 then ACaption:= RootNodeCaption(Item)
else begin
if hasCaption then ACaption:= Item.Caption
else ACaption:= '---';
end;
DeleteAmpersands(ACaption);
if (Level > 0) and ( not hasCaption) then n:= ParentNode
else begin
n := TV.Items.AddChild(ParentNode, Format('%s', [ACaption]));
n.ImageIndex := Item.ImageIndex;
n.SelectedIndex := Item.ImageIndex;
end;
for i := 0 to sec.Count-1 do
AddMenuItem(n, sec.Items[i],Level+1);
end;
end
else begin
if Item.Caption <> '-' then begin // workaround for HTML Editor dividers
ACaption:= Item.Caption;
DeleteAmpersands(ACaption);
ACaption:= ACaption + GetShortcut(Item);
n := TV.Items.AddChild(ParentNode, Format('%s', [ACaption]));
n.ImageIndex := Item.ImageIndex;
n.SelectedIndex := Item.ImageIndex;
n.Data := Item;
end;
if Item.Caption <> '-' then begin // workaround for HTML Editor dividers
n := TV.Items.AddChild(ParentNode, Format('%s', [Item.GetCaptionWithShortCut]));
n.ImageIndex := Item.ImageIndex;
n.SelectedIndex := Item.ImageIndex;
n.Data := Item;
end;
end;
function TToolBarConfig.RootNodeCaption(Item: TIDEMenuItem): string;
function TToolBarConfig.RootNodeCaption(Item: TIDEButtonCommand): string;
var
AName: string;
begin
@ -560,7 +521,7 @@ begin
end;
end;
procedure TToolBarConfig.AddListItem(Item: TIDEMenuItem);
procedure TToolBarConfig.AddListItem(Item: TIDEButtonCommand);
var
aListItem: TLvItem;
begin
@ -575,18 +536,14 @@ begin
end;
end;
procedure TToolBarConfig.AddToolBarItem(Item: TIDEMenuItem);
procedure TToolBarConfig.AddToolBarItem(Item: TIDEButtonCommand);
Var
n: TTreeNode;
ACaption: string;
lvItem: TListItem;
begin
if Assigned(Item) then begin
ACaption:= Item.Caption;
DeleteAmpersands(ACaption);
ACaption:= ACaption+GetShortcut(Item);
lvItem := lvToolbar.Items.Add;
lvItem.Caption:= ACaption;
lvItem.Caption:= Item.GetCaptionWithShortCut;
lvItem.Data:= Item;
{$IF not DEFINED(LCLQt)}
if Item.ImageIndex > -1 then
@ -596,7 +553,8 @@ begin
{$ENDIF}
// lvItem.SubItems.Add(IntToStr(PMask));
n:= TV.Items.FindNodeWithData(Item);
n.Visible:= False;
if n<>nil then
n.Visible:= False;
end;
end;
@ -617,7 +575,7 @@ var
I: Integer;
aListItem: TLvItem;
aCaption: string;
mi: TIDEMenuItem;
mi: TIDEButtonCommand;
begin
for I:= 0 to MainList.Count -1 do
begin
@ -636,7 +594,7 @@ procedure TToolBarConfig.LoadSettings(SL: TStringList);
var
I: Integer;
Value: string;
MI: TIDEMenuItem;
MI: TIDEButtonCommand;
begin
for I := 0 to SL.Count - 1 do
begin
@ -645,7 +603,7 @@ begin
if Value = cIDEToolbarDivider then
MI := nil
else
MI := IDEMenuRoots.FindByPath(Value, false);
MI := IDEToolButtonCategories.FindItemByMenuPathOrName(Value);
AddListItem(MI);
end;
FillToolBar;
@ -663,7 +621,7 @@ begin
if MainList[I] = cIDEToolbarDivider then
SL.Add(cIDEToolbarDivider)
else
SL.Add(lvItem.Item.GetPath);
SL.Add(lvItem.Item.Name);
end;
end;
@ -679,25 +637,20 @@ begin
inherited Destroy;
end;
}
procedure TIDEToolbarBase.AddButton(ACommand: TIDEMenuCommand);
procedure TIDEToolbarBase.AddButton(ACommand: TIDEButtonCommand);
var
B: TIDEToolButton;
ACaption: string;
begin
B := ACommand.ToolButtonClass.Create(FToolBar);
ACaption := ACommand.Caption;
DeleteAmpersands(ACaption);
B.Caption := ACaption;
// Get Shortcut if any, and append to Hint.
ACaption := ACaption + GetShortcut(ACommand);
B.Hint := ACaption;
B.Hint := ACommand.GetHintOrCaptionWithShortCut;
B.Enabled := ACommand.Enabled;
// If we have a image, use it. Otherwise supply a default.
if ACommand.ImageIndex <> -1 then
B.ImageIndex := ACommand.ImageIndex
else
B.ImageIndex := IDEImages.LoadImage(16, 'execute');
B.Style := tbsButton;
B.IdeMenuItem := ACommand;
B.Item := ACommand;
PositionAtEnd(FToolBar, B);
ACommand.ToolButtonAdded(B);
end;