590 lines
15 KiB
ObjectPascal
590 lines
15 KiB
ObjectPascal
{
|
|
Double Commander
|
|
-------------------------------------------------------------------------
|
|
Basic tool items types for KASToolBar
|
|
|
|
Copyright (C) 2012 Przemyslaw Nagay (cobines@gmail.com)
|
|
|
|
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, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
}
|
|
|
|
unit KASToolItems;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, DCXmlConfig, DCBasicTypes;
|
|
|
|
type
|
|
TKASToolBarItems = class;
|
|
TKASToolItem = class;
|
|
|
|
TOnLoadToolItem = procedure (Item: TKASToolItem) of object;
|
|
|
|
{$interfaces corba}
|
|
IToolOwner = interface
|
|
['{A7908D38-1E13-4E8D-8FA7-8830A2FF9290}']
|
|
function ExecuteToolItem(Item: TKASToolItem): Boolean;
|
|
function GetToolItemShortcutsHint(Item: TKASToolItem): String;
|
|
end;
|
|
{$interfaces default}
|
|
|
|
{ TKASToolBarLoader }
|
|
|
|
TKASToolBarLoader = class
|
|
protected
|
|
function CreateItem(Node: TXmlNode): TKASToolItem; virtual;
|
|
public
|
|
procedure Load(Config: TXmlConfig; RootNode: TXmlNode; OnLoadToolItem: TOnLoadToolItem); virtual;
|
|
end;
|
|
|
|
{ TKASToolItem }
|
|
|
|
TKASToolItem = class
|
|
private
|
|
FToolOwner: IToolOwner;
|
|
FUserData: Pointer;
|
|
protected
|
|
property ToolOwner: IToolOwner read FToolOwner;
|
|
public
|
|
procedure Assign(OtherItem: TKASToolItem); virtual;
|
|
function CheckExecute(ToolItemID: String): Boolean; virtual;
|
|
function Clone: TKASToolItem; virtual; abstract;
|
|
function ConfigNodeName: String; virtual; abstract;
|
|
function GetEffectiveHint: String; virtual; abstract;
|
|
function GetEffectiveText: String; virtual; abstract;
|
|
procedure Load(Config: TXmlConfig; Node: TXmlNode; Loader: TKASToolBarLoader); virtual; abstract;
|
|
procedure Save(Config: TXmlConfig; Node: TXmlNode);
|
|
procedure SaveContents(Config: TXmlConfig; Node: TXmlNode); virtual; abstract;
|
|
procedure SetToolOwner(AToolOwner: IToolOwner); virtual;
|
|
property UserData: Pointer read FUserData write FUserData;
|
|
end;
|
|
TKASToolItemClass = class of TKASToolItem;
|
|
|
|
{ TKASSeparatorItem }
|
|
|
|
TKASSeparatorItem = class(TKASToolItem)
|
|
procedure Assign(OtherItem: TKASToolItem); override;
|
|
function Clone: TKASToolItem; override;
|
|
function ConfigNodeName: String; override;
|
|
function GetEffectiveHint: String; override;
|
|
function GetEffectiveText: String; override;
|
|
procedure Load(Config: TXmlConfig; Node: TXmlNode; Loader: TKASToolBarLoader); override;
|
|
procedure SaveContents(Config: TXmlConfig; Node: TXmlNode); override;
|
|
end;
|
|
|
|
{ TKASNormalItem }
|
|
|
|
TKASNormalItem = class(TKASToolItem)
|
|
strict private
|
|
FID: String; // Unique identificator of the button
|
|
function GetID: String;
|
|
strict protected
|
|
procedure SaveHint(Config: TXmlConfig; Node: TXmlNode); virtual;
|
|
procedure SaveIcon(Config: TXmlConfig; Node: TXmlNode); virtual;
|
|
procedure SaveText(Config: TXmlConfig; Node: TXmlNode); virtual;
|
|
public
|
|
Icon: String;
|
|
Text: String;
|
|
Hint: String;
|
|
procedure Assign(OtherItem: TKASToolItem); override;
|
|
function CheckExecute(ToolItemID: String): Boolean; override;
|
|
function Clone: TKASToolItem; override;
|
|
function ConfigNodeName: String; override;
|
|
function GetEffectiveHint: String; override;
|
|
function GetEffectiveText: String; override;
|
|
function GetShortcutsHint: String;
|
|
procedure Load(Config: TXmlConfig; Node: TXmlNode; Loader: TKASToolBarLoader); override;
|
|
procedure SaveContents(Config: TXmlConfig; Node: TXmlNode); override;
|
|
property ID: String read GetID;
|
|
end;
|
|
|
|
{ TKASMenuItem }
|
|
|
|
TKASMenuItem = class(TKASNormalItem)
|
|
procedure ToolItemLoaded(Item: TKASToolItem);
|
|
private
|
|
FItems: TKASToolBarItems;
|
|
public
|
|
constructor Create; reintroduce;
|
|
destructor Destroy; override;
|
|
procedure Assign(OtherItem: TKASToolItem); override;
|
|
function CheckExecute(ToolItemID: String): Boolean; override;
|
|
function Clone: TKASToolItem; override;
|
|
function ConfigNodeName: String; override;
|
|
procedure Load(Config: TXmlConfig; Node: TXmlNode; Loader: TKASToolBarLoader); override;
|
|
procedure SaveContents(Config: TXmlConfig; Node: TXmlNode); override;
|
|
procedure SetToolOwner(AToolOwner: IToolOwner); override;
|
|
property SubItems: TKASToolBarItems read FItems;
|
|
end;
|
|
|
|
{ TKASToolBarItems }
|
|
|
|
TKASToolBarItems = class
|
|
private
|
|
FButtons: TFPList;
|
|
function GetButton(Index: Integer): TKASToolItem;
|
|
function GetButtonCount: Integer;
|
|
procedure SetButton(Index: Integer; const AValue: TKASToolItem);
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
function Add(Item: TKASToolItem): Integer;
|
|
procedure Clear;
|
|
function Insert(InsertAt: Integer; Item: TKASToolItem): Integer;
|
|
procedure Move(FromIndex, ToIndex: Integer);
|
|
{en
|
|
Returns the item at Index, removes it from the list but does not free it like Remove.
|
|
}
|
|
function ReleaseItem(Index: Integer): TKASToolItem;
|
|
procedure Remove(Index: Integer);
|
|
property Count: Integer read GetButtonCount;
|
|
property Items[Index: Integer]: TKASToolItem read GetButton write SetButton; default;
|
|
end;
|
|
|
|
{ TKASToolBarSerializer }
|
|
|
|
TKASToolBarSerializer = class
|
|
private
|
|
FDeserializedItem: TKASToolItem;
|
|
procedure SetDeserializedItem(Item: TKASToolItem);
|
|
public
|
|
function Deserialize(Stream: TStream; Loader: TKASToolBarLoader): TKASToolItem;
|
|
procedure Serialize(Stream: TStream; Item: TKASToolItem);
|
|
end;
|
|
|
|
const
|
|
MenuItemConfigNode = 'Menu';
|
|
NormalItemConfigNode = 'Normal';
|
|
SeparatorItemConfigNode = 'Separator';
|
|
|
|
implementation
|
|
|
|
uses
|
|
DCStrUtils;
|
|
|
|
{ TKASToolItem }
|
|
|
|
procedure TKASToolItem.Assign(OtherItem: TKASToolItem);
|
|
begin
|
|
FUserData := OtherItem.FUserData;
|
|
end;
|
|
|
|
function TKASToolItem.CheckExecute(ToolItemID: String): Boolean;
|
|
begin
|
|
Result := False;
|
|
end;
|
|
|
|
procedure TKASToolItem.Save(Config: TXmlConfig; Node: TXmlNode);
|
|
begin
|
|
Node := Config.AddNode(Node, ConfigNodeName);
|
|
SaveContents(Config, Node);
|
|
end;
|
|
|
|
procedure TKASToolItem.SetToolOwner(AToolOwner: IToolOwner);
|
|
begin
|
|
FToolOwner := AToolOwner;
|
|
end;
|
|
|
|
{ TKASToolBarSerializer }
|
|
|
|
function TKASToolBarSerializer.Deserialize(Stream: TStream; Loader: TKASToolBarLoader): TKASToolItem;
|
|
var
|
|
Config: TXmlConfig;
|
|
begin
|
|
Result := nil;
|
|
FDeserializedItem := nil;
|
|
Config := TXmlConfig.Create;
|
|
try
|
|
Config.ReadFromStream(Stream);
|
|
Loader.Load(Config, Config.RootNode, @SetDeserializedItem);
|
|
Result := FDeserializedItem;
|
|
finally
|
|
Config.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TKASToolBarSerializer.Serialize(Stream: TStream; Item: TKASToolItem);
|
|
var
|
|
Config: TXmlConfig;
|
|
begin
|
|
Config := TXmlConfig.Create;
|
|
try
|
|
Item.Save(Config, Config.RootNode);
|
|
Config.WriteToStream(Stream);
|
|
finally
|
|
Config.Free;
|
|
end;
|
|
end;
|
|
|
|
procedure TKASToolBarSerializer.SetDeserializedItem(Item: TKASToolItem);
|
|
begin
|
|
FDeserializedItem := Item;
|
|
end;
|
|
|
|
{ TKASToolBarLoader }
|
|
|
|
function TKASToolBarLoader.CreateItem(Node: TXmlNode): TKASToolItem;
|
|
begin
|
|
if Node.CompareName(MenuItemConfigNode) = 0 then
|
|
Result := TKASMenuItem.Create
|
|
else if Node.CompareName(NormalItemConfigNode) = 0 then
|
|
Result := TKASNormalItem.Create
|
|
else if Node.CompareName(SeparatorItemConfigNode) = 0 then
|
|
Result := TKASSeparatorItem.Create
|
|
else
|
|
Result := nil;
|
|
end;
|
|
|
|
procedure TKASToolBarLoader.Load(Config: TXmlConfig; RootNode: TXmlNode; OnLoadToolItem: TOnLoadToolItem);
|
|
var
|
|
Node: TXmlNode;
|
|
Item: TKASToolItem;
|
|
begin
|
|
Node := RootNode.FirstChild;
|
|
while Assigned(Node) do
|
|
begin
|
|
Item := CreateItem(Node);
|
|
|
|
if Assigned(Item) then
|
|
try
|
|
Item.Load(Config, Node, Self);
|
|
OnLoadToolItem(Item);
|
|
Item := nil;
|
|
finally
|
|
FreeAndNil(Item);
|
|
end;
|
|
|
|
Node := Node.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
{ TKASMenuItem }
|
|
|
|
procedure TKASMenuItem.Assign(OtherItem: TKASToolItem);
|
|
var
|
|
MenuItem: TKASMenuItem;
|
|
Item: TKASToolItem;
|
|
I: Integer;
|
|
begin
|
|
inherited Assign(OtherItem);
|
|
if OtherItem is TKASMenuItem then
|
|
begin
|
|
MenuItem := TKASMenuItem(OtherItem);
|
|
FItems.Clear;
|
|
for I := 0 to MenuItem.SubItems.Count - 1 do
|
|
begin
|
|
Item := MenuItem.SubItems.Items[I].Clone;
|
|
Item.SetToolOwner(ToolOwner);
|
|
FItems.Add(Item);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TKASMenuItem.CheckExecute(ToolItemID: String): Boolean;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
Result := inherited CheckExecute(ToolItemID);
|
|
if not Result then
|
|
begin
|
|
for I := 0 to SubItems.Count - 1 do
|
|
begin
|
|
if SubItems[I].CheckExecute(ToolItemID) then
|
|
Exit(True);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TKASMenuItem.Clone: TKASToolItem;
|
|
begin
|
|
Result := TKASMenuItem.Create;
|
|
Result.Assign(Self);
|
|
end;
|
|
|
|
function TKASMenuItem.ConfigNodeName: String;
|
|
begin
|
|
Result := MenuItemConfigNode;
|
|
end;
|
|
|
|
constructor TKASMenuItem.Create;
|
|
begin
|
|
FItems := TKASToolBarItems.Create;
|
|
end;
|
|
|
|
destructor TKASMenuItem.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
FItems.Free;
|
|
end;
|
|
|
|
procedure TKASMenuItem.Load(Config: TXmlConfig; Node: TXmlNode; Loader: TKASToolBarLoader);
|
|
begin
|
|
inherited Load(Config, Node, Loader);
|
|
SubItems.Clear;
|
|
Node := Config.FindNode(Node, 'MenuItems', False);
|
|
if Assigned(Node) then
|
|
Loader.Load(Config, Node, @ToolItemLoaded);
|
|
end;
|
|
|
|
procedure TKASMenuItem.SaveContents(Config: TXmlConfig; Node: TXmlNode);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
inherited SaveContents(Config, Node);
|
|
if SubItems.Count > 0 then
|
|
begin
|
|
Node := Config.AddNode(Node, 'MenuItems');
|
|
for I := 0 to SubItems.Count - 1 do
|
|
SubItems.Items[I].Save(Config, Node);
|
|
end;
|
|
end;
|
|
|
|
procedure TKASMenuItem.SetToolOwner(AToolOwner: IToolOwner);
|
|
var
|
|
I: Integer;
|
|
begin
|
|
inherited SetToolOwner(AToolOwner);
|
|
for I := 0 to SubItems.Count - 1 do
|
|
SubItems.Items[I].SetToolOwner(ToolOwner);
|
|
end;
|
|
|
|
procedure TKASMenuItem.ToolItemLoaded(Item: TKASToolItem);
|
|
begin
|
|
Item.SetToolOwner(ToolOwner);
|
|
SubItems.Add(Item);
|
|
end;
|
|
|
|
{ TKASDividerItem }
|
|
|
|
procedure TKASSeparatorItem.Assign(OtherItem: TKASToolItem);
|
|
begin
|
|
inherited Assign(OtherItem);
|
|
end;
|
|
|
|
function TKASSeparatorItem.Clone: TKASToolItem;
|
|
begin
|
|
Result := TKASSeparatorItem.Create;
|
|
Result.Assign(Self);
|
|
end;
|
|
|
|
function TKASSeparatorItem.ConfigNodeName: String;
|
|
begin
|
|
Result := SeparatorItemConfigNode;
|
|
end;
|
|
|
|
function TKASSeparatorItem.GetEffectiveHint: String;
|
|
begin
|
|
Result := '';
|
|
end;
|
|
|
|
function TKASSeparatorItem.GetEffectiveText: String;
|
|
begin
|
|
Result := '';
|
|
end;
|
|
|
|
procedure TKASSeparatorItem.Load(Config: TXmlConfig; Node: TXmlNode; Loader: TKASToolBarLoader);
|
|
begin
|
|
// Empty.
|
|
end;
|
|
|
|
procedure TKASSeparatorItem.SaveContents(Config: TXmlConfig; Node: TXmlNode);
|
|
begin
|
|
// Empty.
|
|
end;
|
|
|
|
{ TKASNormalItem }
|
|
|
|
procedure TKASNormalItem.Assign(OtherItem: TKASToolItem);
|
|
var
|
|
NormalItem: TKASNormalItem;
|
|
begin
|
|
inherited Assign(OtherItem);
|
|
if OtherItem is TKASNormalItem then
|
|
begin
|
|
// Don't copy ID.
|
|
NormalItem := TKASNormalItem(OtherItem);
|
|
Icon := NormalItem.Icon;
|
|
Text := NormalItem.Text;
|
|
Hint := NormalItem.Hint;
|
|
end;
|
|
end;
|
|
|
|
function TKASNormalItem.CheckExecute(ToolItemID: String): Boolean;
|
|
begin
|
|
Result := (ID = ToolItemID);
|
|
if Result and Assigned(FToolOwner) then
|
|
FToolOwner.ExecuteToolItem(Self);
|
|
end;
|
|
|
|
function TKASNormalItem.Clone: TKASToolItem;
|
|
begin
|
|
Result := TKASNormalItem.Create;
|
|
Result.Assign(Self);
|
|
end;
|
|
|
|
function TKASNormalItem.ConfigNodeName: String;
|
|
begin
|
|
Result := NormalItemConfigNode;
|
|
end;
|
|
|
|
function TKASNormalItem.GetEffectiveHint: String;
|
|
var
|
|
ShortcutsHint: String;
|
|
begin
|
|
Result := Hint;
|
|
ShortcutsHint := GetShortcutsHint;
|
|
if ShortcutsHint <> '' then
|
|
AddStrWithSep(Result, '(' + ShortcutsHint + ')', ' ');
|
|
end;
|
|
|
|
function TKASNormalItem.GetEffectiveText: String;
|
|
begin
|
|
Result := Text;
|
|
end;
|
|
|
|
function TKASNormalItem.GetID: String;
|
|
var
|
|
Guid: TGuid;
|
|
begin
|
|
if FID = EmptyStr then
|
|
begin
|
|
if CreateGUID(Guid) = 0 then
|
|
FID := GUIDToString(Guid)
|
|
else
|
|
FID := IntToStr(Random(MaxInt));
|
|
end;
|
|
Result := FID;
|
|
end;
|
|
|
|
function TKASNormalItem.GetShortcutsHint: String;
|
|
begin
|
|
if Assigned(FToolOwner) then
|
|
Result := FToolOwner.GetToolItemShortcutsHint(Self)
|
|
else
|
|
Result := '';
|
|
end;
|
|
|
|
procedure TKASNormalItem.Load(Config: TXmlConfig; Node: TXmlNode; Loader: TKASToolBarLoader);
|
|
begin
|
|
Node := Node.FirstChild;
|
|
while Assigned(Node) do
|
|
begin
|
|
if Node.CompareName('ID') = 0 then
|
|
FID := Config.GetContent(Node)
|
|
else if Node.CompareName('Text') = 0 then
|
|
Text := Config.GetContent(Node)
|
|
else if Node.CompareName('Icon') = 0 then
|
|
Icon := Config.GetContent(Node)
|
|
else if Node.CompareName('Hint') = 0 then
|
|
Hint := Config.GetContent(Node);
|
|
Node := Node.NextSibling;
|
|
end;
|
|
end;
|
|
|
|
procedure TKASNormalItem.SaveContents(Config: TXmlConfig; Node: TXmlNode);
|
|
begin
|
|
Config.AddValue(Node, 'ID', ID);
|
|
SaveText(Config, Node);
|
|
SaveIcon(Config, Node);
|
|
SaveHint(Config, Node);
|
|
end;
|
|
|
|
procedure TKASNormalItem.SaveHint(Config: TXmlConfig; Node: TXmlNode);
|
|
begin
|
|
Config.AddValueDef(Node, 'Hint', Hint, '');
|
|
end;
|
|
|
|
procedure TKASNormalItem.SaveIcon(Config: TXmlConfig; Node: TXmlNode);
|
|
begin
|
|
Config.AddValueDef(Node, 'Icon', Icon, '');
|
|
end;
|
|
|
|
procedure TKASNormalItem.SaveText(Config: TXmlConfig; Node: TXmlNode);
|
|
begin
|
|
Config.AddValueDef(Node, 'Text', Text, '');
|
|
end;
|
|
|
|
{ TKASToolBarItems }
|
|
|
|
constructor TKASToolBarItems.Create;
|
|
begin
|
|
FButtons := TFPList.Create;
|
|
end;
|
|
|
|
destructor TKASToolBarItems.Destroy;
|
|
begin
|
|
Clear;
|
|
inherited Destroy;
|
|
FButtons.Free;
|
|
end;
|
|
|
|
function TKASToolBarItems.Insert(InsertAt: Integer; Item: TKASToolItem): Integer;
|
|
begin
|
|
FButtons.Insert(InsertAt, Item);
|
|
Result := InsertAt;
|
|
end;
|
|
|
|
procedure TKASToolBarItems.Move(FromIndex, ToIndex: Integer);
|
|
begin
|
|
FButtons.Move(FromIndex, ToIndex);
|
|
end;
|
|
|
|
function TKASToolBarItems.ReleaseItem(Index: Integer): TKASToolItem;
|
|
begin
|
|
Result := TKASToolItem(FButtons[Index]);
|
|
FButtons.Delete(Index);
|
|
end;
|
|
|
|
function TKASToolBarItems.Add(Item: TKASToolItem): Integer;
|
|
begin
|
|
Result := FButtons.Add(Item);
|
|
end;
|
|
|
|
procedure TKASToolBarItems.Remove(Index: Integer);
|
|
begin
|
|
TKASToolItem(FButtons[Index]).Free;
|
|
FButtons.Delete(Index);
|
|
end;
|
|
|
|
procedure TKASToolBarItems.Clear;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
for i := 0 to FButtons.Count - 1 do
|
|
TKASToolItem(FButtons[i]).Free;
|
|
FButtons.Clear;
|
|
end;
|
|
|
|
function TKASToolBarItems.GetButtonCount: Integer;
|
|
begin
|
|
Result := FButtons.Count;
|
|
end;
|
|
|
|
function TKASToolBarItems.GetButton(Index: Integer): TKASToolItem;
|
|
begin
|
|
Result := TKASToolItem(FButtons[Index]);
|
|
end;
|
|
|
|
procedure TKASToolBarItems.SetButton(Index: Integer; const AValue: TKASToolItem);
|
|
begin
|
|
TKASToolItem(FButtons[Index]).Free;
|
|
FButtons[Index] := AValue;
|
|
end;
|
|
|
|
end.
|