TB2MRU.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. unit TB2MRU;
  2. {
  3. Toolbar2000
  4. Copyright (C) 1998-2005 by Jordan Russell
  5. All rights reserved.
  6. The contents of this file are subject to the "Toolbar2000 License"; you may
  7. not use or distribute this file except in compliance with the
  8. "Toolbar2000 License". A copy of the "Toolbar2000 License" may be found in
  9. TB2k-LICENSE.txt or at:
  10. http://www.jrsoftware.org/files/tb2k/TB2k-LICENSE.txt
  11. Alternatively, the contents of this file may be used under the terms of the
  12. GNU General Public License (the "GPL"), in which case the provisions of the
  13. GPL are applicable instead of those in the "Toolbar2000 License". A copy of
  14. the GPL may be found in GPL-LICENSE.txt or at:
  15. http://www.jrsoftware.org/files/tb2k/GPL-LICENSE.txt
  16. If you wish to allow use of your version of this file only under the terms of
  17. the GPL and not to allow others to use your version of this file under the
  18. "Toolbar2000 License", indicate your decision by deleting the provisions
  19. above and replace them with the notice and other provisions required by the
  20. GPL. If you do not delete the provisions above, a recipient may use your
  21. version of this file under either the "Toolbar2000 License" or the GPL.
  22. $jrsoftware: tb2k/Source/TB2MRU.pas,v 1.23 2005/01/06 03:56:50 jr Exp $
  23. }
  24. interface
  25. {$I TB2Ver.inc}
  26. uses
  27. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  28. TB2Item, IniFiles, Registry;
  29. type
  30. TTBMRUListClickEvent = procedure(Sender: TObject; const Filename: String) of object;
  31. TTBMRUList = class(TComponent)
  32. private
  33. FAddFullPath: Boolean;
  34. FContainer: TTBCustomItem;
  35. FHidePathExtension: Boolean;
  36. FList: TStrings;
  37. FMaxItems: Integer;
  38. FOnChange: TNotifyEvent;
  39. FOnClick: TTBMRUListClickEvent;
  40. FPrefix: String;
  41. procedure ClickHandler(Sender: TObject);
  42. procedure SetHidePathExtension(Value: Boolean);
  43. procedure SetList(Value: TStrings);
  44. procedure SetMaxItems(Value: Integer);
  45. protected
  46. property Container: TTBCustomItem read FContainer;
  47. function GetFirstKey: Integer; virtual;
  48. function GetItemClass: TTBCustomItemClass; virtual;
  49. procedure SetItemCaptions; virtual;
  50. public
  51. constructor Create(AOwner: TComponent); override;
  52. destructor Destroy; override;
  53. procedure Add(Filename: String);
  54. procedure Remove(const Filename: String);
  55. procedure LoadFromIni(Ini: TCustomIniFile; const Section: String);
  56. procedure LoadFromRegIni(Ini: TRegIniFile; const Section: String);
  57. procedure SaveToIni(Ini: TCustomIniFile; const Section: String);
  58. procedure SaveToRegIni(Ini: TRegIniFile; const Section: String);
  59. published
  60. { MaxItems must be published before Items }
  61. property AddFullPath: Boolean read FAddFullPath write FAddFullPath default True;
  62. property HidePathExtension: Boolean read FHidePathExtension write SetHidePathExtension default True;
  63. property MaxItems: Integer read FMaxItems write SetMaxItems default 4;
  64. property Items: TStrings read FList write SetList;
  65. property OnClick: TTBMRUListClickEvent read FOnClick write FOnClick;
  66. property OnChange: TNotifyEvent read FOnChange write FOnChange;
  67. property Prefix: String read FPrefix write FPrefix;
  68. end;
  69. TTBMRUListItem = class(TTBCustomItem)
  70. private
  71. FMRUList: TTBMRUList;
  72. procedure SetMRUList(Value: TTBMRUList);
  73. protected
  74. procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  75. public
  76. constructor Create(AOwner: TComponent); override;
  77. published
  78. property MRUList: TTBMRUList read FMRUList write SetMRUList;
  79. //property Caption;
  80. //property LinkSubitems;
  81. end;
  82. implementation
  83. uses
  84. TB2Common, TB2Consts, CommDlg;
  85. type
  86. TTBMRUListStrings = class(TStrings)
  87. private
  88. FInternalList: TStrings;
  89. FMRUList: TTBMRUList;
  90. procedure Changed;
  91. public
  92. constructor Create;
  93. destructor Destroy; override;
  94. procedure Clear; override;
  95. procedure Delete(Index: Integer); override;
  96. function Get(Index: Integer): String; override;
  97. function GetCount: Integer; override;
  98. function IndexOf(const S: String): Integer; override;
  99. procedure Insert(Index: Integer; const S: String); override;
  100. procedure Move(CurIndex, NewIndex: Integer); override;
  101. procedure Put(Index: Integer; const S: String); override;
  102. end;
  103. { TTBMRUListStrings }
  104. constructor TTBMRUListStrings.Create;
  105. begin
  106. inherited;
  107. FInternalList := TStringList.Create;
  108. end;
  109. destructor TTBMRUListStrings.Destroy;
  110. begin
  111. inherited;
  112. FInternalList.Free;
  113. end;
  114. procedure TTBMRUListStrings.Changed;
  115. begin
  116. if Assigned(FMRUList.FOnChange) and
  117. not(csLoading in FMRUList.ComponentState) then
  118. FMRUList.FOnChange(FMRUList);
  119. end;
  120. procedure TTBMRUListStrings.Clear;
  121. var
  122. I: Integer;
  123. begin
  124. for I := FInternalList.Count-1 downto 0 do
  125. Delete(I);
  126. end;
  127. procedure TTBMRUListStrings.Delete(Index: Integer);
  128. begin
  129. FMRUList.FContainer[Index].Free;
  130. FInternalList.Delete(Index);
  131. FMRUList.SetItemCaptions;
  132. Changed;
  133. end;
  134. function TTBMRUListStrings.Get(Index: Integer): String;
  135. begin
  136. Result := FInternalList[Index];
  137. end;
  138. function TTBMRUListStrings.GetCount: Integer;
  139. begin
  140. Result := FInternalList.Count;
  141. end;
  142. function TTBMRUListStrings.IndexOf(const S: String): Integer;
  143. begin
  144. { This is identical to TStrings.IndexOf except we use AnsiCompareFileName. }
  145. for Result := 0 to GetCount - 1 do
  146. if AnsiCompareFileName(Get(Result), S) = 0 then Exit;
  147. Result := -1;
  148. end;
  149. procedure TTBMRUListStrings.Insert(Index: Integer; const S: String);
  150. var
  151. Item: TTBCustomItem;
  152. begin
  153. Item := FMRUList.GetItemClass.Create(FMRUList.FContainer);
  154. Item.OnClick := FMRUList.ClickHandler;
  155. FMRUList.FContainer.Insert(Index, Item);
  156. FInternalList.Insert(Index, S);
  157. FMRUList.SetItemCaptions;
  158. Changed;
  159. end;
  160. procedure TTBMRUListStrings.Move(CurIndex, NewIndex: Integer);
  161. begin
  162. FInternalList.Move(CurIndex, NewIndex);
  163. FMRUList.FContainer.Move(CurIndex, NewIndex);
  164. FMRUList.SetItemCaptions;
  165. Changed;
  166. end;
  167. procedure TTBMRUListStrings.Put(Index: Integer; const S: String);
  168. begin
  169. FInternalList[Index] := S;
  170. FMRUList.SetItemCaptions;
  171. Changed;
  172. end;
  173. { TTBMRUList }
  174. constructor TTBMRUList.Create(AOwner: TComponent);
  175. begin
  176. inherited;
  177. FAddFullPath := True;
  178. FHidePathExtension := True;
  179. FMaxItems := 4;
  180. FPrefix := 'MRU';
  181. FList := TTBMRUListStrings.Create;
  182. TTBMRUListStrings(FList).FMRUList := Self;
  183. FContainer := TTBCustomItem.Create(nil);
  184. end;
  185. destructor TTBMRUList.Destroy;
  186. begin
  187. FContainer.Free;
  188. FList.Free;
  189. inherited;
  190. end;
  191. procedure TTBMRUList.Add(Filename: String);
  192. var
  193. I: Integer;
  194. begin
  195. if AddFullPath then
  196. Filename := ExpandFileName(Filename);
  197. { If Filename is already in the MRU list, move it to the top }
  198. I := FList.IndexOf(Filename);
  199. if I <> -1 then begin
  200. if I > 0 then
  201. FList.Move(I, 0);
  202. FList[0] := Filename; { ...in case the capitalization changed }
  203. end
  204. else
  205. FList.Insert(0, Filename);
  206. end;
  207. procedure TTBMRUList.Remove(const Filename: String);
  208. var
  209. I: Integer;
  210. begin
  211. I := FList.IndexOf(Filename);
  212. if I <> -1 then
  213. FList.Delete(I);
  214. end;
  215. procedure TTBMRUList.LoadFromIni(Ini: TCustomIniFile; const Section: String);
  216. var
  217. I: Integer;
  218. S: String;
  219. begin
  220. FList.Clear;
  221. for I := 1 to FMaxItems do begin
  222. S := Ini.ReadString(Section, FPrefix + IntToStr(I), '');
  223. if S <> '' then
  224. FList.Add(S);
  225. end;
  226. end;
  227. procedure TTBMRUList.LoadFromRegIni(Ini: TRegIniFile; const Section: String);
  228. var
  229. I: Integer;
  230. S: String;
  231. begin
  232. FList.Clear;
  233. for I := 1 to FMaxItems do begin
  234. S := Ini.ReadString(Section, FPrefix + IntToStr(I), '');
  235. if S <> '' then
  236. FList.Add(S);
  237. end;
  238. end;
  239. procedure TTBMRUList.SaveToIni(Ini: TCustomIniFile; const Section: String);
  240. var
  241. I: Integer;
  242. begin
  243. for I := 1 to FMaxItems do begin
  244. if I <= FList.Count then
  245. Ini.WriteString(Section, FPrefix + IntToStr(I), FList[I-1])
  246. else
  247. Ini.DeleteKey(Section, FPrefix + IntToStr(I));
  248. end;
  249. end;
  250. procedure TTBMRUList.SaveToRegIni(Ini: TRegIniFile; const Section: String);
  251. var
  252. I: Integer;
  253. begin
  254. for I := 1 to FMaxItems do begin
  255. if I <= FList.Count then
  256. Ini.WriteString(Section, FPrefix + IntToStr(I), FList[I-1])
  257. else
  258. Ini.DeleteKey(Section, FPrefix + IntToStr(I));
  259. end;
  260. end;
  261. procedure TTBMRUList.SetItemCaptions;
  262. var
  263. I, J, N: Integer;
  264. Key: Char;
  265. S: String;
  266. Buf: array[0..MAX_PATH-1] of Char;
  267. begin
  268. while FList.Count > FMaxItems do
  269. FList.Delete(FList.Count-1);
  270. N := GetFirstKey;
  271. for I := 0 to FContainer.Count-1 do begin
  272. Key := #0;
  273. if N < 9 then
  274. Key := Chr(Ord('1') + N)
  275. else begin
  276. { No more numbers; try letters }
  277. J := N - 9;
  278. if J < 26 then
  279. Key := Chr(Ord('A') + J);
  280. end;
  281. S := FList[I];
  282. if HidePathExtension and (GetFileTitle(PChar(S), Buf, SizeOf(Buf)) = 0) then
  283. S := Buf;
  284. S := EscapeAmpersands(S);
  285. if Key <> #0 then
  286. FContainer[I].Caption := Format('&%s %s', [Key, S])
  287. else
  288. FContainer[I].Caption := S;
  289. Inc(N);
  290. end;
  291. end;
  292. procedure TTBMRUList.ClickHandler(Sender: TObject);
  293. var
  294. I: Integer;
  295. begin
  296. I := FContainer.IndexOf(TTBCustomItem(Sender));
  297. if I <> -1 then begin
  298. if I > 0 then
  299. FList.Move(I, 0);
  300. if Assigned(FOnClick) then
  301. FOnClick(Self, FList[0]);
  302. end;
  303. end;
  304. procedure TTBMRUList.SetHidePathExtension(Value: Boolean);
  305. begin
  306. if FHidePathExtension <> Value then begin
  307. FHidePathExtension := Value;
  308. SetItemCaptions;
  309. end;
  310. end;
  311. procedure TTBMRUList.SetList(Value: TStrings);
  312. begin
  313. FList.Assign(Value);
  314. end;
  315. procedure TTBMRUList.SetMaxItems(Value: Integer);
  316. begin
  317. FMaxItems := Value;
  318. SetItemCaptions;
  319. end;
  320. function TTBMRUList.GetItemClass: TTBCustomItemClass;
  321. begin
  322. Result := TTBCustomItem;
  323. end;
  324. function TTBMRUList.GetFirstKey: Integer;
  325. begin
  326. Result := 0;
  327. end;
  328. { TTBMRUListItem }
  329. constructor TTBMRUListItem.Create(AOwner: TComponent);
  330. begin
  331. inherited;
  332. ItemStyle := ItemStyle + [tbisEmbeddedGroup];
  333. Caption := STBMRUListItemDefCaption;
  334. end;
  335. procedure TTBMRUListItem.Notification(AComponent: TComponent;
  336. Operation: TOperation);
  337. begin
  338. inherited;
  339. if (AComponent = FMRUList) and (Operation = opRemove) then
  340. SetMRUList(nil);
  341. end;
  342. procedure TTBMRUListItem.SetMRUList(Value: TTBMRUList);
  343. begin
  344. if FMRUList <> Value then begin
  345. FMRUList := Value;
  346. if Assigned(FMRUList) then begin
  347. Value.FreeNotification(Self);
  348. LinkSubitems := FMRUList.FContainer;
  349. end
  350. else
  351. LinkSubitems := nil;
  352. end;
  353. end;
  354. end.