Browse Source

Fixed SD2-953: Code error is thrown runing a WinForm with the form .resx file opened

The forms designer now uses OpenedFile (SD2-1234) to allow sharing unsaved resource files between resource editor and forms designer.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2662 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 18 years ago
parent
commit
7bd9c2a8b6
  1. 46
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs
  2. 286
      src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs
  3. 2
      src/AddIns/DisplayBindings/WorkflowDesigner/Project/Src/Services/WorkflowSideTabService.cs
  4. 14
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs
  5. 22
      src/Main/Base/Project/Src/Gui/AbstractViewContent.cs
  6. 10
      src/Main/Base/Project/Src/Gui/IViewContent.cs
  7. 2
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/FolderNodeCommands.cs
  8. 1
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs
  9. 1
      src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs
  10. 1
      src/Main/Base/Project/Src/Project/CustomTool.cs
  11. 24
      src/Main/Base/Project/Src/Services/File/FileService.cs
  12. 54
      src/Main/Base/Project/Src/Services/File/OpenedFile.cs
  13. 1
      src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs
  14. 6
      src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs

46
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs

@ -7,6 +7,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.Design; using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization; using System.ComponentModel.Design.Serialization;
@ -65,6 +66,10 @@ namespace ICSharpCode.FormsDesigner
} }
} }
internal new ICollection<OpenedFile> Files {
get { return base.Files; }
}
public IDesignerHost Host { public IDesignerHost Host {
get { get {
if (designSurface == null) if (designSurface == null)
@ -110,7 +115,7 @@ namespace ICSharpCode.FormsDesigner
// may not have been written to disk yet if the user switched // may not have been written to disk yet if the user switched
// between source and design view without saving. // between source and design view without saving.
if (designerResourceService == null) { if (designerResourceService == null) {
designerResourceService = new DesignerResourceService(viewContent.PrimaryFileName); designerResourceService = new DesignerResourceService(this);
} }
serviceContainer.AddService(typeof(System.ComponentModel.Design.IResourceService), designerResourceService); serviceContainer.AddService(typeof(System.ComponentModel.Design.IResourceService), designerResourceService);
AmbientProperties ambientProperties = new AmbientProperties(); AmbientProperties ambientProperties = new AmbientProperties();
@ -127,8 +132,6 @@ namespace ICSharpCode.FormsDesigner
ICSharpCode.FormsDesigner.Services.EventBindingService eventBindingService = new ICSharpCode.FormsDesigner.Services.EventBindingService(designSurface); ICSharpCode.FormsDesigner.Services.EventBindingService eventBindingService = new ICSharpCode.FormsDesigner.Services.EventBindingService(designSurface);
serviceContainer.AddService(typeof(System.ComponentModel.Design.IEventBindingService), eventBindingService); serviceContainer.AddService(typeof(System.ComponentModel.Design.IEventBindingService), eventBindingService);
designerResourceService.Host = Host;
DesignerLoader designerLoader = loaderProvider.CreateLoader(generator); DesignerLoader designerLoader = loaderProvider.CreateLoader(generator);
designSurface.BeginLoad(designerLoader); designSurface.BeginLoad(designerLoader);
@ -137,7 +140,7 @@ namespace ICSharpCode.FormsDesigner
undoEngine = new FormsDesignerUndoEngine(Host); undoEngine = new FormsDesignerUndoEngine(Host);
IComponentChangeService componentChangeService = (IComponentChangeService)designSurface.GetService(typeof(IComponentChangeService)); IComponentChangeService componentChangeService = (IComponentChangeService)designSurface.GetService(typeof(IComponentChangeService));
componentChangeService.ComponentChanged += delegate { this.PrimaryFile.MakeDirty(); }; componentChangeService.ComponentChanged += MakeDirty;
componentChangeService.ComponentAdded += ComponentListChanged; componentChangeService.ComponentAdded += ComponentListChanged;
componentChangeService.ComponentRemoved += ComponentListChanged; componentChangeService.ComponentRemoved += ComponentListChanged;
componentChangeService.ComponentRename += ComponentListChanged; componentChangeService.ComponentRename += ComponentListChanged;
@ -153,9 +156,39 @@ namespace ICSharpCode.FormsDesigner
UpdatePropertyPad(); UpdatePropertyPad();
hasUnmergedChanges = false;
LoggingService.Info("Form Designer: END INITIALIZE"); LoggingService.Info("Form Designer: END INITIALIZE");
} }
bool hasUnmergedChanges;
void MakeDirty(object sender, ComponentChangedEventArgs args)
{
hasUnmergedChanges = true;
this.PrimaryFile.MakeDirty();
designerResourceService.MarkResourceFilesAsDirty();
}
public override void Load(OpenedFile file, System.IO.Stream stream)
{
if (file == PrimaryFile) {
base.Load(file, stream);
} else {
designerResourceService.Load(file, stream);
}
}
public override void Save(OpenedFile file, System.IO.Stream stream)
{
if (file == PrimaryFile) {
base.Save(file, stream);
} else {
if (hasUnmergedChanges) SaveToPrimary();
designerResourceService.Save(file, stream);
}
}
bool shouldUpdateSelectableObjects = false; bool shouldUpdateSelectableObjects = false;
void TransactionClose(object sender, DesignerTransactionCloseEventArgs e) void TransactionClose(object sender, DesignerTransactionCloseEventArgs e)
@ -268,6 +301,7 @@ namespace ICSharpCode.FormsDesigner
LoggingService.Info("Merging form changes..."); LoggingService.Info("Merging form changes...");
designSurface.Flush(); designSurface.Flush();
LoggingService.Info("Finished merging form changes"); LoggingService.Info("Finished merging form changes");
hasUnmergedChanges = false;
this.PrimaryFile.IsDirty = isDirty; this.PrimaryFile.IsDirty = isDirty;
} }
@ -320,7 +354,7 @@ namespace ICSharpCode.FormsDesigner
UpdatePropertyPad(); UpdatePropertyPad();
LoggingService.Info("Designer.OnViewActived 3"); LoggingService.Info("Designer.OnViewActived 3");
} }
*/ */
/* /*
protected override void OnViewDeactivated(EventArgs e) protected override void OnViewDeactivated(EventArgs e)
@ -352,7 +386,7 @@ namespace ICSharpCode.FormsDesigner
UnloadDesigner(); UnloadDesigner();
LoggingService.Info("Unloading form designer finished"); LoggingService.Info("Unloading form designer finished");
} }
*/ */
public override void Dispose() public override void Dispose()
{ {

286
src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs

@ -20,30 +20,80 @@ using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.FormsDesigner.Services namespace ICSharpCode.FormsDesigner.Services
{ {
public class DesignerResourceService : System.ComponentModel.Design.IResourceService , IDisposable sealed class DesignerResourceService : System.ComponentModel.Design.IResourceService , IDisposable
{ {
IDesignerHost host; FormsDesignerViewContent viewContent;
string formFileName;
public string FormFileName { public DesignerResourceService(FormsDesignerViewContent viewContent)
get { {
return formFileName; this.viewContent = viewContent;
}
#region System.ComponentModel.Design.IResourceService interface implementation
public System.Resources.IResourceWriter GetResourceWriter(CultureInfo info)
{
try {
LoggingService.Debug("ResourceWriter requested for culture: " + info.ToString());
return GetResourceStorage(info).GetWriter(this);
} catch (Exception e) {
MessageService.ShowError(e);
return null;
} }
set { }
formFileName = value;
public System.Resources.IResourceReader GetResourceReader(System.Globalization.CultureInfo info)
{
try {
LoggingService.Debug("ResourceReader requested for culture: "+info.ToString());
return GetResourceStorage(info).GetReader();
} catch (Exception e) {
MessageService.ShowError(e);
return null;
} }
} }
#endregion
// Culture name (or empty string) => Resources // Culture name (or empty string) => Resources
Dictionary<string, DesignerResourceService.ResourceStorage> resources = new Dictionary<string, DesignerResourceService.ResourceStorage>(); readonly Dictionary<string, ResourceStorage> resources = new Dictionary<string, ResourceStorage>();
readonly Dictionary<OpenedFile, ResourceStorage> resourceByFile = new Dictionary<OpenedFile, ResourceStorage>();
ResourceStorage GetResourceStorage(CultureInfo culture)
{
ResourceStorage storage;
if (!resources.TryGetValue(culture.Name, out storage)) {
storage = resources[culture.Name] = new ResourceStorage(culture.Name);
string fileName = CalcResourceFileName(viewContent.PrimaryFileName, culture.Name);
CreateOpenedFileForStorage(storage, fileName, File.Exists(fileName));
}
return storage;
}
void CreateOpenedFileForStorage(ResourceStorage storage, string fileName, bool isExistingFile)
{
storage.OpenedFile = FileService.GetOrCreateOpenedFile(fileName);
storage.IsNewFile = !isExistingFile;
if (!isExistingFile && storage.OpenedFile.RegisteredViewContents.Count == 0) {
storage.OpenedFile.SetData(new byte[0]);
}
resourceByFile[storage.OpenedFile] = storage;
// adding the opened file to the view content will load the file content into ResourceStorage.buffer
viewContent.Files.Add(storage.OpenedFile);
}
#region ResourceStorage #region ResourceStorage
public class ResourceStorage sealed class ResourceStorage
{ {
MemoryStream stream; MemoryStream stream;
IResourceWriter writer; IResourceWriter writer;
byte[] buffer; byte[] buffer;
ResourceType type = ResourceType.Resx; readonly string cultureName;
internal OpenedFile OpenedFile;
internal bool IsNewFile;
public ResourceStorage(string cultureName)
{
this.cultureName = cultureName;
}
/// <summary> /// <summary>
/// true, if the currently stored resource is not empty. /// true, if the currently stored resource is not empty.
@ -61,6 +111,8 @@ namespace ICSharpCode.FormsDesigner.Services
if (this.stream != null) { if (this.stream != null) {
this.writer.Dispose(); this.writer.Dispose();
this.stream.Dispose(); this.stream.Dispose();
this.writer = null;
this.stream = null;
} }
this.buffer = null; this.buffer = null;
} }
@ -73,93 +125,115 @@ namespace ICSharpCode.FormsDesigner.Services
byte[] GetBuffer() byte[] GetBuffer()
{ {
if (this.stream != null) { if (this.stream != null) {
byte[] buffer = this.stream.ToArray(); this.writer.Close();
if (buffer.Length > 0) { this.writer.Dispose();
this.writer.Close(); this.buffer = this.stream.ToArray();
this.writer.Dispose(); this.writer = null;
this.buffer = this.stream.ToArray(); this.stream.Dispose();
this.writer = null; this.stream = null;
this.stream.Dispose();
this.stream = null;
}
} }
return this.buffer; return this.buffer;
} }
// load from OpenedFile into memory
public void Load(Stream stream)
{
Dispose();
this.buffer = new byte[stream.Length];
int pos = 0;
while (pos < buffer.Length)
pos += stream.Read(buffer, pos, buffer.Length - pos);
}
/// <summary> /// <summary>
/// Returns a new resource reader for this resource based on the most recent /// Returns a new resource reader for this resource based on the most recent
/// version available (either in memory or on disk). /// version available (either in memory or on disk).
/// </summary> /// </summary>
public IResourceReader GetReader(string resourceFileName) public IResourceReader GetReader()
{ {
if (this.GetBuffer() == null) { if (this.GetBuffer() == null) {
if (File.Exists(resourceFileName)) { if (OpenedFile != null) {
type = GetResourceType(resourceFileName); return CreateResourceReader(OpenFileContentAsMemoryStream(OpenedFile), GetResourceType(OpenedFile.FileName));
return CreateResourceReader(resourceFileName, type);
} else { } else {
return null; return null;
} }
} else { } else {
ResourceType type = (OpenedFile != null) ? GetResourceType(OpenedFile.FileName) : ResourceType.Resx;
return CreateResourceReader(new MemoryStream(this.buffer, false), type); return CreateResourceReader(new MemoryStream(this.buffer, false), type);
} }
} }
static MemoryStream OpenFileContentAsMemoryStream(OpenedFile file)
{
Stream stream = file.OpenRead();
MemoryStream ms = stream as MemoryStream;
if (ms == null) {
// copy stream content to memory
try {
ms = new MemoryStream();
byte[] buffer = new byte[4096];
int c;
do {
c = stream.Read(buffer, 0, buffer.Length);
ms.Write(buffer, 0, c);
} while (c > 0);
ms.Position = 0;
} finally {
stream.Dispose();
}
}
return ms;
}
/// <summary> /// <summary>
/// Returns a new resource writer for this resource. /// Returns a new resource writer for this resource.
/// According to the SDK documentation of IResourceService.GetResourceWriter, /// According to the SDK documentation of IResourceService.GetResourceWriter,
/// a new writer needs to be returned every time one is requested, discarding any /// a new writer needs to be returned every time one is requested, discarding any
/// data written by previously returned writers. /// data written by previously returned writers.
/// </summary> /// </summary>
public IResourceWriter GetWriter() public IResourceWriter GetWriter(DesignerResourceService resourceService)
{ {
this.stream = new MemoryStream(); this.stream = new MemoryStream();
this.writer = CreateResourceWriter(this.stream, type); this.writer = CreateResourceWriter(this.stream, GetResourceType(OpenedFile.FileName));
return this.writer; return this.writer;
} }
public void Save(string fileName) public void Save(Stream stream, DesignerResourceService resourceService)
{ {
if (this.GetBuffer() != null) { if (this.GetBuffer() != null) {
File.WriteAllBytes(fileName, this.buffer); stream.Write(buffer, 0, buffer.Length);
if (IsNewFile) {
resourceService.AddFileToProject(this);
IsNewFile = false;
}
} }
} }
} }
#endregion #endregion
enum ResourceType { public void Load(OpenedFile file, Stream stream)
Resx = 0,
Resources = 1
};
// 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<string, ResourceStorage> Resources
{ {
get { resourceByFile[file].Load(stream);
return resources;
}
set {
resources = value;
}
} }
public IDesignerHost Host {
get { public void Save(OpenedFile file, Stream stream)
return host; {
} resourceByFile[file].Save(stream, this);
set {
host = value;
}
} }
public DesignerResourceService(string formFileName) public void MarkResourceFilesAsDirty()
{ {
this.formFileName = formFileName; foreach (ResourceStorage rs in resourceByFile.Values) {
rs.OpenedFile.MakeDirty();
}
} }
enum ResourceType {
Resx = 0,
Resources = 1
};
static IProject GetProject(string formFileName) static IProject GetProject(string formFileName)
{ {
if (ProjectService.OpenSolution != null && formFileName != null) if (ProjectService.OpenSolution != null && formFileName != null)
@ -168,77 +242,33 @@ namespace ICSharpCode.FormsDesigner.Services
return null; return null;
} }
#region System.ComponentModel.Design.IResourceService interface implementation void AddFileToProject(ResourceStorage storage)
public System.Resources.IResourceWriter GetResourceWriter(CultureInfo info)
{ {
try { string resourceFileName = storage.OpenedFile.FileName;
LoggingService.Debug("ResourceWriter requested for culture: " + info.ToString()); string formFileName = viewContent.PrimaryFileName;
ResourceStorage resourceStorage; IProject project = GetProject(formFileName);
if (resources.ContainsKey(info.Name)) {
resourceStorage = resources[info.Name]; // Add this resource file to the project
} else { if (project != null && !project.IsFileInProject(resourceFileName)) {
resourceStorage = new ResourceStorage(); FileProjectItem newFileProjectItem = new FileProjectItem(project, ItemType.EmbeddedResource);
resources[info.Name] = resourceStorage; newFileProjectItem.DependentUpon = Path.GetFileName(formFileName);
} newFileProjectItem.Include = FileUtility.GetRelativePath(project.Directory, resourceFileName);
return resourceStorage.GetWriter(); ProjectService.AddProjectItem(project, newFileProjectItem);
} catch (Exception e) { FileService.FireFileCreated(resourceFileName);
MessageService.ShowError(e);
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);
return null;
}
}
#endregion
public void Save(string formFileName) PadDescriptor pd = WorkbenchSingleton.Workbench.GetPad(typeof(ProjectBrowserPad));
{ FileNode formFileNode = ((ProjectBrowserPad)pd.PadContent).ProjectBrowserControl.FindFileNode(formFileName);
this.formFileName = formFileName; if (formFileNode != null) {
if (resources != null) { LoggingService.Info("FormFileNode found, adding subitem");
foreach (KeyValuePair<string, ResourceStorage> entry in resources) { FileNode fileNode = new FileNode(resourceFileName, FileNodeStatus.BehindFile);
string cultureName = entry.Key; fileNode.AddTo(formFileNode);
string resourceFileName = CalcResourceFileName(formFileName, cultureName); fileNode.ProjectItem = newFileProjectItem;
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();
}
} }
project.Save();
} }
} }
protected static string CalcResourceFileName(string formFileName, string cultureName) static string CalcResourceFileName(string formFileName, string cultureName)
{ {
StringBuilder resourceFileName = null; StringBuilder resourceFileName = null;
IProject project = GetProject(formFileName); IProject project = GetProject(formFileName);
@ -304,16 +334,10 @@ namespace ICSharpCode.FormsDesigner.Services
return ResourceType.Resources; return ResourceType.Resources;
} }
static IResourceReader CreateResourceReader(string fileName, ResourceType type)
{
if (type == ResourceType.Resources) {
return new ResourceReader(fileName);
}
return new ResXResourceReader(fileName);
}
static IResourceReader CreateResourceReader(Stream stream, ResourceType type) static IResourceReader CreateResourceReader(Stream stream, ResourceType type)
{ {
if (stream.Length == 0)
return null;
if (type == ResourceType.Resources) { if (type == ResourceType.Resources) {
return new ResourceReader(stream); return new ResourceReader(stream);
} }

2
src/AddIns/DisplayBindings/WorkflowDesigner/Project/Src/Services/WorkflowSideTabService.cs

@ -122,7 +122,7 @@ namespace WorkflowDesigner
} }
// Attach the handlers. // Attach the handlers.
viewContent.SwitchedTo += ViewContentActivatedEventHandler; //viewContent.SwitchedTo += ViewContentActivatedEventHandler;
viewContent.Disposed += ViewContentDisposedEventHandler; viewContent.Disposed += ViewContentDisposedEventHandler;
ViewCount++; ViewCount++;

14
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs

@ -133,12 +133,12 @@ namespace ICSharpCode.WpfDesign.AddIn
base.Dispose(); base.Dispose();
} }
protected override void OnSwitchedTo(EventArgs e) // protected override void OnSwitchedTo(EventArgs e)
{ // {
base.OnSwitchedTo(e); // base.OnSwitchedTo(e);
if (designer != null && designer.DesignContext != null) { // if (designer != null && designer.DesignContext != null) {
WpfToolbox.Instance.ToolService = designer.DesignContext.Services.Tool; // WpfToolbox.Instance.ToolService = designer.DesignContext.Services.Tool;
} // }
} // }
} }
} }

22
src/Main/Base/Project/Src/Gui/AbstractViewContent.cs

@ -45,28 +45,6 @@ namespace ICSharpCode.SharpDevelop.Gui
this.Files.Add(file); this.Files.Add(file);
} }
public event EventHandler SwitchedTo;
/// <summary>
/// Is called when the window is switched to.
/// -> Inside the tab (on SelectedIndexChanged of the tab control)
/// -> Inside the workbench (focus change in the docking library).
///
/// You <b>must</b> call base.OnViewActivated if you override this method, otherwise the <see cref="SwitchedTo"/>
/// event will not fire and <see cref="OpenedFile"/> will not work correctly.
/// </summary>
protected virtual void OnSwitchedTo(EventArgs e)
{
if (SwitchedTo != null) {
SwitchedTo(this, e);
}
}
void IViewContent.OnSwitchedTo()
{
OnSwitchedTo(EventArgs.Empty);
}
public abstract Control Control { public abstract Control Control {
get; get;
} }

10
src/Main/Base/Project/Src/Gui/IViewContent.cs

@ -65,16 +65,6 @@ namespace ICSharpCode.SharpDevelop.Gui
get; get;
} }
/// <summary>
/// Used internally.
/// Is called when the window is switched to.
/// -> Inside the tab (on SelectedIndexChanged of the tab control)
/// -> Inside the workbench (focus change in the docking library).
/// </summary>
void OnSwitchedTo();
event EventHandler SwitchedTo;
/// <summary> /// <summary>
/// Reinitializes the content. (Re-initializes all add-in tree stuff) /// Reinitializes the content. (Re-initializes all add-in tree stuff)
/// and redraws the content. /// and redraws the content.

2
src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/FolderNodeCommands.cs

@ -212,6 +212,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
"${res:ProjectComponent.ContextMenu.AddExistingFiles.Link}", "${res:ProjectComponent.ContextMenu.AddExistingFiles.Link}",
"${res:Global.CancelButtonText}"); "${res:Global.CancelButtonText}");
if (res == 1) { if (res == 1) {
// Link
foreach (KeyValuePair<string, string> pair in fileNames) { foreach (KeyValuePair<string, string> pair in fileNames) {
string fileName = pair.Key; string fileName = pair.Key;
string relFileName = FileUtility.GetRelativePath(node.Project.Directory, fileName); string relFileName = FileUtility.GetRelativePath(node.Project.Directory, fileName);
@ -229,6 +230,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
return; return;
} }
if (res == 2) { if (res == 2) {
// Cancel
return; return;
} }
// only continue for res==0 (Copy) // only continue for res==0 (Copy)

1
src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs

@ -619,7 +619,6 @@ namespace ICSharpCode.SharpDevelop.Gui
} }
oldSelectedWindow = newWindow; oldSelectedWindow = newWindow;
if (newWindow != null && newWindow.ActiveViewContent != null) { if (newWindow != null && newWindow.ActiveViewContent != null) {
newWindow.ActiveViewContent.OnSwitchedTo();
newWindow.OnWindowSelected(EventArgs.Empty); newWindow.OnWindowSelected(EventArgs.Empty);
} }
} }

1
src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs

@ -245,7 +245,6 @@ namespace ICSharpCode.SharpDevelop.Gui
this.Controls.Add(viewTabControl); this.Controls.Add(viewTabControl);
viewTabControl.SelectedIndexChanged += delegate { viewTabControl.SelectedIndexChanged += delegate {
this.ActiveViewContent.OnSwitchedTo();
UpdateActiveViewContent(); UpdateActiveViewContent();
}; };
} }

1
src/Main/Base/Project/Src/Project/CustomTool.cs

@ -145,6 +145,7 @@ namespace ICSharpCode.SharpDevelop.Project
outputItem.FileName = outputFileName; outputItem.FileName = outputFileName;
outputItem.DependentUpon = Path.GetFileName(baseItem.FileName); outputItem.DependentUpon = Path.GetFileName(baseItem.FileName);
ProjectService.AddProjectItem(project, outputItem); ProjectService.AddProjectItem(project, outputItem);
FileService.FireFileCreated(outputFileName);
project.Save(); project.Save();
ProjectBrowserPad.Instance.ProjectBrowserControl.RefreshView(); ProjectBrowserPad.Instance.ProjectBrowserControl.RefreshView();
} }

24
src/Main/Base/Project/Src/Services/File/FileService.cs

@ -88,10 +88,10 @@ namespace ICSharpCode.SharpDevelop
/// <summary> /// <summary>
/// Gets or creates an opened file. /// Gets or creates an opened file.
/// Warning: the opened file will be a file without any views attached. /// Warning: the opened file will be a file without any views attached.
/// Make sure to attach a view to it, or call CloseIfAllViewsClosed on the OpenedFile if you /// Make sure to attach a view to it, or call CloseIfAllViewsClosed on the OpenedFile to
/// are not sure that views were attached to it. /// unload the OpenedFile instance if no views were attached to it.
/// </summary> /// </summary>
internal static OpenedFile GetOrCreateOpenedFile(string fileName) public static OpenedFile GetOrCreateOpenedFile(string fileName)
{ {
if (fileName == null) if (fileName == null)
throw new ArgumentNullException("fileName"); throw new ArgumentNullException("fileName");
@ -105,15 +105,16 @@ namespace ICSharpCode.SharpDevelop
} }
/// <summary> /// <summary>
/// Attaches the view to the opened file. Creates a new OpenedFile instance if necessary. /// Creates a new untitled OpenedFile.
/// </summary> /// </summary>
public static OpenedFile AttachToOpenedFile(string fileName, IViewContent view) public static OpenedFile CreateUntitledOpenedFile(string defaultName, byte[] content)
{ {
if (view == null) if (defaultName == null)
throw new ArgumentNullException("view"); throw new ArgumentNullException("defaultName");
OpenedFile file = GetOrCreateOpenedFile(fileName); OpenedFile file = new OpenedFile(content);
file.RegisterView(view); file.FileName = file.GetHashCode() + "/" + defaultName;
openedFileDict[file.FileName] = file;
return file; return file;
} }
@ -248,13 +249,12 @@ namespace ICSharpCode.SharpDevelop
IDisplayBinding binding = DisplayBindingService.GetBindingPerFileName(defaultName); IDisplayBinding binding = DisplayBindingService.GetBindingPerFileName(defaultName);
if (binding != null) { if (binding != null) {
OpenedFile file = new OpenedFile(content); OpenedFile file = CreateUntitledOpenedFile(defaultName, content);
file.FileName = file.GetHashCode() + "/" + defaultName;
openedFileDict[file.FileName] = file;
IViewContent newContent = binding.CreateContentForFile(file); IViewContent newContent = binding.CreateContentForFile(file);
if (newContent == null) { if (newContent == null) {
LoggingService.Warn("Created view content was null - DefaultName:" + defaultName); LoggingService.Warn("Created view content was null - DefaultName:" + defaultName);
file.CloseIfAllViewsClosed();
return null; return null;
} }

54
src/Main/Base/Project/Src/Services/File/OpenedFile.cs

@ -48,7 +48,6 @@ namespace ICSharpCode.SharpDevelop
/// <summary> /// <summary>
/// Creates a dummy opened file instance. Use for unit tests only! /// Creates a dummy opened file instance. Use for unit tests only!
/// Do not call UnregisterView or CloseIfAllViewsClosed on the dummy opened file!!!
/// </summary> /// </summary>
public static OpenedFile CreateDummyOpenedFile(string name, bool isUntitled) public static OpenedFile CreateDummyOpenedFile(string name, bool isUntitled)
{ {
@ -120,6 +119,28 @@ namespace ICSharpCode.SharpDevelop
} }
} }
/// <summary>
/// Sets the internally stored data to the specified byte array.
/// This method should only be used when there is no current view or by the
/// current view.
/// </summary>
/// <remarks>
/// Use this method to specify the initial file content if you use a OpenedFile instance
/// for a file that doesn't exist on disk but should be automatically created when a view
/// with the file is saved, e.g. for .resx files created by the forms designer.
/// </remarks>
public void SetData(byte[] fileData)
{
if (fileData == null)
throw new ArgumentNullException("fileData");
if (inLoadOperation)
throw new InvalidOperationException("SetData cannot be used while loading");
if (inSaveOperation)
throw new InvalidOperationException("SetData cannot be used while saving");
this.fileData = fileData;
}
public void SaveToDisk(string newFileName) public void SaveToDisk(string newFileName)
{ {
this.FileName = newFileName; this.FileName = newFileName;
@ -166,11 +187,18 @@ namespace ICSharpCode.SharpDevelop
// /// </summary> // /// </summary>
// public event EventHandler SavedCurrentView; // public event EventHandler SavedCurrentView;
bool inSaveOperation;
void SaveCurrentViewToStream(Stream stream) void SaveCurrentViewToStream(Stream stream)
{ {
// if (SavingCurrentView != null) // if (SavingCurrentView != null)
// SavingCurrentView(this, EventArgs.Empty); // SavingCurrentView(this, EventArgs.Empty);
currentView.Save(this, stream); inSaveOperation = true;
try {
currentView.Save(this, stream);
} finally {
inSaveOperation = false;
}
// if (SavedCurrentView != null) // if (SavedCurrentView != null)
// SavedCurrentView(this, EventArgs.Empty); // SavedCurrentView(this, EventArgs.Empty);
} }
@ -191,7 +219,10 @@ namespace ICSharpCode.SharpDevelop
registeredViews.Add(view); registeredViews.Add(view);
view.SwitchedTo += SwitchedToView; WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchActiveViewContentChanged;
if (WorkbenchSingleton.Workbench.ActiveViewContent == view) {
SwitchedToView(view);
}
#if DEBUG #if DEBUG
view.Disposed += ViewDisposed; view.Disposed += ViewDisposed;
#endif #endif
@ -203,7 +234,7 @@ namespace ICSharpCode.SharpDevelop
throw new ArgumentNullException("view"); throw new ArgumentNullException("view");
Debug.Assert(registeredViews.Contains(view)); Debug.Assert(registeredViews.Contains(view));
view.SwitchedTo -= SwitchedToView; WorkbenchSingleton.Workbench.ActiveViewContentChanged -= WorkbenchActiveViewContentChanged;
#if DEBUG #if DEBUG
view.Disposed -= ViewDisposed; view.Disposed -= ViewDisposed;
#endif #endif
@ -249,7 +280,7 @@ namespace ICSharpCode.SharpDevelop
if (currentView != view) { if (currentView != view) {
if (currentView == null) { if (currentView == null) {
SwitchedToView(view, EventArgs.Empty); SwitchedToView(view);
} else { } else {
try { try {
inLoadOperation = true; inLoadOperation = true;
@ -263,9 +294,18 @@ namespace ICSharpCode.SharpDevelop
} }
} }
void SwitchedToView(object sender, EventArgs e) void WorkbenchActiveViewContentChanged(object sender, EventArgs e)
{
IViewContent newView = WorkbenchSingleton.Workbench.ActiveViewContent;
if (!registeredViews.Contains(newView))
return;
SwitchedToView(newView);
}
void SwitchedToView(IViewContent newView)
{ {
IViewContent newView = (IViewContent)sender;
if (currentView != null) { if (currentView != null) {
if (newView.SupportsSwitchToThisWithoutSaveLoad(this, currentView) if (newView.SupportsSwitchToThisWithoutSaveLoad(this, currentView)
|| currentView.SupportsSwitchFromThisWithoutSaveLoad(this, newView)) || currentView.SupportsSwitchFromThisWithoutSaveLoad(this, newView))

1
src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs

@ -182,6 +182,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands
FileProjectItem projectItem = new FileProjectItem(project, ItemType.Compile); FileProjectItem projectItem = new FileProjectItem(project, ItemType.Compile);
projectItem.FileName = newFileName; projectItem.FileName = newFileName;
ProjectService.AddProjectItem(project, projectItem); ProjectService.AddProjectItem(project, projectItem);
FileService.FireFileCreated(newFileName);
project.Save(); project.Save();
ProjectBrowserPad.Instance.ProjectBrowserControl.RefreshView(); ProjectBrowserPad.Instance.ProjectBrowserControl.RefreshView();
} }

6
src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs

@ -203,6 +203,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
public override void Save(OpenedFile file, Stream stream) public override void Save(OpenedFile file, Stream stream)
{ {
if (file != PrimaryFile)
throw new ArgumentException("file != PrimaryFile");
if (!textEditorControl.CanSaveWithCurrentEncoding()) { if (!textEditorControl.CanSaveWithCurrentEncoding()) {
if (MessageService.AskQuestion("The file cannot be saved with the current encoding " + if (MessageService.AskQuestion("The file cannot be saved with the current encoding " +
textEditorControl.Encoding.EncodingName + " without losing data." + textEditorControl.Encoding.EncodingName + " without losing data." +
@ -216,6 +219,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
public override void Load(OpenedFile file, Stream stream) public override void Load(OpenedFile file, Stream stream)
{ {
if (file != PrimaryFile)
throw new ArgumentException("file != PrimaryFile");
if (!file.IsUntitled) { if (!file.IsUntitled) {
textEditorControl.IsReadOnly = (File.GetAttributes(file.FileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly; textEditorControl.IsReadOnly = (File.GetAttributes(file.FileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
} }

Loading…
Cancel
Save