LCL: Fix cursor key behavior with TTreeNode.Enabled, add methods to iterate tree. Issue #39590.

This commit is contained in:
Juha 2022-01-24 23:16:37 +02:00
parent 5563e5ff8a
commit cd2ae505e3
2 changed files with 223 additions and 61 deletions

View File

@ -2989,7 +2989,8 @@ type
FSubTreeCount: integer;// total of all child nodes and self FSubTreeCount: integer;// total of all child nodes and self
FText: string; FText: string;
FTop: integer; // top coordinate FTop: integer; // top coordinate
function AreParentsExpandedAndVisible: Boolean; function ParentsExpandedVisible: Boolean;
function ParentsExpandedVisibleEnabled: Boolean;
procedure BindToMultiSelected; procedure BindToMultiSelected;
function CompareCount(CompareMe: Integer): Boolean; function CompareCount(CompareMe: Integer): Boolean;
function DoCanExpand(ExpandIt: Boolean): Boolean; function DoCanExpand(ExpandIt: Boolean): Boolean;
@ -3009,12 +3010,13 @@ type
function GetLevel: Integer; function GetLevel: Integer;
function GetMultiSelected: Boolean; function GetMultiSelected: Boolean;
function GetSelected: Boolean; function GetSelected: Boolean;
function GetState(NodeState: TNodeState): Boolean; function GetState(NodeState: TNodeState): Boolean; inline;
function GetTreeNodes: TTreeNodes; function GetTreeNodes: TTreeNodes;
function GetTreeView: TCustomTreeView; function GetTreeView: TCustomTreeView;
function GetTop: integer; function GetTop: integer;
function GetVisible: Boolean; function GetVisible: Boolean;
function GetEnabled: Boolean; function GetEnabled: Boolean;
function HasStates(NodeStates: TNodeStates): Boolean; inline;
procedure InternalMove(ANode: TTreeNode; AddMode: TAddMode); procedure InternalMove(ANode: TTreeNode; AddMode: TAddMode);
function IsEqual(Node: TTreeNode): Boolean; function IsEqual(Node: TTreeNode): Boolean;
function IsNodeVisible: Boolean; function IsNodeVisible: Boolean;
@ -3068,27 +3070,35 @@ type
function GetFirstChild: TTreeNode; function GetFirstChild: TTreeNode;
function GetFirstSibling: TTreeNode; function GetFirstSibling: TTreeNode;
function GetFirstVisibleChild: TTreeNode; function GetFirstVisibleChild: TTreeNode;
function GetFirstVisibleEnabledChild: TTreeNode;
function GetHandle: THandle; function GetHandle: THandle;
function GetLastChild: TTreeNode; function GetLastChild: TTreeNode;
function GetLastSibling: TTreeNode; function GetLastSibling: TTreeNode;
function GetLastSubChild: TTreeNode; function GetLastSubChild: TTreeNode;
function GetLastVisibleChild: TTreeNode; function GetLastVisibleChild: TTreeNode;
function GetLastVisibleEnabledChild: TTreeNode;
function GetNext: TTreeNode; function GetNext: TTreeNode;
function GetNextChild(AValue: TTreeNode): TTreeNode; function GetNextChild(AValue: TTreeNode): TTreeNode;
function GetNextExpanded: TTreeNode; function GetNextExpanded: TTreeNode;
function GetNextExpandedEnabled: TTreeNode;
function GetNextMultiSelected: TTreeNode; function GetNextMultiSelected: TTreeNode;
function GetNextSibling: TTreeNode; function GetNextSibling: TTreeNode;
function GetNextSkipChildren: TTreeNode; function GetNextSkipChildren: TTreeNode;
function GetNextVisible: TTreeNode; function GetNextVisible: TTreeNode;
function GetNextVisibleEnabled: TTreeNode;
function GetNextVisibleSibling: TTreeNode; function GetNextVisibleSibling: TTreeNode;
function GetNextVisibleEnabledSibling: TTreeNode;
function GetParentNodeOfAbsoluteLevel(TheAbsoluteLevel: integer): TTreeNode; function GetParentNodeOfAbsoluteLevel(TheAbsoluteLevel: integer): TTreeNode;
function GetPrev: TTreeNode; function GetPrev: TTreeNode;
function GetPrevChild(AValue: TTreeNode): TTreeNode; function GetPrevChild(AValue: TTreeNode): TTreeNode;
function GetPrevExpanded: TTreeNode; function GetPrevExpanded: TTreeNode;
function GetPrevExpandedEnabled: TTreeNode;
function GetPrevMultiSelected: TTreeNode; function GetPrevMultiSelected: TTreeNode;
function GetPrevSibling: TTreeNode; function GetPrevSibling: TTreeNode;
function GetPrevVisible: TTreeNode; function GetPrevVisible: TTreeNode;
function GetPrevVisibleEnabled: TTreeNode;
function GetPrevVisibleSibling: TTreeNode; function GetPrevVisibleSibling: TTreeNode;
function GetPrevVisibleEnabledSibling: TTreeNode;
function GetTextPath: string; function GetTextPath: string;
function HasAsParent(AValue: TTreeNode): Boolean; function HasAsParent(AValue: TTreeNode): Boolean;
function IndexOf(AValue: TTreeNode): Integer; function IndexOf(AValue: TTreeNode): Integer;
@ -3228,10 +3238,12 @@ type
function GetEnumerator: TTreeNodesEnumerator; function GetEnumerator: TTreeNodesEnumerator;
function GetFirstNode: TTreeNode; function GetFirstNode: TTreeNode;
function GetFirstVisibleNode: TTreeNode; function GetFirstVisibleNode: TTreeNode;
function GetLastExpandedSubNode: TTreeNode; // absolute last node function GetFirstVisibleEnabledNode: TTreeNode;
function GetLastExpandedSubNode: TTreeNode; // absolute last visible enabled node
function GetLastNode: TTreeNode; // last top level node function GetLastNode: TTreeNode; // last top level node
function GetLastSubNode: TTreeNode; // absolute last node function GetLastSubNode: TTreeNode; // absolute last node
function GetLastVisibleNode: TTreeNode; function GetLastVisibleNode: TTreeNode;
function GetLastVisibleEnabledNode: TTreeNode;
function GetSelections(const AIndex: Integer): TTreeNode; function GetSelections(const AIndex: Integer): TTreeNode;
function Insert(NextNode: TTreeNode; const S: string): TTreeNode; function Insert(NextNode: TTreeNode; const S: string): TTreeNode;
function InsertBehind(PrevNode: TTreeNode; const S: string): TTreeNode; function InsertBehind(PrevNode: TTreeNode; const S: string): TTreeNode;

View File

@ -419,6 +419,11 @@ begin
Result:=nsEnabled in FStates; Result:=nsEnabled in FStates;
end; end;
function TTreeNode.HasStates(NodeStates: TNodeStates): Boolean;
begin
Result:=FStates*NodeStates=NodeStates;
end;
function TTreeNode.HasAsParent(AValue: TTreeNode): Boolean; function TTreeNode.HasAsParent(AValue: TTreeNode): Boolean;
begin begin
if AValue<>nil then begin if AValue<>nil then begin
@ -547,6 +552,7 @@ begin
else else
Exclude(FStates,nsVisible); Exclude(FStates,nsVisible);
Selected := False; Selected := False;
MultiSelected := False;
if TreeView<>nil then if TreeView<>nil then
TreeView.FStates:=TreeView.FStates+[tvsScrollbarChanged,tvsTopsNeedsUpdate, TreeView.FStates:=TreeView.FStates+[tvsScrollbarChanged,tvsTopsNeedsUpdate,
tvsTopItemNeedsUpdate,tvsBottomItemNeedsUpdate, tvsTopItemNeedsUpdate,tvsBottomItemNeedsUpdate,
@ -563,6 +569,7 @@ begin
else else
Exclude(FStates,nsEnabled); Exclude(FStates,nsEnabled);
Selected := False; Selected := False;
MultiSelected := False;
{ {
if TreeView<>nil then if TreeView<>nil then
TreeView.FStates:=TreeView.FStates+[tvsTopsNeedsUpdate, TreeView.FStates:=TreeView.FStates+[tvsTopsNeedsUpdate,
@ -589,14 +596,27 @@ begin
Changed(ncStateIndex); Changed(ncStateIndex);
end; end;
function TTreeNode.AreParentsExpandedAndVisible: Boolean; function TTreeNode.ParentsExpandedVisible: Boolean;
var var
ANode: TTreeNode; ANode: TTreeNode;
begin begin
Result:=false;
ANode:=Parent; ANode:=Parent;
while ANode<>nil do begin while ANode<>nil do begin
if not (ANode.Expanded and ANode.Visible) then exit; if not ANode.HasStates([nsExpanded,nsVisible]) then
exit(false);
ANode:=ANode.Parent;
end;
Result:=true;
end;
function TTreeNode.ParentsExpandedVisibleEnabled: Boolean;
var
ANode: TTreeNode;
begin
ANode:=Parent;
while ANode<>nil do begin
if not ANode.HasStates([nsExpanded,nsVisible,nsEnabled]) then
exit(false);
ANode:=ANode.Parent; ANode:=ANode.Parent;
end; end;
Result:=true; Result:=true;
@ -719,7 +739,7 @@ begin
end; end;
end; end;
procedure TTreeNode.ExpandItem(ExpandIt: Boolean; Recurse: Boolean); procedure TTreeNode.ExpandItem(ExpandIt, Recurse: Boolean);
var var
ANode: TTreeNode; ANode: TTreeNode;
begin begin
@ -816,8 +836,9 @@ begin
if MultiSelect then TV.LockSelectionChangeEvent; if MultiSelect then TV.LockSelectionChangeEvent;
try try
TV.Selected:=Self; TV.Selected:=Self;
if TV.Selected<>Self then Assert(TV.Selected=Self, 'Selected<>Self');
Exclude(FStates,nsSelected); //if TV.Selected<>Self then
// Exclude(FStates,nsSelected);
if (nsSelected in FStates) and MultiSelect then if (nsSelected in FStates) and MultiSelect then
MultiSelected:=true; MultiSelected:=true;
finally finally
@ -951,9 +972,12 @@ begin
end; end;
function TTreeNode.GetNextVisible: TTreeNode; function TTreeNode.GetNextVisible: TTreeNode;
var
Child1: TTreeNode;
begin begin
if Visible and Expanded and (GetFirstVisibleChild<>nil) then Child1:=GetFirstVisibleChild;
Result:=GetFirstVisibleChild if (Child1<>nil) and HasStates([nsExpanded,nsVisible]) then
Result:=Child1
else begin else begin
Result:=Self; Result:=Self;
while (Result<>nil) and (Result.GetNextVisibleSibling=nil) do while (Result<>nil) and (Result.GetNextVisibleSibling=nil) do
@ -961,7 +985,26 @@ begin
if Result<>nil then if Result<>nil then
Result:=Result.GetNextVisibleSibling; Result:=Result.GetNextVisibleSibling;
end; end;
if (Result<>nil) and ( (not Result.Visible) or (not AreParentsExpandedAndVisible) ) then if (Result<>nil) and not (Result.Visible and ParentsExpandedVisible) then
Result:=nil;
end;
function TTreeNode.GetNextVisibleEnabled: TTreeNode;
var
Child1: TTreeNode;
begin
Child1:=GetFirstVisibleEnabledChild;
if (Child1<>nil) and HasStates([nsExpanded,nsVisible,nsEnabled]) then
Result:=Child1
else begin
Result:=Self;
while (Result<>nil) and (Result.GetNextVisibleEnabledSibling=nil) do
Result:=Result.Parent;
if Result<>nil then
Result:=Result.GetNextVisibleEnabledSibling;
end;
if (Result<>nil) and
not (Result.HasStates([nsVisible,nsEnabled]) and ParentsExpandedVisibleEnabled) then
Result:=nil; Result:=nil;
end; end;
@ -970,9 +1013,15 @@ begin
Result := Self; Result := Self;
repeat repeat
Result := Result.GetNextSibling; Result := Result.GetNextSibling;
until ((Result=nil) or (Result.Visible)); until (Result=nil) or Result.Visible;
if (Result<>nil) and (not Result.Visible) then // Result := nil ... will be removed end;
Assert(False,'TTreeNode.GetNextVisibleSibling: (Result<>nil) and (not Result.Visible)');
function TTreeNode.GetNextVisibleEnabledSibling: TTreeNode;
begin
Result := Self;
repeat
Result := Result.GetNextSibling;
until (Result=nil) or Result.HasStates([nsVisible,nsEnabled]);
end; end;
function TTreeNode.GetPrevVisible: TTreeNode; function TTreeNode.GetPrevVisible: TTreeNode;
@ -981,7 +1030,7 @@ var
begin begin
Result:=GetPrevVisibleSibling; Result:=GetPrevVisibleSibling;
if Result <> nil then begin if Result <> nil then begin
while Result.Visible and Result.Expanded do begin while Result.HasStates([nsExpanded,nsVisible]) do begin
ANode:=Result.GetLastVisibleChild; ANode:=Result.GetLastVisibleChild;
if ANode=nil then break; if ANode=nil then break;
Result:=ANode; Result:=ANode;
@ -989,7 +1038,26 @@ begin
end end
else else
Result := Parent; Result := Parent;
if (Result<>nil) and ( (not Result.Visible) or (not AreParentsExpandedAndVisible) ) then if (Result<>nil) and not (Result.Visible and ParentsExpandedVisible) then
Result:=nil;
end;
function TTreeNode.GetPrevVisibleEnabled: TTreeNode;
var
ANode: TTreeNode;
begin
Result:=GetPrevVisibleEnabledSibling;
if Result <> nil then begin
while Result.HasStates([nsExpanded,nsVisible,nsEnabled]) do begin
ANode:=Result.GetLastVisibleEnabledChild;
if ANode=nil then break;
Result:=ANode;
end;
end
else
Result := Parent;
if (Result<>nil) and
not (Result.HasStates([nsVisible,nsEnabled]) and ParentsExpandedVisibleEnabled) then
Result:=nil; Result:=nil;
end; end;
@ -998,9 +1066,15 @@ begin
Result := Self; Result := Self;
repeat repeat
Result := Result.GetPrevSibling; Result := Result.GetPrevSibling;
until ((Result=nil) or (Result.Visible)); until (Result=nil) or Result.Visible;
if (Result<>nil) and (not Result.Visible) then // Result := nil ... will be removed end;
Assert(False,'TTreeNode.GetPrevVisibleSibling: (Result<>nil) and (not Result.Visible)');
function TTreeNode.GetPrevVisibleEnabledSibling: TTreeNode;
begin
Result := Self;
repeat
Result := Result.GetPrevSibling;
until (Result=nil) or Result.HasStates([nsVisible,nsEnabled]);
end; end;
function TTreeNode.GetPrevExpanded: TTreeNode; function TTreeNode.GetPrevExpanded: TTreeNode;
@ -1009,7 +1083,7 @@ var
begin begin
Result:=GetPrevVisibleSibling; Result:=GetPrevVisibleSibling;
if Result <> nil then begin if Result <> nil then begin
while Result.Visible and Result.Expanded do begin while Result.HasStates([nsExpanded,nsVisible]) do begin
ANode:=Result.GetLastVisibleChild; ANode:=Result.GetLastVisibleChild;
if ANode=nil then break; if ANode=nil then break;
Result:=ANode; Result:=ANode;
@ -1019,6 +1093,22 @@ begin
Result:=Parent; Result:=Parent;
end; end;
function TTreeNode.GetPrevExpandedEnabled: TTreeNode;
var
ANode: TTreeNode;
begin
Result:=GetPrevVisibleEnabledSibling;
if Result <> nil then begin
while Result.HasStates([nsExpanded,nsVisible,nsEnabled]) do begin
ANode:=Result.GetLastVisibleEnabledChild;
if ANode=nil then break;
Result:=ANode;
end;
end
else
Result:=Parent;
end;
function TTreeNode.GetNextChild(AValue: TTreeNode): TTreeNode; function TTreeNode.GetNextChild(AValue: TTreeNode): TTreeNode;
begin begin
if AValue <> nil then if AValue <> nil then
@ -1043,6 +1133,22 @@ begin
end; end;
end; end;
function TTreeNode.GetNextExpandedEnabled: TTreeNode;
var
ANode: TTreeNode;
begin
ANode := GetFirstVisibleEnabledChild;
if Expanded and (ANode<>nil) then
Result:=ANode
else begin
Result:=Self;
while (Result<>nil) and (Result.GetNextVisibleEnabledSibling=nil) do
Result:=Result.Parent;
if Result<>nil then
Result:=Result.GetNextVisibleEnabledSibling;
end;
end;
function TTreeNode.GetNextMultiSelected: TTreeNode; function TTreeNode.GetNextMultiSelected: TTreeNode;
begin begin
Result:=FNextMultiSelected; Result:=FNextMultiSelected;
@ -1087,6 +1193,13 @@ begin
Result := Result.GetNextVisibleSibling; Result := Result.GetNextVisibleSibling;
end; end;
function TTreeNode.GetFirstVisibleEnabledChild: TTreeNode;
begin
Result := GetFirstChild;
if (Result<>nil) and not Result.HasStates([nsVisible,nsEnabled]) then
Result := Result.GetNextVisibleEnabledSibling;
end;
function TTreeNode.GetLastSibling: TTreeNode; function TTreeNode.GetLastSibling: TTreeNode;
begin begin
if Parent<>nil then if Parent<>nil then
@ -1111,10 +1224,19 @@ begin
Result := GetLastChild; Result := GetLastChild;
if Assigned(Result) and not Result.Visible then begin if Assigned(Result) and not Result.Visible then begin
Result := Result.GetPrevVisible; Result := Result.GetPrevVisible;
if Result = Self then begin // No visible nodes found. if Result = Self then // No visible nodes found.
Assert(Visible, 'TTreeNode.GetLastVisibleChild: Node is not Visible'); Result := Nil;
end;
end;
function TTreeNode.GetLastVisibleEnabledChild: TTreeNode;
begin
Result := GetLastChild;
if Assigned(Result) and not Result.HasStates([nsVisible,nsEnabled]) then
begin
Result := Result.GetPrevVisibleEnabled;
if Result = Self then // No visible enabled nodes found.
Result := Nil; Result := Nil;
end;
end; end;
end; end;
@ -1245,7 +1367,7 @@ procedure TTreeNode.SetMultiSelected(const AValue: Boolean);
begin begin
if AValue=GetMultiSelected then exit; if AValue=GetMultiSelected then exit;
if AValue then begin if AValue then begin
if (Treeview<>nil) and (not (tvoAllowMultiselect in TreeView.Options)) then if (Treeview<>nil) and not (tvoAllowMultiselect in TreeView.Options) then
exit; exit;
if Assigned(FOwner) then if Assigned(FOwner) then
FOwner.SelectionsChanged(Self, True); FOwner.SelectionsChanged(Self, True);
@ -1681,7 +1803,7 @@ begin
if Assigned(TreeView) then if Assigned(TreeView) then
Result := TreeView.IsNodeVisible(Self) Result := TreeView.IsNodeVisible(Self)
else else
Result := AreParentsExpandedAndVisible; Result := ParentsExpandedVisible;
end; end;
function TTreeNode.IsNodeHeightFullVisible: Boolean; function TTreeNode.IsNodeHeightFullVisible: Boolean;
@ -1689,7 +1811,7 @@ begin
if Assigned(TreeView) then if Assigned(TreeView) then
Result := TreeView.IsNodeHeightFullVisible(Self) Result := TreeView.IsNodeHeightFullVisible(Self)
else else
Result := AreParentsExpandedAndVisible; Result := ParentsExpandedVisible;
end; end;
procedure TTreeNode.Update; procedure TTreeNode.Update;
@ -2430,10 +2552,22 @@ begin
if Assigned(FTopLvlItems) then if Assigned(FTopLvlItems) then
for i := 0 to FTopLvlCount-1 do begin for i := 0 to FTopLvlCount-1 do begin
Node := FTopLvlItems[i]; Node := FTopLvlItems[i];
if Node.Visible then begin if Node.Visible then
Result := Node; exit(Node);
Break; end;
end; end;
function TTreeNodes.GetFirstVisibleEnabledNode: TTreeNode;
var
Node: TTreeNode;
i: Integer;
begin
Result := nil;
if Assigned(FTopLvlItems) then
for i := 0 to FTopLvlCount-1 do begin
Node := FTopLvlItems[i];
if Node.HasStates([nsVisible,nsEnabled]) then
exit(Node);
end; end;
end; end;
@ -2452,12 +2586,26 @@ var
begin begin
Result := nil; Result := nil;
if Assigned(FTopLvlItems) then if Assigned(FTopLvlItems) then
for i := FTopLvlCount-1 downto 0 do begin for i := FTopLvlCount-1 downto 0 do
begin
Node := FTopLvlItems[i]; Node := FTopLvlItems[i];
if Node.Visible then begin if Node.Visible then
Result := Node; exit(Node);
Break; end;
end; end;
function TTreeNodes.GetLastVisibleEnabledNode: TTreeNode;
var
Node: TTreeNode;
i: Integer;
begin
Result := nil;
if Assigned(FTopLvlItems) then
for i := FTopLvlCount-1 downto 0 do
begin
Node := FTopLvlItems[i];
if Node.HasStates([nsVisible,nsEnabled]) then
exit(Node);
end; end;
end; end;
@ -2470,16 +2618,17 @@ begin
if Assigned(Result) then if Assigned(Result) then
begin begin
Node := Result.GetLastSubChild; Node := Result.GetLastSubChild;
if Assigned(Node) then Result := Node; if Assigned(Node) then
Result := Node;
end; end;
end; end;
function TTreeNodes.GetLastExpandedSubNode: TTreeNode; function TTreeNodes.GetLastExpandedSubNode: TTreeNode;
// absolute last expanded node // absolute last expanded visible enabled node
var var
Node: TTreeNode; Node: TTreeNode;
begin begin
Result := GetLastVisibleNode; Result := GetLastVisibleEnabledNode;
while Assigned(Result) and (Result.Expanded) do while Assigned(Result) and (Result.Expanded) do
begin begin
Node := Result.GetLastVisibleChild; Node := Result.GetLastVisibleChild;
@ -3776,7 +3925,7 @@ begin
AIndent := Indent; AIndent := Indent;
while Node <> nil do while Node <> nil do
begin begin
if not Node.AreParentsExpandedAndVisible then if not Node.ParentsExpandedVisible then
begin begin
Node := Node.GetNext; Node := Node.GetNext;
Continue; Continue;
@ -4002,7 +4151,7 @@ begin
if i >= 0 then if i >= 0 then
begin begin
Result := Items.FTopLvlItems[i]; Result := Items.FTopLvlItems[i];
while Result.Visible and Result.Expanded do while Result.HasStates([nsExpanded,nsVisible]) do
begin begin
i := IndexOfNodeAtTop(Result.FItems, Result.FCount, Y); i := IndexOfNodeAtTop(Result.FItems, Result.FCount, Y);
if i >= 0 then if i >= 0 then
@ -4211,7 +4360,7 @@ end;
function TCustomTreeView.IsNodeVisible(ANode: TTreeNode): Boolean; function TCustomTreeView.IsNodeVisible(ANode: TTreeNode): Boolean;
begin begin
Result:=(ANode<>nil) and (ANode.Visible) and (ANode.AreParentsExpandedAndVisible); Result:=(ANode<>nil) and (ANode.Visible) and (ANode.ParentsExpandedVisible);
if Result then begin if Result then begin
//DebugLn('[TCustomTreeView.IsNodeVisible] B Node=',DbgS(ANode), //DebugLn('[TCustomTreeView.IsNodeVisible] B Node=',DbgS(ANode),
// ' ',dbgs(FScrolledTop)+'>=',dbgs(ANode.Top+ANode.Height)+' or =',dbgs(FScrolledTop),'+'+dbgs(ClientHeight)+'<',dbgs(ANode.Top)); // ' ',dbgs(FScrolledTop)+'>=',dbgs(ANode.Top+ANode.Height)+' or =',dbgs(FScrolledTop),'+'+dbgs(ClientHeight)+'<',dbgs(ANode.Top));
@ -4226,7 +4375,7 @@ end;
function TCustomTreeView.IsNodeHeightFullVisible(ANode: TTreeNode): Boolean; function TCustomTreeView.IsNodeHeightFullVisible(ANode: TTreeNode): Boolean;
begin begin
Result:=(ANode<>nil) and (ANode.AreParentsExpandedAndVisible); Result:=(ANode<>nil) and (ANode.ParentsExpandedVisible);
if Result then begin if Result then begin
//DebugLn('[TCustomTreeView.IsNodeVisible] B Node=',DbgS(ANode), //DebugLn('[TCustomTreeView.IsNodeVisible] B Node=',DbgS(ANode),
//' ',FScrolledTop,'>=',ANode.Top,'+',ANode.Height,' or ',FScrolledTop,'+',ClientHeight,'<',ANode.Top); //' ',FScrolledTop,'>=',ANode.Top,'+',ANode.Height,' or ',FScrolledTop,'+',ClientHeight,'<',ANode.Top);
@ -5371,7 +5520,6 @@ var
begin begin
if IsSelected then if IsSelected then
begin begin
Assert(Node.Enabled, 'DrawNodeText: not Enabled.');
if tvoFocusedPainting in FStates then if tvoFocusedPainting in FStates then
Details := ThemeServices.GetElementDetails(ttItemSelected) Details := ThemeServices.GetElementDetails(ttItemSelected)
else else
@ -5919,7 +6067,7 @@ procedure TCustomTreeView.MoveHome(ASelect: Boolean);
var var
lNode: TTreeNode; lNode: TTreeNode;
begin begin
lNode := Items.GetFirstVisibleNode; lNode := Items.GetFirstVisibleEnabledNode;
if lNode <> nil then if lNode <> nil then
MoveSelection(lNode, ASelect); MoveSelection(lNode, ASelect);
end; end;
@ -5927,27 +6075,28 @@ end;
procedure TCustomTreeView.MovePageDown(ASelect: Boolean); procedure TCustomTreeView.MovePageDown(ASelect: Boolean);
var var
I: Integer; I: Integer;
lNode: TTreeNode; lNode, NextNode: TTreeNode;
begin begin
if tvoAllowMultiSelect in FOptions then if tvoAllowMultiSelect in FOptions then
lNode := FTreeNodes.FLastMultiSelected lNode := FTreeNodes.FLastMultiSelected
else else
lNode := Selected; lNode := Selected;
if lNode = nil then if lNode = nil then
lNode := Items.GetFirstVisibleNode; lNode := Items.GetFirstVisibleEnabledNode;
if lNode <> nil then if lNode <> nil then
begin begin
I := Pred(ClientHeight div DefaultItemHeight); I := Pred(ClientHeight div DefaultItemHeight);
while (I > 0) do while (I > 0) do
if lNode.GetNextExpanded <> nil then begin
NextNode := lNode.GetNextExpandedEnabled;
if NextNode <> nil then
begin begin
lNode := lNode.GetNextExpanded; lNode := NextNode;
Dec(I); Dec(I);
end end
else Break; else Break;
end;
end; end;
if lNode <> nil then if lNode <> nil then
MoveSelection(lNode, ASelect); MoveSelection(lNode, ASelect);
@ -5956,27 +6105,28 @@ end;
procedure TCustomTreeView.MovePageUp(ASelect: Boolean); procedure TCustomTreeView.MovePageUp(ASelect: Boolean);
var var
I: Integer; I: Integer;
lNode: TTreeNode; lNode, PrevNode: TTreeNode;
begin begin
if tvoAllowMultiSelect in FOptions then if tvoAllowMultiSelect in FOptions then
lNode := FTreeNodes.FLastMultiSelected lNode := FTreeNodes.FLastMultiSelected
else else
lNode := Selected; lNode := Selected;
if lNode = nil then if lNode = nil then
lNode := Items.GetFirstVisibleNode; lNode := Items.GetFirstVisibleEnabledNode;
if lNode <> nil then if lNode <> nil then
begin begin
I := Pred(ClientHeight div DefaultItemHeight); I := Pred(ClientHeight div DefaultItemHeight);
while (I > 0) do while (I > 0) do
if lNode.GetPrevExpanded <> nil then begin
PrevNode := lNode.GetPrevExpandedEnabled;
if PrevNode <> nil then
begin begin
lNode := lNode.GetPrevExpanded; lNode := PrevNode;
Dec(I); Dec(I);
end end
else Break; else Break;
end;
end; end;
if lNode <> nil then if lNode <> nil then
MoveSelection(lNode, ASelect); MoveSelection(lNode, ASelect);
@ -6605,9 +6755,9 @@ begin
else else
ANode := Selected; ANode := Selected;
if ANode <> nil then if ANode <> nil then
ANode := ANode.GetNextVisible ANode := ANode.GetNextVisibleEnabled
else else
ANode := FTreeNodes.GetFirstVisibleNode; ANode := FTreeNodes.GetFirstVisibleEnabledNode;
if ANode <> nil then if ANode <> nil then
MoveSelection(ANode, ASelect); MoveSelection(ANode, ASelect);
end; end;
@ -6621,9 +6771,9 @@ begin
else else
ANode := Selected; ANode := Selected;
if ANode <> nil then if ANode <> nil then
ANode := ANode.GetPrevVisible ANode := ANode.GetPrevVisibleEnabled
else else
ANode := Items.GetFirstVisibleNode; ANode := Items.GetFirstVisibleEnabledNode;
if ANode <> nil then if ANode <> nil then
MoveSelection(ANode, ASelect); MoveSelection(ANode, ASelect);
end; end;