{
Double Commander
-------------------------------------------------------------------------
Options frame page
Copyright (C) 2006-2020 Alexander Koblov (alexx2000@mail.ru)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
}
unit fOptionsFrame;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, fgl;
type
TOptionsEditorInitFlag = (oeifLoad);
TOptionsEditorInitFlags = set of TOptionsEditorInitFlag;
TOptionsEditorSaveFlag = (oesfNeedsRestart);
TOptionsEditorSaveFlags = set of TOptionsEditorSaveFlag;
TOptionsEditor = class;
TOptionsEditorClass = class of TOptionsEditor;
TOptionsEditorClassList = class;
{ IOptionsDialog }
{$interfaces corba}
IOptionsDialog = interface
['{E62AAF5E-74ED-49AB-93F2-DBE210BF6723}']
procedure LoadSettings;
function GetEditor(EditorClass: TOptionsEditorClass): TOptionsEditor;
end;
{$interfaces default}
{ TOptionsEditor }
// Regarding warning to user when attempting to exit configuration window or "option editor" without having saved a modified setting:
// 1o) Immediately after having load the options in "LoadSettings", we will compute a signature,
// which is a CRC32 of the related settings and memorize it.
// 2o) When will attempt to close options, we'll recalculate again this signature, if it is different,
// we know user has change something and will prompt user to validate if he wants to save, discard or cancel quit.
// 3o) For many option editors, signature may be computed simply by validating actual controls of the window like
// checkboxes state, edit box, etc.
// 4o) For others, we need to run specific computation like signature of list like hot directories list, favorites tabs list, etc.
// 5o) For some computing the signature with controls should not be done.
// 6o) Here is a list of function and procedure around that:
// 7o) "IsSignatureComputedFromAllWindowComponents": Function that may be overloaded by specific option editor to indicate
// if we may compute signature of controls of the editor or not.
// By default, it is the case.
// 8o) "ExtraOptionsSignature": Function that may overloaded by specifica option editor when signature must include extra element not present in controls of the editor like a list of structures, etc.
// By default, nothing more is required.
// 9o) "ComputeCompleteOptionsSignature": Will first compute signature based on controls >IF< "IsSignatureComputedFromAllWindowComponents" is not invalidated by specific option editor
// Then will make progress that signature >IF< "ExtraOptionsSignature" has been overload by specific option editor.
TOptionsEditor = class(TFrame)
private
FOptionsDialog: IOptionsDialog;
FLastLoadedOptionSignature: dword;
protected
procedure Init; virtual;
procedure Done; virtual;
procedure Load; virtual;
function Save: TOptionsEditorSaveFlags; virtual;
property OptionsDialog: IOptionsDialog read FOptionsDialog;
public
property LastLoadedOptionSignature:dword read FLastLoadedOptionSignature write FLastLoadedOptionSignature; // Let it public so Options Forms will be able to know what was initial signature.
destructor Destroy; override;
class function GetIconIndex: Integer; virtual; abstract;
class function GetTitle: String; virtual; abstract;
class function IsEmpty: Boolean; virtual;
function IsSignatureComputedFromAllWindowComponents: Boolean; virtual;
function ComputeCompleteOptionsSignature: dword;
function ExtraOptionsSignature(CurrentSignature:dword):dword; virtual;
function CanWeClose(var SaveFlags:TOptionsEditorSaveFlags; bForceClose:boolean=false):boolean; virtual;
procedure LoadSettings;
function SaveSettings: TOptionsEditorSaveFlags;
procedure Init(AParent: TWinControl;
AOptionsDialog: IOptionsDialog;
Flags: TOptionsEditorInitFlags);
end;
{ TOptionsEditorRec }
TOptionsEditorRec = class
private
FChildren: TOptionsEditorClassList;
FEditorClass: TOptionsEditorClass;
function GetChildren: TOptionsEditorClassList;
public
constructor Create;
destructor Destroy; override;
function Add(Editor: TOptionsEditorClass): TOptionsEditorRec;
function HasChildren: Boolean;
property Children: TOptionsEditorClassList read GetChildren;
property EditorClass: TOptionsEditorClass read FEditorClass write FEditorClass;
end;
{ TBaseOptionsEditorClassList }
TBaseOptionsEditorClassList = specialize TFPGObjectList;
{ TOptionsEditorClassList }
TOptionsEditorClassList = class(TBaseOptionsEditorClassList)
public
function Add(Editor: TOptionsEditorClass): TOptionsEditorRec; overload;
end;
var
OptionsEditorClassList: TOptionsEditorClassList = nil;
implementation
uses
uLng,
uComponentsSignature,
uShowMsg,
fOptions,
fOptionsArchivers,
fOptionsAutoRefresh,
fOptionsBehavior,
fOptionsBriefView,
fOptionsColumnsView,
fOptionsConfiguration,
fOptionsCustomColumns,
fOptionsDragDrop,
fOptionsDrivesListButton,
fOptionsTreeViewMenu,
fOptionsTreeViewMenuColor,
fOptionsFileOperations,
fOptionsFileSearch,
fOptionsMultiRename,
fOptionsFilePanelsColors,
fOptionsFileTypesColors,
fOptionsFilesViews,
fOptionsFilesViewsComplement,
fOptionsFonts,
fOptionsGroups,
fOptionsHotkeys,
{$IFDEF DARWIN}
fOptionsiCloud,
{$ENDIF}
fOptionsIcons,
fOptionsIgnoreList,
fOptionsKeyboard,
fOptionsLanguage,
fOptionsLayout,
fOptionsLog,
fOptionsMisc,
fOptionsMouse,
fOptionsPluginsGroup,
fOptionsPluginsDSX,
fOptionsPluginsWCX,
fOptionsPluginsWDX,
fOptionsPluginsWFX,
fOptionsPluginsWLX,
fOptionsQuickSearchFilter,
fOptionsTabs,
fOptionsFavoriteTabs,
fOptionsTabsExtra,
fOptionsTerminal,
fOptionsToolbar,
fOptionsToolbarExtra,
fOptionsToolbarMiddle,
fOptionsTools,
fOptionsToolsEditor,
fOptionsToolsDiffer,
fOptionsEditorColors,
fOptionsToolTips,
fOptionsFileAssoc,
fOptionsFileAssocExtra,
fOptionsDirectoryHotlist,
fOptionsDirectoryHotlistExtra,
fOptionsColors
;
{ TOptionsEditorRec }
function TOptionsEditorRec.GetChildren: TOptionsEditorClassList;
begin
if not Assigned(FChildren) then
FChildren := TOptionsEditorClassList.Create;
Result := FChildren;
end;
constructor TOptionsEditorRec.Create;
begin
FChildren := nil;
end;
destructor TOptionsEditorRec.Destroy;
begin
inherited Destroy;
FreeAndNil(FChildren);
end;
function TOptionsEditorRec.Add(Editor: TOptionsEditorClass): TOptionsEditorRec;
begin
Result := Children.Add(Editor);
end;
function TOptionsEditorRec.HasChildren: Boolean;
begin
Result := Assigned(FChildren) and (FChildren.Count > 0);
end;
{ TOptionsEditorClassList }
function TOptionsEditorClassList.Add(Editor: TOptionsEditorClass): TOptionsEditorRec;
begin
Result := TOptionsEditorRec.Create;
Add(Result);
Result.EditorClass:= Editor;
end;
{ TOptionsEditor }
procedure TOptionsEditor.Init;
begin
// Empty.
end;
{ TOptionsEditor.ExtraOptionsSignature }
function TOptionsEditor.ExtraOptionsSignature(CurrentSignature:dword):dword;
begin
result := CurrentSignature;
end;
{ TOptionsEditor.ComputeCompleteOptionsSignature }
function TOptionsEditor.ComputeCompleteOptionsSignature:dword;
begin
result := $000000;
if IsSignatureComputedFromAllWindowComponents then
result := ComputeSignatureBasedOnComponent(Self, result);
result := ExtraOptionsSignature(result);
end;
{ TOptionsEditor.CanWeClose }
function TOptionsEditor.CanWeClose(var SaveFlags:TOptionsEditorSaveFlags; bForceClose:boolean=false):boolean;
var
Answer: TMyMsgResult;
begin
SaveFlags:=[];
if bForceClose then
result:=True
else
result := (FLastLoadedOptionSignature = ComputeCompleteOptionsSignature);
if (not result) OR bForceClose then
begin
if bForceClose then
begin
Answer:=mmrYes;
end
else
begin
ShowOptions(Self.ClassName);
Answer := MsgBox(Format(rsOptionsEditorOptionsChanged, [GetTitle]), [msmbYes, msmbNo, msmbCancel], msmbCancel, msmbCancel);
end;
case Answer of
mmrYes:
begin
SaveFlags := SaveSettings;
result := True;
end;
mmrNo: result := True;
else
result := False;
end;
end;
end;
procedure TOptionsEditor.Done;
begin
// Empty.
end;
destructor TOptionsEditor.Destroy;
begin
Done;
inherited Destroy;
end;
class function TOptionsEditor.IsEmpty: Boolean;
begin
Result := False;
end;
{ TOptionsEditor.IsSignatureComputedFromAllWindowComponents }
function TOptionsEditor.IsSignatureComputedFromAllWindowComponents: Boolean;
begin
Result := True;
end;
procedure TOptionsEditor.LoadSettings;
begin
DisableAutoSizing;
try
Load;
FLastLoadedOptionSignature := ComputeCompleteOptionsSignature;
finally
EnableAutoSizing;
end;
end;
function TOptionsEditor.SaveSettings: TOptionsEditorSaveFlags;
begin
Result := Save;
FLastLoadedOptionSignature := ComputeCompleteOptionsSignature;
end;
procedure TOptionsEditor.Load;
begin
// Empty.
end;
function TOptionsEditor.Save: TOptionsEditorSaveFlags;
begin
Result := [];
end;
procedure TOptionsEditor.Init(AParent: TWinControl;
AOptionsDialog: IOptionsDialog;
Flags: TOptionsEditorInitFlags);
begin
DisableAutoSizing;
try
Parent := AParent;
FOptionsDialog := AOptionsDialog;
Init;
if oeifLoad in Flags then
LoadSettings;
finally
EnableAutoSizing;
end;
end;
procedure MakeEditorsClassList;
var
Main: TOptionsEditorClassList absolute OptionsEditorClassList;
Colors, ColumnsView, FilesViews, Keyboard, Layout, Mouse, Tools, Editor,
FileAssoc, ToolbarConfig, FileOperation, FolderTabs, Plugins,
DirectoryHotlistConfig: TOptionsEditorRec;
begin
Main.Add(TfrmOptionsLanguage);
Main.Add(TfrmOptionsBehavior);
Tools := Main.Add(TOptionsToolsGroup);
Tools.Add(TfrmOptionsViewer);
Editor:= Tools.Add(TfrmOptionsEditor);
Editor.Add(TfrmOptionsEditorColors);
Tools.Add(TfrmOptionsDiffer);
Tools.Add(TfrmOptionsTerminal);
Main.Add(TfrmOptionsFonts);
Colors := Main.Add(TfrmOptionsColors);
Colors.Add(TfrmOptionsFilePanelsColors);
Colors.Add(TfrmOptionsFileTypesColors);
Keyboard := Main.Add(TfrmOptionsKeyboard);
Keyboard.Add(TfrmOptionsHotkeys);
Mouse := Main.Add(TfrmOptionsMouse);
Mouse.Add(TfrmOptionsDragDrop);
FilesViews := Main.Add(TfrmOptionsFilesViews);
FilesViews.Add(TfrmOptionsFilesViewsComplement);
FilesViews.Add(TfrmOptionsBriefView);
ColumnsView := FilesViews.Add(TfrmOptionsColumnsView);
ColumnsView.Add(TfrmOptionsCustomColumns);
Plugins := Main.Add(TfrmOptionsPluginsGroup);
Plugins.Add(TfrmOptionsPluginsDSX);
Plugins.Add(TfrmOptionsPluginsWCX);
Plugins.Add(TfrmOptionsPluginsWDX);
Plugins.Add(TfrmOptionsPluginsWFX);
Plugins.Add(TfrmOptionsPluginsWLX);
Layout := Main.Add(TfrmOptionsLayout);
Layout.Add(TfrmOptionsDrivesListButton);
Layout.Add(TfrmOptionsTreeViewMenu);
Layout.Add(TfrmOptionsTreeViewMenuColor);
ToolbarConfig := Main.Add(TfrmOptionsToolbar);
ToolbarConfig.Add(TfrmOptionsToolbarMiddle);
ToolbarConfig.Add(TfrmOptionsToolbarExtra);
FileOperation := Main.Add(TfrmOptionsFileOperations);
FileOperation.Add(TfrmOptionsFileSearch);
FileOperation.Add(TfrmOptionsMultiRename);
FolderTabs := Main.Add(TfrmOptionsTabs);
FolderTabs.Add(TfrmOptionsFavoriteTabs);
FolderTabs.Add(TfrmOptionsTabsExtra);
Main.Add(TfrmOptionsLog);
Main.Add(TfrmOptionsConfiguration);
Main.Add(TfrmOptionsQuickSearchFilter);
Main.Add(TfrmOptionsMisc);
Main.Add(TfrmOptionsAutoRefresh);
{$IFDEF DARWIN}
Main.Add(TfrmOptionsiCloud);
{$ENDIF}
Main.Add(TfrmOptionsIcons);
Main.Add(TfrmOptionsIgnoreList);
Main.Add(TfrmOptionsArchivers);
Main.Add(TfrmOptionsToolTips);
FileAssoc := Main.Add(TfrmOptionsFileAssoc);
FileAssoc.Add(TfrmOptionsFileAssocExtra);
DirectoryHotlistConfig := Main.Add(TfrmOptionsDirectoryHotlist);
DirectoryHotlistConfig.Add(TfrmOptionsDirectoryHotlistExtra);
end;
initialization
OptionsEditorClassList:= TOptionsEditorClassList.Create;
MakeEditorsClassList;
finalization
if Assigned(OptionsEditorClassList) then
FreeAndNil(OptionsEditorClassList);
end.