* (4.8 branch) Synchronize with main svn up to version 206

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1134 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
blikblum
2010-01-23 23:35:25 +00:00
parent b8431de5ff
commit 45b83a0d09

View File

@ -27,6 +27,10 @@ unit VirtualTrees;
// (C) 1999-2001 digital publishing AG. All Rights Reserved. // (C) 1999-2001 digital publishing AG. All Rights Reserved.
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// //
// July 2009
// - Bug fix: TWorkerThread will no longer reference the tree after it has been destroyed (Mantis issue #384)
// - Bug fix: TBaseVirtualTree.InternalConnectNode checked the expanded state of the wrong node if Mode was
// amAddChildFirst or amAddChildLast
// June 2009 // June 2009
// - Bug fix: fixed some issues concerning the vista theme handling // - Bug fix: fixed some issues concerning the vista theme handling
// - Improvement: removed hidden node handling in this branch // - Improvement: removed hidden node handling in this branch
@ -4008,6 +4012,7 @@ type
FWaiterList: TThreadList; FWaiterList: TThreadList;
FRefCount: Cardinal; FRefCount: Cardinal;
protected protected
procedure CancelValidation(Tree: TBaseVirtualTree);
procedure ChangeTreeStates(EnterStates, LeaveStates: TChangeStates); procedure ChangeTreeStates(EnterStates, LeaveStates: TChangeStates);
procedure Execute; override; procedure Execute; override;
public public
@ -4987,6 +4992,10 @@ begin
// Make sure there is no reference remaining to the releasing tree. // Make sure there is no reference remaining to the releasing tree.
Tree.InterruptValidation; Tree.InterruptValidation;
// Borland change (used to debug shutdown issue with dangling FCurrentTree reference)
Assert(WorkerThread.FCurrentTree <> Tree, 'WorkerThread.FCurrentTree dangling reference!');
if WorkerThread.FRefCount = 0 then if WorkerThread.FRefCount = 0 then
begin begin
with WorkerThread do with WorkerThread do
@ -5036,6 +5045,26 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TWorkerThread.CancelValidation(Tree: TBaseVirtualTree);
var
Msg: TMsg;
begin
// Wait for any references to this tree to be released.
// Pump WM_CHANGESTATE messages so the thread doesn't block on SendMessage calls.
while FCurrentTree = Tree do
begin
if Tree.HandleAllocated and PeekMessage(Msg, Tree.Handle, WM_CHANGESTATE, WM_CHANGESTATE, PM_REMOVE) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TWorkerThread.ChangeTreeStates(EnterStates, LeaveStates: TChangeStates); procedure TWorkerThread.ChangeTreeStates(EnterStates, LeaveStates: TChangeStates);
begin begin
@ -5078,14 +5107,14 @@ begin
end; end;
// Something to do? // Something to do?
try
if Assigned(FCurrentTree) then if Assigned(FCurrentTree) then
begin begin
try
ChangeTreeStates([csValidating], [csUseCache]); ChangeTreeStates([csValidating], [csUseCache]);
EnterStates := []; EnterStates := [];
if not (tsStopValidation in FCurrentTree.FStates) and FCurrentTree.DoValidateCache then if not (tsStopValidation in FCurrentTree.FStates) and FCurrentTree.DoValidateCache then
EnterStates := [csUseCache]; EnterStates := [csUseCache];
end;
finally finally
LeaveStates := [csValidating, csStopValidation]; LeaveStates := [csValidating, csStopValidation];
if csUseCache in EnterStates then if csUseCache in EnterStates then
@ -5096,6 +5125,7 @@ begin
end; end;
end; end;
end; end;
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -5113,6 +5143,7 @@ begin
finally finally
FWaiterList.UnlockList; FWaiterList.UnlockList;
end; end;
CancelValidation(Tree);
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -12900,10 +12931,8 @@ end;
procedure TBaseVirtualTree.InterruptValidation; procedure TBaseVirtualTree.InterruptValidation;
// Waits until the worker thread has stopped validating the caches of this tree. var
WasValidating: Boolean;
//var
// Msg: TMsg;
begin begin
DoStateChange([tsStopValidation], [tsUseCache]); DoStateChange([tsStopValidation], [tsUseCache]);
@ -12911,35 +12940,13 @@ begin
// Check the worker thread existance. It might already be gone (usually on destruction of the last tree). // Check the worker thread existance. It might already be gone (usually on destruction of the last tree).
if Assigned(WorkerThread) then if Assigned(WorkerThread) then
begin begin
if tsValidating in FStates then WasValidating := (tsValidating in FStates);
begin
// Do a hard break until the worker thread has stopped validation.
while (tsValidating in FStates) and (WorkerThread.CurrentTree = Self) and not Application.Terminated do
begin
// Pump our own messages to avoid a deadlock.
//todo_lcl_check
Application.ProcessMessages;
{
if PeekMessage(Msg, Handle, 0, 0, PM_REMOVE) then
begin
if Msg.message = WM_QUIT then
begin
PostQuitMessage(Msg.WParam);
Break;
end;
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
}
end;
DoStateChange([tsValidationNeeded]);
end
else // Remove any pending validation.
WorkerThread.RemoveTree(Self); WorkerThread.RemoveTree(Self);
if WasValidating then
DoStateChange([tsValidationNeeded]);
end; end;
{$endif} {$endif}
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.IsFirstVisibleChild(Parent, Node: PVirtualNode): Boolean; function TBaseVirtualTree.IsFirstVisibleChild(Parent, Node: PVirtualNode): Boolean;
@ -21505,7 +21512,7 @@ begin
Include(Destination.States, vsHasChildren); Include(Destination.States, vsHasChildren);
AdjustTotalCount(Destination, Node.TotalCount, True); AdjustTotalCount(Destination, Node.TotalCount, True);
// Add the new node's height only if its parent is expanded. // Add the new node's height only if its parent is expanded.
if Destination.Parent.States * [vsExpanded, vsVisible] = [vsExpanded, vsVisible] then if Destination.States * [vsExpanded, vsVisible] = [vsExpanded, vsVisible] then
AdjustTotalHeight(Destination, Node.TotalHeight, True); AdjustTotalHeight(Destination, Node.TotalHeight, True);
if FullyVisible[Node] then if FullyVisible[Node] then
Inc(FVisibleCount, CountVisibleChildren(Node) + 1); Inc(FVisibleCount, CountVisibleChildren(Node) + 1);
@ -21536,7 +21543,7 @@ begin
Include(Destination.States, vsHasChildren); Include(Destination.States, vsHasChildren);
AdjustTotalCount(Destination, Node.TotalCount, True); AdjustTotalCount(Destination, Node.TotalCount, True);
// Add the new node's height only if its parent is expanded. // Add the new node's height only if its parent is expanded.
if Destination.Parent.States * [vsExpanded, vsVisible] = [vsExpanded, vsVisible] then if Destination.States * [vsExpanded, vsVisible] = [vsExpanded, vsVisible] then
AdjustTotalHeight(Destination, Node.TotalHeight, True); AdjustTotalHeight(Destination, Node.TotalHeight, True);
if FullyVisible[Node] then if FullyVisible[Node] then
Inc(FVisibleCount, CountVisibleChildren(Node) + 1); Inc(FVisibleCount, CountVisibleChildren(Node) + 1);