📄 outline.pas
字号:
Result := FList;
end;
function TOutlineNode.GetNode(Index: LongInt): TOutlineNode;
begin
Result := List[Index];
end;
function TOutlineNode.GetLastIndex: LongInt;
begin
if List.Count <> 0 then
Result := TOutlineNode(List.Last).GetLastIndex
else
Result := Index;
end;
procedure TOutlineNode.SetText(const Value: string);
var
NodeRow: LongInt;
begin
FText := Value;
if not Assigned(FParent) then Exit;
if Parent.Expanded then
begin
NodeRow := 0;
with Outline do
begin
FRootNode.GetRowOfNode(Self, NodeRow);
InvalidateCell(0, NodeRow - 2);
end;
end;
SetHorzScrollBar;
end;
procedure TOutlineNode.ChangeExpandedCount(Value: LongInt);
begin
if not Expanded then Exit;
Inc(FExpandCount, Value);
if Parent <> nil then Parent.ChangeExpandedCount(Value);
end;
function TOutlineNode.GetIndex: LongInt;
begin
if Outline.BadIndex(Self) then SetGoodIndex;
Result := FIndex;
end;
function TOutlineNode.GetLevel: Cardinal;
var
Node: TOutlineNode;
begin
Result := 0;
Node := Parent;
while Node <> nil do
begin
Inc(Result);
Node := Node.Parent;
end;
end;
procedure TOutlineNode.SetLevel(Level: Cardinal);
var
CurLevel: Cardinal;
begin
CurLevel := GetLevel;
if Level = CurLevel then Exit;
Outline.SetLevel(Self, CurLevel, Level);
end;
procedure TOutlineNode.ChangeLevelBy(Value: TChangeRange);
begin
Level := Cardinal(Integer(Level) + Value);
end;
function TOutlineNode.GetDisplayWidth: Integer;
begin
Result := Outline.GetNodeDisplayWidth(Self);
end;
function TOutlineNode.HasVisibleParent: Boolean;
begin
Result := (Parent <> nil) and (Parent.Expanded);
end;
function TOutlineNode.GetVisibleParent: TOutlineNode;
begin
Result := Self;
while (Result.Parent <> nil) and not Result.Parent.Expanded do
Result := Result.Parent;
end;
function TOutlineNode.GetFullPath: string;
begin
if Parent <> nil then
if Parent.Parent <> nil then
Result := Parent.GetFullPath + Outline.ItemSeparator + Text
else
Result := Text
else Result := EmptyStr;
end;
function TOutlineNode.HasAsParent(Value: TOutlineNode): Boolean;
begin
if Self = Value then
Result := True
else if Parent <> nil then Result := Parent.HasAsParent(Value)
else Result := False;
end;
function TOutlineNode.GetTopItem: Longint;
var
Node: TOutlineNode;
begin
Result := 0;
if Parent = nil then Exit;
Node := Self;
while Node.Parent <> nil do
begin
if Node.Parent.Parent = nil then
Result := Node.FIndex;
Node := Node.Parent;
end;
end;
function TOutlineNode.getFirstChild: LongInt;
begin
if List.Count > 0 then Result := Items[0].Index
else Result := InvalidIndex;
end;
function TOutlineNode.GetLastChild: LongInt;
begin
if List.Count > 0 then Result := Items[List.Count - 1].Index
else Result := InvalidIndex;
end;
function TOutlineNode.GetNextChild(Value: LongInt): LongInt;
var
I: Integer;
begin
Result := InvalidIndex;
for I := 0 to List.Count - 1 do
begin
if Items[I].Index = Value then
begin
if I < List.Count - 1 then Result := Items[I + 1].Index;
Break;
end;
end;
end;
function TOutlineNode.GetPrevChild(Value: LongInt): LongInt;
var
I: Integer;
begin
Result := InvalidIndex;
for I := List.Count - 1 downto 0 do
begin
if Items[I].Index = Value then
begin
if I > 0 then Result := Items[I - 1].Index;
Break;
end;
end;
end;
procedure TOutlineNode.MoveTo(Destination: LongInt; AttachMode: TAttachMode);
begin
Outline.Move(Destination, Index, AttachMode);
end;
procedure TOutlineNode.FullExpand;
var
I: Integer;
begin
if HasItems then
begin
Expanded := True;
for I := 0 to List.Count - 1 do
Items[I].FullExpand;
end;
end;
function TOutlineNode.GetRowOfNode(TargetNode: TOutlineNode;
var RowCount: Longint): Boolean;
var
I: Integer;
begin
Inc(RowCount);
if TargetNode = Self then
begin
Result := True;
Exit;
end;
Result := False;
if not Expanded then Exit;
for I := 0 to List.Count - 1 do
begin
Result := Items[I].GetRowOfNode(TargetNode, RowCount);
if Result then Exit
end;
end;
function TOutlineNode.GetVisibleNode(TargetCount: LongInt): TOutlineNode;
var
I, J: Integer;
ExpandedCount, NodeCount, NodesParsed: LongInt;
Node: TOutlineNode;
Count: Integer;
begin
if TargetCount = 0 then
begin
Result := Self;
Exit;
end;
Result := nil;
Count := List.Count;
NodesParsed := 0;
{ Quick exit if we are lucky }
if ExpandCount = Count then
begin
Result := Items[TargetCount - 1];
Exit;
end;
I := 0;
while I <= Count - 1 do
begin
for J := I to Count - 1 do
if Items[J].Expanded then Break;
if J > I then
begin
if J - I >= TargetCount then
begin
Result := Items[I + TargetCount - 1];
Break;
end;
Dec(TargetCount, J - I);
end;
Node := Items[J];
NodeCount := Node.ExpandCount + 1;
ExpandedCount := NodeCount + J - I;
Inc(NodesParsed, ExpandedCount);
if NodeCount >= TargetCount then
begin
Result := Node.GetVisibleNode(Pred(TargetCount));
Break;
end
else if ExpandCount - NodesParsed = Count - (J + 1) then
begin
Result := Items[TargetCount - NodeCount + J];
Exit;
end
else begin
Dec(TargetCount, NodeCount);
I := J;
end;
Inc(I);
end;
if Result = nil then Error(SOutlineIndexError);
end;
function TOutlineNode.GetNodeAtIndex(TargetIndex: LongInt): TOutlineNode;
var
I: Integer;
Node: TOutlineNode;
Lower: Integer;
Upper: Integer;
function RecurseNode: TOutlineNode;
begin
if Node.Index = TargetIndex then
Result := Node
else
Result := Node.GetNodeAtIndex(TargetIndex);
end;
begin
if TargetIndex = Index then
begin
Result := Self;
Exit;
end;
Lower := 0;
Upper := List.Count - 1;
Result := nil;
while Upper >= Lower do
begin
I := (Lower + Upper) div 2;
Node := Items[I];
if Lower = Upper then
begin
Result := RecurseNode;
Break;
end
else if Node.Index > TargetIndex then Upper := Pred(I)
else if (Node.Index < TargetIndex) and (I < Upper) and
(Items[I + 1].Index <= TargetIndex) then Lower := Succ(I)
else begin
Result := RecurseNode;
Break;
end;
end;
if Result = nil then Raise OutlineError.Create;
end;
function TOutlineNode.GetDataItem(Value: Pointer): LongInt;
var
I: Integer;
begin
if Value = Data then
begin
Result := Index;
Exit;
end;
Result := 0;
for I := 0 to List.Count - 1 do
begin
Result := Items[I].GetDataItem(Value);
if Result <> 0 then Break;
end;
end;
function TOutlineNode.GetTextItem(const Value: string): LongInt;
var
I: Integer;
begin
if Value = Text then
begin
Result := Index;
Exit;
end;
Result := 0;
for I := 0 to List.Count - 1 do
begin
Result := Items[I].GetTextItem(Value);
if Result <> 0 then Break;
end;
end;
procedure TOutlineNode.Expand;
begin
Expanded := True;
end;
procedure TOutlineNode.Collapse;
begin
Expanded := False;
end;
procedure TOutlineNode.SetExpandedState(Value: Boolean);
var
ParentNode: TOutlineNode;
begin
if FState <> Value then
begin
if Value then
begin
ParentNode := Self.Parent;
while ParentNode <> nil do
begin
if not ParentNode.Expanded then Error(SOutlineExpandError);
ParentNode := ParentNode.Parent;
end;
Outline.Expand(Index);
FState := True;
ChangeExpandedCount(List.Count);
end
else begin
CloseNode;
if List.Count > 0 then ChangeExpandedCount(-List.Count);
if Outline.ResizeGrid then Outline.Invalidate;
Outline.Collapse(Index);
FState := False;
end;
SetHorzScrollBar;
Repaint;
end;
end;
procedure TOutlineNode.CloseNode;
var
I: Integer;
begin
for I := 0 to List.Count - 1 do
Items[I].CloseNode;
if List.Count > 0 then ChangeExpandedCount(-List.Count);
FState := False;
end;
procedure TOutlineNode.Repaint;
begin
if Outline <> nil then
if Outline.ResizeGrid then Outline.Invalidate;
end;
procedure TOutlineNode.SetGoodIndex;
var
StartNode: TOutlineNode;
ParentNode: TOutlineNode;
begin
StartNode := Outline.SetGoodIndex(Self);
ParentNode := StartNode.Parent;
if ParentNode <> nil then
ParentNode.ReIndex(StartNode, Self, StartNode.FIndex, True)
else if Self <> Outline.FRootNode then
FIndex := Succ(StartNode.FIndex);
Outline.FGoodNode := Self;
end;
function TOutlineNode.AddNode(Value: TOutlineNode): LongInt;
begin
List.Add(Value);
Value.FParent := Self;
ChangeExpandedCount(Value.ExpandCount + 1);
if not Outline.FBlockInsert then Value.SetGoodIndex;
with Value do
begin
Result := FIndex;
SetHorzScrollBar;
end;
end;
function TOutlineNode.InsertNode(Index: LongInt; Value: TOutlineNode): LongInt;
var
CurIndex: LongInt;
I: Integer;
begin
for I := 0 to List.Count - 1 do
begin
CurIndex := Items[I].FIndex;
if CurIndex = Index then
begin
List.Insert(I, Value);
Value.FParent := Self;
Break;
end;
end;
ChangeExpandedCount(Value.ExpandCount + 1);
if not Outline.FBlockInsert then Value.SetGoodIndex;
with Value do
begin
Result := FIndex;
SetHorzScrollBar;
end;
end;
procedure TOutlineNode.InternalRemove(Value: TOutlineNode; Index: Integer);
begin
if Index <> 0 then
Outline.SetGoodIndex(Items[Index - 1]) else
Outline.SetGoodIndex(Self);
List.Delete(Index);
ChangeExpandedCount(-(Value.ExpandCount + 1));
if (List.Count = 0) and (Parent <> nil) then Expanded := False;
SetHorzScrollBar;
end;
procedure TOutlineNode.Remove(Value: TOutlineNode);
begin
InternalRemove(Value, List.IndexOf(Value));
end;
procedure TOutlineNode.ReIndex(StartNode, EndNode: TOutlineNode;
NewIndex: LongInt; IncludeStart: Boolean);
var
I: Integer;
begin
for I := List.IndexOf(StartNode) to List.Count - 1 do
begin
if IncludeStart then
begin
if Items[I].Resync(NewIndex, EndNode) then Exit;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -