* Backported changes done in main svn tree up to svn rev 143 (version 4.5.4)

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@223 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
blikblum
2007-07-23 14:43:56 +00:00
parent d27d04532d
commit 0e95629552

View File

@@ -2,7 +2,7 @@ unit VirtualTrees;
{$mode delphi}{$H+} {$mode delphi}{$H+}
// Version 4.5.1 // Version 4.5.4
// //
// The contents of this file are subject to the Mozilla Public License // The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in compliance // Version 1.1 (the "License"); you may not use this file except in compliance
@@ -26,9 +26,24 @@ unit VirtualTrees;
// (C) 1999-2001 digital publishing AG. All Rights Reserved. // (C) 1999-2001 digital publishing AG. All Rights Reserved.
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
// //
// June 2007
// - Bug fix: Fixed a problem with potentially large amount of nodes (larger than 2 billion) in
// TBaseVirtualTree.SetChildCount.
// - Bug fix: remove hint if any in case the tree loses the focus.
// - Improvement: TVirtualTreeColumns.HandleClick is now virtual, introduced TVTHeader.DoSetSortColumn.
// - Bug fix: compiler error due to old variable reference when enabling flat scrollbars.
// May 2007
// - Improvement: new functions: GetPreviousSelected, GetPreviousChecked, GetCheckedCount,
// GetPreviousCutCopy, GetCutCopyCount, GetFirstLeaf, GetNextLeaf,
// GetPreviousLeaf, GetFirstLevel, GetNextLevel, GetPreviousLevel
// - Improvement: new properties: CheckedCount, CutCopyCount
// - Improvement: DoFocusChanging for finding a valid column (TBaseVirtualTree.WMKeyDown)
// March 2007
// - Improvement: adjusted accessibility implementation to compile with pre-BDS IDEs.
// - If a column is not visible, MultiColumnAccessibility now will not include it.
// January 2007 // January 2007
// - Improvement: added code donation from Marco Zehe (with help from Sebastian Modersohn) which implements the // - Improvement: added code donation from Marco Zehe (with help from Sebastian Modersohn) which implements the
// MS accessability interface for Virtual Treeview. // MS accessibility interface for Virtual Treeview.
// December 2006 // December 2006
// - Improvement: bidi mode implementation finished (toAutoBidiColumnOrdering introduced) // - Improvement: bidi mode implementation finished (toAutoBidiColumnOrdering introduced)
// - Change: right-to-left flag removed from shorten string methods/events (not necessary) // - Change: right-to-left flag removed from shorten string methods/events (not necessary)
@@ -135,7 +150,7 @@ uses
const const
{$I lclconstants.inc} {$I lclconstants.inc}
VTVersion = '4.5.1'; VTVersion = '4.5.4';
VTTreeStreamVersion = 2; VTTreeStreamVersion = 2;
VTHeaderStreamVersion = 3; // The header needs an own stream version to indicate changes only relevant to the header. VTHeaderStreamVersion = 3; // The header needs an own stream version to indicate changes only relevant to the header.
@@ -1072,7 +1087,7 @@ type
procedure FixPositions; procedure FixPositions;
function GetColumnAndBounds(P: TPoint; var ColumnLeft, ColumnRight: Integer; Relative: Boolean = True): Integer; function GetColumnAndBounds(P: TPoint; var ColumnLeft, ColumnRight: Integer; Relative: Boolean = True): Integer;
function GetOwner: TPersistent; override; function GetOwner: TPersistent; override;
procedure HandleClick(P: TPoint; Button: TMouseButton; Force, DblClick: Boolean); procedure HandleClick(P: TPoint; Button: TMouseButton; Force, DblClick: Boolean); virtual;
procedure IndexChanged(OldIndex, NewIndex: Integer); procedure IndexChanged(OldIndex, NewIndex: Integer);
procedure InitializePositionArray; procedure InitializePositionArray;
procedure ReorderColumns(RTL: Boolean); procedure ReorderColumns(RTL: Boolean);
@@ -1208,6 +1223,7 @@ type
function CanWriteColumns: Boolean; virtual; function CanWriteColumns: Boolean; virtual;
procedure ChangeScale(M, D: Integer); virtual; procedure ChangeScale(M, D: Integer); virtual;
function DetermineSplitterIndex(P: TPoint): Boolean; virtual; function DetermineSplitterIndex(P: TPoint): Boolean; virtual;
procedure DoSetSortColumn(Value: TColumnIndex); virtual;
procedure DragTo(P: TPoint); procedure DragTo(P: TPoint);
function GetColumnsClass: TVirtualTreeColumnsClass; virtual; function GetColumnsClass: TVirtualTreeColumnsClass; virtual;
function GetOwner: TPersistent; override; function GetOwner: TPersistent; override;
@@ -1986,10 +2002,12 @@ TBaseVirtualTree = class(TCustomControl)
function FindInPositionCache(Position: Cardinal; var CurrentPos: Cardinal): PVirtualNode; overload; function FindInPositionCache(Position: Cardinal; var CurrentPos: Cardinal): PVirtualNode; overload;
procedure FixupTotalCount(Node: PVirtualNode); procedure FixupTotalCount(Node: PVirtualNode);
procedure FixupTotalHeight(Node: PVirtualNode); procedure FixupTotalHeight(Node: PVirtualNode);
function GetCheckedCount: Integer;
function GetCheckState(Node: PVirtualNode): TCheckState; function GetCheckState(Node: PVirtualNode): TCheckState;
function GetCheckType(Node: PVirtualNode): TCheckType; function GetCheckType(Node: PVirtualNode): TCheckType;
function GetChildCount(Node: PVirtualNode): Cardinal; function GetChildCount(Node: PVirtualNode): Cardinal;
function GetChildrenInitialized(Node: PVirtualNode): Boolean; function GetChildrenInitialized(Node: PVirtualNode): Boolean;
function GetCutCopyCount: Integer;
function GetDisabled(Node: PVirtualNode): Boolean; function GetDisabled(Node: PVirtualNode): Boolean;
function GetDragManager: IVTDragManager; function GetDragManager: IVTDragManager;
function GetExpanded(Node: PVirtualNode): Boolean; function GetExpanded(Node: PVirtualNode): Boolean;
@@ -2261,6 +2279,8 @@ TBaseVirtualTree = class(TCustomControl)
procedure DoTimerScroll; virtual; procedure DoTimerScroll; virtual;
procedure DoUpdating(State: TVTUpdateState); virtual; procedure DoUpdating(State: TVTUpdateState); virtual;
function DoValidateCache: Boolean; virtual; function DoValidateCache: Boolean; virtual;
procedure DragAndDrop(AllowedEffects: Integer; DataObject: IDataObject;
DragEffect: Integer); virtual;
procedure DragCanceled; override; procedure DragCanceled; override;
function DragDrop(const DataObject: IDataObject; KeyState: Integer; Pt: TPoint; function DragDrop(const DataObject: IDataObject; KeyState: Integer; Pt: TPoint;
var Effect: LongWord): HResult; reintroduce; virtual; var Effect: LongWord): HResult; reintroduce; virtual;
@@ -2532,6 +2552,8 @@ TBaseVirtualTree = class(TCustomControl)
function GetFirstChild(Node: PVirtualNode): PVirtualNode; function GetFirstChild(Node: PVirtualNode): PVirtualNode;
function GetFirstCutCopy: PVirtualNode; function GetFirstCutCopy: PVirtualNode;
function GetFirstInitialized: PVirtualNode; function GetFirstInitialized: PVirtualNode;
function GetFirstLeaf: PVirtualNode;
function GetFirstLevel(NodeLevel: Cardinal): PVirtualNode;
function GetFirstNoInit: PVirtualNode; function GetFirstNoInit: PVirtualNode;
function GetFirstSelected: PVirtualNode; function GetFirstSelected: PVirtualNode;
function GetFirstVisible: PVirtualNode; function GetFirstVisible: PVirtualNode;
@@ -2553,6 +2575,8 @@ TBaseVirtualTree = class(TCustomControl)
function GetNextChecked(Node: PVirtualNode; State: TCheckState = csCheckedNormal): PVirtualNode; function GetNextChecked(Node: PVirtualNode; State: TCheckState = csCheckedNormal): PVirtualNode;
function GetNextCutCopy(Node: PVirtualNode): PVirtualNode; function GetNextCutCopy(Node: PVirtualNode): PVirtualNode;
function GetNextInitialized(Node: PVirtualNode): PVirtualNode; function GetNextInitialized(Node: PVirtualNode): PVirtualNode;
function GetNextLeaf(Node: PVirtualNode): PVirtualNode;
function GetNextLevel(Node: PVirtualNode; NodeLevel: Cardinal): PVirtualNode;
function GetNextNoInit(Node: PVirtualNode): PVirtualNode; function GetNextNoInit(Node: PVirtualNode): PVirtualNode;
function GetNextSelected(Node: PVirtualNode): PVirtualNode; function GetNextSelected(Node: PVirtualNode): PVirtualNode;
function GetNextSibling(Node: PVirtualNode): PVirtualNode; function GetNextSibling(Node: PVirtualNode): PVirtualNode;
@@ -2565,8 +2589,13 @@ TBaseVirtualTree = class(TCustomControl)
function GetNodeData(Node: PVirtualNode): Pointer; function GetNodeData(Node: PVirtualNode): Pointer;
function GetNodeLevel(Node: PVirtualNode): Cardinal; function GetNodeLevel(Node: PVirtualNode): Cardinal;
function GetPrevious(Node: PVirtualNode): PVirtualNode; function GetPrevious(Node: PVirtualNode): PVirtualNode;
function GetPreviousChecked(Node: PVirtualNode; State: TCheckState = csCheckedNormal): PVirtualNode;
function GetPreviousCutCopy(Node: PVirtualNode): PVirtualNode;
function GetPreviousInitialized(Node: PVirtualNode): PVirtualNode; function GetPreviousInitialized(Node: PVirtualNode): PVirtualNode;
function GetPreviousLeaf(Node: PVirtualNode): PVirtualNode;
function GetPreviousLevel(Node: PVirtualNode; NodeLevel: Cardinal): PVirtualNode;
function GetPreviousNoInit(Node: PVirtualNode): PVirtualNode; function GetPreviousNoInit(Node: PVirtualNode): PVirtualNode;
function GetPreviousSelected(Node: PVirtualNode): PVirtualNode;
function GetPreviousSibling(Node: PVirtualNode): PVirtualNode; function GetPreviousSibling(Node: PVirtualNode): PVirtualNode;
function GetPreviousVisible(Node: PVirtualNode): PVirtualNode; function GetPreviousVisible(Node: PVirtualNode): PVirtualNode;
function GetPreviousVisibleNoInit(Node: PVirtualNode): PVirtualNode; function GetPreviousVisibleNoInit(Node: PVirtualNode): PVirtualNode;
@@ -2630,11 +2659,13 @@ TBaseVirtualTree = class(TCustomControl)
property AccessibleItem: IAccessible read FAccessibleItem write FAccessibleItem; property AccessibleItem: IAccessible read FAccessibleItem write FAccessibleItem;
property AccessibleName: string read FAccessibleName write FAccessibleName; property AccessibleName: string read FAccessibleName write FAccessibleName;
{$endif} {$endif}
property CheckedCount: Integer read GetCheckedCount;
property CheckImages: TBitmap read FCheckImages; property CheckImages: TBitmap read FCheckImages;
property CheckState[Node: PVirtualNode]: TCheckState read GetCheckState write SetCheckState; property CheckState[Node: PVirtualNode]: TCheckState read GetCheckState write SetCheckState;
property CheckType[Node: PVirtualNode]: TCheckType read GetCheckType write SetCheckType; property CheckType[Node: PVirtualNode]: TCheckType read GetCheckType write SetCheckType;
property ChildCount[Node: PVirtualNode]: Cardinal read GetChildCount write SetChildCount; property ChildCount[Node: PVirtualNode]: Cardinal read GetChildCount write SetChildCount;
property ChildrenInitialized[Node: PVirtualNode]: Boolean read GetChildrenInitialized; property ChildrenInitialized[Node: PVirtualNode]: Boolean read GetChildrenInitialized;
property CutCopyCount: Integer read GetCutCopyCount;
property DragImage: TVTDragImage read FDragImage; property DragImage: TVTDragImage read FDragImage;
property DragManager: IVTDragManager read GetDragManager; property DragManager: IVTDragManager read GetDragManager;
property DropTargetNode: PVirtualNode read FDropTargetNode; property DropTargetNode: PVirtualNode read FDropTargetNode;
@@ -2924,7 +2955,8 @@ type
property Colors; property Colors;
property Constraints; property Constraints;
property Ctl3D; property Ctl3D;
property CustomCheckImages; //todo: see a way to set CustomCheckImages at design time
//property CustomCheckImages;
property DefaultNodeHeight; property DefaultNodeHeight;
property DefaultPasteMode; property DefaultPasteMode;
property DefaultText; property DefaultText;
@@ -9936,22 +9968,7 @@ begin
if csLoading in Treeview.ComponentState then if csLoading in Treeview.ComponentState then
FSortColumn := Value FSortColumn := Value
else else
begin DoSetSortColumn(Value);
if Value < NoColumn then
Value := NoColumn;
if Value > Columns.Count - 1 then
Value := Columns.Count - 1;
if FSortColumn <> Value then
begin
if FSortColumn > NoColumn then
Invalidate(Columns[FSortColumn]);
FSortColumn := Value;
if FSortColumn > NoColumn then
Invalidate(Columns[FSortColumn]);
if (toAutoSort in Treeview.FOptions.FAutoOptions) and (Treeview.FUpdateCount = 0) then
Treeview.SortTree(FSortColumn, FSortDirection, True);
end;
end;
end; end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
@@ -10074,6 +10091,27 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TVTHeader.DoSetSortColumn(Value: TColumnIndex);
begin
if Value < NoColumn then
Value := NoColumn;
if Value > Columns.Count - 1 then
Value := Columns.Count - 1;
if FSortColumn <> Value then
begin
if FSortColumn > NoColumn then
Invalidate(Columns[FSortColumn]);
FSortColumn := Value;
if FSortColumn > NoColumn then
Invalidate(Columns[FSortColumn]);
if (toAutoSort in Treeview.FOptions.FAutoOptions) and (Treeview.FUpdateCount = 0) then
Treeview.SortTree(FSortColumn, FSortDirection, True);
end;
end;
//----------------------------------------------------------------------------------------------------------------------
procedure TVTHeader.DragTo(P: TPoint); procedure TVTHeader.DragTo(P: TPoint);
// Moves the drag image to a new position, which is determined from the passed point P and the previous // Moves the drag image to a new position, which is determined from the passed point P and the previous
@@ -12284,6 +12322,16 @@ begin
end; end;
end; end;
procedure TBaseVirtualTree.DragAndDrop(AllowedEffects: Integer;
DataObject: IDataObject; DragEffect: Integer);
begin
{$ifdef UseExternalDragManager}
VirtualDragManager.DoDragDrop(DataObject, DragManager as IDropSource, AllowedEffects, @DragEffect);
{$else}
ActiveX.DoDragDrop(DataObject, DragManager as IDropSource, AllowedEffects, @DragEffect);
{$endif}
end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
procedure TBaseVirtualTree.DrawLineImage(const PaintInfo: TVTPaintInfo; X, Y, H, VAlign: Integer; Style: TVTLineType; procedure TBaseVirtualTree.DrawLineImage(const PaintInfo: TVTPaintInfo; X, Y, H, VAlign: Integer; Style: TVTLineType;
@@ -12457,6 +12505,22 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetCheckedCount: Integer;
var
Node: PVirtualNode;
begin
Result := 0;
Node := GetFirstChecked;
while Assigned(Node) do begin
Inc(Result);
Node := GetNextChecked(Node);
end;
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetCheckState(Node: PVirtualNode): TCheckState; function TBaseVirtualTree.GetCheckState(Node: PVirtualNode): TCheckState;
begin begin
@@ -12492,6 +12556,21 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetCutCopyCount: Integer;
var
Node: PVirtualNode;
begin
Result := 0;
Node := GetFirstCutCopy;
while Assigned(Node) do begin
Inc(Result);
Node := GetNextCutCopy(Node);
end;
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetDisabled(Node: PVirtualNode): Boolean; function TBaseVirtualTree.GetDisabled(Node: PVirtualNode): Boolean;
begin begin
@@ -13025,7 +13104,10 @@ begin
if PeekMessage(Msg, Handle, 0, 0, PM_REMOVE) then if PeekMessage(Msg, Handle, 0, 0, PM_REMOVE) then
begin begin
if Msg.message = WM_QUIT then if Msg.message = WM_QUIT then
begin
PostQuitMessage(Msg.WParam);
Break; Break;
end;
TranslateMessage(Msg); TranslateMessage(Msg);
DispatchMessage(Msg); DispatchMessage(Msg);
end; end;
@@ -13766,10 +13848,10 @@ procedure TBaseVirtualTree.SetChildCount(Node: PVirtualNode; NewChildCount: Card
// routine is used. // routine is used.
var var
Count: Integer; Remaining: Cardinal;
Index: Cardinal; Index: Cardinal;
Child: PVirtualNode; Child: PVirtualNode;
C: Integer; Count: Integer;
NewHeight: Integer; NewHeight: Integer;
begin begin
@@ -13782,18 +13864,17 @@ begin
DeleteChildren(Node) DeleteChildren(Node)
else else
begin begin
Count := Integer(NewChildCount) - Integer(Node.ChildCount);
// If nothing changed then do nothing. // If nothing changed then do nothing.
if Count <> 0 then if NewChildCount <> Node.ChildCount then
begin begin
InterruptValidation; InterruptValidation;
C := Count;
NewHeight := 0; NewHeight := 0;
if Count > 0 then if NewChildCount > Node.ChildCount then
begin begin
Remaining := NewChildCount - Node.ChildCount;
Count := Remaining;
// New nodes to add. // New nodes to add.
if Assigned(Node.LastChild) then if Assigned(Node.LastChild) then
Index := Node.LastChild.Index + 1 Index := Node.LastChild.Index + 1
@@ -13805,7 +13886,7 @@ begin
Node.States := Node.States - [vsAllChildrenHidden, vsHeightMeasured]; Node.States := Node.States - [vsAllChildrenHidden, vsHeightMeasured];
// New nodes are by default always visible, so we don't need to check the visibility. // New nodes are by default always visible, so we don't need to check the visibility.
while Count > 0 do while Remaining > 0 do
begin begin
Child := MakeNewNode; Child := MakeNewNode;
Child.Index := Index; Child.Index := Index;
@@ -13816,7 +13897,7 @@ begin
Node.LastChild := Child; Node.LastChild := Child;
if Node.FirstChild = nil then if Node.FirstChild = nil then
Node.FirstChild := Child; Node.FirstChild := Child;
Dec(Count); Dec(Remaining);
Inc(Index); Inc(Index);
// The actual node height will later be computed once it is clear // The actual node height will later be computed once it is clear
@@ -13828,10 +13909,10 @@ begin
begin begin
AdjustTotalHeight(Node, NewHeight, True); AdjustTotalHeight(Node, NewHeight, True);
if FullyVisible[Node] then if FullyVisible[Node] then
Inc(Integer(FVisibleCount), C); Inc(Integer(FVisibleCount), Count);
end; end;
AdjustTotalCount(Node, C, True); AdjustTotalCount(Node, Count, True);
Node.ChildCount := NewChildCount; Node.ChildCount := NewChildCount;
if (FUpdateCount = 0) and (toAutoSort in FOptions.FAutoOptions) and (FHeader.FSortColumn > InvalidColumn) then if (FUpdateCount = 0) and (toAutoSort in FOptions.FAutoOptions) and (FHeader.FSortColumn > InvalidColumn) then
Sort(Node, FHeader.FSortColumn, FHeader.FSortDirection, True); Sort(Node, FHeader.FSortColumn, FHeader.FSortDirection, True);
@@ -13841,10 +13922,11 @@ begin
else else
begin begin
// Nodes have to be deleted. // Nodes have to be deleted.
while Count < 0 do Remaining := Node.ChildCount - NewChildCount;
while Remaining > 0 do
begin begin
DeleteNode(Node.LastChild); DeleteNode(Node.LastChild);
Inc(Count); Dec(Remaining);
end; end;
end; end;
@@ -15749,7 +15831,10 @@ begin
else else
NewColumn := NoColumn; NewColumn := NoColumn;
// Find a column for the new/current node which can be focused. // Find a column for the new/current node which can be focused.
while (NewColumn > NoColumn) and not DoFocusChanging(FFocusedNode, Node, FFocusedColumn, NewColumn) do // Make the 'DoFocusChanging' for finding a valid column
// identifiable from the 'DoFocusChanging' raised later on by
// "FocusedNode := Node;"
while (NewColumn > NoColumn) and not DoFocusChanging(FFocusedNode, FFocusedNode, FFocusedColumn, NewColumn) do
NewColumn := GetNextColumn(NewColumn); NewColumn := GetNextColumn(NewColumn);
if NewColumn > InvalidColumn then if NewColumn > InvalidColumn then
begin begin
@@ -16242,6 +16327,9 @@ var
begin begin
Logger.EnterMethod([lcMessages],'WMKillFocus'); Logger.EnterMethod([lcMessages],'WMKillFocus');
inherited WMKillFocus(Msg); inherited WMKillFocus(Msg);
// Remove hint if shown currently.
Application.CancelHint;
// Stop wheel panning if active. // Stop wheel panning if active.
StopWheelPanning; StopWheelPanning;
@@ -18428,11 +18516,7 @@ begin
DragEffect := DROPEFFECT_NONE; DragEffect := DROPEFFECT_NONE;
AllowedEffects := GetDragOperations; AllowedEffects := GetDragOperations;
try try
{$ifdef UseExternalDragManager} DragAndDrop(AllowedEffects, DataObject, DragEffect);
virtualdragmanager.DoDragDrop(DataObject, DragManager as IDropSource, AllowedEffects, @DragEffect);
{$else}
ActiveX.DoDragDrop(DataObject, DragManager as IDropSource, AllowedEffects, @DragEffect);
{$endif}
DragManager.ForceDragLeave; DragManager.ForceDragLeave;
finally finally
GetCursorPos(P); GetCursorPos(P);
@@ -24931,6 +25015,36 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetFirstLeaf: PVirtualNode;
// Returns the first node in the tree which has currently no children.
// The result is initialized if necessary.
begin
Result := GetNextLeaf(nil);
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetFirstLevel(NodeLevel: Cardinal): PVirtualNode;
// Returns the first node in the tree on a specific level.
// The result is initialized if necessary.
begin
Result := GetFirstNoInit;
while Assigned(Result) and (GetNodeLevel(Result) <> NodeLevel) do
Result := GetNextNoInit(Result);
if Assigned(Result) and (GetNodeLevel(Result) <> NodeLevel) then // i.e. there is no node with the desired level in the tree
Result := nil;
if Assigned(Result) and not (vsInitialized in Result.States) then
InitNode(Result);
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetFirstNoInit: PVirtualNode; function TBaseVirtualTree.GetFirstNoInit: PVirtualNode;
begin begin
@@ -25573,6 +25687,69 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetNextLeaf(Node: PVirtualNode): PVirtualNode;
// Returns the next node in the tree which has currently no children.
// The result is initialized if necessary.
begin
if (Node = nil) or (Node = FRoot) then
Result := FRoot.FirstChild
else
Result := GetNext(Node);
while Assigned(Result) and (vsHasChildren in Result.States) do
Result := GetNext(Result);
if Assigned(Result) and not (vsInitialized in Result.States) then
InitNode(Result);
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetNextLevel(Node: PVirtualNode; NodeLevel: Cardinal): PVirtualNode;
// Returns the next node in the tree on a specific level.
// The result is initialized if necessary.
var
StartNodeLevel: Cardinal;
begin
Result := nil;
if Assigned(Node) and (Node <> FRoot) then
begin
StartNodeLevel := GetNodeLevel(Node);
if StartNodeLevel < NodeLevel then
begin
Result := GetNext(Node);
if Assigned(Result) and (GetNodeLevel(Result) <> NodeLevel) then
Result := GetNextLevel(Result, NodeLevel);
end else if StartNodeLevel = NodeLevel then
begin
Result := Node.NextSibling;
if not Assigned(Result) then // i.e. start node was a last sibling
begin
Result := Node.Parent;
if Assigned(Result) then
begin
// go to next anchestor of the start node which has a next sibling (if exists)
while Assigned(Result) and not Assigned(Result.NextSibling) do
Result := Result.Parent;
if Assigned(Result) then
Result := GetNextLevel(Result.NextSibling, NodeLevel);
end;
end;
end else // i.e. StartNodeLevel > NodeLevel
Result := GetNextLevel(Node.Parent, NodeLevel);
end;
if Assigned(Result) and not (vsInitialized in Result.States) then
InitNode(Result);
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetNextNoInit(Node: PVirtualNode): PVirtualNode; function TBaseVirtualTree.GetNextNoInit(Node: PVirtualNode): PVirtualNode;
// Optimized variant of GetNext, no initialization of nodes is performed (if a node is not initialized // Optimized variant of GetNext, no initialization of nodes is performed (if a node is not initialized
@@ -25998,6 +26175,49 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetPreviousChecked(Node: PVirtualNode; State: TCheckState = csCheckedNormal): PVirtualNode;
begin
if (Node = nil) or (Node = FRoot) then
Result := FRoot.LastChild
else
Result := GetPreviousNoInit(Node);
while Assigned(Result) and (Result.CheckState <> State) do
Result := GetPreviousNoInit(Result);
if Assigned(Result) and not (vsInitialized in Result.States) then
InitNode(Result);
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetPreviousCutCopy(Node: PVirtualNode): PVirtualNode;
// Returns the previous node in the tree which is currently marked for a clipboard operation. Since only visible nodes can
// be marked (or they are hidden after they have been marked) it is not necessary to initialize nodes to check for
// child nodes. The result, however, is initialized if necessary.
begin
if ClipboardStates * FStates <> [] then
begin
if (Node = nil) or (Node = FRoot) then
Result := FRoot.LastChild
else
Result := GetPreviousNoInit(Node);
while Assigned(Result) and not (vsCutOrCopy in Result.States) do
Result := GetPreviousNoInit(Result);
if Assigned(Result) and not (vsInitialized in Result.States) then
InitNode(Result);
end
else
Result := nil;
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetPreviousInitialized(Node: PVirtualNode): PVirtualNode; function TBaseVirtualTree.GetPreviousInitialized(Node: PVirtualNode): PVirtualNode;
// Returns the previous node in tree which is initialized. // Returns the previous node in tree which is initialized.
@@ -26011,6 +26231,70 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetPreviousLeaf(Node: PVirtualNode): PVirtualNode;
// Returns the previous node in the tree which has currently no children.
// The result is initialized if necessary.
begin
if (Node = nil) or (Node = FRoot) then
Result := FRoot.LastChild
else
Result := GetPrevious(Node);
while Assigned(Result) and (vsHasChildren in Result.States) do
Result := GetPrevious(Result);
if Assigned(Result) and not (vsInitialized in Result.States) then
InitNode(Result);
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetPreviousLevel(Node: PVirtualNode; NodeLevel: Cardinal): PVirtualNode;
// Returns the previous node in the tree on a specific level.
// The result is initialized if necessary.
var
StartNodeLevel: Cardinal;
begin
Result := nil;
if Assigned(Node) and (Node <> FRoot) then
begin
StartNodeLevel := GetNodeLevel(Node);
if StartNodeLevel < NodeLevel then
begin
Result := Node.PrevSibling;
if Assigned(Result) then
begin
// go to last descendant of previous sibling with desired node level (if exists)
while Assigned(Result) and (GetNodeLevel(Result) < NodeLevel) do
Result := GetLastChild(Result);
if not Assigned(Result) then
Result := GetPreviousLevel(Node.PrevSibling, NodeLevel);
end else
Result := GetPreviousLevel(Node.Parent, NodeLevel);
end else if StartNodeLevel = NodeLevel then
begin
Result := Node.PrevSibling;
if not Assigned(Result) then // i.e. start node was a first sibling
begin
Result := Node.Parent;
if Assigned(Result) then
Result := GetPreviousLevel(Result, NodeLevel);
end;
end else // i.e. StartNodeLevel > NodeLevel
Result := GetPreviousLevel(Node.Parent, NodeLevel);
end;
if Assigned(Result) and not (vsInitialized in Result.States) then
InitNode(Result);
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetPreviousNoInit(Node: PVirtualNode): PVirtualNode; function TBaseVirtualTree.GetPreviousNoInit(Node: PVirtualNode): PVirtualNode;
// Returns the previous node in the tree with regard to Node. No initialization in done, hence this // Returns the previous node in the tree with regard to Node. No initialization in done, hence this
@@ -26041,6 +26325,30 @@ end;
//---------------------------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetPreviousSelected(Node: PVirtualNode): PVirtualNode;
// Returns the previous node in the tree which is currently selected. Since children of unitialized nodes cannot be
// in the current selection (because they simply do not exist yet) it is not necessary to initialize nodes here.
// The result however is initialized if necessary.
begin
if FSelectionCount > 0 then
begin
if (Node = nil) or (Node = FRoot) then
Result := FRoot.LastChild
else
Result := GetPreviousNoInit(Node);
while Assigned(Result) and not (vsSelected in Result.States) do
Result := GetPreviousNoInit(Result);
if Assigned(Result) and not (vsInitialized in Result.States) then
InitNode(Result);
end
else
Result := nil;
end;
//----------------------------------------------------------------------------------------------------------------------
function TBaseVirtualTree.GetPreviousSibling(Node: PVirtualNode): PVirtualNode; function TBaseVirtualTree.GetPreviousSibling(Node: PVirtualNode): PVirtualNode;
// Get next sibling of Node, initialize it if necessary. // Get next sibling of Node, initialize it if necessary.
@@ -28970,7 +29278,7 @@ begin
// Since the position is automatically changed if it doesn't meet the range // Since the position is automatically changed if it doesn't meet the range
// we better read the current position back to stay synchronized. // we better read the current position back to stay synchronized.
{$ifdef UseFlatScrollbars} {$ifdef UseFlatScrollbars}
FScrollOffsetX := FlatSB_GetScrollPos(Handle, SB_HORZ); FEffectiveOffsetX := FlatSB_GetScrollPos(Handle, SB_HORZ);
{$else} {$else}
//todo: Use get scrollinfo instead of GetScrollPos?? //todo: Use get scrollinfo instead of GetScrollPos??
FEffectiveOffsetX := GetScrollPos(Handle, SB_HORZ); FEffectiveOffsetX := GetScrollPos(Handle, SB_HORZ);