diff --git a/Src/FmMain.pas b/Src/FmMain.pas
index 8bffbe2b8..770455f0e 100644
--- a/Src/FmMain.pas
+++ b/Src/FmMain.pas
@@ -522,12 +522,6 @@ TMainForm = class(THelpAwareForm)
/// Object that manages favourites.
fFavouritesMgr: TFavouritesManager;
- /// Handles the WM_POWERBROADCAST messages to detect and
- /// respond to hibernation messages.
- /// !! HACK necessary as part of the fix for an obscure bug. See
- /// https://github.com/delphidabbler/codesnip/issues/70
- procedure WMPowerBroadcast(var Msg: TMessage); message WM_POWERBROADCAST;
-
/// Displays view item given by TViewItemAction instance
/// referenced by Sender and adds to history list.
procedure ActViewItemExecute(Sender: TObject);
@@ -1586,19 +1580,5 @@ procedure TMainForm.splitVertCanResize(Sender: TObject;
Accept := False;
end;
-procedure TMainForm.WMPowerBroadcast(var Msg: TMessage);
-begin
- // !! HACK
- // Sometimes when the computer is resumed from hibernation the tree view in
- // the overview frame is destroyed and recreated by Windows. Unfortunately the
- // IView instances associated with the recreated tree nodes are lost.
- // Attempting to read those (now nil) IView instances was resulting in an
- // access violation.
- case Msg.WParam of
- PBT_APMSUSPEND:
- fMainDisplayMgr._HACK_PrepareForHibernate;
- end;
-end;
-
end.
diff --git a/Src/FrOverview.dfm b/Src/FrOverview.dfm
index 159f3cddc..b47989bbd 100644
--- a/Src/FrOverview.dfm
+++ b/Src/FrOverview.dfm
@@ -1,9 +1,9 @@
inherited OverviewFrame: TOverviewFrame
inherited pnlTitle: TPanel
inherited lblTitle: TLabel
- Width = 54
+ Width = 53
Caption = 'Overview'
- ExplicitWidth = 54
+ ExplicitWidth = 53
end
object tbarOverview: TToolBar
Left = 224
diff --git a/Src/FrOverview.pas b/Src/FrOverview.pas
index 9cf76a2a8..8355d9ad6 100644
--- a/Src/FrOverview.pas
+++ b/Src/FrOverview.pas
@@ -18,6 +18,7 @@ interface
uses
// Delphi
+ Generics.Collections,
ComCtrls, Controls, Classes, Windows, ExtCtrls, StdCtrls, ToolWin, Menus,
// Project
DB.USnippet, FrTitled, IntfFrameMgrs, IntfNotifier, UCommandBars,
@@ -26,29 +27,6 @@ interface
type
- // !! HACK
- // Horrible hack to expose CreateWnd for overiding TTreeView.CreateWnd for the
- // existing TTreeView component of TOverviewFrame. The hack avoids having to
- // remove the component and replacing it with a descendant class that is
- // manually constructed at run time.
- // This is here to enable the tree view to be recreated with correctly
- // instantiated TViewItemTreeNode nodes after Windows recreates the tree
- // behind the scenes after resuming from hibernation.
- // I am deeply ashamed of this hack.
- TTreeView = class(ComCtrls.TTreeView)
- strict private
- var
- _HACK_fOnAfterCreateNilViews: TNotifyEvent;
- protected
- procedure CreateWnd; override;
- public
- /// !! HACK. Event triggered after the inherited CreateWnd is
- /// called. Only called if the tree view has nil references to IView
- /// objects.
- property _HACK_OnAfterCreateNilViews: TNotifyEvent
- read _HACK_fOnAfterCreateNilViews write _HACK_fOnAfterCreateNilViews;
- end;
-
{
TOverviewFrame:
Titled frame that displays lists of snippets grouped in various ways and
@@ -111,6 +89,7 @@ TTVDraw = class(TSnippetsTVDraw)
end;
var
+ fViewStore : TList; // Stores the references of the Views
fTVDraw: TTVDraw; // Object that renders tree view nodes
fNotifier: INotifier; // Notifies app of user initiated events
fCanChange: Boolean; // Whether selected node allowed to change
@@ -237,10 +216,6 @@ TTVDraw = class(TSnippetsTVDraw)
procedure RestoreTreeState;
{Restores last saved treeview expansion state from memory.
}
- /// !! HACK: Sets an event handler on the tree view to work
- /// around a bug that can occur after resuming from hibernation.
- /// Method of IOverviewDisplayMgr.
- procedure _HACK_SetHibernateHandler(const AHandler: TNotifyEvent);
{ IPaneInfo }
function IsInteractive: Boolean;
{Checks if the pane is currently interactive with user.
@@ -311,6 +286,7 @@ constructor TOverviewFrame.Create(AOwner: TComponent);
TabIdx: Integer; // loops through tabs
begin
inherited;
+ fViewStore := TList.Create;
// Create delegated (contained) command bar manager for toolbar and popup menu
fCommandBars := TCommandBarMgr.Create(Self);
fCommandBars.AddCommandBar(
@@ -346,6 +322,7 @@ destructor TOverviewFrame.Destroy;
fSelectedItem := nil;
fSnippetList.Free; // does not free referenced snippets
fCommandBars.Free;
+ fViewStore.Free;
inherited;
end;
@@ -547,7 +524,7 @@ procedure TOverviewFrame.Redisplay;
Exit;
// Build new treeview using grouping determined by selected tab
Builder := BuilderClasses[tcDisplayStyle.TabIndex].Create(
- tvSnippets, fSnippetList
+ tvSnippets, fSnippetList, fViewStore
);
Builder.Build;
// Restore state of treeview based on last time it was displayed
@@ -982,12 +959,6 @@ procedure TOverviewFrame.UpdateTreeState(const State: TTreeNodeAction);
end;
end;
-procedure TOverviewFrame._HACK_SetHibernateHandler(
- const AHandler: TNotifyEvent);
-begin
- tvSnippets._HACK_OnAfterCreateNilViews := AHandler;
-end;
-
{ TOverviewFrame.TTVDraw }
function TOverviewFrame.TTVDraw.IsSectionHeadNode(
@@ -1026,24 +997,5 @@ function TOverviewFrame.TTVDraw.IsUserDefinedNode(
Result := False;
end;
-{ TTreeView }
-
-procedure TTreeView.CreateWnd;
-var
- HasNilViews: Boolean;
- Node: TTreeNode;
-begin
- inherited;
- HasNilViews := False;
- for Node in Items do
- begin
- HasNilViews := not Assigned((Node as TViewItemTreeNode).ViewItem);
- if HasNilViews then
- Break;
- end;
- if HasNilViews and Assigned(_HACK_fOnAfterCreateNilViews) then
- _HACK_fOnAfterCreateNilViews(Self);
-end;
-
end.
diff --git a/Src/IntfFrameMgrs.pas b/Src/IntfFrameMgrs.pas
index b3cb76101..813d320ad 100644
--- a/Src/IntfFrameMgrs.pas
+++ b/Src/IntfFrameMgrs.pas
@@ -19,7 +19,6 @@ interface
uses
// Delphi
SHDocVw, ActiveX,
- Classes, // !! For HACK
// Project
Browser.IntfDocHostUI, DB.USnippet, Compilers.UGlobals, UCommandBars, UView;
@@ -146,9 +145,6 @@ interface
/// Restore expand / collapse state of treeview to last save
/// state.
procedure RestoreTreeState;
- /// !! HACK: Sets an event handler on the tree view to work
- /// around a bug that can occur after resuming from hibernation.
- procedure _HACK_SetHibernateHandler(const AHandler: TNotifyEvent);
end;
type
diff --git a/Src/UMainDisplayMgr.pas b/Src/UMainDisplayMgr.pas
index 0c64a17d5..15020fb34 100644
--- a/Src/UMainDisplayMgr.pas
+++ b/Src/UMainDisplayMgr.pas
@@ -165,11 +165,6 @@ TMainDisplayMgr = class(TObject)
procedure DisplayViewItem(ViewItem: IView; Mode: TDetailPageDisplayMode);
overload;
- /// !! HACK event handle to redisplay the overview pane treeview.
- /// Called only if Windows has mysteriously recreated the treeview and lost
- /// necessary object references.
- procedure _HACK_HibernateHandler(Sender: TObject);
-
public
/// Object contructor. Sets up object to work with given frame
/// manager objects.
@@ -297,13 +292,6 @@ TMainDisplayMgr = class(TObject)
/// Prepares display ready for database to be reloaded.
procedure PrepareForDBReload;
- /// !!HACK: gets the overview frame prepared for program
- /// hibernation.
- /// Saves the overview tree view state ready for restoring after
- /// hibernation if Windows has recreated the overview pane's treeview,
- /// losing necessary IView object references..
- procedure _HACK_PrepareForHibernate;
-
end;
@@ -704,21 +692,5 @@ procedure TMainDisplayMgr.UpdateOverviewTreeState(const State: TTreeNodeAction);
(fOverviewMgr as IOverviewDisplayMgr).UpdateTreeState(State);
end;
-procedure TMainDisplayMgr._HACK_HibernateHandler(Sender: TObject);
-begin
- (fOverviewMgr as IOverviewDisplayMgr).Display(Query.Selection, True);
- (fOverviewMgr as IOverviewDisplayMgr).RestoreTreeState;
- // disable this handler until next resume from hibernation
- (fOverviewMgr as IOverviewDisplayMgr)._HACK_SetHibernateHandler(nil);
-end;
-
-procedure TMainDisplayMgr._HACK_PrepareForHibernate;
-begin
- (fOverviewMgr as IOverviewDisplayMgr).SaveTreeState;
- (fOverviewMgr as IOverviewDisplayMgr)._HACK_SetHibernateHandler(
- _HACK_HibernateHandler
- );
-end;
-
end.
diff --git a/Src/UOverviewTreeBuilder.pas b/Src/UOverviewTreeBuilder.pas
index 87a32f23c..7e0e835e3 100644
--- a/Src/UOverviewTreeBuilder.pas
+++ b/Src/UOverviewTreeBuilder.pas
@@ -18,6 +18,7 @@ interface
uses
// Delphu
+ Generics.Collections,
ComCtrls,
// Project
DB.USnippet, UGroups, UView, UViewItemTreeNode;
@@ -34,11 +35,14 @@ TOverviewTreeBuilder = class abstract(TObject)
var
fTreeView: TTreeView; // Value of TreeView property
fSnippetList: TSnippetList; // Value of SnippetList property
+ fViewStore : TList;
strict protected
property TreeView: TTreeView read fTreeView;
{Reference to treeview populated by class}
property SnippetList: TSnippetList read fSnippetList;
{List of snippets to be displayed in treeview}
+ property ViewStore : TList read fViewStore;
+ {List of views attached to treeview nodes}
function AddViewItemNode(const ParentNode: TViewItemTreeNode;
ViewItem: IView): TViewItemTreeNode;
{Adds a new node to the tree view that represents a view item.
@@ -57,7 +61,7 @@ TOverviewTreeBuilder = class abstract(TObject)
@return Required view item object.
}
public
- constructor Create(const TV: TTreeView; const SnippetList: TSnippetList);
+ constructor Create(const TV: TTreeView; const SnippetList: TSnippetList; const ViewStore : TList);
{Class constructor. Sets up object to populate a treeview with a list of
snippets.
@param TV [in] Treeview control to be populated.
@@ -177,7 +181,9 @@ procedure TOverviewTreeBuilder.Build;
ParentNode: TViewItemTreeNode; // each section node in tree
Grouping: TGrouping; // groups snippets
Group: TGroupItem; // each group of snippets
+ View: IView;
begin
+ ViewStore.Clear;
// Create required grouping of snippets
Grouping := CreateGrouping;
try
@@ -186,11 +192,17 @@ procedure TOverviewTreeBuilder.Build;
begin
if not Group.IsEmpty or Preferences.ShowEmptySections then
begin
- ParentNode := AddViewItemNode(nil, CreateViewItemForGroup(Group));
+ View := CreateViewItemForGroup(Group);
+ ParentNode := AddViewItemNode(nil, View);
+ ViewStore.Add(View);
for Snippet in Group.SnippetList do
+ begin
+ View := TViewFactory.CreateSnippetView(Snippet);
AddViewItemNode(
- ParentNode, TViewFactory.CreateSnippetView(Snippet)
+ ParentNode, View
);
+ ViewStore.Add(View);
+ end;
end;
end;
finally
@@ -199,7 +211,7 @@ procedure TOverviewTreeBuilder.Build;
end;
constructor TOverviewTreeBuilder.Create(const TV: TTreeView;
- const SnippetList: TSnippetList);
+ const SnippetList: TSnippetList; const ViewStore : TList);
{Class constructor. Sets up object to populate a treeview with a list of
snippets.
@param TV [in] Treeview control to be populated.
@@ -209,6 +221,7 @@ constructor TOverviewTreeBuilder.Create(const TV: TTreeView;
inherited Create;
fTreeView := TV;
fSnippetList := SnippetList;
+ fViewStore := ViewStore;
end;
{ TOverviewCategorisedTreeBuilder }
diff --git a/Src/UViewItemTreeNode.pas b/Src/UViewItemTreeNode.pas
index 44e258c24..51180997c 100644
--- a/Src/UViewItemTreeNode.pas
+++ b/Src/UViewItemTreeNode.pas
@@ -31,14 +31,28 @@ interface
}
TViewItemTreeNode = class(TTreeNode)
strict private
- var fViewItem: IView; // Value of ViewItem property
+ function GetViewItem: IView;
+ procedure SetViewItem(const Value: IView);
+ published // Value of ViewItem property
public
- property ViewItem: IView read fViewItem write fViewItem;
+ property ViewItem: IView read GetViewItem write SetViewItem;
{View item associated with tree node}
end;
implementation
+{ TViewItemTreeNode }
+
+function TViewItemTreeNode.GetViewItem: IView;
+begin
+ Result := IView(Data);
+end;
+
+procedure TViewItemTreeNode.SetViewItem(const Value: IView);
+begin
+ Data := Pointer(Value);
+end;
+
end.