@@ -32,26 +32,14 @@ interface
3232 // / </remarks>
3333 TPreferencesDlg = class (TGenericOKDlg, INoPublicConstruct)
3434 pcMain: TPageControl;
35+ lbPages: TListBox;
3536 // / <summary>OK button click event handler. Writes preference data to
3637 // / persistent storage.</summary>
3738 procedure btnOKClick (Sender: TObject);
38- // / <param>Called when current tab sheet has changed. Gets newly selected
39- // / page to re-initialise its controls from local preferences.</param>
40- // / <remarks>This enables any pages that depend on preferences that may
41- // / have been changed in other pages to update appropriately.</remarks>
42- procedure pcMainChange (Sender: TObject);
43- // / <summary>Called just before active tab sheet is changed. Causes page
44- // / about to be deselected to update local preferences with any changes.
45- // / </summary>
46- // / <remarks>We do this in case another page needs to update due to changes
47- // / made on current page.</remarks>
48- procedure pcMainChanging (Sender: TObject; var AllowChange: Boolean);
49- // / <summary>Handles event triggered when user clicks on one of page
50- // / control tabs. Ensures page control has focus.</summary>
51- // / <remarks>Without this fix, page control does not always get focus when
52- // / a tab is clicked.</remarks>
53- procedure pcMainMouseDown (Sender: TObject; Button: TMouseButton;
54- Shift: TShiftState; X, Y: Integer);
39+ // / <summary>Handles event triggered when list box is clicked or changed
40+ // / via keyboard.</summary>
41+ procedure lbPagesClick (Sender: TObject);
42+ procedure FormDestroy (Sender: TObject);
5543 strict private
5644 class var
5745 // / <summary>List of registered page frames</summary>
@@ -62,6 +50,10 @@ TPreferencesDlg = class(TGenericOKDlg, INoPublicConstruct)
6250 // / <summary>Records if main UI needs to be updated to reflect changed
6351 // / preferences.</summary>
6452 fUpdateUI: Boolean;
53+ // / <summary>Records flags to be passed to frames.</summary>
54+ fFrameFlags: UInt64;
55+ // / <summary>Records index of currently select tab/list item.</summary>
56+ fCurrentPageIdx: Integer;
6557 // / <summary>Creates the required frames and displays each in a tab sheet
6658 // / within the page control.</summary>
6759 // / <param name="FrameClasses">array of TPrefsFrameClass [in] Class
@@ -83,6 +75,13 @@ TPreferencesDlg = class(TGenericOKDlg, INoPublicConstruct)
8375 // / <summary>Gets reference to preferences frame on currently selected tab.
8476 // / </summary>
8577 function GetSelectedPage : TPrefsBaseFrame;
78+ // / <summary>Selects given tab.</summary>
79+ // / <remarks>Stores state of tab being closed and restores state of tab
80+ // / being opened.</remarks>
81+ procedure SelectTab (TS: TTabSheet);
82+ // / <summary>Returns index of tab selected when dialogue box was last
83+ // / closed or -1 if no tab recorded or tab doesn't exist.</summary>
84+ function GetLastTabIdx : Integer;
8685 strict protected
8786 // / <summary>Gets the help A-link keyword to be used when help button
8887 // / clicked.</summary>
@@ -111,7 +110,8 @@ TPreferencesDlg = class(TGenericOKDlg, INoPublicConstruct)
111110 // / <returns>Boolean. True if user clicks OK to accept changes or False if
112111 // / user cancels and no changes made.</returns>
113112 class function Execute (AOwner: TComponent;
114- const Pages: array of TPrefsFrameClass; out UpdateUI: Boolean): Boolean;
113+ const Pages: array of TPrefsFrameClass; out UpdateUI: Boolean;
114+ const Flags: UInt64 = 0 ): Boolean;
115115 overload;
116116 // / <summary>Displays dialog with pages for each specified preferences
117117 // / frame.</summary>
@@ -122,7 +122,8 @@ TPreferencesDlg = class(TGenericOKDlg, INoPublicConstruct)
122122 // / <returns>Boolean. True if user clicks OK to accept changes or False if
123123 // / user cancels and no changes made.</returns>
124124 class function Execute (AOwner: TComponent;
125- const Pages: array of TPrefsFrameClass): Boolean; overload;
125+ const Pages: array of TPrefsFrameClass; const Flags: UInt64 = 0 ):
126+ Boolean; overload;
126127 // / <summary>Displays preferences dialog with all registered preference
127128 // / frames.</summary>
128129 // / <param name="AOwner">TComponent [in] Component that owns dialog.
@@ -131,8 +132,8 @@ TPreferencesDlg = class(TGenericOKDlg, INoPublicConstruct)
131132 // / be updated as a result of preference changes.</param>
132133 // / <returns>Boolean. True if user clicks OK to accept changes or False if
133134 // / user cancels and no changes made.</returns>
134- class function Execute (AOwner: TComponent; out UpdateUI: Boolean): Boolean ;
135- overload;
135+ class function Execute (AOwner: TComponent; out UpdateUI: Boolean;
136+ const Flags: UInt64 = 0 ): Boolean; overload;
136137 // / <summary>Displays dialogue with showing a single frame, specified by
137138 // / its class name.</summary>
138139 // / <param name="AOwner">TComponent [in] Component that owns dialog.
@@ -144,7 +145,7 @@ TPreferencesDlg = class(TGenericOKDlg, INoPublicConstruct)
144145 // / <returns>Boolean. True if user clicks OK to accept changes or False if
145146 // / user cancels and no changes made.</returns>
146147 class function Execute (AOwner: TComponent; const PageClsName: string;
147- out UpdateUI: Boolean): Boolean; overload;
148+ out UpdateUI: Boolean; const Flags: UInt64 = 0 ): Boolean; overload;
148149 // / <summary>Registers given preferences frame class for inclusion in the
149150 // / preferences dialog box.</summary>
150151 // / <remarks>Registered frames are created when the dialog box is displayed
@@ -177,7 +178,8 @@ implementation
177178
178179uses
179180 // Project
180- IntfCommon;
181+ IntfCommon,
182+ UStrUtils;
181183
182184
183185{ $R *.dfm}
@@ -241,6 +243,10 @@ procedure TPreferencesDlg.CreatePages(
241243 Frame.Top := 4 ;
242244 // set tab sheet caption to frame's display name
243245 TS.Caption := Frame.DisplayName;
246+ TS.TabVisible := False;
247+
248+ // Create list box item for page
249+ lbPages.Items.AddObject(Frame.DisplayName, TS);
244250 end ;
245251end ;
246252
@@ -256,10 +262,12 @@ function TPreferencesDlg.CustomHelpKeyword: string;
256262end ;
257263
258264class function TPreferencesDlg.Execute (AOwner: TComponent;
259- const Pages: array of TPrefsFrameClass; out UpdateUI: Boolean): Boolean;
265+ const Pages: array of TPrefsFrameClass; out UpdateUI: Boolean;
266+ const Flags: UInt64): Boolean;
260267begin
261268 with InternalCreate(AOwner) do
262269 try
270+ fFrameFlags := Flags;
263271 CreatePages(Pages);
264272 Result := ShowModal = mrOK;
265273 if Result then
@@ -272,21 +280,22 @@ class function TPreferencesDlg.Execute(AOwner: TComponent;
272280end ;
273281
274282class function TPreferencesDlg.Execute (AOwner: TComponent;
275- out UpdateUI: Boolean): Boolean;
283+ out UpdateUI: Boolean; const Flags: UInt64 ): Boolean;
276284begin
277- Result := Execute(AOwner, fPages.ToArray, UpdateUI);
285+ Result := Execute(AOwner, fPages.ToArray, UpdateUI, Flags );
278286end ;
279287
280288class function TPreferencesDlg.Execute (AOwner: TComponent;
281- const Pages: array of TPrefsFrameClass): Boolean;
289+ const Pages: array of TPrefsFrameClass; const Flags: UInt64 ): Boolean;
282290var
283291 Dummy: Boolean; // unused UpdateUI parameters
284292begin
285- Result := Execute(AOwner, Pages, Dummy);
293+ Result := Execute(AOwner, Pages, Dummy, Flags );
286294end ;
287295
288296class function TPreferencesDlg.Execute (AOwner: TComponent;
289- const PageClsName: string; out UpdateUI: Boolean): Boolean;
297+ const PageClsName: string; out UpdateUI: Boolean; const Flags: UInt64):
298+ Boolean;
290299var
291300 FrameClass: TPrefsFrameClass;
292301begin
@@ -295,14 +304,36 @@ class function TPreferencesDlg.Execute(AOwner: TComponent;
295304 Result := Execute(AOwner, [FrameClass], UpdateUI);
296305end ;
297306
307+ procedure TPreferencesDlg.FormDestroy (Sender: TObject);
308+ begin
309+ // Save current tab
310+ if Assigned(pcMain.ActivePage) then
311+ Preferences.LastTab := MapTabSheetToPage(pcMain.ActivePage).DisplayName;
312+ inherited ;
313+ end ;
314+
315+ function TPreferencesDlg.GetLastTabIdx : Integer;
316+ var
317+ TabName: string;
318+ ListIdx: Integer;
319+ begin
320+ TabName := Preferences.LastTab;
321+ if TabName = ' ' then
322+ Exit(-1 );
323+ for ListIdx := 0 to Pred(lbPages.Count) do
324+ if StrSameText(TabName, lbPages.Items[ListIdx]) then
325+ Exit(ListIdx);
326+ Result := -1 ;
327+ end ;
328+
298329function TPreferencesDlg.GetSelectedPage : TPrefsBaseFrame;
299330begin
300331 Result := MapTabSheetToPage(pcMain.ActivePage);
301332end ;
302333
303334procedure TPreferencesDlg.InitForm ;
304335var
305- TabIdx: Integer; // loops thru tabs in page control
336+ TabIdx: Integer; // loops thru tabs in page control
306337begin
307338 inherited ;
308339 // Take local copy of global preferences. This local copy will be updated as
@@ -311,9 +342,22 @@ procedure TPreferencesDlg.InitForm;
311342 fLocalPrefs := (Preferences as IClonable).Clone as IPreferences;
312343 // Display and initialise required pages
313344 for TabIdx := 0 to Pred(pcMain.PageCount) do
314- MapTabSheetToPage(TabIdx).LoadPrefs(fLocalPrefs);
315- // Select first TabSheet
316- pcMain.ActivePageIndex := 0 ;
345+ MapTabSheetToPage(TabIdx).LoadPrefs(fLocalPrefs, fFrameFlags);
346+ // Select last use tab sheet (or 1st if last not known)
347+ fCurrentPageIdx := GetLastTabIdx;
348+ if fCurrentPageIdx < 0 then
349+ fCurrentPageIdx := 0 ;
350+ pcMain.ActivePageIndex := fCurrentPageIdx;
351+ lbPages.ItemIndex := fCurrentPageIdx;
352+ end ;
353+
354+ procedure TPreferencesDlg.lbPagesClick (Sender: TObject);
355+ begin
356+ if lbPages.ItemIndex < 0 then
357+ Exit;
358+ if lbPages.ItemIndex = fCurrentPageIdx then
359+ Exit;
360+ SelectTab(lbPages.Items.Objects[lbPages.ItemIndex] as TTabSheet)
317361end ;
318362
319363class function TPreferencesDlg.MapClassNameToPageClass (const ClsName: string):
@@ -351,24 +395,6 @@ function TPreferencesDlg.MapTabSheetToPage(
351395 Assert(Assigned(Result), ClassName + ' .MapTabSheetToPage: Frame not found' );
352396end ;
353397
354- procedure TPreferencesDlg.pcMainChange (Sender: TObject);
355- begin
356- GetSelectedPage.Activate(fLocalPrefs);
357- end ;
358-
359- procedure TPreferencesDlg.pcMainChanging (Sender: TObject;
360- var AllowChange: Boolean);
361- begin
362- GetSelectedPage.Deactivate(fLocalPrefs);
363- end ;
364-
365- procedure TPreferencesDlg.pcMainMouseDown (Sender: TObject; Button: TMouseButton;
366- Shift: TShiftState; X, Y: Integer);
367- begin
368- if htOnItem in pcMain.GetHitTestInfoAt(X, Y) then
369- pcMain.SetFocus;
370- end ;
371-
372398class procedure TPreferencesDlg.RegisterPage (const FrameCls: TPrefsFrameClass);
373399var
374400 PageIdx: Integer; // loops through all registered frames
@@ -389,5 +415,14 @@ class procedure TPreferencesDlg.RegisterPage(const FrameCls: TPrefsFrameClass);
389415 fPages.Insert(InsIdx, FrameCls);
390416end ;
391417
418+ procedure TPreferencesDlg.SelectTab (TS: TTabSheet);
419+ begin
420+ Assert(Assigned(TS), ClassName + ' .SelectTab: TS is nil' );
421+ GetSelectedPage.Deactivate(fLocalPrefs);
422+ pcMain.ActivePage := TS;
423+ GetSelectedPage.Activate(fLocalPrefs, fFrameFlags);
424+ fCurrentPageIdx := pcMain.ActivePageIndex;
425+ end ;
426+
392427end .
393428
0 commit comments