mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-23 19:34:15 +08:00
virtual file system preliminary implementation.
This commit is contained in:
parent
47b3d6adf0
commit
9d1d320cd2
105
App.xaml.cs
105
App.xaml.cs
@ -49,16 +49,6 @@ namespace GARbro.GUI
|
||||
/// </summary>
|
||||
public string InitPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the currently open archive, or empty string if none.
|
||||
/// </summary>
|
||||
public string CurrentPath { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Archive file being browsed, or null.
|
||||
/// </summary>
|
||||
public ArcFile CurrentArchive { get; private set; }
|
||||
|
||||
void ApplicationStartup (object sender, StartupEventArgs e)
|
||||
{
|
||||
#if DEBUG
|
||||
@ -90,106 +80,11 @@ namespace GARbro.GUI
|
||||
|
||||
if (string.IsNullOrEmpty (InitPath))
|
||||
InitPath = Directory.GetCurrentDirectory();
|
||||
|
||||
CurrentPath = "";
|
||||
}
|
||||
|
||||
void ApplicationExit (object sender, ExitEventArgs e)
|
||||
{
|
||||
Settings.Default.Save();
|
||||
}
|
||||
|
||||
public ICollection<Entry> GetDirectoryList (string path)
|
||||
{
|
||||
var info = new DirectoryInfo (path);
|
||||
var list = new List<Entry>();
|
||||
foreach (var subdir in info.EnumerateDirectories())
|
||||
{
|
||||
if (0 != (subdir.Attributes & (FileAttributes.Hidden | FileAttributes.System)))
|
||||
continue;
|
||||
list.Add (new SubDirEntry (subdir.Name));
|
||||
}
|
||||
foreach (var file in info.EnumerateFiles())
|
||||
{
|
||||
if (0 != (file.Attributes & (FileAttributes.System)))
|
||||
continue;
|
||||
var entry = FormatCatalog.Instance.Create<Entry> (file.Name);
|
||||
entry.Size = (uint)Math.Min (file.Length, uint.MaxValue);
|
||||
list.Add (entry);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public ArcFile GetArchive (string path)
|
||||
{
|
||||
if (path.Equals (CurrentPath, StringIgnoreCase))
|
||||
return CurrentArchive;
|
||||
FormatCatalog.Instance.LastError = null;
|
||||
var arc = ArcFile.TryOpen (path);
|
||||
if (null == arc)
|
||||
{
|
||||
if (null != FormatCatalog.Instance.LastError)
|
||||
throw FormatCatalog.Instance.LastError;
|
||||
throw new UnknownFormatException();
|
||||
}
|
||||
if (null != CurrentArchive)
|
||||
CurrentArchive.Dispose();
|
||||
CurrentPath = path;
|
||||
CurrentArchive = arc;
|
||||
return CurrentArchive;
|
||||
}
|
||||
|
||||
public void ResetCache ()
|
||||
{
|
||||
if (null != CurrentArchive)
|
||||
CurrentArchive.Dispose();
|
||||
CurrentArchive = null;
|
||||
CurrentPath = "";
|
||||
}
|
||||
|
||||
// Update UI on demand.
|
||||
|
||||
private static DispatcherOperationCallback exitFrameCallback =
|
||||
new DispatcherOperationCallback(ExitFrame);
|
||||
|
||||
/// <summary>
|
||||
/// Processes all UI messages currently in the message queue.
|
||||
/// </summary>
|
||||
public static void DoEvents()
|
||||
{
|
||||
// Create new nested message pump.
|
||||
DispatcherFrame nestedFrame = new DispatcherFrame();
|
||||
|
||||
// Dispatch a callback to the current message queue, when getting called,
|
||||
// this callback will end the nested message loop.
|
||||
// note that the priority of this callback should be lower than the that of UI event messages.
|
||||
DispatcherOperation exitOperation = Dispatcher.CurrentDispatcher.BeginInvoke(
|
||||
DispatcherPriority.Background, exitFrameCallback, nestedFrame);
|
||||
|
||||
// pump the nested message loop, the nested message loop will
|
||||
// immediately process the messages left inside the message queue.
|
||||
Dispatcher.PushFrame(nestedFrame);
|
||||
|
||||
// If the "exitFrame" callback doesn't get finished, Abort it.
|
||||
if (exitOperation.Status != DispatcherOperationStatus.Completed)
|
||||
exitOperation.Abort();
|
||||
}
|
||||
|
||||
static Object ExitFrame(Object state)
|
||||
{
|
||||
DispatcherFrame frame = state as DispatcherFrame;
|
||||
|
||||
// Exit the nested message loop.
|
||||
frame.Continue = false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class UnknownFormatException : Exception
|
||||
{
|
||||
public UnknownFormatException () : base (guiStrings.MsgUnknownFormat) { }
|
||||
public UnknownFormatException (string path)
|
||||
: base (string.Format ("{1}: {0}", guiStrings.MsgUnknownFormat, path))
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion ("1.1.10.422")]
|
||||
[assembly: AssemblyFileVersion ("1.1.10.422")]
|
||||
[assembly: AssemblyVersion ("1.1.12.423")]
|
||||
[assembly: AssemblyFileVersion ("1.1.12.423")]
|
||||
|
25
GARbro.sln
25
GARbro.sln
@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GARbro.Console", "Console\GARbro.Console.csproj", "{B966F292-431A-4D8A-A1D3-1EB45048A1D2}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
@ -17,9 +17,6 @@ EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameRes", "GameRes\GameRes.csproj", "{453C087F-E416-4AE9-8C03-D8760DA0574B}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GARbro.GUI", "GARbro.GUI.csproj", "{2935BE57-C4E0-43E7-86DE-C1848C820B19}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4} = {A8865685-27CC-427B-AC38-E48D2AD05DF4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Image.Convert", "Image.Convert\Image.Convert.csproj", "{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
@ -32,26 +29,22 @@ Global
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -49,8 +49,6 @@ namespace GameRes
|
||||
/// <summary>Archive contents.</summary>
|
||||
public ICollection<Entry> Dir { get { return m_dir; } }
|
||||
|
||||
public event EventHandler<OverwriteEventArgs> OverwriteNotify;
|
||||
|
||||
public ArcFile (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir)
|
||||
{
|
||||
m_arc = arc;
|
||||
@ -66,11 +64,11 @@ namespace GameRes
|
||||
/// </returns>
|
||||
public static ArcFile TryOpen (string filename)
|
||||
{
|
||||
var info = new FileInfo (filename);
|
||||
if (info.Length < 4)
|
||||
var entry = VFS.FindFile (filename);
|
||||
if (entry.Size < 4)
|
||||
return null;
|
||||
var ext = new Lazy<string> (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant());
|
||||
var file = new ArcView (filename);
|
||||
var file = VFS.OpenView (entry);
|
||||
try
|
||||
{
|
||||
uint signature = file.View.ReadUInt32 (0);
|
||||
@ -191,15 +189,6 @@ namespace GameRes
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create file corresponding to <paramref name="entry"/> within current directory and open
|
||||
/// it for writing.
|
||||
/// </summary>
|
||||
public Stream CreateFile (Entry entry)
|
||||
{
|
||||
return ArchiveFormat.CreateFile (entry.Name);
|
||||
}
|
||||
|
||||
public IFileSystem CreateFileSystem ()
|
||||
{
|
||||
if (m_interface.IsHierarchic)
|
||||
@ -229,98 +218,4 @@ namespace GameRes
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class OverwriteEventArgs : EventArgs
|
||||
{
|
||||
public string Filename { get; set; }
|
||||
public bool Overwrite { get; set; }
|
||||
}
|
||||
|
||||
public class AppendStream : System.IO.Stream
|
||||
{
|
||||
private Stream m_base;
|
||||
private long m_start_pos;
|
||||
|
||||
public override bool CanRead { get { return true; } }
|
||||
public override bool CanSeek { get { return true; } }
|
||||
public override bool CanWrite { get { return true; } }
|
||||
public override long Length { get { return m_base.Length - m_start_pos; } }
|
||||
public override long Position
|
||||
{
|
||||
get { return m_base.Position - m_start_pos; }
|
||||
set { m_base.Position = Math.Max (m_start_pos+value, m_start_pos); }
|
||||
}
|
||||
|
||||
public AppendStream (System.IO.Stream file)
|
||||
{
|
||||
m_base = file;
|
||||
m_start_pos = m_base.Seek (0, SeekOrigin.End);
|
||||
}
|
||||
|
||||
public AppendStream (System.IO.Stream file, long offset)
|
||||
{
|
||||
m_base = file;
|
||||
m_start_pos = m_base.Seek (offset, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
public Stream BaseStream { get { return m_base; } }
|
||||
|
||||
public override void Flush()
|
||||
{
|
||||
m_base.Flush();
|
||||
}
|
||||
|
||||
public override long Seek (long offset, SeekOrigin origin)
|
||||
{
|
||||
if (SeekOrigin.Begin == origin)
|
||||
{
|
||||
offset = Math.Max (offset + m_start_pos, m_start_pos);
|
||||
}
|
||||
long position = m_base.Seek (offset, origin);
|
||||
if (position < m_start_pos)
|
||||
{
|
||||
m_base.Seek (m_start_pos, SeekOrigin.Begin);
|
||||
position = m_start_pos;
|
||||
}
|
||||
return position - m_start_pos;
|
||||
}
|
||||
|
||||
public override void SetLength (long length)
|
||||
{
|
||||
if (length < 0)
|
||||
length = 0;
|
||||
m_base.SetLength (length + m_start_pos);
|
||||
}
|
||||
|
||||
public override int Read (byte[] buffer, int offset, int count)
|
||||
{
|
||||
return m_base.Read (buffer, offset, count);
|
||||
}
|
||||
|
||||
public override int ReadByte ()
|
||||
{
|
||||
return m_base.ReadByte();
|
||||
}
|
||||
|
||||
public override void Write (byte[] buffer, int offset, int count)
|
||||
{
|
||||
m_base.Write (buffer, offset, count);
|
||||
}
|
||||
|
||||
public override void WriteByte (byte value)
|
||||
{
|
||||
m_base.WriteByte (value);
|
||||
}
|
||||
|
||||
bool disposed = false;
|
||||
protected override void Dispose (bool disposing)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
m_base = null;
|
||||
disposed = true;
|
||||
base.Dispose (disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,16 +28,28 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using GameRes.Strings;
|
||||
|
||||
namespace GameRes
|
||||
{
|
||||
public interface IFileSystem : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Open file for reading.
|
||||
/// Returns entry corresponding to the given filename within filesystem.
|
||||
/// </summary>
|
||||
/// <exception cref="FileNotFoundException">File is not found.</exception>
|
||||
Entry FindFile (string filename);
|
||||
|
||||
/// <summary>
|
||||
/// Open file for reading as stream.
|
||||
/// </summary>
|
||||
Stream OpenStream (Entry entry);
|
||||
|
||||
Stream OpenSeekableStream (Entry entry);
|
||||
|
||||
/// <summary>
|
||||
/// Open file for reading as memory-mapped view.
|
||||
/// </summary>
|
||||
ArcView OpenView (Entry entry);
|
||||
|
||||
/// <summary>
|
||||
@ -47,7 +59,7 @@ namespace GameRes
|
||||
|
||||
/// <summary>
|
||||
/// Recursively enumerates files in the current directory and its subdirectories.
|
||||
/// Subdirectory entries are omitted.
|
||||
/// Subdirectory entries are omitted from resulting set.
|
||||
/// </summary>
|
||||
IEnumerable<Entry> GetFilesRecursive ();
|
||||
|
||||
@ -73,6 +85,15 @@ namespace GameRes
|
||||
set { Directory.SetCurrentDirectory (value); }
|
||||
}
|
||||
|
||||
public Entry FindFile (string filename)
|
||||
{
|
||||
var attr = File.GetAttributes (filename);
|
||||
if ((attr & FileAttributes.Directory) == FileAttributes.Directory)
|
||||
return new SubDirEntry (filename);
|
||||
else
|
||||
return EntryFromFileInfo (new FileInfo (filename));
|
||||
}
|
||||
|
||||
public IEnumerable<Entry> GetFiles ()
|
||||
{
|
||||
var info = new DirectoryInfo (CurrentDirectory);
|
||||
@ -84,7 +105,7 @@ namespace GameRes
|
||||
}
|
||||
foreach (var file in info.EnumerateFiles())
|
||||
{
|
||||
if (0 != (file.Attributes & (FileAttributes.Hidden | FileAttributes.System)))
|
||||
if (0 != (file.Attributes & FileAttributes.System))
|
||||
continue;
|
||||
yield return EntryFromFileInfo (file);
|
||||
}
|
||||
@ -113,6 +134,11 @@ namespace GameRes
|
||||
return File.OpenRead (entry.Name);
|
||||
}
|
||||
|
||||
public Stream OpenSeekableStream (Entry entry)
|
||||
{
|
||||
return OpenStream (entry);
|
||||
}
|
||||
|
||||
public ArcView OpenView (Entry entry)
|
||||
{
|
||||
return new ArcView (entry.Name);
|
||||
@ -126,7 +152,10 @@ namespace GameRes
|
||||
|
||||
public class FlatArchiveFileSystem : IFileSystem
|
||||
{
|
||||
protected ArcFile m_arc;
|
||||
protected readonly ArcFile m_arc;
|
||||
protected readonly Dictionary<string, Entry> m_dir;
|
||||
|
||||
public ArcFile Source { get { return m_arc; } }
|
||||
|
||||
public virtual string CurrentDirectory
|
||||
{
|
||||
@ -146,6 +175,11 @@ namespace GameRes
|
||||
public FlatArchiveFileSystem (ArcFile arc)
|
||||
{
|
||||
m_arc = arc;
|
||||
m_dir = new Dictionary<string, Entry> (arc.Dir.Count, StringComparer.InvariantCultureIgnoreCase);
|
||||
foreach (var entry in arc.Dir)
|
||||
{
|
||||
m_dir.Add (entry.Name, entry);
|
||||
}
|
||||
}
|
||||
|
||||
public Stream OpenStream (Entry entry)
|
||||
@ -153,11 +187,24 @@ namespace GameRes
|
||||
return m_arc.OpenEntry (entry);
|
||||
}
|
||||
|
||||
public Stream OpenSeekableStream (Entry entry)
|
||||
{
|
||||
return m_arc.OpenSeekableEntry (entry);
|
||||
}
|
||||
|
||||
public ArcView OpenView (Entry entry)
|
||||
{
|
||||
return m_arc.OpenView (entry);
|
||||
}
|
||||
|
||||
public virtual Entry FindFile (string filename)
|
||||
{
|
||||
Entry entry = null;
|
||||
if (!m_dir.TryGetValue (filename, out entry))
|
||||
throw new FileNotFoundException();
|
||||
return entry;
|
||||
}
|
||||
|
||||
public virtual IEnumerable<Entry> GetFiles ()
|
||||
{
|
||||
return m_arc.Dir;
|
||||
@ -211,6 +258,16 @@ namespace GameRes
|
||||
set { ChDir (value); }
|
||||
}
|
||||
|
||||
public override Entry FindFile (string filename)
|
||||
{
|
||||
Entry entry = null;
|
||||
if (m_dir.TryGetValue (filename, out entry))
|
||||
return entry;
|
||||
if (m_dir.Keys.Any (n => n.StartsWith (filename + PathDelimiter)))
|
||||
return new SubDirEntry (filename);
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
static readonly Regex path_re = new Regex (@"\G[/\\]?([^/\\]+)([/\\])");
|
||||
|
||||
public override IEnumerable<Entry> GetFiles ()
|
||||
@ -300,4 +357,188 @@ namespace GameRes
|
||||
m_cwd = new_path;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FileSystemStack : IDisposable
|
||||
{
|
||||
Stack<IFileSystem> m_fs_stack = new Stack<IFileSystem>();
|
||||
Stack<string> m_arc_name_stack = new Stack<string>();
|
||||
|
||||
public IEnumerable<IFileSystem> All { get { return m_fs_stack; } }
|
||||
|
||||
public IFileSystem Top { get { return m_fs_stack.Peek(); } }
|
||||
public int Count { get { return m_fs_stack.Count; } }
|
||||
public IEnumerable<string> ArcStack { get { return m_arc_name_stack; } }
|
||||
|
||||
public ArcFile CurrentArchive { get; private set; }
|
||||
private IFileSystem LastVisitedArc { get; set; }
|
||||
private string LastVisitedPath { get; set; }
|
||||
|
||||
public FileSystemStack ()
|
||||
{
|
||||
m_fs_stack.Push (new PhysicalFileSystem());
|
||||
}
|
||||
|
||||
public void ChDir (Entry entry)
|
||||
{
|
||||
if (entry is SubDirEntry)
|
||||
{
|
||||
if (1 == m_fs_stack.Count)
|
||||
{
|
||||
Top.CurrentDirectory = entry.Name;
|
||||
return;
|
||||
}
|
||||
if (".." == entry.Name && string.IsNullOrEmpty (Top.CurrentDirectory))
|
||||
{
|
||||
Pop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (entry.Name == LastVisitedPath && null != LastVisitedArc)
|
||||
{
|
||||
Push (LastVisitedPath, LastVisitedArc);
|
||||
return;
|
||||
}
|
||||
Flush();
|
||||
var arc = ArcFile.TryOpen (entry.Name);
|
||||
if (null == arc)
|
||||
throw new UnknownFormatException();
|
||||
try
|
||||
{
|
||||
Push (entry.Name, arc.CreateFileSystem());
|
||||
CurrentArchive = arc;
|
||||
}
|
||||
catch
|
||||
{
|
||||
arc.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private void Push (string path, IFileSystem fs)
|
||||
{
|
||||
m_fs_stack.Push (fs);
|
||||
m_arc_name_stack.Push (path);
|
||||
}
|
||||
|
||||
private void Pop ()
|
||||
{
|
||||
if (m_fs_stack.Count > 1)
|
||||
{
|
||||
Flush();
|
||||
LastVisitedArc = m_fs_stack.Pop();
|
||||
LastVisitedPath = m_arc_name_stack.Pop();
|
||||
if (m_fs_stack.Count > 1 && m_fs_stack.Peek() is FlatArchiveFileSystem)
|
||||
CurrentArchive = (m_fs_stack.Peek() as FlatArchiveFileSystem).Source;
|
||||
else
|
||||
CurrentArchive = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Flush ()
|
||||
{
|
||||
if (LastVisitedArc != null)
|
||||
{
|
||||
LastVisitedArc.Dispose();
|
||||
LastVisitedArc = null;
|
||||
LastVisitedPath = null;
|
||||
}
|
||||
}
|
||||
|
||||
private bool _disposed = false;
|
||||
public void Dispose ()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
Flush();
|
||||
foreach (var fs in m_fs_stack.Reverse())
|
||||
fs.Dispose();
|
||||
_disposed = true;
|
||||
}
|
||||
GC.SuppressFinalize (this);
|
||||
}
|
||||
}
|
||||
|
||||
public static class VFS
|
||||
{
|
||||
private static FileSystemStack m_vfs = new FileSystemStack();
|
||||
|
||||
public static IFileSystem Top { get { return m_vfs.Top; } }
|
||||
public static bool IsVirtual { get { return m_vfs.Count > 1; } }
|
||||
public static int Count { get { return m_vfs.Count; } }
|
||||
|
||||
public static ArcFile CurrentArchive { get { return m_vfs.CurrentArchive; } }
|
||||
|
||||
private static string[] m_top_path = new string[1];
|
||||
|
||||
public static IEnumerable<string> FullPath
|
||||
{
|
||||
get
|
||||
{
|
||||
m_top_path[0] = Top.CurrentDirectory;
|
||||
if (1 == Count)
|
||||
return m_top_path;
|
||||
else
|
||||
return m_vfs.ArcStack.Concat (m_top_path);
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!value.Any())
|
||||
return;
|
||||
var new_vfs = new FileSystemStack();
|
||||
var desired = value.ToArray();
|
||||
for (int i = 0; i < desired.Length-1; ++i)
|
||||
new_vfs.ChDir (new_vfs.Top.FindFile (desired[i]));
|
||||
new_vfs.Top.CurrentDirectory = desired.Last();
|
||||
m_vfs.Dispose();
|
||||
m_vfs = new_vfs;
|
||||
}
|
||||
}
|
||||
|
||||
public static Entry FindFile (string filename)
|
||||
{
|
||||
if (".." == filename)
|
||||
return new SubDirEntry ("..");
|
||||
return m_vfs.Top.FindFile (filename);
|
||||
}
|
||||
|
||||
public static Stream OpenStream (Entry entry)
|
||||
{
|
||||
return m_vfs.Top.OpenStream (entry);
|
||||
}
|
||||
|
||||
public static Stream OpenSeekableStream (Entry entry)
|
||||
{
|
||||
return m_vfs.Top.OpenSeekableStream (entry);
|
||||
}
|
||||
|
||||
public static ArcView OpenView (Entry entry)
|
||||
{
|
||||
return m_vfs.Top.OpenView (entry);
|
||||
}
|
||||
|
||||
public static void ChDir (Entry entry)
|
||||
{
|
||||
m_vfs.ChDir (entry);
|
||||
}
|
||||
|
||||
public static void ChDir (string path)
|
||||
{
|
||||
m_vfs.ChDir (FindFile (path));
|
||||
}
|
||||
|
||||
public static void Flush ()
|
||||
{
|
||||
m_vfs.Flush();
|
||||
}
|
||||
|
||||
public static IEnumerable<Entry> GetFiles ()
|
||||
{
|
||||
return m_vfs.Top.GetFiles();
|
||||
}
|
||||
}
|
||||
|
||||
public class UnknownFormatException : FileFormatException
|
||||
{
|
||||
public UnknownFormatException () : base (garStrings.MsgUnknownFormat) { }
|
||||
}
|
||||
}
|
||||
|
@ -261,6 +261,12 @@ namespace GameRes
|
||||
public ResourceOptions Options { get; set; }
|
||||
}
|
||||
|
||||
public class OverwriteEventArgs : EventArgs
|
||||
{
|
||||
public string Filename { get; set; }
|
||||
public bool Overwrite { get; set; }
|
||||
}
|
||||
|
||||
public sealed class FormatCatalog
|
||||
{
|
||||
private static readonly FormatCatalog m_instance = new FormatCatalog();
|
||||
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion ("1.1.7.90")]
|
||||
[assembly: AssemblyFileVersion ("1.1.7.90")]
|
||||
[assembly: AssemblyVersion ("1.1.9.91")]
|
||||
[assembly: AssemblyFileVersion ("1.1.9.91")]
|
||||
|
11
GameRes/Strings/garStrings.Designer.cs
generated
11
GameRes/Strings/garStrings.Designer.cs
generated
@ -1,7 +1,7 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.18444
|
||||
// Runtime Version:4.0.30319.34209
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@ -104,5 +104,14 @@ namespace GameRes.Strings {
|
||||
return ResourceManager.GetString("MsgUnknownEncryption", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to file could not be opened as resource archive.
|
||||
/// </summary>
|
||||
public static string MsgUnknownFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgUnknownFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,4 +132,7 @@
|
||||
<data name="MsgUnknownEncryption" xml:space="preserve">
|
||||
<value>Unknown encryption scheme</value>
|
||||
</data>
|
||||
<data name="MsgUnknownFormat" xml:space="preserve">
|
||||
<value>file could not be opened as resource archive</value>
|
||||
</data>
|
||||
</root>
|
@ -132,4 +132,7 @@
|
||||
<data name="MsgUnknownEncryption" xml:space="preserve">
|
||||
<value>Неизвестный метод шифрования</value>
|
||||
</data>
|
||||
<data name="MsgUnknownFormat" xml:space="preserve">
|
||||
<value>файл не может быть открыт как архив ресурсов</value>
|
||||
</data>
|
||||
</root>
|
@ -68,7 +68,7 @@ namespace GARbro.GUI
|
||||
}
|
||||
try
|
||||
{
|
||||
Directory.SetCurrentDirectory (ViewModel.Path);
|
||||
Directory.SetCurrentDirectory (ViewModel.Path.First());
|
||||
var converter = new GarConvertMedia (this);
|
||||
converter.IgnoreErrors = convert_dialog.IgnoreErrors.IsChecked ?? false;
|
||||
converter.Convert (source, format);
|
||||
|
@ -34,6 +34,7 @@ using System.Windows.Input;
|
||||
using System.Windows.Media.Imaging;
|
||||
using Ookii.Dialogs.Wpf;
|
||||
using GameRes;
|
||||
using GameRes.Strings;
|
||||
using GARbro.GUI.Strings;
|
||||
using GARbro.GUI.Properties;
|
||||
|
||||
@ -58,11 +59,12 @@ namespace GARbro.GUI
|
||||
string destination = Settings.Default.appLastDestination;
|
||||
if (!Directory.Exists (destination))
|
||||
destination = "";
|
||||
if (!ViewModel.IsArchive)
|
||||
var vm = ViewModel;
|
||||
if (!vm.IsArchive)
|
||||
{
|
||||
if (!entry.IsDirectory)
|
||||
{
|
||||
var arc_dir = CurrentPath;
|
||||
var arc_dir = vm.Path.First();
|
||||
var source = Path.Combine (arc_dir, entry.Name);
|
||||
if (string.IsNullOrEmpty (destination))
|
||||
destination = arc_dir;
|
||||
@ -73,13 +75,13 @@ namespace GARbro.GUI
|
||||
extractor.ExtractAll (destination);
|
||||
}
|
||||
}
|
||||
else if (null != m_app.CurrentArchive)
|
||||
else if (vm.Path.Skip (1).Any())
|
||||
{
|
||||
var vm = ViewModel as ArchiveViewModel;
|
||||
if (string.IsNullOrEmpty (destination))
|
||||
destination = Path.GetDirectoryName (vm.Path);
|
||||
extractor = new GarExtract (this, vm.Path, m_app.CurrentArchive);
|
||||
if (null == entry || (entry.Name == ".." && vm.SubDir == "")) // root entry
|
||||
destination = Path.GetDirectoryName (vm.Path.First());
|
||||
var archive_name = vm.Path.Reverse().Skip (1).First();
|
||||
extractor = new GarExtract (this, archive_name, VFS.CurrentArchive);
|
||||
if (null == entry || (entry.Name == ".." && string.IsNullOrEmpty (vm.Path.Last()))) // root entry
|
||||
extractor.ExtractAll (destination);
|
||||
else
|
||||
extractor.Extract (entry, destination);
|
||||
@ -132,7 +134,7 @@ namespace GARbro.GUI
|
||||
if (FormatCatalog.Instance.LastError != null)
|
||||
error_message = FormatCatalog.Instance.LastError.Message;
|
||||
else
|
||||
error_message = guiStrings.MsgUnknownFormat;
|
||||
error_message = garStrings.MsgUnknownFormat;
|
||||
throw new OperationCanceledException (string.Format ("{1}: {0}", error_message, m_arc_name));
|
||||
}
|
||||
m_should_dispose = true;
|
||||
|
@ -75,14 +75,13 @@ namespace GARbro.GUI
|
||||
|
||||
class PreviewFile
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public IEnumerable<string> Path { get; set; }
|
||||
public string Name { get; set; }
|
||||
public Entry Entry { get; set; }
|
||||
public ArcFile Archive { get; set; }
|
||||
public Entry Entry { get; set; }
|
||||
|
||||
public bool IsEqual (string path, string name)
|
||||
public bool IsEqual (IEnumerable<string> path, string name)
|
||||
{
|
||||
return path.Equals (Path) && name.Equals (Name);
|
||||
return Path != null && path.SequenceEqual (Path) && name.Equals (Name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,8 +166,6 @@ namespace GARbro.GUI
|
||||
ActiveViewer = ImageView;
|
||||
return;
|
||||
}
|
||||
if (vm.IsArchive)
|
||||
m_current_preview.Archive = m_app.CurrentArchive;
|
||||
if ("image" != entry.Type)
|
||||
LoadPreviewText (m_current_preview);
|
||||
else if (!m_preview_worker.IsBusy)
|
||||
@ -193,15 +190,7 @@ namespace GARbro.GUI
|
||||
|
||||
Stream OpenPreviewStream (PreviewFile preview)
|
||||
{
|
||||
if (null == preview.Archive)
|
||||
{
|
||||
string filename = Path.Combine (preview.Path, preview.Name);
|
||||
return File.OpenRead (filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
return preview.Archive.OpenSeekableEntry (preview.Entry);
|
||||
}
|
||||
return VFS.OpenSeekableStream (preview.Entry);
|
||||
}
|
||||
|
||||
void LoadPreviewText (PreviewFile preview)
|
||||
|
@ -223,16 +223,15 @@ namespace GARbro.GUI
|
||||
StopWatchDirectoryChanges();
|
||||
var cvs = this.Resources["ListViewSource"] as CollectionViewSource;
|
||||
cvs.Source = value;
|
||||
pathLine.Text = value.Path;
|
||||
pathLine.Text = value.Path.Last();
|
||||
|
||||
if (value.IsArchive)
|
||||
PushRecentFile (value.Path);
|
||||
if (value.IsArchive && !value.Path.Skip (2).Any())
|
||||
PushRecentFile (value.Path.First());
|
||||
|
||||
lv_Sort (SortMode, m_lvSortDirection);
|
||||
if (!value.IsArchive && !string.IsNullOrEmpty (value.Path))
|
||||
if (!value.IsArchive && !string.IsNullOrEmpty (value.Path.First()))
|
||||
{
|
||||
Directory.SetCurrentDirectory (value.Path);
|
||||
WatchDirectoryChanges (value.Path);
|
||||
WatchDirectoryChanges (value.Path.First());
|
||||
}
|
||||
CurrentDirectory.UpdateLayout();
|
||||
}
|
||||
@ -240,16 +239,13 @@ namespace GARbro.GUI
|
||||
|
||||
DirectoryViewModel GetNewViewModel (string path)
|
||||
{
|
||||
path = Path.GetFullPath (path);
|
||||
if (Directory.Exists (path))
|
||||
{
|
||||
return new DirectoryViewModel (path, m_app.GetDirectoryList (path));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!VFS.IsVirtual)
|
||||
path = Path.GetFullPath (path);
|
||||
var entry = VFS.FindFile (path);
|
||||
if (!(entry is SubDirEntry))
|
||||
SetBusyState();
|
||||
return new ArchiveViewModel (path, m_app.GetArchive (path));
|
||||
}
|
||||
VFS.ChDir (entry);
|
||||
return new DirectoryViewModel (VFS.FullPath, VFS.GetFiles(), VFS.IsVirtual);
|
||||
}
|
||||
|
||||
private bool m_busy_state = false;
|
||||
@ -293,7 +289,7 @@ namespace GARbro.GUI
|
||||
catch (Exception X)
|
||||
{
|
||||
PopupError (X.Message, guiStrings.MsgErrorOpening);
|
||||
return new DirectoryViewModel ("", new Entry[0]);
|
||||
return new DirectoryViewModel (new string[] { "" }, new Entry[0], false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,13 +319,14 @@ namespace GARbro.GUI
|
||||
|
||||
public void ResumeWatchDirectoryChanges ()
|
||||
{
|
||||
m_watcher.EnableRaisingEvents = true;
|
||||
m_watcher.EnableRaisingEvents = !ViewModel.IsArchive;
|
||||
}
|
||||
|
||||
private void InvokeRefreshView (object source, FileSystemEventArgs e)
|
||||
{
|
||||
var watcher = source as FileSystemWatcher;
|
||||
if (watcher.Path == ViewModel.Path)
|
||||
var vm = ViewModel;
|
||||
if (!vm.IsArchive && vm.Path.First() == watcher.Path)
|
||||
{
|
||||
watcher.EnableRaisingEvents = false;
|
||||
Dispatcher.Invoke (RefreshView);
|
||||
@ -632,7 +629,7 @@ namespace GARbro.GUI
|
||||
|
||||
#region Navigation history implementation
|
||||
|
||||
internal string CurrentPath { get { return ViewModel.Path; } }
|
||||
internal string CurrentPath { get { return ViewModel.Path.First(); } }
|
||||
|
||||
HistoryStack<DirectoryPosition> m_history = new HistoryStack<DirectoryPosition>();
|
||||
|
||||
@ -644,12 +641,12 @@ namespace GARbro.GUI
|
||||
|
||||
public bool SetCurrentPosition (DirectoryPosition pos)
|
||||
{
|
||||
var vm = TryCreateViewModel (pos.Path);
|
||||
if (null == vm)
|
||||
return false;
|
||||
try
|
||||
{
|
||||
vm.SetPosition (pos);
|
||||
VFS.FullPath = pos.Path;
|
||||
var vm = TryCreateViewModel (pos.Path.Last());
|
||||
if (null == vm)
|
||||
return false;
|
||||
ViewModel = vm;
|
||||
if (null != pos.Item)
|
||||
lv_SelectItem (pos.Item);
|
||||
@ -670,7 +667,7 @@ namespace GARbro.GUI
|
||||
public void ChangePosition (DirectoryPosition new_pos)
|
||||
{
|
||||
var current = GetCurrentPosition();
|
||||
if (current.Path != new_pos.Path || current.ArchivePath != new_pos.ArchivePath)
|
||||
if (!current.Path.SequenceEqual (new_pos.Path))
|
||||
SaveCurrentPosition();
|
||||
SetCurrentPosition (new_pos);
|
||||
}
|
||||
@ -722,8 +719,8 @@ namespace GARbro.GUI
|
||||
var vm = GetNewViewModel (filename);
|
||||
SaveCurrentPosition();
|
||||
ViewModel = vm;
|
||||
if (null != m_app.CurrentArchive)
|
||||
SetStatusText (m_app.CurrentArchive.Description);
|
||||
if (null != VFS.CurrentArchive)
|
||||
SetStatusText (VFS.CurrentArchive.Description);
|
||||
lv_SelectItem (0);
|
||||
}
|
||||
catch (OperationCanceledException X)
|
||||
@ -766,48 +763,37 @@ namespace GARbro.GUI
|
||||
PlayFile (entry.Source);
|
||||
return;
|
||||
}
|
||||
if (vm.IsArchive) // tried to open file inside archive
|
||||
{
|
||||
var arc_vm = vm as ArchiveViewModel;
|
||||
if (!("" == arc_vm.SubDir && ".." == entry.Name))
|
||||
{
|
||||
OpenArchiveEntry (arc_vm, entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
OpenDirectoryEntry (vm, entry);
|
||||
}
|
||||
|
||||
private void OpenDirectoryEntry (DirectoryViewModel vm, EntryViewModel entry)
|
||||
{
|
||||
string old_dir = vm.Path;
|
||||
string new_dir = Path.Combine (old_dir, entry.Name);
|
||||
string old_dir = vm.Path.Last();
|
||||
string new_dir = entry.Source.Name;
|
||||
if (!vm.IsArchive && ".." == new_dir)
|
||||
new_dir = Path.Combine (old_dir, entry.Name);
|
||||
Trace.WriteLine (new_dir, "OpenDirectoryEntry");
|
||||
int old_fs_count = VFS.Count;
|
||||
vm = TryCreateViewModel (new_dir);
|
||||
if (null == vm)
|
||||
{
|
||||
// if (entry.Type != "archive")
|
||||
// SystemOpen (new_dir);
|
||||
return;
|
||||
}
|
||||
SaveCurrentPosition();
|
||||
ViewModel = vm;
|
||||
if (vm.IsArchive && null != m_app.CurrentArchive)
|
||||
SetStatusText (string.Format ("{0}: {1}", m_app.CurrentArchive.Description,
|
||||
Localization.Format ("MsgFiles", m_app.CurrentArchive.Dir.Count())));
|
||||
if (VFS.Count > old_fs_count && null != VFS.CurrentArchive)
|
||||
SetStatusText (string.Format ("{0}: {1}", VFS.CurrentArchive.Description,
|
||||
Localization.Format ("MsgFiles", VFS.CurrentArchive.Dir.Count())));
|
||||
else
|
||||
SetStatusText ("");
|
||||
var old_parent = Directory.GetParent (old_dir);
|
||||
if (null != old_parent && vm.Path == old_parent.FullName)
|
||||
{
|
||||
|
||||
if (".." == entry.Name)
|
||||
lv_SelectItem (Path.GetFileName (old_dir));
|
||||
}
|
||||
else
|
||||
{
|
||||
lv_SelectItem (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private void OpenArchiveEntry (ArchiveViewModel vm, EntryViewModel entry)
|
||||
{
|
||||
if (entry.IsDirectory)
|
||||
@ -829,14 +815,11 @@ namespace GARbro.GUI
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Stream OpenEntry (Entry entry)
|
||||
{
|
||||
var vm = ViewModel;
|
||||
if (vm.IsArchive)
|
||||
return m_app.CurrentArchive.OpenEntry (entry);
|
||||
else
|
||||
return File.OpenRead (Path.Combine (vm.Path, entry.Name));
|
||||
return VFS.OpenStream (entry);
|
||||
}
|
||||
|
||||
WaveOutEvent m_audio_device;
|
||||
@ -935,7 +918,7 @@ namespace GARbro.GUI
|
||||
|
||||
public void RefreshView ()
|
||||
{
|
||||
m_app.ResetCache();
|
||||
VFS.Flush();
|
||||
var pos = GetCurrentPosition();
|
||||
SetCurrentPosition (pos);
|
||||
}
|
||||
@ -974,7 +957,7 @@ namespace GARbro.GUI
|
||||
this.IsEnabled = false;
|
||||
try
|
||||
{
|
||||
m_app.ResetCache();
|
||||
VFS.Flush();
|
||||
ResetPreviewPane();
|
||||
if (!items.Skip (1).Any()) // items.Count() == 1
|
||||
{
|
||||
|
@ -51,5 +51,5 @@ using System.Windows;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion ("1.1.6.659")]
|
||||
[assembly: AssemblyFileVersion ("1.1.6.659")]
|
||||
[assembly: AssemblyVersion ("1.1.8.660")]
|
||||
[assembly: AssemblyFileVersion ("1.1.8.660")]
|
||||
|
9
Strings/guiStrings.Designer.cs
generated
9
Strings/guiStrings.Designer.cs
generated
@ -729,15 +729,6 @@ namespace GARbro.GUI.Strings {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to file could not be opened as resource archive.
|
||||
/// </summary>
|
||||
public static string MsgUnknownFormat {
|
||||
get {
|
||||
return ResourceManager.GetString("MsgUnknownFormat", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Version {0}.
|
||||
/// </summary>
|
||||
|
@ -243,9 +243,6 @@
|
||||
<data name="MsgUnableInterpretImage" xml:space="preserve">
|
||||
<value>unable to interpret image format</value>
|
||||
</data>
|
||||
<data name="MsgUnknownFormat" xml:space="preserve">
|
||||
<value>file could not be opened as resource archive</value>
|
||||
</data>
|
||||
<data name="MsgVersion" xml:space="preserve">
|
||||
<value>Version {0}</value>
|
||||
</data>
|
||||
|
@ -237,9 +237,6 @@
|
||||
<data name="MsgUnableInterpretImage" xml:space="preserve">
|
||||
<value>не удалось интерпретировать формат изображения</value>
|
||||
</data>
|
||||
<data name="MsgUnknownFormat" xml:space="preserve">
|
||||
<value>файл не может быть открыт как архив ресурсов</value>
|
||||
</data>
|
||||
<data name="MsgVersion" xml:space="preserve">
|
||||
<value>Версия {0}</value>
|
||||
</data>
|
||||
|
28
ViewModel.cs
28
ViewModel.cs
@ -41,20 +41,22 @@ namespace GARbro.GUI
|
||||
{
|
||||
public class DirectoryViewModel : ObservableCollection<EntryViewModel>
|
||||
{
|
||||
public string Path { get; private set; }
|
||||
public ICollection<Entry> Source { get; private set; }
|
||||
public virtual bool IsArchive { get { return false; } }
|
||||
public IEnumerable<string> Path { get; private set; }
|
||||
public IEnumerable<Entry> Source { get; private set; }
|
||||
public bool IsArchive { get; private set; }
|
||||
|
||||
public DirectoryViewModel (string path, ICollection<Entry> filelist)
|
||||
public DirectoryViewModel (IEnumerable<string> path, IEnumerable<Entry> filelist, bool is_archive)
|
||||
{
|
||||
Path = path;
|
||||
Source = filelist;
|
||||
IsArchive = is_archive;
|
||||
ImportFromSource();
|
||||
}
|
||||
|
||||
protected virtual void ImportFromSource ()
|
||||
protected void ImportFromSource ()
|
||||
{
|
||||
if (!string.IsNullOrEmpty (Path) && null != Directory.GetParent (Path))
|
||||
var last_dir = Path.Last();
|
||||
if (IsArchive || !string.IsNullOrEmpty (last_dir) && null != Directory.GetParent (last_dir))
|
||||
{
|
||||
Add (new EntryViewModel (new SubDirEntry (".."), -2));
|
||||
}
|
||||
@ -80,6 +82,7 @@ namespace GARbro.GUI
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public class ArchiveViewModel : DirectoryViewModel
|
||||
{
|
||||
public override bool IsArchive { get { return true; } }
|
||||
@ -212,6 +215,7 @@ namespace GARbro.GUI
|
||||
base.OnCollectionChanged(e);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
public class EntryViewModel : INotifyPropertyChanged
|
||||
{
|
||||
@ -332,24 +336,18 @@ namespace GARbro.GUI
|
||||
/// </summary>
|
||||
public class DirectoryPosition
|
||||
{
|
||||
public string Path { get; set; }
|
||||
public string ArchivePath { get; set; }
|
||||
public string Item { get; set; }
|
||||
public IEnumerable<string> Path { get; set; }
|
||||
public string Item { get; set; }
|
||||
|
||||
public DirectoryPosition (DirectoryViewModel vm, EntryViewModel item)
|
||||
{
|
||||
Path = vm.Path;
|
||||
Item = null != item ? item.Name : null;
|
||||
if (vm.IsArchive)
|
||||
ArchivePath = (vm as ArchiveViewModel).SubDir;
|
||||
else
|
||||
ArchivePath = "";
|
||||
}
|
||||
|
||||
public DirectoryPosition (string filename)
|
||||
{
|
||||
Path = System.IO.Path.GetDirectoryName (filename);
|
||||
ArchivePath = "";
|
||||
Path = new string[] { System.IO.Path.GetDirectoryName (filename) };
|
||||
Item = System.IO.Path.GetFileName (filename);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user