lazarus/components/iconfinder/source/iconviewer.pas

528 lines
15 KiB
ObjectPascal

{
*****************************************************************************
This file is part of a Lazarus Package, IconFinder.
See the file COPYING.modifiedLGPL.txt, included in the Lazarus distribution,
for details about the license.
*****************************************************************************
A frame composed of the essential controls for viewing thumbnails and
filtering them.
Is used by the imagelist component editor, by the graphic property editor
and by the IDE settings page.
}
unit IconViewer;
{$mode ObjFPC}{$H+}
interface
uses
// RTL/FCL
Classes, SysUtils,
// LazUtils
LazFileUtils, LazLoggerBase,
// LCL/LazControls
Forms, Controls, Graphics, StdCtrls, ExtCtrls, FileCtrl, Buttons, Dialogs,
ImgList, DividerBevel,
// Icon Finder
IconFinderStrConsts, IconThumbnails, IconKeywordFilterEditor;
type
{ TIconViewerFrame }
TIconViewerFrame = class(TFrame)
Bevel2: TBevel;
btnKeywordEditor: TSpeedButton;
cmbFilterByKeywords: TComboBox;
cmbFilterBySize: TComboBox;
cmbFilterByStyle: TComboBox;
DividerBevel1: TDividerBevel;
FilterPanel: TPanel;
infoFileName: TLabel;
infoKeywords: TLabel;
infoSize: TLabel;
infoStyle: TLabel;
lblFileName: TLabel;
lblKeywords: TLabel;
lblSize: TLabel;
lblStyle: TLabel;
IconDetailsPanel: TPanel;
btnExecuteFilter: TSpeedButton;
btnClearFilter: TSpeedButton;
CaptionPanel: TPanel;
procedure btnClearFilterClick(Sender: TObject);
procedure btnExecuteFilterClick(Sender: TObject);
procedure btnKeywordEditorClick(Sender: TObject);
procedure cmbFilterByKeywordsEditingDone(Sender: TObject);
procedure cmbFilterBySizeChange(Sender: TObject);
procedure cmbFilterByStyleChange(Sender: TObject);
procedure IconDetailsPanelResize(Sender: TObject);
private
FIconViewer: TIconThumbnailViewer;
FOnChange: TNotifyEvent;
FOnFilter: TNotifyEvent;
FOnIconDblClick: TNotifyEvent;
function GetFilteredCount: Integer;
function GetImageIndex(AIndex: Integer): TImageIndex;
function GetImageList: TCustomImageList;
function GetSelectedIcon: TIconItem;
function GetSizeFilter: String;
function GetStyleFilter: String;
function GetTotalCount: Integer;
procedure SetImageIndex(AIndex: Integer; AValue: TImageIndex);
procedure SetImageList(AValue: TCustomImageList);
procedure SetSizeFilter(AValue: String);
procedure SetStyleFilter(AValue: String);
protected
procedure AddKeywordFilterToHistory(AFilter: String);
procedure DoIconViewerDblClick(Sender: TObject);
procedure DoIconViewerFilter(Sender: TObject);
procedure DoIconViewerSelect(Sender: TObject);
procedure UpdateCmds;
procedure UpdateIconDetails;
public
constructor Create(AOwner: TComponent); override;
procedure AddIconFolder(AFolder: String; Hidden: Boolean = false);
procedure CopyMetadataToNameBase(AIcon: TIconItem);
procedure DeleteSelectedIcon;
procedure FocusKeywordFilter;
procedure GetKeywordsHistory(AList: TStrings);
function IndexOfIconFolder(AFolder: String): Integer;
procedure ReadIconFolders(AList: TStrings);
procedure SetKeywordsHistory(AList: TStrings);
procedure UpdateIconCount;
procedure UpdateIconSizes(ASizeIndex: Integer);
procedure UpdateIconStyles(AStyleIndex: Integer);
procedure UpdateLanguage;
property FilteredCount: Integer read GetFilteredCount;
property IconViewer: TIconThumbnailViewer read FIconViewer;
property ImageIndex_ExecuteFilter: TImageIndex index 0 read GetImageIndex write SetImageIndex;
property ImageIndex_ClearFilter: TImageIndex index 1 read GetImageIndex write SetImageIndex;
property ImageList: TCustomImageList read GetImageList write SetImageList;
property SelectedIcon: TIconItem read GetSelectedIcon;
property SizeFilter: String read GetSizeFilter write SetSizeFilter;
property StyleFilter: String read GetStyleFilter write SetStyleFilter;
property TotalCount: Integer read GetTotalCount;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnFilter: TNotifyEvent read FOnFilter write FOnFilter;
property OnIconDblClick: TNotifyEvent read FOnIconDblClick write FOnIconDblClick;
end;
implementation
{$R *.lfm}
const
MAX_KEYWORDS_HISTORY = 20;
{ TIconViewerFrame }
constructor TIconViewerFrame.Create(AOwner: TComponent);
begin
inherited;
FIconViewer := TIconThumbnailViewer.Create(self);
FIconViewer.Align := alClient;
FIconViewer.FocusedColor := clWindowText;
FIconViewer.Parent := self;
FIconViewer.OnDblClick := @DoIconViewerDblClick;
FIconViewer.OnFilter := @DoIconViewerFilter;
FIconViewer.OnSelect := @DoIconViewerSelect;
UpdateIconDetails;
UpdateLanguage;
end;
procedure TIconViewerFrame.AddIconFolder(AFolder: String; Hidden: Boolean = false);
var
filterByStyle: Integer;
filterBySize: Integer;
begin
filterByStyle := cmbFilterByStyle.ItemIndex;
if filterByStyle = -1 then filterByStyle := 0;
filterBySize := cmbFilterBySize.ItemIndex;
if filterBySize = -1 then filterBySize := 0;
AFolder := AppendPathDelim(SwitchPathDelims(AFolder, true));
IconViewer.AddIconFolder(AFolder, Hidden);
UpdateIconSizes(filterBySize);
UpdateIconStyles(filterByStyle);
UpdateIconDetails;
UpdateIconCount;
UpdateCmds;
end;
procedure TIconViewerFrame.AddKeywordFilterToHistory(AFilter: String);
var
idx: Integer;
begin
if AFilter = '' then
exit;
idx := cmbFilterByKeywords.Items.IndexOf(AFilter);
if idx = -1 then
cmbFilterByKeywords.Items.Insert(0, AFilter)
else
cmbFilterByKeywords.Items.Move(idx, 0);
while cmbFilterByKeywords.Items.Count > MAX_KEYWORDS_HISTORY do
cmbFilterByKeywords.Items.Delete(cmbFilterByKeywords.Items.Count-1);
end;
procedure TIconViewerFrame.btnKeywordEditorClick(Sender: TObject);
var
F: TKeywordFilterEditorForm;
L: TStringList;
P: TPoint;
begin
F := TKeywordFilterEditorForm.Create(Self);
L := TStringList.Create;
try
F.Position := poDesigned;
P := ClientToScreen(Point(cmbFilterByKeywords.Left, cmbFilterByKeywords.Top + cmbFilterByKeywords.Height));
F.SetBounds(P.X, P.Y, F.Width, F.Height);
F.Filter := cmbFilterByKeywords.Text;
FIconViewer.GetKeywordsAsStrings(L);
F.Keywords := L;
if F.ShowModal = mrOK then
begin
cmbFilterByKeywords.Text := F.Filter;
FIconViewer.FilterByIconKeywords := F.Filter;
AddKeywordFilterToHistory(F.Filter);
end;
finally
L.Free;
F.Free;
end;
end;
procedure TIconViewerFrame.btnClearFilterClick(Sender: TObject);
begin
cmbFilterByKeywords.Text := '';
FIconViewer.FilterByIconKeywords := '';
end;
procedure TIconViewerFrame.btnExecuteFilterClick(Sender: TObject);
var
filter: String;
begin
filter := cmbFilterByKeywords.Text;
FIconViewer.FilterByIconKeywords := filter;
AddKeywordFilterToHistory(filter);
cmbFilterByKeywords.Text := filter; // Must be after AddKeywordFilterToHistory!
UpdateIconCount;
end;
procedure TIconViewerFrame.cmbFilterByKeywordsEditingDone(Sender: TObject);
begin
btnExecuteFilterClick(nil);
end;
procedure TIconViewerFrame.cmbFilterBySizeChange(Sender: TObject);
begin
if cmbFilterBySize.ItemIndex = 0 then // Filter by any size
FIconViewer.FilterByIconSize := ''
else
FIconViewer.FilterByIconSize := cmbFilterBySize.Items[cmbFilterBySize.ItemIndex];
FIconViewer.Invalidate;
UpdateIconCount;
end;
procedure TIconViewerFrame.cmbFilterByStyleChange(Sender: TObject);
begin
FIconViewer.FilterByIconStyle := TIconStyle(cmbFilterByStyle.ItemIndex);
FIconViewer.Invalidate;
UpdateIconCount;
end;
procedure TIconViewerFrame.CopyMetadataToNameBase(AIcon: TIconItem);
begin
IconViewer.CopyMetadataToNameBase(AIcon);
IconViewer.Invalidate;
UpdateIconDetails;
end;
procedure TIconViewerFrame.DeleteSelectedIcon;
var
res: TModalResult;
begin
res := MessageDlg(RSIconViewer_ConfirmDeleteIconMsg, mtConfirmation, [mbYes, mbNo], 0);
if res = mrYes then
begin
IconViewer.DeleteIcon(IconViewer.SelectedIcon);
UpdateIconDetails;
end;
end;
procedure TIconViewerFrame.DoIconViewerDblClick(Sender: TObject);
begin
if Assigned(FOnIconDblClick) then
FOnIconDblClick(Self);
end;
procedure TIconViewerFrame.DoIconViewerFilter(Sender: TObject);
begin
UpdateIconCount;
if Assigned(FOnFilter) then
FOnFilter(Self);
end;
procedure TIconViewerFrame.DoIconViewerSelect(Sender: TObject);
begin
UpdateIconDetails;
if Assigned(FOnChange) then
FOnChange(self);
end;
procedure TIconViewerFrame.FocusKeywordFilter;
begin
if HandleAllocated and cmbFilterByKeywords.CanFocus then
cmbFilterByKeywords.SetFocus;
end;
function TIconViewerFrame.GetFilteredCount: Integer;
begin
Result := FIconViewer.ThumbnailCount;
end;
function TIconViewerFrame.GetImageIndex(AIndex: Integer): TImageIndex;
begin
case AIndex of
0: Result := btnExecuteFilter.ImageIndex;
1: Result := btnClearFilter.ImageIndex;
end;
end;
function TIconViewerFrame.GetImageList: TCustomImageList;
begin
Result := btnExecuteFilter.Images;
end;
procedure TIconViewerFrame.GetKeywordsHistory(AList: TStrings);
begin
AList.Assign(cmbFilterByKeywords.Items);
end;
function TIconViewerFrame.GetSelectedIcon: TIconItem;
begin
Result := FIconViewer.SelectedIcon;
end;
function TIconViewerFrame.GetSizeFilter: String;
begin
if cmbFilterBySize.ItemIndex <= 0 then
Result := ''
else
Result := cmbFilterBySize.Items[cmbFilterBySize.ItemIndex];
end;
function TIconViewerFrame.GetStyleFilter: String;
begin
Result := IconStyleToStr(TIconStyle(cmbFilterByStyle.ItemIndex));
end;
function TIconViewerFrame.GetTotalCount: Integer;
begin
Result := FIconViewer.IconCount;
end;
procedure TIconViewerFrame.IconDetailsPanelResize(Sender: TObject);
begin
if FIconViewer.SelectedIcon <> nil then
begin
infoFileName.Hint := FIconViewer.SelectedIcon.FileName;
infoFileName.Caption := MinimizeName(infoFileName.Hint, infoFileName.Canvas, IconDetailsPanel.Width - infoFileName.Left);
end;
end;
function TIconViewerFrame.IndexOfIconFolder(AFolder: String): Integer;
begin
Result := FIconViewer.IndexOfFolder(AFolder);
end;
{ Reads the icons from the directories contained in AList and adds them to the
library. }
procedure TIconViewerFrame.ReadIconFolders(AList: TStrings);
var
sizeFilt, styleFilt: Integer;
selectedIconFileName: String = '';
begin
styleFilt := cmbFilterByStyle.ItemIndex;
if styleFilt = -1 then styleFilt := 0;
sizeFilt := cmbFilterBySize.ItemIndex;
if sizeFilt = -1 then sizeFilt := 0;
if Assigned(IconViewer.SelectedIcon) then
selectedIconFileName := IconViewer.SelectedIcon.FileName;
IconViewer.LockFilter;
try
IconViewer.ReadIconFolders(AList);
UpdateIconSizes(sizefilt);
UpdateIconStyles(stylefilt);
finally
IconViewer.UnlockFilter;
IconViewer.SelectIconInFile(selectedIconFileName);;
end;
end;
procedure TIconViewerFrame.SetImageIndex(AIndex: Integer; AValue: TImageIndex);
begin
case AIndex of
0: btnExecuteFilter.ImageIndex := AValue;
1: btnClearFilter.ImageIndex := AValue;
end;
end;
procedure TIconViewerFrame.SetImageList(AValue: TCustomImageList);
begin
btnExecuteFilter.Images := AValue;
btnClearFilter.Images := AValue;
end;
procedure TIconViewerFrame.SetKeywordsHistory(AList: TStrings);
begin
cmbFilterByKeywords.Items.BeginUpdate;
try
cmbFilterByKeywords.Items.Assign(AList);
while cmbFilterByKeywords.Items.Count > MAX_KEYWORDS_HISTORY do
cmbFilterByKeywords.Items.Delete(cmbFilterByKeywords.Items.Count-1);
finally
cmbFilterByKeywords.Items.EndUpdate;
end;
end;
procedure TIconViewerFrame.SetSizeFilter(AValue: String);
var
idx: Integer;
begin
idx := cmbFilterBySize.Items.IndexOf(AValue);
if idx = -1 then
cmbFilterBySize.ItemIndex := 0
else
cmbFilterBySize.ItemIndex := idx;
cmbFilterBySizeChange(nil);
end;
procedure TIconViewerFrame.SetStyleFilter(AValue: String);
var
idx: Integer;
begin
idx := cmbFilterByStyle.Items.IndexOf(AValue);
if idx = -1 then
cmbFilterByStyle.ItemIndex := 0
else
cmbFilterByStyle.ItemIndex := idx;
cmbFilterByStyleChange(nil);
end;
procedure TIconViewerFrame.UpdateCmds;
begin
btnKeywordEditor.Enabled := TotalCount > 0;
end;
procedure TIconViewerFrame.UpdateIconCount;
begin
DividerBevel1.Caption := Format(RSIconViewer_IconCountInfo,
[ FIconViewer.ThumbnailCount, FIconViewer.IconCount ]
);
end;
procedure TIconViewerFrame.UpdateIconDetails;
var
keywordList: TStrings;
begin
if FIconViewer.SelectedIcon <> nil then
begin
infoFileName.Hint := FIconViewer.SelectedIcon.FileName;
infoFileName.Caption := MinimizeName(infoFileName.Hint, infoFileName.Canvas, IconDetailsPanel.Width - infoFileName.Left);
infoSize.Caption := FIconViewer.SelectedIcon.SizeAsString;
infoStyle.Caption := FIconViewer.SelectedIcon.StyleAsString;
keywordList := TStringList.Create;
try
FIconViewer.SelectedIcon.ExportKeywordsToStrings(keywordList);
keywordList.Delimiter := ';';
keywordList.StrictDelimiter := true;
infoKeywords.Caption := StringReplace(keywordList.DelimitedText, ';', '; ', [rfReplaceAll]);
finally
keywordList.Free;
end;
end else
begin
infoFileName.Caption := '';
infoFileName.Hint := '';
infoStyle.Caption := '';
infoSize.Caption := '';
infoKeywords.Caption := '';
end;
end;
procedure TIconViewerFrame.UpdateIconSizes(ASizeIndex: Integer);
begin
FIconViewer.GetIconSizesAsStrings(cmbFilterBySize.Items);
cmbFilterBySize.Items.Insert(0, RSMetadata_AnySize);
if ASizeIndex < 0 then ASizeIndex := 0;
cmbFilterBySize.ItemIndex := ASizeIndex;
if ASizeIndex = 0 then
FIconViewer.FilterByIconSize := ''
else
FIconViewer.FilterByIconSize := cmbFilterBySize.Items[ASizeIndex];
end;
procedure TIconViewerFrame.UpdateIconStyles(AStyleIndex: Integer);
begin
IconStylesToStrings(cmbFilterByStyle.Items);
if AStyleIndex < 0 then AStyleIndex := 0;
cmbFilterByStyle.ItemIndex := AStyleIndex;
if AStyleIndex = 0 then
FIconViewer.FilterByIconStyle := isAnyStyle
else
FIconViewer.FilterByIconStyle := TIconStyle(AStyleIndex);
end;
procedure TIconViewerFrame.UpdateLanguage;
begin
cmbFilterBySize.Hint := RSIconViewer_FilterByIconSizeHint;
cmbFilterByStyle.Hint := RSIconViewer_FilterByIconStyleHint;
cmbFilterByKeywords.Hint := RSIconViewer_ExpressionToFilterByKeywordsHint;
btnKeywordEditor.Hint := RSIconViewer_EditKeywordFilterHint;
btnClearFilter.Hint := RSIconViewer_ClearFilterHint;
btnExecuteFilter.Hint := RSIconViewer_FilterByKeywordsHint;
lblFileName.Caption := RSIconViewer_FileNameLbl;
lblSize.Caption := RSIconViewer_SizeLbl;
lblStyle.Caption := RSIconViewer_StyleLbl;
lblKeywords.Caption := RSIconViewer_KeywordsLbl;
cmbFilterByKeywords.TextHint := RSIconViewer_EnterKeywordsHere;
(* // activate only when translation of keywords and styles is ready!
idx := cmbFilterByStyle.ItemIndex;
cmbFilterByStyle.Items.BeginUpdate;
try
cmbFilterByStyle.Clear;
cmbFilterByStyle.Items.Add(RSMetadata_ClassicStyle);
cmbFilterByStyle.Items.Add(RSMetadata_Flatstyle);
cmbFilterByStyle.Items.Add(RSMetadata_OutlineStyle);
cmbFilterByStyle.Items.Add(RSMetadata_Outline2Style);
if idx < cmbFilterBystyle.Items.Count then
cmbFilterByStyle.ItemIndex := idx;
finally
cmbFilterByStyle.Items.EndUpdate;
end;
*)
// UpdateLayout;
end;
end.