//
//
//
//
// $Revision: 2072 $
//
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Globalization;
using System.IO;
using System.Resources;
using System.Text;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.FormsDesigner.Services
{
public class DesignerResourceService : System.ComponentModel.Design.IResourceService , IDisposable
{
IDesignerHost host;
FormsDesignerViewContent formsDesignerViewContent;
public string FormFileName {
get {
return formsDesignerViewContent.FileName;
}
}
// Culture name (or empty string) => Resources
Dictionary resources = new Dictionary();
public List ResourcesFileNames
{
get
{
if (resources != null)
{
List resfn = new List();
foreach (KeyValuePair entry in resources)
{
string cultureName = entry.Key;
string resourceFileName = CalcResourceFileName(FormFileName, cultureName);
if (entry.Value.ContainsData || entry.Value.IsReadFromFile)
resfn.Add(resourceFileName);
}
return resfn;
}
return null;
}
}
#region ResourceStorage
public class ResourceStorage
{
MemoryStream stream;
IResourceWriter writer;
byte[] buffer;
///
/// true, if the currently stored resource is not empty.
/// Note that this property is only valid after at least one
/// of GetReader, GetWriter or Save has been called.
///
public bool ContainsData {
get {
return this.buffer != null;
}
}
public void Dispose()
{
if (this.stream != null) {
this.writer.Dispose();
this.stream.Dispose();
}
this.buffer = null;
}
///
/// Writes the byte array containing the most recent version of the resource
/// represented by this instance into the private field "buffer" and returns it.
/// Returns null, if this resource has not been written to yet.
///
byte[] GetBuffer()
{
if (this.stream != null) {
byte[] buffer = this.stream.ToArray();
if (buffer.Length > 0) {
this.writer.Close();
this.writer.Dispose();
this.buffer = this.stream.ToArray();
this.writer = null;
this.stream.Dispose();
this.stream = null;
}
}
return this.buffer;
}
///
/// Returns a new resource reader for this resource based on the most recent
/// version available (either in memory or on disk).
///
public bool IsReadFromFile = false;
public IResourceReader GetReader(string resourceFileName)
{
if (this.GetBuffer() == null) {
if (File.Exists(resourceFileName)) {
IsReadFromFile = true;
return CreateResourceReader(resourceFileName);
} else {
return null;
}
} else {
return CreateResourceReader(new MemoryStream(this.buffer, false));
}
}
///
/// Returns a new resource writer for this resource.
/// According to the SDK documentation of IResourceService.GetResourceWriter,
/// a new writer needs to be returned every time one is requested, discarding any
/// data written by previously returned writers.
///
public IResourceWriter GetWriter()
{
this.stream = new MemoryStream();
this.writer = CreateResourceWriter(this.stream);
return this.writer;
}
public void Save(string fileName)
{
if (this.GetBuffer() != null) {
File.WriteAllBytes(fileName, this.buffer);
}
}
}
#endregion
// In ResourceMemoryStreams are stored:
// Key: Culture name (empty string for invariant culture)
// Value: ResourceStorage, where the resources are stored
// Memory streams are cleared, when WriteSerialization will start
// or File in the editor will be reloaded from the disc and of
// course in Dispose of the service
public Dictionary Resources
{
get {
return resources;
}
set {
resources = value;
}
}
public IDesignerHost Host {
get {
return host;
}
set {
host = value;
}
}
public DesignerResourceService(FormsDesignerViewContent formsDesigner)
{
this.formsDesignerViewContent = formsDesigner;
this.host = formsDesigner.Host;
}
static IProject GetProject(string formFileName)
{
if (ProjectService.OpenSolution != null && formFileName != null)
return ProjectService.OpenSolution.FindProjectContainingFile(formFileName);
else
return null;
}
#region System.ComponentModel.Design.IResourceService interface implementation
public System.Resources.IResourceWriter GetResourceWriter(CultureInfo info)
{
try {
LoggingService.Debug("ResourceWriter requested for culture: " + info.ToString());
ResourceStorage resourceStorage;
if (resources.ContainsKey(info.Name)) {
resourceStorage = resources[info.Name];
} else {
resourceStorage = new ResourceStorage();
resources[info.Name] = resourceStorage;
}
return resourceStorage.GetWriter();
} catch (Exception e) {
MessageService.ShowError(e.Message);
return null;
}
}
public System.Resources.IResourceReader GetResourceReader(System.Globalization.CultureInfo info)
{
try {
LoggingService.Debug("ResourceReader requested for culture: "+info.ToString());
ResourceStorage resourceStorage;
if (resources != null && resources.ContainsKey(info.Name)) {
resourceStorage = resources[info.Name];
} else {
resourceStorage = new ResourceStorage();
resources[info.Name] = resourceStorage;
}
return resourceStorage.GetReader(CalcResourceFileName(FormFileName, info.Name));
} catch (Exception e) {
MessageService.ShowError(e.Message);
return null;
}
}
#endregion
public void Save()
{
if (resources != null) {
foreach (KeyValuePair entry in resources) {
string cultureName = entry.Key;
string resourceFileName = CalcResourceFileName(FormFileName, cultureName);
FileUtility.ObservedSave(new NamedFileOperationDelegate(entry.Value.Save), resourceFileName, FileErrorPolicy.Inform);
IProject project = GetProject(FormFileName);
// Add this resource file to the project
if (entry.Value.ContainsData && project != null && !project.IsFileInProject(resourceFileName)) {
FileProjectItem newFileProjectItem = new FileProjectItem(project, ItemType.EmbeddedResource);
newFileProjectItem.DependentUpon = Path.GetFileName(FormFileName);
newFileProjectItem.Include = FileUtility.GetRelativePath(project.Directory, resourceFileName);
ProjectService.AddProjectItem(project, newFileProjectItem);
PadDescriptor pd = WorkbenchSingleton.Workbench.GetPad(typeof(ProjectBrowserPad));
FileNode formFileNode = ((ProjectBrowserPad)pd.PadContent).ProjectBrowserControl.FindFileNode(FormFileName);
if (formFileNode != null) {
LoggingService.Info("FormFileNode found, adding subitem");
FileNode fileNode = new FileNode(resourceFileName, FileNodeStatus.BehindFile);
fileNode.AddTo(formFileNode);
fileNode.ProjectItem = newFileProjectItem;
}
project.Save();
}
}
}
}
protected string CalcResourceFileName(string formFileName, string cultureName)
{
StringBuilder resourceFileName = null;
IProject project = GetProject(formFileName);
if (formFileName != null && formFileName != String.Empty) {
resourceFileName = new StringBuilder(Path.GetDirectoryName(formFileName));
} else if (project != null) {
resourceFileName = new StringBuilder(project.Directory);
} else {
// required for untitled files. Untitled files should NOT save their resources.
resourceFileName = new StringBuilder(Path.GetTempPath());
}
resourceFileName.Append(Path.DirectorySeparatorChar);
string sourceFileName = null;
if (project != null && formFileName != null) {
// Try to find the source file name by using the project dependencies first.
FileProjectItem sourceItem = project.FindFile(formFileName);
if (sourceItem != null && sourceItem.DependentUpon != null && sourceItem.DependentUpon.Length > 0) {
sourceFileName = Path.GetFileNameWithoutExtension(sourceItem.DependentUpon);
}
}
if (sourceFileName == null) {
// If the source file name cannot be found using the project dependencies,
// assume the resource file name to be equal to the current source file name.
// Remove the ".Designer" part if present.
sourceFileName = Path.GetFileNameWithoutExtension(formFileName);
if (sourceFileName != null && sourceFileName.ToLowerInvariant().EndsWith(".designer")) {
sourceFileName = sourceFileName.Substring(0, sourceFileName.Length - 9);
}
}
resourceFileName.Append(sourceFileName);
if (!string.IsNullOrEmpty(cultureName)) {
resourceFileName.Append('.');
resourceFileName.Append(cultureName);
}
resourceFileName.Append('.');
resourceFileName.Append(Host.RootComponent.Site.Name);//roman//
resourceFileName.Append(".resources");
return resourceFileName.ToString();
}
public void Dispose()
{
if (resources != null) {
foreach (ResourceStorage storage in resources.Values) {
storage.Dispose();
}
resources.Clear();
}
}
static IResourceReader CreateResourceReader(string fileName)
{
return new ResourceReader(fileName);
}
static IResourceReader CreateResourceReader(Stream stream)
{
return new ResourceReader(stream);
}
static IResourceWriter CreateResourceWriter(Stream stream)
{
return new ResourceWriter(stream);
}
}
}