IDE, Component Palette options: Refactoring. Implement "Restore defaults". Don't change settings when user clicks Cancel.

git-svn-id: trunk@46871 -
This commit is contained in:
juha 2014-11-18 00:01:51 +00:00
parent d01c453f5f
commit ca628990f5
5 changed files with 354 additions and 291 deletions

View File

@ -11,10 +11,11 @@
for details about the license.
*****************************************************************************
Author: Mattias Gaertner
Author: Mattias Gaertner, Juha Manninen
Abstract:
Interface to the component palette and the registered component classes.
Supports reordering of pages and components by user settings in environment options.
}
unit ComponentReg;
@ -53,33 +54,46 @@ type
TOnGetCreationClass = procedure(Sender: TObject;
var NewComponentClass: TComponentClass) of object;
{ TCompPaletteOptions }
{ TBaseCompPaletteOptions }
TCompPaletteOptions = class
private
FConfigStore: TConfigStorage;
TBaseCompPaletteOptions = class
protected
// Pages reordered by user.
FPageNames: TStringList;
// Pages removed or renamed. They must be hidden in the palette.
FHiddenPageNames: TStringList;
// List of page names with changed component contents.
// List of page names with component contents.
// Object holds another StringList for the component names.
FComponentPages: TStringList;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure ClearComponentPages;
procedure AssignComponentPages(aPageName: string; aList: TStringList);
procedure Assign(Source: TBaseCompPaletteOptions);
procedure AssignComponentPage(aPageName: string; aList: TStringList);
public
property PageNames: TStringList read FPageNames;
property ComponentPages: TStringList read FComponentPages;
end;
{ TCompPaletteOptions }
TCompPaletteOptions = class(TBaseCompPaletteOptions)
private
FConfigStore: TConfigStorage;
// Pages removed or renamed. They must be hidden in the palette.
FHiddenPageNames: TStringList;
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure Assign(Source: TCompPaletteOptions);
function Load: boolean;
function Save: boolean;
public
property ConfigStore: TConfigStorage read FConfigStore write FConfigStore;
property PageNames: TStringList read FPageNames;
property HiddenPageNames: TStringList read FHiddenPageNames;
property ComponentPages: TStringList read FComponentPages;
end;
{ TRegisteredComponent }
TRegisteredComponent = class
@ -87,8 +101,8 @@ type
FButton: TComponent;
FComponentClass: TComponentClass;
FOnGetCreationClass: TOnGetCreationClass;
FRealPage: TBaseComponentPage;
FOrigPageName: string;
FRealPage: TBaseComponentPage;
FVisible: boolean;
protected
procedure SetVisible(const AValue: boolean); virtual;
@ -111,7 +125,9 @@ type
property Button: TComponent read FButton write FButton;
property Visible: boolean read FVisible write SetVisible;
end;
TRegisteredComponentClass = class of TRegisteredComponent;
TRegisteredComponentList = specialize TFPGList<TRegisteredComponent>;
{ TBaseComponentPage }
@ -130,20 +146,18 @@ type
public
constructor Create(const ThePageName: string);
destructor Destroy; override;
function FindComponent(const CompClassName: string): TRegisteredComponent;
function FindButton(Button: TComponent): TRegisteredComponent;
procedure UpdateVisible;
function GetScrollBox: TScrollBox;
public
property PageName: string read FPageName;
property Palette: TBaseComponentPalette read FPalette;
property Palette: TBaseComponentPalette read FPalette write FPalette;
property Priority: TComponentPriority read FPriority write FPriority;
property PageComponent: TCustomPage read FPageComponent write FPageComponent;
property SelectButton: TComponent read FSelectButton write FSelectButton;
property Visible: boolean read FVisible write SetVisible;
end;
TBaseComponentPageClass = class of TBaseComponentPage;
TBaseComponentPageClass = class of TBaseComponentPage;
{ TBaseComponentPalette }
@ -159,18 +173,11 @@ type
TComponentAddedEvent = procedure of object;
RegisterUnitComponentProc = procedure(const Page, UnitName: ShortString;
ComponentClass: TComponentClass);
TBaseComponentPageList = specialize TFPGList<TBaseComponentPage>;
TPagePriorityList = specialize TFPGMap<String, TComponentPriority>;
TBaseComponentPalette = class
private
FPages: TList; // list of TBaseComponentPage
FComps: TList; // list of all TRegisteredComponent in all pages
// New pages added and their priorities, ordered by priority.
fOrigPagePriorities: TPagePriorityList;
// All pages, including the original ones, ordered by user. Contains page name +
// another StringList for component names, like TCompPaletteOptions.ComponentPages.
fPagesUserOrder: TStringList;
//
FHandlers: array[TComponentPaletteHandlerType] of TMethodList;
FBaseComponentPageClass: TBaseComponentPageClass;
FRegisteredComponentClass: TRegisteredComponentClass;
@ -179,14 +186,18 @@ type
FHideControls: boolean;
FUpdateLock: integer;
fChanged: boolean;
function GetPages(Index: integer): TBaseComponentPage;
function GetComps(Index: integer): TRegisteredComponent;
procedure AddHandler(HandlerType: TComponentPaletteHandlerType;
const AMethod: TMethod; AsLast: boolean = false);
procedure RemoveHandler(HandlerType: TComponentPaletteHandlerType;
const AMethod: TMethod);
procedure SetHideControls(const AValue: boolean);
protected
// List of pages, created based on fUserAndOrigPages data.
fPages: TBaseComponentPageList;
// List of all components in all pages.
fComps: TRegisteredComponentList;
// New pages added and their priorities, ordered by priority.
fOrigPagePriorities: TPagePriorityList;
procedure DoChange; virtual;
procedure DoBeginUpdate; virtual;
procedure DoEndUpdate(Changed: boolean); virtual;
@ -205,19 +216,14 @@ type
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure ClearButtons; virtual; abstract;
procedure BeginUpdate(Change: boolean);
procedure EndUpdate;
function IsUpdateLocked: boolean;
procedure DoAfterComponentAdded; virtual;
function PageCount: integer;
function GetPage(const APageName: string; aCaseSens: Boolean = False): TBaseComponentPage;
function IndexOfPageName(const APageName: string): integer;
function IndexOfPageWithName(const APageName: string): integer;
function CompCount: integer;
function GetPage(const APageName: string; aCaseSens: Boolean = False): TBaseComponentPage;
procedure AddComponent(NewComponent: TRegisteredComponent);
function CreateNewPage(const NewPageName: string;
const Priority: TComponentPriority): TBaseComponentPage;
procedure RemoveComponent(AComponent: TRegisteredComponent);
function FindComponent(const CompClassName: string): TRegisteredComponent; virtual;
function FindButton(Button: TComponent): TRegisteredComponent;
@ -238,8 +244,8 @@ type
procedure RemoveHandlerComponentAdded(
const OnComponentAddedEvent: TComponentAddedEvent);
public
property Pages[Index: integer]: TBaseComponentPage read GetPages; default;
property Comps[Index: integer]: TRegisteredComponent read GetComps;
property Pages: TBaseComponentPageList read fPages;
property Comps: TRegisteredComponentList read fComps;
property BaseComponentPageClass: TBaseComponentPageClass read FBaseComponentPageClass;
property RegisteredComponentClass: TRegisteredComponentClass
read FRegisteredComponentClass;
@ -249,7 +255,6 @@ type
property HideControls: boolean read FHideControls write SetHideControls;
property Selected: TRegisteredComponent read GetSelected write SetSelected;
property OrigPagePriorities: TPagePriorityList read fOrigPagePriorities;
property PagesUserOrder: TStringList read fPagesUserOrder;
end;
@ -306,26 +311,30 @@ begin
Result:='Cat='+dbgs(p.Category)+',Lvl='+IntToStr(p.Level);
end;
{ TCompPaletteOptions }
{ TBaseCompPaletteOptions }
constructor TCompPaletteOptions.Create;
constructor TBaseCompPaletteOptions.Create;
begin
inherited Create;
FPageNames := TStringList.Create;
FHiddenPageNames := TStringList.Create;
FComponentPages := TStringList.Create;
end;
destructor TCompPaletteOptions.Destroy;
destructor TBaseCompPaletteOptions.Destroy;
begin
ClearComponentPages;
FComponentPages.Free;
FHiddenPageNames.Free;
FPageNames.Free;
inherited Destroy;
end;
procedure TCompPaletteOptions.ClearComponentPages;
procedure TBaseCompPaletteOptions.Clear;
begin
FPageNames.Clear;
ClearComponentPages;
end;
procedure TBaseCompPaletteOptions.ClearComponentPages;
var
i: Integer;
begin
@ -334,7 +343,18 @@ begin
FComponentPages.Clear;
end;
procedure TCompPaletteOptions.AssignComponentPages(aPageName: string; aList: TStringList);
procedure TBaseCompPaletteOptions.Assign(Source: TBaseCompPaletteOptions);
var
i: Integer;
begin
FPageNames.Assign(Source.FPageNames);
ClearComponentPages;
for i:=0 to Source.FComponentPages.Count-1 do
AssignComponentPage(Source.FComponentPages[i],
TStringList(Source.FComponentPages.Objects[i]));
end;
procedure TBaseCompPaletteOptions.AssignComponentPage(aPageName: string; aList: TStringList);
var
sl: TStringList;
begin
@ -343,6 +363,32 @@ begin
FComponentPages.AddObject(aPageName, sl);
end;
{ TCompPaletteOptions }
constructor TCompPaletteOptions.Create;
begin
inherited Create;
FHiddenPageNames := TStringList.Create;
end;
destructor TCompPaletteOptions.Destroy;
begin
FHiddenPageNames.Free;
inherited Destroy;
end;
procedure TCompPaletteOptions.Clear;
begin
inherited Clear;
FHiddenPageNames.Clear;
end;
procedure TCompPaletteOptions.Assign(Source: TCompPaletteOptions);
begin
inherited Assign(Source);
FHiddenPageNames.Assign(Source.FHiddenPageNames);
end;
function TCompPaletteOptions.Load: boolean;
var
CompList: TStringList;
@ -502,6 +548,19 @@ end;
{ TBaseComponentPage }
constructor TBaseComponentPage.Create(const ThePageName: string);
begin
FPageName:=ThePageName;
FVisible:=FPageName<>'';
end;
destructor TBaseComponentPage.Destroy;
begin
FreeAndNil(FPageComponent);
FreeAndNil(FSelectButton);
inherited Destroy;
end;
procedure TBaseComponentPage.SetVisible(const AValue: boolean);
begin
if FVisible=AValue then exit;
@ -516,43 +575,6 @@ begin
FPalette.OnComponentVisibleChanged(AComponent);
end;
constructor TBaseComponentPage.Create(const ThePageName: string);
begin
FPageName:=ThePageName;
FVisible:=FPageName<>'';
end;
destructor TBaseComponentPage.Destroy;
begin
FreeAndNil(FPageComponent);
FreeAndNil(FSelectButton);
inherited Destroy;
end;
function TBaseComponentPage.FindComponent(const CompClassName: string): TRegisteredComponent;
var
i: Integer;
begin
for i:=0 to Palette.CompCount-1 do begin
Result:=Palette.Comps[i];
if (Result.RealPage = Self)
and (CompareText(Result.ComponentClass.ClassName,CompClassName) = 0) then
exit;
end;
Result:=nil;
end;
function TBaseComponentPage.FindButton(Button: TComponent): TRegisteredComponent;
var
i: Integer;
begin
for i:=0 to Palette.CompCount-1 do begin
Result:=Palette.Comps[i];
if Result.Button=Button then exit;
end;
Result:=nil;
end;
procedure TBaseComponentPage.UpdateVisible;
var
i: Integer;
@ -560,7 +582,7 @@ var
begin
if Palette = nil then Exit;
HasVisibleComponents:=false;
for i:=0 to Palette.CompCount-1 do
for i:=0 to Palette.Comps.Count-1 do
if (Palette.Comps[i].RealPage = Self) then
if Palette.UpdateVisible(Palette.Comps[i]) then
HasVisibleComponents:=true;
@ -578,14 +600,37 @@ end;
{ TBaseComponentPalette }
function TBaseComponentPalette.GetPages(Index: integer): TBaseComponentPage;
constructor TBaseComponentPalette.Create;
begin
Result:=TBaseComponentPage(FPages[Index]);
fPages:=TBaseComponentPageList.Create;
fComps:=TRegisteredComponentList.Create;
fOrigPagePriorities:=TPagePriorityList.Create;
end;
function TBaseComponentPalette.GetComps(Index: integer): TRegisteredComponent;
destructor TBaseComponentPalette.Destroy;
var
HandlerType: TComponentPaletteHandlerType;
begin
Result:=TRegisteredComponent(FComps[Index])
Clear;
FreeAndNil(fOrigPagePriorities);
FreeAndNil(fComps);
FreeAndNil(fPages);
for HandlerType:=Low(HandlerType) to High(HandlerType) do
FHandlers[HandlerType].Free;
inherited Destroy;
end;
procedure TBaseComponentPalette.Clear;
var
i: Integer;
begin
for i:=0 to fPages.Count-1 do
fPages[i].Free;
fPages.Clear;
for i:=0 to fComps.Count-1 do
fComps[i].RealPage:=nil;
fComps.Clear;
fOrigPagePriorities.Clear;
end;
procedure TBaseComponentPalette.AddHandler(HandlerType: TComponentPaletteHandlerType;
@ -684,44 +729,6 @@ begin
FRegisteredComponentClass:=AValue;
end;
constructor TBaseComponentPalette.Create;
begin
FPages:=TList.Create;
FComps:=TList.Create;
fOrigPagePriorities:=TPagePriorityList.Create;
fPagesUserOrder:=TStringList.Create;
end;
destructor TBaseComponentPalette.Destroy;
var
HandlerType: TComponentPaletteHandlerType;
i: Integer;
begin
Clear;
for i := 0 to fPagesUserOrder.Count-1 do
fPagesUserOrder.Objects[i].Free; // Free also contained StringLists.
FreeAndNil(fPagesUserOrder);
FreeAndNil(fOrigPagePriorities);
FreeAndNil(FComps);
FreeAndNil(FPages);
for HandlerType:=Low(HandlerType) to High(HandlerType) do
FHandlers[HandlerType].Free;
inherited Destroy;
end;
procedure TBaseComponentPalette.Clear;
var
i: Integer;
begin
ClearButtons;
for i:=0 to FComps.Count-1 do
Comps[i].RealPage:=nil;
FComps.Clear;
for i:=0 to FPages.Count-1 do
Pages[i].Free;
FPages.Clear;
end;
procedure TBaseComponentPalette.BeginUpdate(Change: boolean);
begin
inc(FUpdateLock);
@ -754,9 +761,18 @@ begin
TComponentAddedEvent(FHandlers[cphtComponentAdded][i])();
end;
function TBaseComponentPalette.PageCount: integer;
function TBaseComponentPalette.IndexOfPageName(const APageName: string): integer;
begin
Result:=FPages.Count;
Result:=Pages.Count-1; // Case sensitive search
while (Result>=0) and (Pages[Result].PageName <> APageName) do
dec(Result);
end;
function TBaseComponentPalette.IndexOfPageWithName(const APageName: string): integer;
begin
Result:=Pages.Count-1; // Case in-sensitive search
while (Result>=0) and (AnsiCompareText(Pages[Result].PageName,APageName)<>0) do
dec(Result);
end;
function TBaseComponentPalette.GetPage(const APageName: string;
@ -774,42 +790,24 @@ begin
Result:=nil;
end;
function TBaseComponentPalette.IndexOfPageName(const APageName: string): integer;
begin
Result:=PageCount-1; // Case sensitive search
while (Result>=0) and (Pages[Result].PageName <> APageName) do
dec(Result);
end;
function TBaseComponentPalette.IndexOfPageWithName(const APageName: string): integer;
begin
Result:=PageCount-1; // Case in-sensitive search
while (Result>=0) and (AnsiCompareText(Pages[Result].PageName,APageName)<>0) do
dec(Result);
end;
function TBaseComponentPalette.CompCount: integer;
begin
Result:=FComps.Count;
end;
procedure TBaseComponentPalette.AddComponent(NewComponent: TRegisteredComponent);
var
NewPriority: TComponentPriority;
InsertIndex: Integer;
begin
// Store components to FComps, sorting them by priority.
// Store components to fComps, sorting them by priority.
NewPriority:=NewComponent.GetPriority;
InsertIndex:=0;
while (InsertIndex<FComps.Count)
while (InsertIndex<fComps.Count)
and (ComparePriority(NewPriority,Comps[InsertIndex].GetPriority)<=0) do
inc(InsertIndex);
FComps.Insert(InsertIndex,NewComponent);
fComps.Insert(InsertIndex,NewComponent);
OnPageAddedComponent(NewComponent);
// Store a list of page names and their priorities.
if (NewComponent.OrigPageName <> '')
and (fOrigPagePriorities.IndexOf(NewComponent.OrigPageName) = -1) then begin
and (fOrigPagePriorities.IndexOf(NewComponent.OrigPageName) = -1) then
begin
InsertIndex:=0;
while (InsertIndex<fOrigPagePriorities.Count)
and (ComparePriority(NewPriority, fOrigPagePriorities.Data[InsertIndex])<=0) do
@ -818,26 +816,9 @@ begin
end;
end;
function TBaseComponentPalette.CreateNewPage(const NewPageName: string;
const Priority: TComponentPriority): TBaseComponentPage;
var
InsertIndex: Integer;
begin
Result:=TBaseComponentPage.Create(NewPageName);
Result.Priority:=Priority;
InsertIndex:=0;
while (InsertIndex<PageCount)
and (ComparePriority(Priority,Pages[InsertIndex].Priority)<=0) do
inc(InsertIndex);
FPages.Insert(InsertIndex,Result);
Result.FPalette:=Self;
if CompareText(NewPageName,'Hidden')=0 then
Result.Visible:=false;
end;
procedure TBaseComponentPalette.RemoveComponent(AComponent: TRegisteredComponent);
begin
FComps.Remove(AComponent);
fComps.Remove(AComponent);
AComponent.RealPage:=nil;
//ToDo: fix OnPageRemovedComponent(AComponent.RealPage,AComponent);
end;
@ -846,9 +827,10 @@ function TBaseComponentPalette.FindComponent(const CompClassName: string): TRegi
var
i: Integer;
begin
for i:=0 to PageCount-1 do begin
Result:=Pages[i].FindComponent(CompClassName);
if Result<>nil then exit;
for i:=0 to Comps.Count-1 do begin
Result:=Comps[i];
if CompareText(Result.ComponentClass.ClassName,CompClassName) = 0 then
exit;
end;
Result:=nil;
end;
@ -857,9 +839,9 @@ function TBaseComponentPalette.FindButton(Button: TComponent): TRegisteredCompon
var
i: Integer;
begin
for i:=0 to PageCount-1 do begin
Result:=Pages[i].FindButton(Button);
if Result<>nil then exit;
for i:=0 to Comps.Count-1 do begin
Result:=Comps[i];
if Result.Button=Button then exit;
end;
Result:=nil;
end;
@ -882,7 +864,7 @@ end;
function TBaseComponentPalette.IndexOfPageComponent(AComponent: TComponent): integer;
begin
if AComponent<>nil then begin
Result:=PageCount-1;
Result:=Pages.Count-1;
while (Result>=0) and (Pages[Result].PageComponent<>AComponent) do
dec(Result);
end else
@ -894,7 +876,7 @@ var
i: Integer;
begin
BeginUpdate(false);
for i:=0 to PageCount-1 do
for i:=0 to Pages.Count-1 do
Pages[i].UpdateVisible;
EndUpdate;
end;
@ -903,7 +885,7 @@ procedure TBaseComponentPalette.IterateRegisteredClasses(Proc: TGetComponentClas
var
i: Integer;
begin
for i:=0 to CompCount-1 do
for i:=0 to Comps.Count-1 do
Proc(Comps[i].ComponentClass);
end;

View File

@ -191,11 +191,11 @@ var
begin
if Assigned(IDEComponentPalette) then
begin
for i := 0 to IDEComponentPalette.PageCount-1 do
for i := 0 to IDEComponentPalette.Pages.Count-1 do
begin
APage := IDEComponentPalette.Pages[i];
if APage.Visible then
for j := 0 to IDEComponentPalette.CompCount-1 do
for j := 0 to IDEComponentPalette.Comps.Count-1 do
begin
AComponent := IDEComponentPalette.Comps[j];
if (AComponent.RealPage = APage)

View File

@ -25,10 +25,11 @@
* *
***************************************************************************
Author: Mattias Gaertner
Author: Mattias Gaertner, Juha Manninen
Abstract:
The implementation of the component palette.
Supports reordering of pages and components by user settings in environment options.
}
unit ComponentPalette;
@ -52,6 +53,24 @@ type
csmMulty // don't reset selection on component add
);
{ TCompPaletteUserOrder }
// Like TCompPaletteOptions but collects all pages and components,
// including the original ones. The palette is later synchronized with this.
TCompPaletteUserOrder = class(TBaseCompPaletteOptions)
private
fPalette: TBaseComponentPalette;
// Reference to either EnvironmentOptions.ComponentPaletteOptions or a copy of it.
fOptions: TCompPaletteOptions;
public
constructor Create(aPalette: TBaseComponentPalette);
destructor Destroy; override;
procedure Clear;
function SortPagesAndCompsUserOrder: Boolean;
public
property Options: TCompPaletteOptions read fOptions write fOptions;
end;
{ TComponentPalette }
TComponentPalette = class(TBaseComponentPalette)
@ -67,7 +86,8 @@ type
procedure PalettePopupMenuPopup(Sender: TObject);
procedure PopupMenuPopup(Sender: TObject);
private
fComponents: TAVLTree; // tree of TRegisteredComponent sorted for componentclass
// Tree of TRegisteredComponent sorted for componentclass
fComponents: TAVLTree;
FPageControl: TPageControl;
fNoteBookNeedsUpdate: boolean;
FOnOpenPackage: TNotifyEvent;
@ -78,6 +98,8 @@ type
fUnregisteredIcon: TCustomBitmap;
fSelectButtonIcon: TCustomBitmap;
fUpdatingPageControl: boolean;
// User ordered + original pages and components.
fUserOrder: TCompPaletteUserOrder;
procedure SetPageControl(const AValue: TPageControl);
procedure SelectionToolClick(Sender: TObject);
procedure ComponentBtnMouseDown(Sender: TObject; Button: TMouseButton;
@ -89,7 +111,6 @@ type
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
procedure CreatePopupMenu;
procedure UnselectAllButtons;
function SortPagesAndCompsUserOrder: Boolean;
protected
procedure DoBeginUpdate; override;
procedure DoEndUpdate(Changed: boolean); override;
@ -104,10 +125,14 @@ type
public
constructor Create;
destructor Destroy; override;
procedure Clear;
procedure ClearButtons;
function CreateNewPage(const NewPageName: string;
const Priority: TComponentPriority): TBaseComponentPage;
function CreatePagesFromUserOrder: Boolean;
procedure DoAfterComponentAdded; override;
function GetUnregisteredIcon: TCustomBitmap;
function GetSelectButtonIcon: TCustomBitmap;
procedure ClearButtons; override;
function SelectButton(Button: TComponent): boolean;
procedure ReAlignButtons(Page: TCustomPage);
procedure UpdateNoteBookButtons;
@ -124,6 +149,8 @@ type
property OnOpenPackage: TNotifyEvent read FOnOpenPackage write FOnOpenPackage;
property OnOpenUnit: TNotifyEvent read FOnOpenUnit write FOnOpenUnit;
property OnClassSelected: TNotifyEvent read FOnClassSelected write FOnClassSelected;
// User ordered + original pages and components.
property UserOrder: TCompPaletteUserOrder read fUserOrder;
end;
function CompareControlsWithTag(Control1, Control2: Pointer): integer;
@ -172,6 +199,66 @@ begin
Result:=0;
end;
{ TCompPaletteUserOrder }
constructor TCompPaletteUserOrder.Create(aPalette: TBaseComponentPalette);
begin
inherited Create;
fPalette:=aPalette;
end;
destructor TCompPaletteUserOrder.Destroy;
begin
Clear;
inherited Destroy;
end;
procedure TCompPaletteUserOrder.Clear;
begin
inherited Clear;
end;
function TCompPaletteUserOrder.SortPagesAndCompsUserOrder: Boolean;
// Calculate page order using user config and default order. User config takes priority.
// This order will finally be shown in the palette.
var
Comp: TRegisteredComponent;
DstComps: TStringList;
i, j: Integer;
PgName: String;
begin
Result:=True;
Clear;
// First add user defined page order from EnvironmentOptions,
FComponentPages.Assign(fOptions.PageNames);
// then add other pages which don't have user configuration
for i := 0 to fPalette.OrigPagePriorities.Count-1 do
begin
PgName:=fPalette.OrigPagePriorities.Keys[i];
if (FComponentPages.IndexOf(PgName) = -1)
and (fOptions.HiddenPageNames.IndexOf(PgName) = -1) then
FComponentPages.Add(PgName);
end;
// Map components with their pages
for i := 0 to FComponentPages.Count-1 do
begin
PgName := FComponentPages[i];
DstComps := TStringList.Create;
FComponentPages.Objects[i] := DstComps;
j := fOptions.ComponentPages.IndexOf(PgName);
if j >= 0 then
// Add components that were reordered by user
DstComps.Assign(fOptions.ComponentPages.Objects[j] as TStringList)
else
// Add components that were not reordered.
for j := 0 to fPalette.Comps.Count-1 do begin
Comp := fPalette.Comps[j];
if SameText(Comp.OrigPageName, PgName) then
DstComps.Add(Comp.ComponentClass.ClassName);
end;
end;
end;
{ TComponentPalette }
procedure TComponentPalette.ActivePageChanged(Sender: TObject);
@ -354,7 +441,7 @@ var
CurPage: TBaseComponentPage;
SelectButtonOnPage: TSpeedButton;
begin
for i:=0 to PageCount-1 do begin
for i:=0 to Pages.Count-1 do begin
CurPage:=Pages[i];
if (FSelected=nil) or (FSelected.RealPage<>CurPage) then begin
SelectButtonOnPage:=TSpeedButton(CurPage.SelectButton);
@ -486,7 +573,9 @@ end;
constructor TComponentPalette.Create;
begin
inherited Create;
FSelectionMode := csmSingle;
FSelectionMode:=csmSingle;
fUserOrder:=TCompPaletteUserOrder.Create(Self);
fUserOrder.Options:=EnvironmentOptions.ComponentPaletteOptions;
fComponents:=TAVLTree.Create(@CompareRegisteredComponents);
OnComponentIsInvisible:=@CheckComponentDesignerVisible;
end;
@ -497,6 +586,7 @@ begin
OnComponentIsInvisible:=nil;
PageControl:=nil;
FreeAndNil(fComponents);
FreeAndNil(fUserOrder);
FreeAndNil(fUnregisteredIcon);
FreeAndNil(fSelectButtonIcon);
FreeAndNil(PopupMenu);
@ -504,6 +594,70 @@ begin
inherited Destroy;
end;
procedure TComponentPalette.Clear;
begin
ClearButtons;
fUserOrder.Clear;
inherited Clear;
end;
procedure TComponentPalette.ClearButtons;
begin
if FPageControl<>nil then
FPageControl.DisableAlign;
Selected:=nil;
if PopupMenu<>nil then begin
PopupMenu.Free;
PopupMenu:=nil;
OpenPackageMenuItem:=nil;
end;
if FPageControl<>nil then
FPageControl.EnableAlign;
end;
function TComponentPalette.CreateNewPage(const NewPageName: string;
const Priority: TComponentPriority): TBaseComponentPage;
var
InsertIndex: Integer;
begin
Result:=TBaseComponentPage.Create(NewPageName);
Result.Priority:=Priority;
InsertIndex:=0;
while (InsertIndex<Pages.Count)
and (ComparePriority(Priority,Pages[InsertIndex].Priority)<=0) do
inc(InsertIndex);
fPages.Insert(InsertIndex,Result);
Result.Palette:=Self;
if CompareText(NewPageName,'Hidden')=0 then
Result.Visible:=false;
end;
function TComponentPalette.CreatePagesFromUserOrder: Boolean;
var
i, j: Integer;
PgName: String;
Pg: TBaseComponentPage;
CompNames: TStringList;
Comp: TRegisteredComponent;
begin
Result := True;
for i:=0 to fPages.Count-1 do
fPages[i].Free;
fPages.Clear;
for i := 0 to fUserOrder.ComponentPages.Count-1 do
begin
PgName := fUserOrder.ComponentPages[i];
Pg:=CreateNewPage(PgName, ComponentPriorityNormal);
CompNames := TStringList(fUserOrder.ComponentPages.Objects[i]);
for j := 0 to CompNames.Count-1 do
begin
Comp := FindComponent(CompNames[j]);
if Assigned(Comp) then
Comp.RealPage := Pg;
end;
end;
end;
procedure TComponentPalette.DoAfterComponentAdded;
begin
inherited DoAfterComponentAdded;
@ -529,21 +683,6 @@ begin
Result:=fSelectButtonIcon;
end;
procedure TComponentPalette.ClearButtons;
begin
if FPageControl<>nil then
FPageControl.DisableAlign;
Selected:=nil;
if PopupMenu<>nil then begin
PopupMenu.Free;
PopupMenu:=nil;
OpenPackageMenuItem:=nil;
end;
//inherited ClearButtons;
if FPageControl<>nil then
FPageControl.EnableAlign;
end;
function TComponentPalette.SelectButton(Button: TComponent): boolean;
var
NewComponent: TRegisteredComponent;
@ -623,71 +762,6 @@ begin
end;
end;
function TComponentPalette.SortPagesAndCompsUserOrder: Boolean;
// Calculate page order by user config and default order. User config takes priority.
// This order will be shown in the palette.
var
Pg: TBaseComponentPage;
Comp: TRegisteredComponent;
SrcComps, DstComps: TStringList;
i, DefPgInd, OptPgInd, CompInd: Integer;
PgName, CompName: String;
begin
Result := True;
for i:=0 to PagesUserOrder.Count-1 do
PagesUserOrder.Objects[i].Free; // Free also the contained StringList.
PagesUserOrder.Clear;
with EnvironmentOptions do begin
// First add user defined page order from EnvironmentOptions,
PagesUserOrder.Assign(ComponentPaletteOptions.PageNames);
// then add other pages which don't have user configuration
for DefPgInd := 0 to OrigPagePriorities.Count-1 do
begin
PgName:=OrigPagePriorities.Keys[DefPgInd];
if (PagesUserOrder.IndexOf(PgName) = -1)
and (ComponentPaletteOptions.HiddenPageNames.IndexOf(PgName) = -1) then
PagesUserOrder.Add(PgName);
end;
// Add pages and components for them
for i := 0 to PagesUserOrder.Count-1 do
begin
PgName := PagesUserOrder[i];
DefPgInd := IndexOfPageWithName(PgName);
if DefPgInd >= 0 then
Pg:=Pages[DefPgInd]
else begin
Pg:=CreateNewPage(PgName, ComponentPriorityNormal);
end;
DstComps := TStringList.Create;
PagesUserOrder.Objects[i] := DstComps;
OptPgInd := ComponentPaletteOptions.ComponentPages.IndexOf(PgName);
if OptPgInd >= 0 then
begin
// Add components that were reordered by user
SrcComps := ComponentPaletteOptions.ComponentPages.Objects[OptPgInd] as TStringList;
DstComps.Assign(SrcComps);
for CompInd := 0 to DstComps.Count-1 do
begin
CompName := DstComps[CompInd];
Comp := FindComponent(CompName);
Comp.RealPage := Pg;
end;
end
// Add components that were not reordered.
else begin
OptPgInd := CompCount;
for CompInd := 0 to CompCount-1 do begin
Comp := Comps[CompInd];
if SameText(Comp.OrigPageName, Pg.PageName) then begin
Comp.RealPage:=Pg;
DstComps.Add(Comp.ComponentClass.ClassName);
end;
end;
end;
end;
end;
end;
procedure TComponentPalette.UpdateNoteBookButtons;
var
OldActivePage: TTabSheet;
@ -884,22 +958,24 @@ begin
FPageControl.DisableAlign;
try
OldActivePage:=FPageControl.ActivePage;
SortPagesAndCompsUserOrder; // Updates PagesUserOrder
fUserOrder.SortPagesAndCompsUserOrder;
CreatePagesFromUserOrder;
// remove every page in the PageControl without a visible page
for i:=FPageControl.PageCount-1 downto 0 do
RemoveUnneededPage(FPageControl.Pages[i]);
// insert a PageControl page for every visible palette page
VisPageIndex := 0;
for i := 0 to PagesUserOrder.Count-1 do
for i := 0 to fUserOrder.ComponentPages.Count-1 do
begin
PgName := PagesUserOrder[i];
PgName := fUserOrder.ComponentPages[i];
PgInd := IndexOfPageName(PgName);
if PgInd >= 0 then
begin
InsertVisiblePage(Pages[PgInd], VisPageIndex);
CreateButtons(PgInd, PagesUserOrder.Objects[i] as TStringList);
CreateButtons(PgInd, fUserOrder.ComponentPages.Objects[i] as TStringList);
end;
end;
// restore active page
if (OldActivePage<>nil) and (FPageControl.IndexOf(OldActivePage) >= 0) then
FPageControl.ActivePage:=OldActivePage

View File

@ -28,7 +28,7 @@ uses
Classes, SysUtils,
Graphics, Forms, Controls, StdCtrls, Dialogs, Buttons, ComCtrls, ExtCtrls,
FileUtil, LCLProc, LCLType, IDEProcs, EnvironmentOpts, LazarusIDEStrConsts,
IDEOptionsIntf, IDEImagesIntf, ComponentReg, PackageDefs;
IDEOptionsIntf, IDEImagesIntf, ComponentReg, ComponentPalette, PackageDefs;
type
{ TCompPaletteOptionsFrame }
@ -69,6 +69,8 @@ type
procedure PagesListBoxSelectionChange(Sender: TObject; User: boolean);
procedure RestoreButtonClick(Sender: TObject);
private
fLocalOptions: TCompPaletteOptions;
fLocalUserOrder: TCompPaletteUserOrder;
procedure WritePages(cpo: TCompPaletteOptions);
procedure WriteComponents(cpo: TCompPaletteOptions);
procedure FillPages;
@ -101,12 +103,16 @@ end;
constructor TCompPaletteOptionsFrame.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
fLocalOptions:=TCompPaletteOptions.Create;
fLocalUserOrder:=TCompPaletteUserOrder.Create(IDEComponentPalette);
end;
destructor TCompPaletteOptionsFrame.Destroy;
var
i: Integer;
begin
fLocalUserOrder.Free;
fLocalOptions.Free;
for i := 0 to PagesListBox.Count-1 do
PagesListBox.Items.Objects[i].Free; // Free the contained StringList.
inherited Destroy;
@ -119,9 +125,9 @@ begin
RestoreButton.Caption := lisCmpRestoreDefaults;
ComponentsGroupBox.Caption := lisCmpLstComponents;
ComponentsListView.Column[1].Caption := lisName;
ComponentsListView.Column[2].Caption := lisPage;
ComponentsListView.Column[3].Caption := lisPackage;
ComponentsListView.Column[1].Caption := lisName;
ComponentsListView.Column[2].Caption := lisPage;
ComponentsListView.Column[3].Caption := lisPackage;
ComponentsListView.SmallImages := IDEImages.Images_24;
// Arrow buttons for pages
PageMoveUpBtn.LoadGlyphFromResourceName(HInstance, 'arrow_up');
@ -141,7 +147,9 @@ end;
procedure TCompPaletteOptionsFrame.ReadSettings(AOptions: TAbstractIDEOptions);
begin
// AOptions is not needed because data is already loaded to IDEComponentPalette.
fLocalOptions.Assign((AOptions as TEnvironmentOptions).ComponentPaletteOptions);
fLocalUserOrder.Options:=fLocalOptions;
fLocalUserOrder.SortPagesAndCompsUserOrder;
FillPages;
end;
@ -210,7 +218,7 @@ begin
if Assigned(Pg) then // Can be Nil if this page was added or renamed.
begin
// Collect original components from this page
for CompCnt := 0 to IDEComponentPalette.CompCount-1 do
for CompCnt := 0 to IDEComponentPalette.Comps.Count-1 do
begin
Comp := IDEComponentPalette.Comps[CompCnt];
if Comp.OrigPageName = PgName then
@ -219,7 +227,7 @@ begin
end;
// Differs from original order -> add configuration for components
if not OrigComps.Equals(UserComps) then
cpo.AssignComponentPages(PgName, UserComps);
cpo.AssignComponentPage(PgName, UserComps);
end;
finally
OrigComps.Free;
@ -227,9 +235,8 @@ begin
end;
procedure TCompPaletteOptionsFrame.FillPages;
//Collect all available components (excluding hidden)
// Collect all available components (excluding hidden)
var
Pg: TBaseComponentPage;
CompList: TStringList;
i: Integer;
PgName: String;
@ -238,17 +245,13 @@ begin
begin
PagesListBox.Clear;
PagesListBox.Items.Add(lis_All_);
for i := 0 to IDEComponentPalette.PagesUserOrder.Count-1 do
for i := 0 to fLocalUserOrder.ComponentPages.Count-1 do
begin
PgName := IDEComponentPalette.PagesUserOrder[i];
Pg := IDEComponentPalette.GetPage(PgName, True);
Assert(Assigned(Pg), 'TCompPaletteOptionsFrame.FillPages: PageName "'+PgName+'" not found.');
if (Pg<>nil) and Pg.Visible then
begin // StringList will hold components for this page.
CompList := TStringList.Create;
InitialComps(Pg.PageName, CompList);
PagesListBox.AddItem(Pg.PageName, CompList);
end;
PgName := fLocalUserOrder.ComponentPages[i];
Assert(PgName<>'', 'TCompPaletteOptionsFrame.FillPages: PageName is empty.');
CompList := TStringList.Create; // StringList will hold components for this page.
InitialComps(PgName, CompList);
PagesListBox.AddItem(PgName, CompList);
end;
PagesListBox.ItemIndex := 0; // Activate first item
end;
@ -261,11 +264,11 @@ var
i, PgInd: Integer;
CompName: String;
begin
PgInd := IDEComponentPalette.PagesUserOrder.IndexOf(aPageName);
PgInd := fLocalUserOrder.ComponentPages.IndexOf(aPageName);
Assert(PgInd > -1, 'TCompPaletteOptionsFrame.InitialComps: PageName "'+aPageName+'" not found');
if PgInd>=0 then
begin
OrderedComps := IDEComponentPalette.PagesUserOrder.Objects[PgInd] as TStringList;
OrderedComps := fLocalUserOrder.ComponentPages.Objects[PgInd] as TStringList;
for i := 0 to OrderedComps.Count-1 do
begin
CompName := OrderedComps[i];
@ -333,7 +336,9 @@ end;
procedure TCompPaletteOptionsFrame.RestoreButtonClick(Sender: TObject);
begin
; // ToDo
fLocalOptions.Clear;
fLocalUserOrder.SortPagesAndCompsUserOrder; // Only updates data structure.
FillPages;
end;
// Drag-drop PagesListBox

View File

@ -1343,8 +1343,8 @@ var
begin
// get all current pagenames (excluding the hidden page)
sl:=TStringList.Create;
for i:=0 to IDEComponentPalette.PageCount-1 do begin
APageName:=IDEComponentPalette[i].PageName;
for i:=0 to IDEComponentPalette.Pages.Count-1 do begin
APageName:=IDEComponentPalette.Pages[i].PageName;
if APageName<>'' then
sl.Add(APageName);
end;