* (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.
//----------------------------------------------------------------------------------------------------------------------
//
// 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
// - Bug fix: fixed some issues concerning the vista theme handling
// - Improvement: removed hidden node handling in this branch
@ -4008,6 +4012,7 @@ type
FWaiterList: TThreadList;
FRefCount: Cardinal;
protected
procedure CancelValidation(Tree: TBaseVirtualTree);
procedure ChangeTreeStates(EnterStates, LeaveStates: TChangeStates);
procedure Execute; override;
public
@ -4987,6 +4992,10 @@ begin
// Make sure there is no reference remaining to the releasing tree.
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
begin
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);
begin
@ -5078,20 +5107,21 @@ begin
end;
// Something to do?
try
if Assigned(FCurrentTree) then
begin
if Assigned(FCurrentTree) then
begin
try
ChangeTreeStates([csValidating], [csUseCache]);
EnterStates := [];
if not (tsStopValidation in FCurrentTree.FStates) and FCurrentTree.DoValidateCache then
EnterStates := [csUseCache];
finally
LeaveStates := [csValidating, csStopValidation];
if csUseCache in EnterStates then
Include(LeaveStates, csValidationNeeded);
ChangeTreeStates(EnterStates, LeaveStates);
FCurrentTree := nil;
end;
finally
LeaveStates := [csValidating, csStopValidation];
if csUseCache in EnterStates then
Include(LeaveStates, csValidationNeeded);
ChangeTreeStates(EnterStates, LeaveStates);
FCurrentTree := nil;
end;
end;
end;
@ -5113,6 +5143,7 @@ begin
finally
FWaiterList.UnlockList;
end;
CancelValidation(Tree);
end;
//----------------------------------------------------------------------------------------------------------------------
@ -12900,10 +12931,8 @@ end;
procedure TBaseVirtualTree.InterruptValidation;
// Waits until the worker thread has stopped validating the caches of this tree.
//var
// Msg: TMsg;
var
WasValidating: Boolean;
begin
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).
if Assigned(WorkerThread) then
begin
if tsValidating in FStates then
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;
WasValidating := (tsValidating in FStates);
WorkerThread.RemoveTree(Self);
if WasValidating then
DoStateChange([tsValidationNeeded]);
end
else // Remove any pending validation.
WorkerThread.RemoveTree(Self);
end;
{$endif}
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.IsFirstVisibleChild(Parent, Node: PVirtualNode): Boolean;
@ -21505,7 +21512,7 @@ begin
Include(Destination.States, vsHasChildren);
AdjustTotalCount(Destination, Node.TotalCount, True);
// 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);
if FullyVisible[Node] then
Inc(FVisibleCount, CountVisibleChildren(Node) + 1);
@ -21536,7 +21543,7 @@ begin
Include(Destination.States, vsHasChildren);
AdjustTotalCount(Destination, Node.TotalCount, True);
// 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);
if FullyVisible[Node] then
Inc(FVisibleCount, CountVisibleChildren(Node) + 1);