summaryrefslogtreecommitdiff
path: root/src/gui/gui_mru.pas
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/gui_mru.pas')
-rw-r--r--src/gui/gui_mru.pas273
1 files changed, 273 insertions, 0 deletions
diff --git a/src/gui/gui_mru.pas b/src/gui/gui_mru.pas
new file mode 100644
index 00000000..353a2d03
--- /dev/null
+++ b/src/gui/gui_mru.pas
@@ -0,0 +1,273 @@
+{
+ fpGUI - Free Pascal GUI Library
+
+ Copyright (C) 2006 - 2007 See the file AUTHORS.txt, included in this
+ distribution, for details of the copyright.
+
+ See the file COPYING.modifiedLGPL, included in this distribution,
+ for details about redistributing fpGUI.
+
+ 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.
+
+ Description:
+ A component implementing a 'Most Recently Used' feature normally
+ inserted in the File menu.
+}
+
+unit gui_mru;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, gui_menu;
+
+type
+
+ TMRUClickEvent = procedure(Sender: TObject; const FileName: String) of object;
+
+ TfpgMRU = class(TComponent)
+ private
+ FItems: TStringList;
+ FMaxItems: cardinal;
+ FShowFullPath: boolean;
+ FParentMenuItem: TfpgPopupMenu;
+ FIniFilePath: string;
+ FOnClick: TMRUClickEvent;
+ procedure SetMaxItems(const AValue: cardinal);
+// procedure SetIniFilePath(const AValue: string);
+ procedure SetParentMenuItem(const AValue: TfpgPopupMenu);
+ procedure SetShowFullPath(const AValue: boolean);
+ procedure SaveMRU;
+ procedure ItemsChange(Sender: TObject);
+ procedure ClearParentMenu;
+ protected
+ // this never gets called without a Form Streaming class, which fpGUI doesn't use
+ procedure Loaded; override;
+ procedure Notification(AComponent: TComponent; Operation: TOperation); override;
+ procedure DoClick(Sender: TObject);
+ public
+ constructor Create(AOwner: TComponent); override;
+ destructor Destroy; override;
+ procedure AddItem(const FileName: string);
+ function RemoveItem(const FileName : string) : boolean;
+ procedure LoadMRU;
+ published
+ property MaxItems: cardinal read FMaxItems write SetMaxItems default 4;
+// property IniFilePath: string read FIniFilePath write SetIniFilePath;
+ property ShowFullPath: boolean read FShowFullPath write SetShowFullPath default True;
+ property ParentMenuItem: TfpgPopupMenu read FParentMenuItem write SetParentMenuItem;
+ property OnClick: TMRUClickEvent read FOnClick write FOnClick;
+ end;
+
+
+implementation
+
+uses
+ gui_iniutils;
+
+type
+ //to be able to recognize MRU menu item when deleting
+ TMRUMenuItem = class(TfpgMenuItem);
+
+
+{ TfpgMRU }
+
+procedure TfpgMRU.SetMaxItems(const AValue: cardinal);
+begin
+ if AValue <> FMaxItems then
+ begin
+ if AValue < 1 then FMaxItems := 1
+ else
+ if AValue > MaxInt then
+ FMaxItems := MaxInt - 1
+ else
+ begin
+ FMaxItems := AValue;
+ FItems.BeginUpdate;
+ try
+ while FItems.Count > MaxItems do
+ FItems.Delete(FItems.Count - 1);
+ finally
+ FItems.EndUpdate;
+ end;
+ end;
+ end;
+end;
+
+{
+procedure TfpgMRU.SetIniFilePath(const AValue: string);
+begin
+ if FIniFilePath=AValue then exit;
+ FIniFilePath:=AValue;
+end;
+}
+
+procedure TfpgMRU.SetParentMenuItem(const AValue: TfpgPopupMenu);
+begin
+ if AValue = FParentMenuItem then
+ Exit;
+ FParentMenuItem := AValue;
+end;
+
+procedure TfpgMRU.SetShowFullPath(const AValue: boolean);
+begin
+ if FShowFullPath <> AValue then
+ begin
+ FShowFullPath := AValue;
+ ItemsChange(Self);
+ end;
+end;
+
+procedure TfpgMRU.LoadMRU;
+var
+ i: cardinal;
+begin
+ FItems.BeginUpdate;
+ FItems.Clear;
+ try
+ for i := 1 to FMaxItems do
+ if gINI.ValueExists('MRU', 'MRU'+IntToStr(i)) then
+ FItems.Add(gINI.ReadString('MRU', 'MRU'+IntToStr(i), ''));
+ finally
+ FItems.EndUpdate;
+ end;
+end;
+
+procedure TfpgMRU.SaveMRU;
+var
+ i: integer;
+begin
+ if FItems.Count = 0 then
+ Exit;
+
+ //delete old mru
+ i := 1;
+ while gINI.ValueExists('MRU', 'MRU'+IntToStr(i)) do
+ begin
+ gINI.DeleteKey('MRU', 'MRU'+IntToStr(i));
+ Inc(i);
+ end;
+
+ //write new mru
+ for i := 0 to FItems.Count-1 do
+ gINI.WriteString('MRU', 'MRU'+IntToStr(i+1), FItems[i]);
+end;
+
+procedure TfpgMRU.ItemsChange(Sender: TObject);
+var
+ i: Integer;
+ NewMenuItem: TfpgMenuItem;
+ FileName: String;
+begin
+// writeln('TfpgMRU.ItemsChange');
+ if ParentMenuItem <> nil then
+ begin
+ ClearParentMenu;
+ if FItems.Count = 0 then
+ ParentMenuItem.AddMenuItem('-', '', nil); // add something if we have no previous MRU's
+ for i := 0 to -1 + FItems.Count do
+ begin
+ if ShowFullPath then
+ FileName := StringReplace(FItems[I], '&', '&&', [rfReplaceAll, rfIgnoreCase])
+ else
+ FileName := StringReplace(ExtractFileName(FItems[i]), '&', '&&', [rfReplaceAll, rfIgnoreCase]);
+
+// NewMenuItem := ParentMenuItem.AddMenuItem(Format('%s', [FileName]), '', @DoClick);
+// NewMenuItem.Tag := i;
+ NewMenuItem := TMRUMenuItem.Create(ParentMenuItem);
+ NewMenuItem.Text := Format('%s', [FileName]);
+ NewMenuItem.Tag := i;
+ NewMenuItem.OnClick := @DoClick;
+ end;
+ end;
+end;
+
+procedure TfpgMRU.ClearParentMenu;
+//var
+// i:integer;
+begin
+ if Assigned(ParentMenuItem) then
+ ParentMenuItem.DestroyComponents;
+{
+ for i := ParentMenuItem.ComponentCount-1 downto 0 do
+ if ParentMenuItem.Components[i] is TMRUMenuItem then
+ ParentMenuItem.Delete(i);
+}
+end;
+
+procedure TfpgMRU.Loaded;
+begin
+ inherited Loaded;
+ if not (csDesigning in ComponentState) then
+// if FIniFilePath <> '' then
+ LoadMRU;
+end;
+
+procedure TfpgMRU.Notification(AComponent: TComponent; Operation: TOperation);
+begin
+ inherited Notification(AComponent, Operation);
+ if (Operation = opRemove) and (AComponent = FParentMenuItem) then
+ FParentMenuItem := nil;
+end;
+
+procedure TfpgMRU.DoClick(Sender: TObject);
+begin
+ if Assigned(FOnClick) and (Sender is TMRUMenuItem) then
+ FOnClick(Self, FItems[TMRUMenuItem(Sender).Tag]);
+end;
+
+constructor TfpgMRU.Create(AOwner: TComponent);
+begin
+ inherited Create(AOwner);
+ FParentMenuItem := nil;
+ FItems := TStringList.Create;
+ FItems.OnChange := @ItemsChange;
+ FMaxItems := 4;
+ FShowFullPath := True;
+// Loaded;
+end;
+
+destructor TfpgMRU.Destroy;
+begin
+ if not (csDesigning in ComponentState) then
+ SaveMRU;
+ FItems.OnChange := nil;
+ FItems.Free;
+ inherited Destroy;
+end;
+
+procedure TfpgMRU.AddItem(const FileName: string);
+begin
+ if FileName <> '' then
+ begin
+ FItems.BeginUpdate;
+ try
+ if FItems.IndexOf(FileName) > -1 then
+ FItems.Delete(FItems.IndexOf(FileName));
+ FItems.Insert(0, FileName);
+
+ while FItems.Count > MaxItems do
+ FItems.Delete(MaxItems);
+ finally
+ FItems.EndUpdate;
+ end;
+ end;
+end;
+
+function TfpgMRU.RemoveItem(const FileName: string): boolean;
+begin
+ if FItems.IndexOf(FileName) > -1 then
+ begin
+ FItems.Delete(FItems.IndexOf(FileName));
+ Result := True;
+ end
+ else
+ Result := False;
+end;
+
+end.
+