709 lines
13 KiB
Ucode
709 lines
13 KiB
Ucode
//==============================================================================
|
|
// Created on: 10/21/2003
|
|
// File System Object
|
|
//
|
|
// Written by Ron Prestenback
|
|
// © 2003, Epic Games, Inc. All Rights Reserved
|
|
//==============================================================================
|
|
class StreamDirectoryNode extends StreamBase
|
|
within DirectoryTreeList;
|
|
|
|
var() StreamDirectoryNode Parent;
|
|
var() editconst editinline array<StreamDirectoryNode> Children;
|
|
var() editconst editinline array<string> Contents;
|
|
|
|
var() private int NodeRenderCost, ChildRenderCost;
|
|
var() editconst private string MyPath;
|
|
var() editconst private string DirectoryName;
|
|
var() private bool bExpanded;
|
|
var() private bool bInitialized;
|
|
|
|
function InitializeNode()
|
|
{
|
|
if ( Initialized() )
|
|
return;
|
|
|
|
Clear();
|
|
bInitialized = True;
|
|
|
|
// Maybe root
|
|
if ( Parent == None || MyPath == "" || MyPath == ".." )
|
|
return;
|
|
|
|
if ( bSimpleFileBrowsing )
|
|
AddChild("..").InitializeNode();
|
|
|
|
RefreshNodeContents();
|
|
}
|
|
|
|
function RefreshNodeContents()
|
|
{
|
|
local int i;
|
|
local array<string> Directories, Files;
|
|
|
|
if ( FileManager == None )
|
|
{
|
|
log("Cannot refresh node '"$MyPath$"' contents - File Manager not set.",'MusicPlayer');
|
|
return;
|
|
}
|
|
|
|
if ( HasChildren() )
|
|
{
|
|
for ( i = Children.Length - 1; i >= 0; i-- )
|
|
if ( Children[i].GetPath() != ".." )
|
|
Children.Remove(i,1);
|
|
}
|
|
|
|
Contents.Remove(0, Contents.Length);
|
|
|
|
FileManager.GetDirectoryContents( Directories, MyPath, FILE_Directory );
|
|
for ( i = 0; i < Directories.Length; i++ )
|
|
AddChild(Directories[i]);
|
|
|
|
FileManager.GetDirectoryContents( Files, MyPath, FILE_Stream );
|
|
FileManager.GetDirectoryContents( Files, MyPath, FILE_Playlist );
|
|
for ( i = 0; i < Files.Length; i++ )
|
|
AddContent(Files[i]);
|
|
|
|
UpdateCost();
|
|
}
|
|
|
|
function Clear( optional bool bPropagate )
|
|
{
|
|
local int i;
|
|
|
|
// log(GetName()@"Clear");
|
|
if ( HasChildren() && bPropagate )
|
|
{
|
|
for ( i = 0; i < Children.Length; i++ )
|
|
Children[i].Clear(bPropagate);
|
|
}
|
|
|
|
Children.Remove(0, Children.Length);
|
|
Contents.Remove(0, Contents.Length);
|
|
UpdateCost();
|
|
|
|
bInitialized = False;
|
|
}
|
|
|
|
function string GetIndent()
|
|
{
|
|
local string Indent;
|
|
|
|
if ( bSimpleFileBrowsing )
|
|
return "";
|
|
|
|
if ( Parent != None )
|
|
Indent = Parent.GetIndent() $ " ";
|
|
|
|
return Indent;
|
|
}
|
|
|
|
function string GetNodePrefix( bool bNoPrefix )
|
|
{
|
|
if ( bNoPrefix )
|
|
return "";
|
|
|
|
if ( IsEmpty() )
|
|
return GetIndent() $ ". ";
|
|
|
|
if ( !IsOpen() )
|
|
return GetIndent() $ "+ ";
|
|
|
|
return GetIndent() $ "- ";
|
|
}
|
|
|
|
function string NodeText( int VisibleIndex, optional bool bNoPrefix )
|
|
{
|
|
local StreamDirectoryNode Node;
|
|
|
|
if ( !IsOpen() )
|
|
return GetNodePrefix(bNoPrefix) $ DirectoryName;
|
|
|
|
Node = FindVisibleNode(VisibleIndex);
|
|
if ( Node == Self )
|
|
{
|
|
if ( VisibleIndex >= 0 && VisibleIndex < Contents.Length )
|
|
return Contents[VisibleIndex];
|
|
|
|
return GetNodePrefix(bNoPrefix) $ DirectoryName;
|
|
}
|
|
|
|
return Node.NodeText(VisibleIndex,bNoPrefix);
|
|
}
|
|
|
|
function StreamDirectoryNode FindVisibleNode( out int idx )
|
|
{
|
|
local int count, i;
|
|
|
|
if ( !IsOpen() )
|
|
return Self;
|
|
|
|
InitializeNode();
|
|
if ( idx > 0 )
|
|
{
|
|
count = Children[0].Cost();
|
|
if ( HasChildren() )
|
|
{
|
|
while ( count <= idx && ++i < Children.Length )
|
|
count += Children[i].Cost();
|
|
}
|
|
|
|
if ( i == Children.Length || !HasChildren() )
|
|
{
|
|
idx -= count;
|
|
return Self;
|
|
}
|
|
|
|
idx = count - idx;
|
|
}
|
|
|
|
return Children[i].FindVisibleNode( idx );
|
|
}
|
|
|
|
function int FindVisibleNodeIndex( string Path )
|
|
{
|
|
local int i, VisibleIndex;
|
|
local string MyComponent;
|
|
|
|
if ( Path == "" )
|
|
return 1;
|
|
|
|
InitializeNode();
|
|
MyComponent = StripPathComponent(Path);
|
|
if ( MyComponent == "" )
|
|
MyComponent = Path;
|
|
|
|
VisibleIndex = 1;
|
|
for ( i = 0; i < Children.Length; i++ )
|
|
{
|
|
if ( CompareNames(MyComponent, Children[i].GetName()) )
|
|
return VisibleIndex + Children[i].FindVisibleNodeIndex(Path);
|
|
|
|
VisibleIndex += Children[i].Cost();
|
|
}
|
|
|
|
for ( i = 0; i < Contents.Length; i++ )
|
|
{
|
|
if ( CompareNames(MyComponent, Contents[i]) )
|
|
break;
|
|
|
|
VisibleIndex++;
|
|
}
|
|
|
|
return VisibleIndex;
|
|
}
|
|
|
|
function int Cost()
|
|
{
|
|
return NodeRenderCost + ChildRenderCost;
|
|
}
|
|
|
|
function UpdateCost( optional bool bFullUpdate )
|
|
{
|
|
local int i;
|
|
|
|
NodeRenderCost = 0;
|
|
ChildRenderCost = 0;
|
|
|
|
if ( !IsOpen() )
|
|
NodeRenderCost = 1;
|
|
|
|
else
|
|
{
|
|
if ( !bSimpleFileBrowsing )
|
|
NodeRenderCost = 1;
|
|
|
|
for ( i = 0; i < Children.Length; i++ )
|
|
{
|
|
if ( bFullUpdate )
|
|
Children[i].UpdateCost( bFullUpdate );
|
|
|
|
ChildRenderCost += Children[i].Cost();
|
|
}
|
|
|
|
NodeRenderCost += Contents.Length;
|
|
}
|
|
}
|
|
|
|
function Toggle()
|
|
{
|
|
if ( IsOpen() )
|
|
Collapse();
|
|
|
|
else Expand();
|
|
}
|
|
|
|
function Expand( optional bool bFullUpdate )
|
|
{
|
|
InitializeNode();
|
|
|
|
bExpanded = True;
|
|
UpdateCost(bFullUpdate);
|
|
}
|
|
|
|
function Collapse( optional bool bFullUpdate )
|
|
{
|
|
InitializeNode();
|
|
|
|
bExpanded = False;
|
|
UpdateCost(bFullUpdate);
|
|
}
|
|
|
|
function bool ChangeDirectory( string Path, out StreamDirectoryNode Node, optional bool bRefreshContents )
|
|
{
|
|
local int i;
|
|
local string MyComponent;
|
|
|
|
InitializeNode();
|
|
|
|
// log(GetName()@"ChangeDirectory to '"$Path$"'",'MusicPlayer');
|
|
if ( Path == "" || Path == "." )
|
|
{
|
|
if ( bRefreshContents && Initialized() )
|
|
RefreshNodeContents();
|
|
|
|
if ( IsEmpty() )
|
|
{
|
|
Node = None;
|
|
return false;
|
|
}
|
|
|
|
Expand();
|
|
Node = Self;
|
|
return true;
|
|
}
|
|
|
|
if ( Path == ".." )
|
|
{
|
|
if ( Parent == None )
|
|
{
|
|
Expand();
|
|
Node = Self;
|
|
return true;
|
|
}
|
|
|
|
Collapse();
|
|
return Parent.ChangeDirectory("",Node,bRefreshContents);
|
|
}
|
|
|
|
MyComponent = StripPathComponent(Path);
|
|
if ( MyComponent == "" )
|
|
{
|
|
MyComponent = Path;
|
|
Path = "";
|
|
}
|
|
|
|
i = FindChildIndex(MyComponent);
|
|
if ( Valid(i) )
|
|
{
|
|
if ( Children[i].ChangeDirectory(Path, Node, bRefreshContents) )
|
|
{
|
|
Collapse();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
Node = None;
|
|
return false;
|
|
}
|
|
|
|
function bool ExpandPath( string Path )
|
|
{
|
|
local int i, idx;
|
|
local string s;
|
|
|
|
InitializeNode();
|
|
if ( Path == "" )
|
|
{
|
|
Expand();
|
|
return true;
|
|
}
|
|
|
|
s = StripPathComponent(Path);
|
|
if ( s == "" )
|
|
s = Path;
|
|
|
|
if ( s != "" )
|
|
{
|
|
idx = FindChildIndex(s);
|
|
if ( Valid(idx) )
|
|
{
|
|
for ( i = 0; i < Children.Length; i++ )
|
|
{
|
|
if ( Children[i] != Children[idx] )
|
|
Children[i].Collapse();
|
|
}
|
|
|
|
if ( Path != "" )
|
|
Children[idx].ExpandPath(Path);
|
|
}
|
|
|
|
Expand();
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function StreamDirectoryNode AddChild( string ChildName )
|
|
{
|
|
local int i;
|
|
local string s;
|
|
local StreamDirectoryNode Child;
|
|
|
|
if ( ChildName == "" )
|
|
return None;
|
|
|
|
InitializeNode();
|
|
|
|
// log(DirectoryName@"adding directory:"@ChildName,'MusicPlayer');
|
|
while ( i < Children.Length )
|
|
{
|
|
s = Children[i].GetName();
|
|
if ( CompareNames(s, ChildName) )
|
|
return Children[i];
|
|
|
|
if ( ChildName < s )
|
|
break;
|
|
|
|
i++;
|
|
}
|
|
|
|
Child = CreateChild(ChildName);
|
|
if ( Child == None )
|
|
{
|
|
log(GetName()@"failed to successfully create child '"$ChildName$"'",'MusicPlayer');
|
|
return None;
|
|
}
|
|
|
|
Children.Insert( i, 1 );
|
|
Children[i] = Child;
|
|
UpdateCost();
|
|
|
|
return Child;
|
|
}
|
|
|
|
function bool AddContent( string ContentName )
|
|
{
|
|
local int i;
|
|
local string s;
|
|
|
|
if ( ContentName == "" )
|
|
return false;
|
|
|
|
InitializeNode();
|
|
|
|
s = StripPathComponent(ContentName);
|
|
if ( s != "" )
|
|
{
|
|
i = FindChildIndex(s);
|
|
if ( Valid(i) )
|
|
return Children[i].AddContent(ContentName);
|
|
|
|
return false;
|
|
}
|
|
|
|
i = FindFileIndex(ContentName);
|
|
if ( i == -1 )
|
|
Contents[Contents.Length] = ContentName;
|
|
|
|
return true;
|
|
}
|
|
|
|
function bool RemoveChild( StreamDirectoryNode Child )
|
|
{
|
|
local int i;
|
|
|
|
if ( Child == None )
|
|
return false;
|
|
|
|
InitializeNode();
|
|
i = FindChildIndex(Child.GetName());
|
|
return RemoveChildAt(i);
|
|
}
|
|
|
|
function bool RemoveChildAt( int i )
|
|
{
|
|
if ( Valid(i) )
|
|
{
|
|
Children.Remove(i,1);
|
|
UpdateCost(True);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function bool RemoveContent( string Path )
|
|
{
|
|
local string s;
|
|
local int i;
|
|
|
|
InitializeNode();
|
|
|
|
s = StripPathComponent(Path);
|
|
if ( s != "" )
|
|
{
|
|
i = FindChildIndex(s);
|
|
if ( Valid(i) )
|
|
return Children[i].RemoveContent(Path);
|
|
|
|
return false;
|
|
}
|
|
|
|
i = FindFileIndex(Path);
|
|
return RemoveContentAt(i);
|
|
}
|
|
|
|
function bool RemoveContentAt( int i )
|
|
{
|
|
if ( ValidFile(i) )
|
|
{
|
|
Contents.Remove(i,1);
|
|
UpdateCost(True);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function int FindFileIndex( string FileName )
|
|
{
|
|
local int i;
|
|
|
|
if ( FileName == "" )
|
|
return -1;
|
|
|
|
InitializeNode();
|
|
|
|
for ( i = 0; i < Contents.Length; i++ )
|
|
if ( CompareNames(Contents[i], FileName) )
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
function bool SetName( string InName )
|
|
{
|
|
if ( InName == "" )
|
|
return false;
|
|
|
|
DirectoryName = InName;
|
|
return true;
|
|
}
|
|
|
|
function bool SetParent( StreamDirectoryNode InParent )
|
|
{
|
|
if ( InParent == None || Parent != None )
|
|
return false;
|
|
|
|
Parent = InParent;
|
|
return true;
|
|
}
|
|
|
|
function bool SetPath( string InPath )
|
|
{
|
|
if ( MyPath != "" )
|
|
return false;
|
|
|
|
if ( DirectoryName == ".." )
|
|
{
|
|
MyPath = DirectoryName;
|
|
return true;
|
|
}
|
|
|
|
MyPath = InPath $ DirectoryName $ GetPathSeparator();
|
|
return true;
|
|
}
|
|
|
|
function bool Initialized()
|
|
{
|
|
return bInitialized;
|
|
}
|
|
|
|
function bool IsEmpty()
|
|
{
|
|
return Initialized() && !HasChildren() && Contents.Length == 0;
|
|
}
|
|
|
|
function bool IsOpen()
|
|
{
|
|
return bExpanded;
|
|
}
|
|
|
|
function string GetName()
|
|
{
|
|
return DirectoryName;
|
|
}
|
|
|
|
function string GetPath()
|
|
{
|
|
return MyPath;
|
|
}
|
|
|
|
function StreamDirectoryNode FindChildByPath( out string Path )
|
|
{
|
|
local string ChildName;
|
|
local int i;
|
|
|
|
InitializeNode();
|
|
if ( Path == "" )
|
|
return Self;
|
|
|
|
ChildName = StripPathComponent(Path);
|
|
if ( ChildName == "" )
|
|
return Self;
|
|
|
|
i = FindChildIndex(ChildName);
|
|
if ( Valid(i) )
|
|
return Children[i].FindChildByPath(Path);
|
|
|
|
return None;
|
|
}
|
|
|
|
function StreamDirectoryNode FindChild( string ChildName, optional bool bDeepSearch )
|
|
{
|
|
local int i;
|
|
local StreamDirectoryNode Node;
|
|
|
|
InitializeNode();
|
|
for ( i = 0; i < Children.Length; i++ )
|
|
{
|
|
if ( CompareNames(Children[i].GetName(), ChildName) )
|
|
return Children[i];
|
|
|
|
if ( bDeepSearch )
|
|
{
|
|
Node = Children[i].FindChild(ChildName, bDeepSearch);
|
|
if ( Node != None )
|
|
return Node;
|
|
}
|
|
}
|
|
|
|
return None;
|
|
}
|
|
|
|
function int FindChildIndex( string ChildName )
|
|
{
|
|
local int i;
|
|
|
|
if ( ChildName == "" )
|
|
return -1;
|
|
|
|
InitializeNode();
|
|
|
|
// log(GetName()@"FindChildIndex ChildName '"$ChildName$"'",'MusicPlayer');
|
|
if ( Right(ChildName,1) == GetPathSeparator() )
|
|
ChildName = Left(ChildName, Len(ChildName) - 1);
|
|
|
|
for ( i = 0; i < Children.Length; i++ )
|
|
if ( CompareNames(Children[i].GetName(), ChildName) )
|
|
return i;
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
function bool HasChildren()
|
|
{
|
|
if ( bSimpleFileBrowsing )
|
|
return Children.Length > 1;
|
|
|
|
return Children.Length > 0;
|
|
}
|
|
|
|
function bool Valid( int i )
|
|
{
|
|
return i >= 0 && i < Children.Length && Children[i] != None;
|
|
}
|
|
|
|
function bool ValidFile( int i )
|
|
{
|
|
return i >= 0 && i < Contents.Length;
|
|
}
|
|
|
|
// =====================================================================================================================
|
|
//
|
|
// Internal
|
|
//
|
|
// =====================================================================================================================
|
|
|
|
protected function StreamDirectoryNode CreateChild( string ChildName )
|
|
{
|
|
local StreamDirectoryNode Child;
|
|
|
|
if ( ChildName == "" )
|
|
return None;
|
|
|
|
Child = new(Outer) class'GUI2K4.StreamDirectoryNode';
|
|
Assert(Child != None);
|
|
|
|
Child.SetParent( Self );
|
|
Child.SetName( ChildName );
|
|
Child.SetPath( MyPath );
|
|
return Child;
|
|
}
|
|
|
|
static function string StripPathComponent( out string Path )
|
|
{
|
|
local string s;
|
|
local int i;
|
|
|
|
if ( Path == "" )
|
|
return "";
|
|
|
|
i = InStr(Path, GetPathSeparator());
|
|
if ( i == -1 )
|
|
return "";
|
|
|
|
s = Left(Path,i);
|
|
Path = Mid(Path,i+1);
|
|
return s;
|
|
}
|
|
|
|
function bool HandleDebugExec( string Command, string Param )
|
|
{
|
|
local int i;
|
|
local StreamDirectoryNode Node;
|
|
|
|
switch ( Command )
|
|
{
|
|
case "cwd":
|
|
log("Current Directory:"$GetPath(),'MusicPlayer');
|
|
return true;
|
|
|
|
case "dumpcwd":
|
|
log("Dumping directory contents for"@GetName(),'MusicPlayer');
|
|
for ( i = 0; i < Children.Length; i++ )
|
|
log(" Child "$i@"'"$Children[i].GetName()$"'",'MusicPlayer');
|
|
for ( i = 0; i < Contents.Length; i++ )
|
|
log(" Content "$i@"'"$Contents[i]$"'",'MusicPlayer');
|
|
|
|
return true;
|
|
|
|
case "cost":
|
|
if ( Param == "" )
|
|
Node = Self;
|
|
else
|
|
{
|
|
Node = FindChild(Param);
|
|
if ( Node == None )
|
|
{
|
|
log("Couldn't find child '"$Param$"' in directory"@GetName(),'MusicPlayer');
|
|
return true;
|
|
}
|
|
}
|
|
|
|
log("Cost for directory '"$Node.GetName()$"': "$Node.Cost()@"Open:"$Node.IsOpen()@"Initialized:"$Node.Initialized(),'MusicPlayer');
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
DefaultProperties
|
|
{
|
|
NodeRenderCost=1
|
|
}
|