mirror of
https://github.com/crskycode/GARbro.git
synced 2024-12-24 03:44:13 +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>
|
/// </summary>
|
||||||
public string InitPath { get; private set; }
|
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)
|
void ApplicationStartup (object sender, StartupEventArgs e)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
@ -90,106 +80,11 @@ namespace GARbro.GUI
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty (InitPath))
|
if (string.IsNullOrEmpty (InitPath))
|
||||||
InitPath = Directory.GetCurrentDirectory();
|
InitPath = Directory.GetCurrentDirectory();
|
||||||
|
|
||||||
CurrentPath = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationExit (object sender, ExitEventArgs e)
|
void ApplicationExit (object sender, ExitEventArgs e)
|
||||||
{
|
{
|
||||||
Settings.Default.Save();
|
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
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion ("1.1.10.422")]
|
[assembly: AssemblyVersion ("1.1.12.423")]
|
||||||
[assembly: AssemblyFileVersion ("1.1.10.422")]
|
[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
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 2013
|
# Visual Studio 2013
|
||||||
VisualStudioVersion = 12.0.21005.1
|
VisualStudioVersion = 12.0.31101.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GARbro.Console", "Console\GARbro.Console.csproj", "{B966F292-431A-4D8A-A1D3-1EB45048A1D2}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GARbro.Console", "Console\GARbro.Console.csproj", "{B966F292-431A-4D8A-A1D3-1EB45048A1D2}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
@ -17,9 +17,6 @@ EndProject
|
|||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameRes", "GameRes\GameRes.csproj", "{453C087F-E416-4AE9-8C03-D8760DA0574B}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameRes", "GameRes\GameRes.csproj", "{453C087F-E416-4AE9-8C03-D8760DA0574B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GARbro.GUI", "GARbro.GUI.csproj", "{2935BE57-C4E0-43E7-86DE-C1848C820B19}"
|
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
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Image.Convert", "Image.Convert\Image.Convert.csproj", "{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Image.Convert", "Image.Convert\Image.Convert.csproj", "{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
@ -32,26 +29,22 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{B966F292-431A-4D8A-A1D3-1EB45048A1D2}.Release|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 = 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 = Release|Any CPU
|
||||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{A8865685-27CC-427B-AC38-E48D2AD05DF4}.Release|Any CPU.ActiveCfg = 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
|
{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.ActiveCfg = Release|Any CPU
|
||||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Debug|Any CPU.Build.0 = Debug|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.ActiveCfg = Release|Any CPU
|
||||||
{453C087F-E416-4AE9-8C03-D8760DA0574B}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Debug|Any CPU.Build.0 = Debug|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.ActiveCfg = Release|Any CPU
|
||||||
{2935BE57-C4E0-43E7-86DE-C1848C820B19}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{757EB8B1-F62C-4690-AC3D-DAE4A5576B3E}.Release|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
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -49,8 +49,6 @@ namespace GameRes
|
|||||||
/// <summary>Archive contents.</summary>
|
/// <summary>Archive contents.</summary>
|
||||||
public ICollection<Entry> Dir { get { return m_dir; } }
|
public ICollection<Entry> Dir { get { return m_dir; } }
|
||||||
|
|
||||||
public event EventHandler<OverwriteEventArgs> OverwriteNotify;
|
|
||||||
|
|
||||||
public ArcFile (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir)
|
public ArcFile (ArcView arc, ArchiveFormat impl, ICollection<Entry> dir)
|
||||||
{
|
{
|
||||||
m_arc = arc;
|
m_arc = arc;
|
||||||
@ -66,11 +64,11 @@ namespace GameRes
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public static ArcFile TryOpen (string filename)
|
public static ArcFile TryOpen (string filename)
|
||||||
{
|
{
|
||||||
var info = new FileInfo (filename);
|
var entry = VFS.FindFile (filename);
|
||||||
if (info.Length < 4)
|
if (entry.Size < 4)
|
||||||
return null;
|
return null;
|
||||||
var ext = new Lazy<string> (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant());
|
var ext = new Lazy<string> (() => Path.GetExtension (filename).TrimStart ('.').ToLowerInvariant());
|
||||||
var file = new ArcView (filename);
|
var file = VFS.OpenView (entry);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
uint signature = file.View.ReadUInt32 (0);
|
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 ()
|
public IFileSystem CreateFileSystem ()
|
||||||
{
|
{
|
||||||
if (m_interface.IsHierarchic)
|
if (m_interface.IsHierarchic)
|
||||||
@ -229,98 +218,4 @@ namespace GameRes
|
|||||||
}
|
}
|
||||||
#endregion
|
#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.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using GameRes.Strings;
|
||||||
|
|
||||||
namespace GameRes
|
namespace GameRes
|
||||||
{
|
{
|
||||||
public interface IFileSystem : IDisposable
|
public interface IFileSystem : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <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>
|
/// </summary>
|
||||||
Stream OpenStream (Entry entry);
|
Stream OpenStream (Entry entry);
|
||||||
|
|
||||||
|
Stream OpenSeekableStream (Entry entry);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Open file for reading as memory-mapped view.
|
||||||
|
/// </summary>
|
||||||
ArcView OpenView (Entry entry);
|
ArcView OpenView (Entry entry);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -47,7 +59,7 @@ namespace GameRes
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recursively enumerates files in the current directory and its subdirectories.
|
/// Recursively enumerates files in the current directory and its subdirectories.
|
||||||
/// Subdirectory entries are omitted.
|
/// Subdirectory entries are omitted from resulting set.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IEnumerable<Entry> GetFilesRecursive ();
|
IEnumerable<Entry> GetFilesRecursive ();
|
||||||
|
|
||||||
@ -73,6 +85,15 @@ namespace GameRes
|
|||||||
set { Directory.SetCurrentDirectory (value); }
|
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 ()
|
public IEnumerable<Entry> GetFiles ()
|
||||||
{
|
{
|
||||||
var info = new DirectoryInfo (CurrentDirectory);
|
var info = new DirectoryInfo (CurrentDirectory);
|
||||||
@ -84,7 +105,7 @@ namespace GameRes
|
|||||||
}
|
}
|
||||||
foreach (var file in info.EnumerateFiles())
|
foreach (var file in info.EnumerateFiles())
|
||||||
{
|
{
|
||||||
if (0 != (file.Attributes & (FileAttributes.Hidden | FileAttributes.System)))
|
if (0 != (file.Attributes & FileAttributes.System))
|
||||||
continue;
|
continue;
|
||||||
yield return EntryFromFileInfo (file);
|
yield return EntryFromFileInfo (file);
|
||||||
}
|
}
|
||||||
@ -113,6 +134,11 @@ namespace GameRes
|
|||||||
return File.OpenRead (entry.Name);
|
return File.OpenRead (entry.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream OpenSeekableStream (Entry entry)
|
||||||
|
{
|
||||||
|
return OpenStream (entry);
|
||||||
|
}
|
||||||
|
|
||||||
public ArcView OpenView (Entry entry)
|
public ArcView OpenView (Entry entry)
|
||||||
{
|
{
|
||||||
return new ArcView (entry.Name);
|
return new ArcView (entry.Name);
|
||||||
@ -126,7 +152,10 @@ namespace GameRes
|
|||||||
|
|
||||||
public class FlatArchiveFileSystem : IFileSystem
|
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
|
public virtual string CurrentDirectory
|
||||||
{
|
{
|
||||||
@ -146,6 +175,11 @@ namespace GameRes
|
|||||||
public FlatArchiveFileSystem (ArcFile arc)
|
public FlatArchiveFileSystem (ArcFile arc)
|
||||||
{
|
{
|
||||||
m_arc = 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)
|
public Stream OpenStream (Entry entry)
|
||||||
@ -153,11 +187,24 @@ namespace GameRes
|
|||||||
return m_arc.OpenEntry (entry);
|
return m_arc.OpenEntry (entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream OpenSeekableStream (Entry entry)
|
||||||
|
{
|
||||||
|
return m_arc.OpenSeekableEntry (entry);
|
||||||
|
}
|
||||||
|
|
||||||
public ArcView OpenView (Entry entry)
|
public ArcView OpenView (Entry entry)
|
||||||
{
|
{
|
||||||
return m_arc.OpenView (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 ()
|
public virtual IEnumerable<Entry> GetFiles ()
|
||||||
{
|
{
|
||||||
return m_arc.Dir;
|
return m_arc.Dir;
|
||||||
@ -211,6 +258,16 @@ namespace GameRes
|
|||||||
set { ChDir (value); }
|
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[/\\]?([^/\\]+)([/\\])");
|
static readonly Regex path_re = new Regex (@"\G[/\\]?([^/\\]+)([/\\])");
|
||||||
|
|
||||||
public override IEnumerable<Entry> GetFiles ()
|
public override IEnumerable<Entry> GetFiles ()
|
||||||
@ -300,4 +357,188 @@ namespace GameRes
|
|||||||
m_cwd = new_path;
|
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 ResourceOptions Options { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class OverwriteEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public string Filename { get; set; }
|
||||||
|
public bool Overwrite { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class FormatCatalog
|
public sealed class FormatCatalog
|
||||||
{
|
{
|
||||||
private static readonly FormatCatalog m_instance = new 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
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion ("1.1.7.90")]
|
[assembly: AssemblyVersion ("1.1.9.91")]
|
||||||
[assembly: AssemblyFileVersion ("1.1.7.90")]
|
[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>
|
// <auto-generated>
|
||||||
// This code was generated by a tool.
|
// 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
|
// Changes to this file may cause incorrect behavior and will be lost if
|
||||||
// the code is regenerated.
|
// the code is regenerated.
|
||||||
@ -104,5 +104,14 @@ namespace GameRes.Strings {
|
|||||||
return ResourceManager.GetString("MsgUnknownEncryption", resourceCulture);
|
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">
|
<data name="MsgUnknownEncryption" xml:space="preserve">
|
||||||
<value>Unknown encryption scheme</value>
|
<value>Unknown encryption scheme</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MsgUnknownFormat" xml:space="preserve">
|
||||||
|
<value>file could not be opened as resource archive</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -132,4 +132,7 @@
|
|||||||
<data name="MsgUnknownEncryption" xml:space="preserve">
|
<data name="MsgUnknownEncryption" xml:space="preserve">
|
||||||
<value>Неизвестный метод шифрования</value>
|
<value>Неизвестный метод шифрования</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="MsgUnknownFormat" xml:space="preserve">
|
||||||
|
<value>файл не может быть открыт как архив ресурсов</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
@ -68,7 +68,7 @@ namespace GARbro.GUI
|
|||||||
}
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Directory.SetCurrentDirectory (ViewModel.Path);
|
Directory.SetCurrentDirectory (ViewModel.Path.First());
|
||||||
var converter = new GarConvertMedia (this);
|
var converter = new GarConvertMedia (this);
|
||||||
converter.IgnoreErrors = convert_dialog.IgnoreErrors.IsChecked ?? false;
|
converter.IgnoreErrors = convert_dialog.IgnoreErrors.IsChecked ?? false;
|
||||||
converter.Convert (source, format);
|
converter.Convert (source, format);
|
||||||
|
@ -34,6 +34,7 @@ using System.Windows.Input;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using Ookii.Dialogs.Wpf;
|
using Ookii.Dialogs.Wpf;
|
||||||
using GameRes;
|
using GameRes;
|
||||||
|
using GameRes.Strings;
|
||||||
using GARbro.GUI.Strings;
|
using GARbro.GUI.Strings;
|
||||||
using GARbro.GUI.Properties;
|
using GARbro.GUI.Properties;
|
||||||
|
|
||||||
@ -58,11 +59,12 @@ namespace GARbro.GUI
|
|||||||
string destination = Settings.Default.appLastDestination;
|
string destination = Settings.Default.appLastDestination;
|
||||||
if (!Directory.Exists (destination))
|
if (!Directory.Exists (destination))
|
||||||
destination = "";
|
destination = "";
|
||||||
if (!ViewModel.IsArchive)
|
var vm = ViewModel;
|
||||||
|
if (!vm.IsArchive)
|
||||||
{
|
{
|
||||||
if (!entry.IsDirectory)
|
if (!entry.IsDirectory)
|
||||||
{
|
{
|
||||||
var arc_dir = CurrentPath;
|
var arc_dir = vm.Path.First();
|
||||||
var source = Path.Combine (arc_dir, entry.Name);
|
var source = Path.Combine (arc_dir, entry.Name);
|
||||||
if (string.IsNullOrEmpty (destination))
|
if (string.IsNullOrEmpty (destination))
|
||||||
destination = arc_dir;
|
destination = arc_dir;
|
||||||
@ -73,13 +75,13 @@ namespace GARbro.GUI
|
|||||||
extractor.ExtractAll (destination);
|
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))
|
if (string.IsNullOrEmpty (destination))
|
||||||
destination = Path.GetDirectoryName (vm.Path);
|
destination = Path.GetDirectoryName (vm.Path.First());
|
||||||
extractor = new GarExtract (this, vm.Path, m_app.CurrentArchive);
|
var archive_name = vm.Path.Reverse().Skip (1).First();
|
||||||
if (null == entry || (entry.Name == ".." && vm.SubDir == "")) // root entry
|
extractor = new GarExtract (this, archive_name, VFS.CurrentArchive);
|
||||||
|
if (null == entry || (entry.Name == ".." && string.IsNullOrEmpty (vm.Path.Last()))) // root entry
|
||||||
extractor.ExtractAll (destination);
|
extractor.ExtractAll (destination);
|
||||||
else
|
else
|
||||||
extractor.Extract (entry, destination);
|
extractor.Extract (entry, destination);
|
||||||
@ -132,7 +134,7 @@ namespace GARbro.GUI
|
|||||||
if (FormatCatalog.Instance.LastError != null)
|
if (FormatCatalog.Instance.LastError != null)
|
||||||
error_message = FormatCatalog.Instance.LastError.Message;
|
error_message = FormatCatalog.Instance.LastError.Message;
|
||||||
else
|
else
|
||||||
error_message = guiStrings.MsgUnknownFormat;
|
error_message = garStrings.MsgUnknownFormat;
|
||||||
throw new OperationCanceledException (string.Format ("{1}: {0}", error_message, m_arc_name));
|
throw new OperationCanceledException (string.Format ("{1}: {0}", error_message, m_arc_name));
|
||||||
}
|
}
|
||||||
m_should_dispose = true;
|
m_should_dispose = true;
|
||||||
|
@ -75,14 +75,13 @@ namespace GARbro.GUI
|
|||||||
|
|
||||||
class PreviewFile
|
class PreviewFile
|
||||||
{
|
{
|
||||||
public string Path { get; set; }
|
public IEnumerable<string> Path { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public Entry Entry { get; set; }
|
public Entry Entry { get; set; }
|
||||||
public ArcFile Archive { 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;
|
ActiveViewer = ImageView;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (vm.IsArchive)
|
|
||||||
m_current_preview.Archive = m_app.CurrentArchive;
|
|
||||||
if ("image" != entry.Type)
|
if ("image" != entry.Type)
|
||||||
LoadPreviewText (m_current_preview);
|
LoadPreviewText (m_current_preview);
|
||||||
else if (!m_preview_worker.IsBusy)
|
else if (!m_preview_worker.IsBusy)
|
||||||
@ -193,15 +190,7 @@ namespace GARbro.GUI
|
|||||||
|
|
||||||
Stream OpenPreviewStream (PreviewFile preview)
|
Stream OpenPreviewStream (PreviewFile preview)
|
||||||
{
|
{
|
||||||
if (null == preview.Archive)
|
return VFS.OpenSeekableStream (preview.Entry);
|
||||||
{
|
|
||||||
string filename = Path.Combine (preview.Path, preview.Name);
|
|
||||||
return File.OpenRead (filename);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return preview.Archive.OpenSeekableEntry (preview.Entry);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoadPreviewText (PreviewFile preview)
|
void LoadPreviewText (PreviewFile preview)
|
||||||
|
@ -223,16 +223,15 @@ namespace GARbro.GUI
|
|||||||
StopWatchDirectoryChanges();
|
StopWatchDirectoryChanges();
|
||||||
var cvs = this.Resources["ListViewSource"] as CollectionViewSource;
|
var cvs = this.Resources["ListViewSource"] as CollectionViewSource;
|
||||||
cvs.Source = value;
|
cvs.Source = value;
|
||||||
pathLine.Text = value.Path;
|
pathLine.Text = value.Path.Last();
|
||||||
|
|
||||||
if (value.IsArchive)
|
if (value.IsArchive && !value.Path.Skip (2).Any())
|
||||||
PushRecentFile (value.Path);
|
PushRecentFile (value.Path.First());
|
||||||
|
|
||||||
lv_Sort (SortMode, m_lvSortDirection);
|
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.First());
|
||||||
WatchDirectoryChanges (value.Path);
|
|
||||||
}
|
}
|
||||||
CurrentDirectory.UpdateLayout();
|
CurrentDirectory.UpdateLayout();
|
||||||
}
|
}
|
||||||
@ -240,16 +239,13 @@ namespace GARbro.GUI
|
|||||||
|
|
||||||
DirectoryViewModel GetNewViewModel (string path)
|
DirectoryViewModel GetNewViewModel (string path)
|
||||||
{
|
{
|
||||||
path = Path.GetFullPath (path);
|
if (!VFS.IsVirtual)
|
||||||
if (Directory.Exists (path))
|
path = Path.GetFullPath (path);
|
||||||
{
|
var entry = VFS.FindFile (path);
|
||||||
return new DirectoryViewModel (path, m_app.GetDirectoryList (path));
|
if (!(entry is SubDirEntry))
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SetBusyState();
|
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;
|
private bool m_busy_state = false;
|
||||||
@ -293,7 +289,7 @@ namespace GARbro.GUI
|
|||||||
catch (Exception X)
|
catch (Exception X)
|
||||||
{
|
{
|
||||||
PopupError (X.Message, guiStrings.MsgErrorOpening);
|
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 ()
|
public void ResumeWatchDirectoryChanges ()
|
||||||
{
|
{
|
||||||
m_watcher.EnableRaisingEvents = true;
|
m_watcher.EnableRaisingEvents = !ViewModel.IsArchive;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void InvokeRefreshView (object source, FileSystemEventArgs e)
|
private void InvokeRefreshView (object source, FileSystemEventArgs e)
|
||||||
{
|
{
|
||||||
var watcher = source as FileSystemWatcher;
|
var watcher = source as FileSystemWatcher;
|
||||||
if (watcher.Path == ViewModel.Path)
|
var vm = ViewModel;
|
||||||
|
if (!vm.IsArchive && vm.Path.First() == watcher.Path)
|
||||||
{
|
{
|
||||||
watcher.EnableRaisingEvents = false;
|
watcher.EnableRaisingEvents = false;
|
||||||
Dispatcher.Invoke (RefreshView);
|
Dispatcher.Invoke (RefreshView);
|
||||||
@ -632,7 +629,7 @@ namespace GARbro.GUI
|
|||||||
|
|
||||||
#region Navigation history implementation
|
#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>();
|
HistoryStack<DirectoryPosition> m_history = new HistoryStack<DirectoryPosition>();
|
||||||
|
|
||||||
@ -644,12 +641,12 @@ namespace GARbro.GUI
|
|||||||
|
|
||||||
public bool SetCurrentPosition (DirectoryPosition pos)
|
public bool SetCurrentPosition (DirectoryPosition pos)
|
||||||
{
|
{
|
||||||
var vm = TryCreateViewModel (pos.Path);
|
|
||||||
if (null == vm)
|
|
||||||
return false;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
vm.SetPosition (pos);
|
VFS.FullPath = pos.Path;
|
||||||
|
var vm = TryCreateViewModel (pos.Path.Last());
|
||||||
|
if (null == vm)
|
||||||
|
return false;
|
||||||
ViewModel = vm;
|
ViewModel = vm;
|
||||||
if (null != pos.Item)
|
if (null != pos.Item)
|
||||||
lv_SelectItem (pos.Item);
|
lv_SelectItem (pos.Item);
|
||||||
@ -670,7 +667,7 @@ namespace GARbro.GUI
|
|||||||
public void ChangePosition (DirectoryPosition new_pos)
|
public void ChangePosition (DirectoryPosition new_pos)
|
||||||
{
|
{
|
||||||
var current = GetCurrentPosition();
|
var current = GetCurrentPosition();
|
||||||
if (current.Path != new_pos.Path || current.ArchivePath != new_pos.ArchivePath)
|
if (!current.Path.SequenceEqual (new_pos.Path))
|
||||||
SaveCurrentPosition();
|
SaveCurrentPosition();
|
||||||
SetCurrentPosition (new_pos);
|
SetCurrentPosition (new_pos);
|
||||||
}
|
}
|
||||||
@ -722,8 +719,8 @@ namespace GARbro.GUI
|
|||||||
var vm = GetNewViewModel (filename);
|
var vm = GetNewViewModel (filename);
|
||||||
SaveCurrentPosition();
|
SaveCurrentPosition();
|
||||||
ViewModel = vm;
|
ViewModel = vm;
|
||||||
if (null != m_app.CurrentArchive)
|
if (null != VFS.CurrentArchive)
|
||||||
SetStatusText (m_app.CurrentArchive.Description);
|
SetStatusText (VFS.CurrentArchive.Description);
|
||||||
lv_SelectItem (0);
|
lv_SelectItem (0);
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException X)
|
catch (OperationCanceledException X)
|
||||||
@ -766,48 +763,37 @@ namespace GARbro.GUI
|
|||||||
PlayFile (entry.Source);
|
PlayFile (entry.Source);
|
||||||
return;
|
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);
|
OpenDirectoryEntry (vm, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OpenDirectoryEntry (DirectoryViewModel vm, EntryViewModel entry)
|
private void OpenDirectoryEntry (DirectoryViewModel vm, EntryViewModel entry)
|
||||||
{
|
{
|
||||||
string old_dir = vm.Path;
|
string old_dir = vm.Path.Last();
|
||||||
string new_dir = Path.Combine (old_dir, entry.Name);
|
string new_dir = entry.Source.Name;
|
||||||
|
if (!vm.IsArchive && ".." == new_dir)
|
||||||
|
new_dir = Path.Combine (old_dir, entry.Name);
|
||||||
Trace.WriteLine (new_dir, "OpenDirectoryEntry");
|
Trace.WriteLine (new_dir, "OpenDirectoryEntry");
|
||||||
|
int old_fs_count = VFS.Count;
|
||||||
vm = TryCreateViewModel (new_dir);
|
vm = TryCreateViewModel (new_dir);
|
||||||
if (null == vm)
|
if (null == vm)
|
||||||
{
|
{
|
||||||
// if (entry.Type != "archive")
|
|
||||||
// SystemOpen (new_dir);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SaveCurrentPosition();
|
SaveCurrentPosition();
|
||||||
ViewModel = vm;
|
ViewModel = vm;
|
||||||
if (vm.IsArchive && null != m_app.CurrentArchive)
|
if (VFS.Count > old_fs_count && null != VFS.CurrentArchive)
|
||||||
SetStatusText (string.Format ("{0}: {1}", m_app.CurrentArchive.Description,
|
SetStatusText (string.Format ("{0}: {1}", VFS.CurrentArchive.Description,
|
||||||
Localization.Format ("MsgFiles", m_app.CurrentArchive.Dir.Count())));
|
Localization.Format ("MsgFiles", VFS.CurrentArchive.Dir.Count())));
|
||||||
else
|
else
|
||||||
SetStatusText ("");
|
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));
|
lv_SelectItem (Path.GetFileName (old_dir));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
lv_SelectItem (0);
|
lv_SelectItem (0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
private void OpenArchiveEntry (ArchiveViewModel vm, EntryViewModel entry)
|
private void OpenArchiveEntry (ArchiveViewModel vm, EntryViewModel entry)
|
||||||
{
|
{
|
||||||
if (entry.IsDirectory)
|
if (entry.IsDirectory)
|
||||||
@ -829,14 +815,11 @@ namespace GARbro.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
Stream OpenEntry (Entry entry)
|
Stream OpenEntry (Entry entry)
|
||||||
{
|
{
|
||||||
var vm = ViewModel;
|
return VFS.OpenStream (entry);
|
||||||
if (vm.IsArchive)
|
|
||||||
return m_app.CurrentArchive.OpenEntry (entry);
|
|
||||||
else
|
|
||||||
return File.OpenRead (Path.Combine (vm.Path, entry.Name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WaveOutEvent m_audio_device;
|
WaveOutEvent m_audio_device;
|
||||||
@ -935,7 +918,7 @@ namespace GARbro.GUI
|
|||||||
|
|
||||||
public void RefreshView ()
|
public void RefreshView ()
|
||||||
{
|
{
|
||||||
m_app.ResetCache();
|
VFS.Flush();
|
||||||
var pos = GetCurrentPosition();
|
var pos = GetCurrentPosition();
|
||||||
SetCurrentPosition (pos);
|
SetCurrentPosition (pos);
|
||||||
}
|
}
|
||||||
@ -974,7 +957,7 @@ namespace GARbro.GUI
|
|||||||
this.IsEnabled = false;
|
this.IsEnabled = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_app.ResetCache();
|
VFS.Flush();
|
||||||
ResetPreviewPane();
|
ResetPreviewPane();
|
||||||
if (!items.Skip (1).Any()) // items.Count() == 1
|
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
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion ("1.1.6.659")]
|
[assembly: AssemblyVersion ("1.1.8.660")]
|
||||||
[assembly: AssemblyFileVersion ("1.1.6.659")]
|
[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>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to Version {0}.
|
/// Looks up a localized string similar to Version {0}.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -243,9 +243,6 @@
|
|||||||
<data name="MsgUnableInterpretImage" xml:space="preserve">
|
<data name="MsgUnableInterpretImage" xml:space="preserve">
|
||||||
<value>unable to interpret image format</value>
|
<value>unable to interpret image format</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgUnknownFormat" xml:space="preserve">
|
|
||||||
<value>file could not be opened as resource archive</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgVersion" xml:space="preserve">
|
<data name="MsgVersion" xml:space="preserve">
|
||||||
<value>Version {0}</value>
|
<value>Version {0}</value>
|
||||||
</data>
|
</data>
|
||||||
|
@ -237,9 +237,6 @@
|
|||||||
<data name="MsgUnableInterpretImage" xml:space="preserve">
|
<data name="MsgUnableInterpretImage" xml:space="preserve">
|
||||||
<value>не удалось интерпретировать формат изображения</value>
|
<value>не удалось интерпретировать формат изображения</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MsgUnknownFormat" xml:space="preserve">
|
|
||||||
<value>файл не может быть открыт как архив ресурсов</value>
|
|
||||||
</data>
|
|
||||||
<data name="MsgVersion" xml:space="preserve">
|
<data name="MsgVersion" xml:space="preserve">
|
||||||
<value>Версия {0}</value>
|
<value>Версия {0}</value>
|
||||||
</data>
|
</data>
|
||||||
|
28
ViewModel.cs
28
ViewModel.cs
@ -41,20 +41,22 @@ namespace GARbro.GUI
|
|||||||
{
|
{
|
||||||
public class DirectoryViewModel : ObservableCollection<EntryViewModel>
|
public class DirectoryViewModel : ObservableCollection<EntryViewModel>
|
||||||
{
|
{
|
||||||
public string Path { get; private set; }
|
public IEnumerable<string> Path { get; private set; }
|
||||||
public ICollection<Entry> Source { get; private set; }
|
public IEnumerable<Entry> Source { get; private set; }
|
||||||
public virtual bool IsArchive { get { return false; } }
|
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;
|
Path = path;
|
||||||
Source = filelist;
|
Source = filelist;
|
||||||
|
IsArchive = is_archive;
|
||||||
ImportFromSource();
|
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));
|
Add (new EntryViewModel (new SubDirEntry (".."), -2));
|
||||||
}
|
}
|
||||||
@ -80,6 +82,7 @@ namespace GARbro.GUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
public class ArchiveViewModel : DirectoryViewModel
|
public class ArchiveViewModel : DirectoryViewModel
|
||||||
{
|
{
|
||||||
public override bool IsArchive { get { return true; } }
|
public override bool IsArchive { get { return true; } }
|
||||||
@ -212,6 +215,7 @@ namespace GARbro.GUI
|
|||||||
base.OnCollectionChanged(e);
|
base.OnCollectionChanged(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
public class EntryViewModel : INotifyPropertyChanged
|
public class EntryViewModel : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
@ -332,24 +336,18 @@ namespace GARbro.GUI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class DirectoryPosition
|
public class DirectoryPosition
|
||||||
{
|
{
|
||||||
public string Path { get; set; }
|
public IEnumerable<string> Path { get; set; }
|
||||||
public string ArchivePath { get; set; }
|
public string Item { get; set; }
|
||||||
public string Item { get; set; }
|
|
||||||
|
|
||||||
public DirectoryPosition (DirectoryViewModel vm, EntryViewModel item)
|
public DirectoryPosition (DirectoryViewModel vm, EntryViewModel item)
|
||||||
{
|
{
|
||||||
Path = vm.Path;
|
Path = vm.Path;
|
||||||
Item = null != item ? item.Name : null;
|
Item = null != item ? item.Name : null;
|
||||||
if (vm.IsArchive)
|
|
||||||
ArchivePath = (vm as ArchiveViewModel).SubDir;
|
|
||||||
else
|
|
||||||
ArchivePath = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DirectoryPosition (string filename)
|
public DirectoryPosition (string filename)
|
||||||
{
|
{
|
||||||
Path = System.IO.Path.GetDirectoryName (filename);
|
Path = new string[] { System.IO.Path.GetDirectoryName (filename) };
|
||||||
ArchivePath = "";
|
|
||||||
Item = System.IO.Path.GetFileName (filename);
|
Item = System.IO.Path.GetFileName (filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user