* Synchronize with main VTV repository up to svn rev 274

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3289 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
blikblum
2014-07-06 14:27:04 +00:00
parent 878363e736
commit 9ac30f010f

View File

@ -27,11 +27,32 @@ unit VirtualTrees;
// (C) 1999-2001 digital publishing AG. All Rights Reserved. // (C) 1999-2001 digital publishing AG. All Rights Reserved.
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// //
// August 2010
// - Bug fix: TBaseVirtualTree.OnRemoveFromSelection is now triggered by TBaseVirtualTree.RemoveFromSelection
// as intended
// July 2010
// - Bug fix: Toggling toShowFilteredNodes will now update the node counts in the tree even if its handle has not
// been allocated so far
// - Bug fix: TBaseVirtualTree.FindNodeInSelection should now work correctly with nodes above the 2gb boundary
// - Bug fix: Nodes that are about to be deleted are now removed from TBaseVirtualTree.FDragSelection
// - Bug fix: Changed TBaseVirtualTree.WMKeyDown to correctly handle special keys in Unicode based Delphi versions
// - Bug fix: Changed declaration of TBaseVirtualTree.EmptyListMessage to UnicodeString
// - Improvement: Added new property TBaseVirtualTree.EmptyListMessage. If this property is not empty, the assigned
// text will be displayed if there are no nodes to display, similar to the Windows XP file search.
// - Improvement: Added tstChecked to TVSTTextSourceType enumeration and support for the new flag to
// GetRenderStartValues(). So you can export only checked nodes.
// June 2010 // June 2010
// - Bug fix: range select with no nodes will no longer result in an access violation
// - Bug fix: TBaseVirtualTree.SetVisible now correctly decrements the visible node count
// - Bug fix: TStringEditLink.BeginEdit now calls AutoAdjustSize to ensure a consistent size of the edit field
// - Improvement: TVTHeader.AutoFitColumns is now declared virtual // - Improvement: TVTHeader.AutoFitColumns is now declared virtual
// - Bug fix: header captions were badly positioned text if Extra Large fonts have been activated in the Windows // - Bug fix: header captions were badly positioned text if Extra Large fonts have been activated in the Windows
// display options // display options
// May 2010
// - Improvement: TBaseVirtualTree.PaintTree is now declared virtual
// - Bug fix: corrected calculations regarding tree height and visible count when using filtered nodes
// April 2010 // April 2010
// - Bug fix: Changed TBaseVirtualTree.SetChildCount and TBaseVirtualTree.InitNode to correctly handle filtered nodes
// - Bug fix: Ctrl+Click on a node often cause a delayed update of the displayed selection due to a missing (or // - Bug fix: Ctrl+Click on a node often cause a delayed update of the displayed selection due to a missing (or
// misplaced) call to Invalidate() in HandleClickSelection(). // misplaced) call to Invalidate() in HandleClickSelection().
// - Bug fix: Shift+PgUp and Shift+PgDown now behave like a usual List(View) and select the node of the previous/ // - Bug fix: Shift+PgUp and Shift+PgDown now behave like a usual List(View) and select the node of the previous/
@ -2237,6 +2258,7 @@ type
FHeaderRect: TRect; // Space which the header currently uses in the control (window coords). FHeaderRect: TRect; // Space which the header currently uses in the control (window coords).
FLastHintRect: TRect; // Area which the mouse must leave to reshow a hint. FLastHintRect: TRect; // Area which the mouse must leave to reshow a hint.
FUpdateRect: TRect; FUpdateRect: TRect;
FEmptyListMessage: String; // Optional message that will be displayed if no nodes exist in the control.
// paint support and images // paint support and images
FPlusBM, FPlusBM,
@ -2650,6 +2672,8 @@ type
{$endif} {$endif}
{$endif ThemeSupport} {$endif ThemeSupport}
procedure WMVScroll(var Message: TLMVScroll); message LM_VSCROLL; procedure WMVScroll(var Message: TLMVScroll); message LM_VSCROLL;
protected
procedure SetEmptyListMessage(const Value: String);
procedure AddToSelection(Node: PVirtualNode); overload; virtual; procedure AddToSelection(Node: PVirtualNode); overload; virtual;
procedure AddToSelection(const NewItems: TNodeArray; NewLength: Integer; ForceInsert: Boolean = False); overload; virtual; procedure AddToSelection(const NewItems: TNodeArray; NewLength: Integer; ForceInsert: Boolean = False); overload; virtual;
procedure AdjustPaintCellRect(var PaintInfo: TVTPaintInfo; out NextNonEmpty: TColumnIndex); virtual; procedure AdjustPaintCellRect(var PaintInfo: TVTPaintInfo; out NextNonEmpty: TColumnIndex); virtual;
@ -3140,7 +3164,8 @@ type
function GetMaxColumnWidth(Column: TColumnIndex; UseSmartColumnWidth: Boolean = False): Integer; function GetMaxColumnWidth(Column: TColumnIndex; UseSmartColumnWidth: Boolean = False): Integer;
function GetNext(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode; function GetNext(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode;
function GetNextChecked(Node: PVirtualNode; State: TCheckState = csCheckedNormal; function GetNextChecked(Node: PVirtualNode; State: TCheckState = csCheckedNormal;
ConsiderChildrenAbove: Boolean = False): PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode; overload;
function GetNextChecked(Node: PVirtualNode; ConsiderChildrenAbove: Boolean): PVirtualNode; overload;
function GetNextCutCopy(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode; function GetNextCutCopy(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode;
function GetNextInitialized(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode; function GetNextInitialized(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode;
function GetNextLeaf(Node: PVirtualNode): PVirtualNode; function GetNextLeaf(Node: PVirtualNode): PVirtualNode;
@ -3194,7 +3219,7 @@ type
procedure MoveTo(Node: PVirtualNode; Tree: TBaseVirtualTree; Mode: TVTNodeAttachMode; procedure MoveTo(Node: PVirtualNode; Tree: TBaseVirtualTree; Mode: TVTNodeAttachMode;
ChildrenOnly: Boolean); overload; ChildrenOnly: Boolean); overload;
procedure PaintTree(TargetCanvas: TCanvas; const Window: TRect; Target: TPoint; PaintOptions: TVTInternalPaintOptions; procedure PaintTree(TargetCanvas: TCanvas; const Window: TRect; Target: TPoint; PaintOptions: TVTInternalPaintOptions;
PixelFormat: TPixelFormat = pfDevice); PixelFormat: TPixelFormat = pfDevice); virtual;
function PasteFromClipboard: Boolean; virtual; function PasteFromClipboard: Boolean; virtual;
procedure PrepareDragImage(HotSpot: TPoint; const DataObject: IDataObject); procedure PrepareDragImage(HotSpot: TPoint; const DataObject: IDataObject);
{$ifdef EnablePrint} {$ifdef EnablePrint}
@ -3217,8 +3242,11 @@ type
procedure SortTree(Column: TColumnIndex; Direction: TSortDirection; DoInit: Boolean = True); virtual; procedure SortTree(Column: TColumnIndex; Direction: TSortDirection; DoInit: Boolean = True); virtual;
procedure ToggleNode(Node: PVirtualNode); procedure ToggleNode(Node: PVirtualNode);
function UpdateAction(Action: TBasicAction): Boolean; override; function UpdateAction(Action: TBasicAction): Boolean; override;
procedure UpdateHorizontalRange;
procedure UpdateHorizontalScrollBar(DoRepaint: Boolean); procedure UpdateHorizontalScrollBar(DoRepaint: Boolean);
procedure UpdateRanges;
procedure UpdateScrollBars(DoRepaint: Boolean); virtual; procedure UpdateScrollBars(DoRepaint: Boolean); virtual;
procedure UpdateVerticalRange;
procedure UpdateVerticalScrollBar(DoRepaint: Boolean); procedure UpdateVerticalScrollBar(DoRepaint: Boolean);
//lcl: reenable in case TControl implementation change to match Delphi //lcl: reenable in case TControl implementation change to match Delphi
// function UseRightToLeftReading: Boolean; // function UseRightToLeftReading: Boolean;
@ -3241,6 +3269,7 @@ type
property VTVDragManager: IVTDragManager read GetDragManager; property VTVDragManager: IVTDragManager read GetDragManager;
property DropTargetNode: PVirtualNode read FDropTargetNode; property DropTargetNode: PVirtualNode read FDropTargetNode;
property EditLink: IVTEditLink read FEditLink; property EditLink: IVTEditLink read FEditLink;
property EmptyListMessage: String read FEmptyListMessage write SetEmptyListMessage;
property Expanded[Node: PVirtualNode]: Boolean read GetExpanded write SetExpanded; property Expanded[Node: PVirtualNode]: Boolean read GetExpanded write SetExpanded;
property FocusedColumn: TColumnIndex read FFocusedColumn write SetFocusedColumn default InvalidColumn; property FocusedColumn: TColumnIndex read FFocusedColumn write SetFocusedColumn default InvalidColumn;
property FocusedNode: PVirtualNode read FFocusedNode write SetFocusedNode; property FocusedNode: PVirtualNode read FFocusedNode write SetFocusedNode;
@ -3389,7 +3418,8 @@ type
tstInitialized, // Only initialized nodes are rendered. tstInitialized, // Only initialized nodes are rendered.
tstSelected, // Only selected nodes are rendered. tstSelected, // Only selected nodes are rendered.
tstCutCopySet, // Only nodes currently marked as being in the cut/copy clipboard set are rendered. tstCutCopySet, // Only nodes currently marked as being in the cut/copy clipboard set are rendered.
tstVisible // Only visible nodes are rendered. tstVisible, // Only visible nodes are rendered.
tstChecked // Only checked nodes are rendered
); );
TVTPaintText = procedure(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TVTPaintText = procedure(Sender: TBaseVirtualTree; const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
@ -5565,6 +5595,7 @@ var
ToBeSet, ToBeSet,
ToBeCleared: TVTPaintOptions; ToBeCleared: TVTPaintOptions;
Run: PVirtualNode; Run: PVirtualNode;
HandleWasAllocated: Boolean;
begin begin
if FPaintOptions <> Value then if FPaintOptions <> Value then
@ -5573,6 +5604,34 @@ begin
ToBeCleared := FPaintOptions - Value; ToBeCleared := FPaintOptions - Value;
FPaintOptions := Value; FPaintOptions := Value;
with FOwner do with FOwner do
begin
HandleWasAllocated := HandleAllocated;
if not (csLoading in ComponentState) and (toShowFilteredNodes in ToBeSet + ToBeCleared) then
begin
if HandleWasAllocated then
BeginUpdate;
InterruptValidation;
Run := GetFirstNoInit;
while Assigned(Run) do
begin
if (vsFiltered in Run.States) and FullyVisible[Run] then
if toShowFilteredNodes in ToBeSet then
begin
Inc(FVisibleCount);
AdjustTotalHeight(Run, Run.NodeHeight, True);
end
else
begin
AdjustTotalHeight(Run, -Run.NodeHeight, True);
Dec(FVisibleCount);
end;
Run := GetNextNoInit(Run);
end;
if HandleWasAllocated then
EndUpdate;
end;
if HandleAllocated then if HandleAllocated then
begin begin
{$ifdef ThemeSupport} {$ifdef ThemeSupport}
@ -5608,32 +5667,9 @@ begin
PrepareBitmaps(True, False); PrepareBitmaps(True, False);
RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_VALIDATE or RDW_FRAME); RedrawWindow(Handle, nil, 0, RDW_INVALIDATE or RDW_VALIDATE or RDW_FRAME);
end end;
else
{$endif ThemeSupport} {$endif ThemeSupport}
if toShowFilteredNodes in ToBeSet + ToBeCleared then
begin
BeginUpdate;
InterruptValidation;
Run := GetFirst;
while Assigned(Run) do
begin
if (vsFiltered in Run.States) and FullyVisible[Run] then
if toShowFilteredNodes in ToBeSet then
begin
Inc(FVisibleCount);
AdjustTotalHeight(Run.Parent, Run.NodeHeight, True);
end
else
begin
AdjustTotalHeight(Run.Parent, -Run.NodeHeight, True);
Dec(FVisibleCount);
end;
Run := GetNext(Run);
end;
EndUpdate;
end
else
if toChildrenAbove in ToBeSet + ToBeCleared then if toChildrenAbove in ToBeSet + ToBeCleared then
begin begin
InvalidateCache; InvalidateCache;
@ -5642,12 +5678,14 @@ begin
ValidateCache; ValidateCache;
Invalidate; Invalidate;
end; end;
end else end;
Invalidate; Invalidate;
end; end;
end; end;
end; end;
end; end;
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@ -12803,7 +12841,7 @@ begin
while Assigned(Child) do while Assigned(Child) do
begin begin
FixupTotalHeight(Child); FixupTotalHeight(Child);
if IsEffectivelyVisible[Child] then if vsVisible in Child.States then
Inc(Node.TotalHeight, Child.TotalHeight); Inc(Node.TotalHeight, Child.TotalHeight);
Child := Child.NextSibling; Child := Child.NextSibling;
end; end;
@ -13118,7 +13156,7 @@ begin
else else
AddToSelection(NewNode); AddToSelection(NewNode);
end; end;
Invalidate; Update;//Invalidate didn't update owner drawn selections
end end
else else
// Shift key down // Shift key down
@ -14020,7 +14058,7 @@ begin
if vsExpanded in Node.States then if vsExpanded in Node.States then
begin begin
AdjustTotalHeight(Node, NewHeight, True); AdjustTotalHeight(Node, NewHeight, True);
if FullyVisible[Node] and not IsEffectivelyFiltered[Node] then if FullyVisible[Node] then
Inc(Integer(FVisibleCount), Count); Inc(Integer(FVisibleCount), Count);
end; end;
@ -14146,6 +14184,16 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.SetEmptyListMessage(const Value: String);
begin
if Value <> EmptyListMessage then
begin
FEmptyListMessage := Value;
Invalidate;
end;
end;
procedure TBaseVirtualTree.SetExpanded(Node: PVirtualNode; Value: Boolean); procedure TBaseVirtualTree.SetExpanded(Node: PVirtualNode; Value: Boolean);
begin begin
@ -14256,6 +14304,10 @@ var
begin begin
Assert(Assigned(Node) and (Node <> FRoot), 'Invalid parameter.'); Assert(Assigned(Node) and (Node <> FRoot), 'Invalid parameter.');
// Initialize the node if necessary as this might change the filtered state.
if not (vsInitialized in Node.States) then
InitNode(Node);
if Value <> (vsFiltered in Node.States) then if Value <> (vsFiltered in Node.States) then
begin begin
InterruptValidation; InterruptValidation;
@ -14263,13 +14315,15 @@ begin
if Value then if Value then
begin begin
Include(Node.States, vsFiltered); Include(Node.States, vsFiltered);
if (vsExpanded in Node.Parent.States) and not (toShowFilteredNodes in FOptions.FPaintOptions) then if not (toShowFilteredNodes in FOptions.FPaintOptions) then
AdjustTotalHeight(Node.Parent, -Integer(NodeHeight[Node]), True); begin
if VisiblePath[Node] then AdjustTotalHeight(Node, -Integer(NodeHeight[Node]), True);
if FullyVisible[Node] then
begin begin
Dec(FVisibleCount); Dec(FVisibleCount);
NeedUpdate := True; NeedUpdate := True;
end; end;
end;
if FUpdateCount = 0 then if FUpdateCount = 0 then
DetermineHiddenChildrenFlag(Node.Parent) DetermineHiddenChildrenFlag(Node.Parent)
@ -14279,13 +14333,14 @@ begin
else else
begin begin
Exclude(Node.States, vsFiltered); Exclude(Node.States, vsFiltered);
if (vsExpanded in Node.Parent.States) and not (toShowFilteredNodes in FOptions.FPaintOptions) then if not (toShowFilteredNodes in FOptions.FPaintOptions) then
AdjustTotalHeight(Node.Parent, Integer(NodeHeight[Node]), True);
if VisiblePath[Node] then
begin begin
Inc(FVisibleCount); AdjustTotalHeight(Node, Integer(NodeHeight[Node]), True);
NeedUpdate := True; if FullyVisible[Node] then
begin
Inc(FVisibleCount);
NeedUpdate := True;
end;
end; end;
if vsVisible in Node.States then if vsVisible in Node.States then
@ -14450,20 +14505,25 @@ begin
begin begin
Difference := Integer(Value) - Integer(Node.NodeHeight); Difference := Integer(Value) - Integer(Node.NodeHeight);
Node.NodeHeight := Value; Node.NodeHeight := Value;
AdjustTotalHeight(Node, Difference, True);
// If an edit operation is currently active then update the editors boundaries as well. // If the node is effectively filtered out, nothing else has to be done, as it is not visible anyway.
UpdateEditBounds; if not IsEffectivelyFiltered[Node] then
// Stay away from touching the node cache while it is being validated.
if not (tsValidating in FStates) and FullyVisible[Node] and not IsEffectivelyFiltered[Node] then
begin begin
InvalidateCache; AdjustTotalHeight(Node, Difference, True);
if FUpdateCount = 0 then
// If an edit operation is currently active then update the editors boundaries as well.
UpdateEditBounds;
// Stay away from touching the node cache while it is being validated.
if not (tsValidating in FStates) and FullyVisible[Node] and not IsEffectivelyFiltered[Node] then
begin begin
ValidateCache; InvalidateCache;
InvalidateToBottom(Node); if FUpdateCount = 0 then
UpdateScrollBars(True); begin
ValidateCache;
InvalidateToBottom(Node);
UpdateScrollBars(True);
end;
end; end;
end; end;
end; end;
@ -14721,24 +14781,25 @@ begin
AdjustTotalHeight(Node.Parent, Node.TotalHeight, True); AdjustTotalHeight(Node.Parent, Node.TotalHeight, True);
if VisiblePath[Node] then if VisiblePath[Node] then
begin begin
Inc(FVisibleCount, 1 + CountVisibleChildren(Node)); Inc(FVisibleCount, CountVisibleChildren(Node) + Cardinal(IfThen(IsEffectivelyVisible[Node], 1)));
NeedUpdate := True; NeedUpdate := True;
end; end;
// Update the hidden children flag of the parent. // Update the hidden children flag of the parent.
// Since this node is now visible we simply have to remove the flag. // Since this node is now visible we simply have to remove the flag.
if not IsEffectivelyFiltered[Node] then
Exclude(Node.Parent.States, vsAllChildrenHidden); Exclude(Node.Parent.States, vsAllChildrenHidden);
end end
else else
begin begin
Exclude(Node.States, vsVisible);
if vsExpanded in Node.Parent.States then if vsExpanded in Node.Parent.States then
AdjustTotalHeight(Node.Parent, -Integer(Node.TotalHeight), True); AdjustTotalHeight(Node.Parent, -Integer(Node.TotalHeight), True);
if VisiblePath[Node] then if VisiblePath[Node] then
begin begin
Dec(FVisibleCount, 1 + CountVisibleChildren(Node)); Dec(FVisibleCount, CountVisibleChildren(Node) + Cardinal(IfThen(IsEffectivelyVisible[Node], 1)));
NeedUpdate := True; NeedUpdate := True;
end; end;
Exclude(Node.States, vsVisible);
if FUpdateCount = 0 then if FUpdateCount = 0 then
DetermineHiddenChildrenFlag(Node.Parent) DetermineHiddenChildrenFlag(Node.Parent)
@ -15948,7 +16009,7 @@ var
GetNextNode: TGetNextNodeProc; GetNextNode: TGetNextNodeProc;
KeyState: TKeyboardState; KeyState: TKeyboardState;
Buffer: array[0..1] of Char; Buffer: array[0..1] of AnsiChar;
begin begin
{$ifdef DEBUG_VTV}Logger.EnterMethod([lcMessages],'WMKeyDown');{$endif} {$ifdef DEBUG_VTV}Logger.EnterMethod([lcMessages],'WMKeyDown');{$endif}
@ -16353,13 +16414,17 @@ begin
FRangeAnchor := FFocusedNode; FRangeAnchor := FFocusedNode;
FLastSelectionLevel := GetNodeLevel(FFocusedNode); FLastSelectionLevel := GetNodeLevel(FFocusedNode);
end; end;
// Finally change the selection for a specific range of nodes.
if DoRangeSelect then
ToggleSelection(LastFocused, FFocusedNode);
// Make sure the new focused node is also selected. if Assigned(FFocusedNode) then
if Assigned(FFocusedNode) and ((LastFocused <> FFocusedNode) or ForceSelection) then begin
AddToSelection(FFocusedNode); // Finally change the selection for a specific range of nodes.
if DoRangeSelect then
ToggleSelection(LastFocused, FFocusedNode);
// Make sure the new focused node is also selected.
if (LastFocused <> FFocusedNode) or ForceSelection then
AddToSelection(FFocusedNode);
end;
// If a repaint is needed then paint the entire tree because of the ClearSelection call, // If a repaint is needed then paint the entire tree because of the ClearSelection call,
if NeedInvalidate then if NeedInvalidate then
@ -17807,9 +17872,8 @@ begin
Node := Node.FirstChild; Node := Node.FirstChild;
while Assigned(Node) do while Assigned(Node) do
begin begin
if (vsVisible in Node.States) and (not (vsFiltered in Node.States) or if vsVisible in Node.States then
(toShowFilteredNodes in FOptions.FPaintOptions)) then Inc(Result, CountVisibleChildren(Node) + Cardinal(IfThen(IsEffectivelyVisible[Node], 1)));
Inc(Result, CountVisibleChildren(Node) + 1);
Node := Node.NextSibling; Node := Node.NextSibling;
end; end;
end; end;
@ -18752,7 +18816,6 @@ procedure TBaseVirtualTree.DoDragging(P: TPoint);
var var
DragEffect, AllowedEffects: LongWord; DragEffect, AllowedEffects: LongWord;
I: Integer;
DragObject: TDragObject; DragObject: TDragObject;
DataObject: IDataObject; DataObject: IDataObject;
@ -18811,15 +18874,7 @@ begin
if (DragEffect = DROPEFFECT_MOVE) and (toAutoDeleteMovedNodes in TreeOptions.AutoOptions) then if (DragEffect = DROPEFFECT_MOVE) and (toAutoDeleteMovedNodes in TreeOptions.AutoOptions) then
begin begin
// The operation was a move so delete the previously selected nodes. // The operation was a move so delete the previously selected nodes.
BeginUpdate; DeleteSelectedNodes;
try
// The list of selected nodes was retrieved in resolved state. That means there can never be a node
// in the list whose parent (or its parent etc.) is also selected.
for I := 0 to High(FDragSelection) do
DeleteNode(FDragSelection[I]);
finally
EndUpdate;
end;
end; end;
DoStateChange([], [tsOLEDragging]); DoStateChange([], [tsOLEDragging]);
@ -20542,7 +20597,7 @@ function TBaseVirtualTree.FindNodeInSelection(P: PVirtualNode; var Index: Intege
var var
L, H, L, H,
I, C: PtrInt; I: PtrInt;
begin begin
Result := False; Result := False;
@ -20555,13 +20610,12 @@ begin
while L <= H do while L <= H do
begin begin
I := (L + H) shr 1; I := (L + H) shr 1;
C := PtrInt(FSelection[I]) - PtrInt(P); if PtrInt(FSelection[I]) < PtrInt(P) then
if C < 0 then
L := I + 1 L := I + 1
else else
begin begin
H := I - 1; H := I - 1;
if C = 0 then if FSelection[I] = P then
begin begin
Result := True; Result := True;
L := I; L := I;
@ -21786,7 +21840,16 @@ begin
if ivsMultiline in InitStates then if ivsMultiline in InitStates then
Include(States, vsMultiline); Include(States, vsMultiline);
if ivsFiltered in InitStates then if ivsFiltered in InitStates then
begin
Include(States, vsFiltered); Include(States, vsFiltered);
if not (toShowFilteredNodes in FOptions.FPaintOptions) then
begin
AdjustTotalHeight(Node, -NodeHeight, True);
if FullyVisible[Node] then
Dec(FVisibleCount);
UpdateScrollBars(True);
end;
end;
// Expanded may already be set (when called from ReinitNode) or be set in DoInitNode, allow both. // Expanded may already be set (when called from ReinitNode) or be set in DoInitNode, allow both.
if (vsExpanded in Node.States) xor (ivsExpanded in InitStates) then if (vsExpanded in Node.States) xor (ivsExpanded in InitStates) then
@ -22086,13 +22149,10 @@ begin
AdjustTotalCount(Destination.Parent, Node.TotalCount, True); AdjustTotalCount(Destination.Parent, 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 (vsExpanded in Destination.Parent.States) and IsEffectivelyVisible[Node] then
AdjustTotalHeight(Destination.Parent, Node.TotalHeight, True);
if FullyVisible[Node] then if FullyVisible[Node] then
begin begin
Inc(FVisibleCount, CountVisibleChildren(Node)); AdjustTotalHeight(Destination.Parent, Node.TotalHeight, True);
if not IsEffectivelyFiltered[Node] then Inc(FVisibleCount, CountVisibleChildren(Node) + Cardinal(IfThen(IsEffectivelyVisible[Node], 1)));
Inc(FVisibleCount);
end; end;
end; end;
amInsertAfter: amInsertAfter:
@ -22120,13 +22180,10 @@ begin
AdjustTotalCount(Destination.Parent, Node.TotalCount, True); AdjustTotalCount(Destination.Parent, 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 (vsExpanded in Destination.Parent.States) and IsEffectivelyVisible[Node] then
AdjustTotalHeight(Destination.Parent, Node.TotalHeight, True);
if FullyVisible[Node] then if FullyVisible[Node] then
begin begin
Inc(FVisibleCount, CountVisibleChildren(Node)); AdjustTotalHeight(Destination.Parent, Node.TotalHeight, True);
if not IsEffectivelyFiltered[Node] then Inc(FVisibleCount, CountVisibleChildren(Node) + Cardinal(IfThen(IsEffectivelyVisible[Node], 1)));
Inc(FVisibleCount);
end; end;
end; end;
amAddChildFirst: amAddChildFirst:
@ -22160,13 +22217,10 @@ 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 (vsExpanded in Destination.States) and IsEffectivelyVisible[Node] then
AdjustTotalHeight(Destination, Node.TotalHeight, True);
if FullyVisible[Node] then if FullyVisible[Node] then
begin begin
Inc(FVisibleCount, CountVisibleChildren(Node)); AdjustTotalHeight(Destination, Node.TotalHeight, True);
if not IsEffectivelyFiltered[Node] then Inc(FVisibleCount, CountVisibleChildren(Node) + Cardinal(IfThen(IsEffectivelyVisible[Node], 1)));
Inc(FVisibleCount);
end; end;
end; end;
amAddChildLast: amAddChildLast:
@ -22195,13 +22249,10 @@ 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 (vsExpanded in Destination.States) and IsEffectivelyVisible[Node] then
AdjustTotalHeight(Destination, Node.TotalHeight, True);
if FullyVisible[Node] then if FullyVisible[Node] then
begin begin
Inc(FVisibleCount, CountVisibleChildren(Node)); AdjustTotalHeight(Destination, Node.TotalHeight, True);
if not IsEffectivelyFiltered[Node] then Inc(FVisibleCount, CountVisibleChildren(Node) + Cardinal(IfThen(IsEffectivelyVisible[Node], 1)));
Inc(FVisibleCount);
end; end;
end; end;
else else
@ -22276,7 +22327,7 @@ begin
Node.States := Node.States - [vsChecking]; Node.States := Node.States - [vsChecking];
Parent := Node.Parent; Parent := Node.Parent;
Dec(Parent.ChildCount); Dec(Parent.ChildCount);
AdjustHeight := (vsExpanded in Parent.States) and IsEffectivelyVisible[Node]; AdjustHeight := (vsExpanded in Parent.States) and (vsVisible in Node.States);
if Parent.ChildCount = 0 then if Parent.ChildCount = 0 then
begin begin
Parent.States := Parent.States - [vsAllChildrenHidden, vsHasChildren]; Parent.States := Parent.States - [vsAllChildrenHidden, vsHasChildren];
@ -22287,11 +22338,7 @@ begin
if AdjustHeight then if AdjustHeight then
AdjustTotalHeight(Parent, -Integer(Node.TotalHeight), True); AdjustTotalHeight(Parent, -Integer(Node.TotalHeight), True);
if FullyVisible[Node] then if FullyVisible[Node] then
begin Dec(FVisibleCount, CountVisibleChildren(Node) + Cardinal(IfThen(IsEffectivelyVisible[Node], 1)));
Dec(FVisibleCount, CountVisibleChildren(Node));
if not IsEffectivelyFiltered[Node] then
Dec(FVisibleCount);
end;
if Assigned(Node.PrevSibling) then if Assigned(Node.PrevSibling) then
Node.PrevSibling.NextSibling := Node.NextSibling Node.PrevSibling.NextSibling := Node.NextSibling
@ -22407,6 +22454,7 @@ begin
Inc(PtrUInt(FSelection[Index])); Inc(PtrUInt(FSelection[Index]));
if Assigned(FOnRemoveFromSelection) then if Assigned(FOnRemoveFromSelection) then
FOnRemoveFromSelection(Self, Node); FOnRemoveFromSelection(Self, Node);
AdviseChangeEvent(False, Node, crIgnore);
end; end;
end; end;
@ -23624,6 +23672,8 @@ begin
if FSelectionCount = 0 then if FSelectionCount = 0 then
ResetRangeAnchor; ResetRangeAnchor;
if Assigned(FOnRemoveFromSelection) then
FOnRemoveFromSelection(Self, Node);
Change(Node); Change(Node);
end; end;
end; end;
@ -24741,6 +24791,7 @@ begin
Self.Visible := Visible; Self.Visible := Visible;
Self.SelectionCurveRadius := SelectionCurveRadius; Self.SelectionCurveRadius := SelectionCurveRadius;
Self.SelectionBlendFactor := SelectionBlendFactor; Self.SelectionBlendFactor := SelectionBlendFactor;
Self.EmptyListMessage := EmptyListMessage;
end end
else else
inherited; inherited;
@ -25712,9 +25763,9 @@ begin
Result := Rect(0, 0, 0, 0); Result := Rect(0, 0, 0, 0);
// Check whether the node is visible (determine indentation level btw.). // Check whether the node is visible (determine indentation level btw.).
Temp := Node; if not IsEffectivelyVisible[Node] then
if not IsEffectivelyVisible[Temp] then
Exit; Exit;
Temp := Node;
Indent := 0; Indent := 0;
while Temp <> FRoot do while Temp <> FRoot do
begin begin
@ -26829,6 +26880,13 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetNextChecked(Node: PVirtualNode; ConsiderChildrenAbove: Boolean): PVirtualNode;
begin
Result := Self.GetNextChecked(Node, csCheckedNormal, ConsiderChildrenAbove);
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetNextCutCopy(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode; function TBaseVirtualTree.GetNextCutCopy(Node: PVirtualNode; ConsiderChildrenAbove: Boolean = False): PVirtualNode;
// Returns the next node in the tree which is currently marked for a clipboard operation. Since only visible nodes can // Returns the next node in the tree which is currently marked for a clipboard operation. Since only visible nodes can
@ -29372,6 +29430,13 @@ begin
NodeBitmap.Canvas.Unlock; NodeBitmap.Canvas.Unlock;
NodeBitmap.Free; NodeBitmap.Free;
end; end;
if (Self.ChildCount[nil]=0) and (FEmptyListMessage<>'') then begin
// output a message if no items are to display
Canvas.Font := Self.Font;
SetBkMode(TargetCanvas.Handle, TRANSPARENT);
TextOut(TargetCanvas.Handle, 2, 2, PAnsiChar(FEmptyListMessage), Length(FEmptyListMessage));
end;//if
DoAfterPaint(TargetCanvas); DoAfterPaint(TargetCanvas);
finally finally
DoStateChange([], [tsPainting]); DoStateChange([], [tsPainting]);
@ -30293,27 +30358,7 @@ var
TotalFit: Boolean; TotalFit: Boolean;
ToggleData: TToggleAnimationData; ToggleData: TToggleAnimationData;
//--------------- local functions ------------------------------------------- //--------------- local function --------------------------------------------
procedure UpdateRanges;
// This function is used to adjust FRangeX/FRangeY in order to correctly
// reflect the tree's state after a toggle, because it is essential that
// these values are correct if we need to scroll afterwards. To avoid a
// useless call to UpdateScrollbars we do it right here.
begin
if FRoot.TotalHeight < FDefaultNodeHeight then
FRoot.TotalHeight := FDefaultNodeHeight;
FRangeY := FRoot.TotalHeight - FRoot.NodeHeight + FBottomSpace;
if FHeader.UseColumns then
FRangeX := FHeader.FColumns.TotalWidth
else
FRangeX := GetMaxRightExtend;
end;
//---------------------------------------------------------------------------
procedure PrepareAnimation; procedure PrepareAnimation;
@ -30362,7 +30407,7 @@ var
end; end;
end; end;
//--------------- end local functions --------------------------------------- //--------------- end local function ----------------------------------------
begin begin
Assert(Assigned(Node), 'Node must not be nil.'); Assert(Assigned(Node), 'Node must not be nil.');
@ -30468,7 +30513,7 @@ begin
end; end;
// collapse the node // collapse the node
AdjustTotalHeight(Node, NodeHeight[Node]); AdjustTotalHeight(Node, IfThen(IsEffectivelyFiltered[Node], 0, NodeHeight[Node]));
if FullyVisible[Node] then if FullyVisible[Node] then
Dec(FVisibleCount, CountVisibleChildren(Node)); Dec(FVisibleCount, CountVisibleChildren(Node));
Exclude(Node.States, vsExpanded); Exclude(Node.States, vsExpanded);
@ -30760,16 +30805,24 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.UpdateHorizontalScrollBar(DoRepaint: Boolean); procedure TBaseVirtualTree.UpdateHorizontalRange;
var
ScrollInfo: TScrollInfo;
begin begin
if FHeader.UseColumns then if FHeader.UseColumns then
FRangeX := FHeader.FColumns.TotalWidth FRangeX := FHeader.FColumns.TotalWidth
else else
FRangeX := GetMaxRightExtend; FRangeX := GetMaxRightExtend;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.UpdateHorizontalScrollBar(DoRepaint: Boolean);
var
ScrollInfo: TScrollInfo;
begin
UpdateHorizontalRange;
if tsUpdating in FStates then if tsUpdating in FStates then
exit; exit;
@ -30847,6 +30900,15 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.UpdateRanges;
begin
UpdateVerticalRange;
UpdateHorizontalRange;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.UpdateScrollBars(DoRepaint: Boolean); procedure TBaseVirtualTree.UpdateScrollBars(DoRepaint: Boolean);
// adjusts scrollbars to reflect current size and paint offset of the tree // adjusts scrollbars to reflect current size and paint offset of the tree
@ -30861,16 +30923,24 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.UpdateVerticalScrollBar(DoRepaint: Boolean); procedure TBaseVirtualTree.UpdateVerticalRange;
var
ScrollInfo: TScrollInfo;
begin begin
// Total node height includes the height of the invisible root node. // Total node height includes the height of the invisible root node.
if FRoot.TotalHeight < FDefaultNodeHeight then if FRoot.TotalHeight < FDefaultNodeHeight then
FRoot.TotalHeight := FDefaultNodeHeight; FRoot.TotalHeight := FDefaultNodeHeight;
FRangeY := FRoot.TotalHeight - FRoot.NodeHeight + FBottomSpace; FRangeY := FRoot.TotalHeight - FRoot.NodeHeight + FBottomSpace;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.UpdateVerticalScrollBar(DoRepaint: Boolean);
var
ScrollInfo: TScrollInfo;
begin
UpdateVerticalRange;
if tsUpdating in FStates then if tsUpdating in FStates then
exit; exit;
@ -31316,6 +31386,7 @@ begin
FEdit.Show; FEdit.Show;
FEdit.SelectAll; FEdit.SelectAll;
FEdit.SetFocus; FEdit.SetFocus;
FEdit.AutoAdjustSize;
end; end;
end; end;
@ -31503,6 +31574,11 @@ begin
Node := GetFirstVisible(nil, True); Node := GetFirstVisible(nil, True);
NextNodeProc := GetNextVisible; NextNodeProc := GetNextVisible;
end; end;
tstChecked:
begin
Node := GetFirstChecked;
NextNodeProc := GetNextChecked;
end;
else // tstAll else // tstAll
Node := GetFirst; Node := GetFirst;
NextNodeProc := GetNext; NextNodeProc := GetNext;
@ -32387,7 +32463,7 @@ function TCustomVirtualStringTree.ContentToHTML(Source: TVSTTextSourceType; cons
// Renders the current tree content (depending on Source) as HTML text encoded in UTF-8. // Renders the current tree content (depending on Source) as HTML text encoded in UTF-8.
// If Caption is not empty then it is used to create and fill the header for the table built here. // If Caption is not empty then it is used to create and fill the header for the table built here.
// Based on ideas and code from Frank van den Bergh and Andreas H?rstemeier. // Based on ideas and code from Frank van den Bergh and Andreas Hörstemeier.
type type
UCS2 = Word; UCS2 = Word;
@ -32704,7 +32780,7 @@ begin
begin begin
Buffer.Add(' <td height="'); Buffer.Add(' <td height="');
Buffer.Add(IntToStr(NodeHeight[Run])); Buffer.Add(IntToStr(NodeHeight[Run]));
Buffer.Add('px">&nbsp;</td>'); Buffer.Add('px" class="normalborder">&nbsp;</td>');
end end
else else
Buffer.Add(' <td>&nbsp;</td>'); Buffer.Add(' <td>&nbsp;</td>');
@ -32810,7 +32886,7 @@ end;
function TCustomVirtualStringTree.ContentToRTF(Source: TVSTTextSourceType): AnsiString; function TCustomVirtualStringTree.ContentToRTF(Source: TVSTTextSourceType): AnsiString;
// Renders the current tree content (depending on Source) as RTF (rich text). // Renders the current tree content (depending on Source) as RTF (rich text).
// Based on ideas and code from Frank van den Bergh and Andreas H?rstemeier. // Based on ideas and code from Frank van den Bergh and Andreas Hörstemeier.
var var
Fonts: TStringList; Fonts: TStringList;