diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs index ad0c830734..59e36e14d8 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/DesignerViewContent.cs @@ -7,6 +7,7 @@ using System; using System.Collections; +using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.Design; using System.ComponentModel.Design.Serialization; @@ -65,6 +66,10 @@ namespace ICSharpCode.FormsDesigner } } + internal new ICollection Files { + get { return base.Files; } + } + public IDesignerHost Host { get { if (designSurface == null) @@ -110,7 +115,7 @@ namespace ICSharpCode.FormsDesigner // may not have been written to disk yet if the user switched // between source and design view without saving. if (designerResourceService == null) { - designerResourceService = new DesignerResourceService(viewContent.PrimaryFileName); + designerResourceService = new DesignerResourceService(this); } serviceContainer.AddService(typeof(System.ComponentModel.Design.IResourceService), designerResourceService); AmbientProperties ambientProperties = new AmbientProperties(); @@ -127,8 +132,6 @@ namespace ICSharpCode.FormsDesigner ICSharpCode.FormsDesigner.Services.EventBindingService eventBindingService = new ICSharpCode.FormsDesigner.Services.EventBindingService(designSurface); serviceContainer.AddService(typeof(System.ComponentModel.Design.IEventBindingService), eventBindingService); - designerResourceService.Host = Host; - DesignerLoader designerLoader = loaderProvider.CreateLoader(generator); designSurface.BeginLoad(designerLoader); @@ -137,7 +140,7 @@ namespace ICSharpCode.FormsDesigner undoEngine = new FormsDesignerUndoEngine(Host); IComponentChangeService componentChangeService = (IComponentChangeService)designSurface.GetService(typeof(IComponentChangeService)); - componentChangeService.ComponentChanged += delegate { this.PrimaryFile.MakeDirty(); }; + componentChangeService.ComponentChanged += MakeDirty; componentChangeService.ComponentAdded += ComponentListChanged; componentChangeService.ComponentRemoved += ComponentListChanged; componentChangeService.ComponentRename += ComponentListChanged; @@ -153,9 +156,39 @@ namespace ICSharpCode.FormsDesigner UpdatePropertyPad(); + hasUnmergedChanges = false; + 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; void TransactionClose(object sender, DesignerTransactionCloseEventArgs e) @@ -268,6 +301,7 @@ namespace ICSharpCode.FormsDesigner LoggingService.Info("Merging form changes..."); designSurface.Flush(); LoggingService.Info("Finished merging form changes"); + hasUnmergedChanges = false; this.PrimaryFile.IsDirty = isDirty; } @@ -320,7 +354,7 @@ namespace ICSharpCode.FormsDesigner UpdatePropertyPad(); LoggingService.Info("Designer.OnViewActived 3"); } - */ + */ /* protected override void OnViewDeactivated(EventArgs e) @@ -352,7 +386,7 @@ namespace ICSharpCode.FormsDesigner UnloadDesigner(); LoggingService.Info("Unloading form designer finished"); } - */ + */ public override void Dispose() { diff --git a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs index 59bc841813..d8dac508e6 100644 --- a/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs +++ b/src/AddIns/DisplayBindings/FormsDesigner/Project/Src/Services/DesignerResourceService.cs @@ -20,30 +20,80 @@ using ICSharpCode.SharpDevelop.Project; namespace ICSharpCode.FormsDesigner.Services { - public class DesignerResourceService : System.ComponentModel.Design.IResourceService , IDisposable + sealed class DesignerResourceService : System.ComponentModel.Design.IResourceService , IDisposable { - IDesignerHost host; - string formFileName; + FormsDesignerViewContent viewContent; - public string FormFileName { - get { - return formFileName; + public DesignerResourceService(FormsDesignerViewContent viewContent) + { + 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 - Dictionary resources = new Dictionary(); + readonly Dictionary resources = new Dictionary(); + readonly Dictionary resourceByFile = new Dictionary(); + + 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 - public class ResourceStorage + sealed class ResourceStorage { MemoryStream stream; IResourceWriter writer; byte[] buffer; - ResourceType type = ResourceType.Resx; + readonly string cultureName; + internal OpenedFile OpenedFile; + internal bool IsNewFile; + + public ResourceStorage(string cultureName) + { + this.cultureName = cultureName; + } /// /// true, if the currently stored resource is not empty. @@ -61,6 +111,8 @@ namespace ICSharpCode.FormsDesigner.Services if (this.stream != null) { this.writer.Dispose(); this.stream.Dispose(); + this.writer = null; + this.stream = null; } this.buffer = null; } @@ -73,93 +125,115 @@ namespace ICSharpCode.FormsDesigner.Services 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; - } + this.writer.Close(); + this.writer.Dispose(); + this.buffer = this.stream.ToArray(); + this.writer = null; + this.stream.Dispose(); + this.stream = null; } 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); + } + /// /// Returns a new resource reader for this resource based on the most recent /// version available (either in memory or on disk). /// - public IResourceReader GetReader(string resourceFileName) + public IResourceReader GetReader() { if (this.GetBuffer() == null) { - if (File.Exists(resourceFileName)) { - type = GetResourceType(resourceFileName); - return CreateResourceReader(resourceFileName, type); + if (OpenedFile != null) { + return CreateResourceReader(OpenFileContentAsMemoryStream(OpenedFile), GetResourceType(OpenedFile.FileName)); } else { return null; } } else { + ResourceType type = (OpenedFile != null) ? GetResourceType(OpenedFile.FileName) : ResourceType.Resx; 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; + } + /// /// 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() + public IResourceWriter GetWriter(DesignerResourceService resourceService) { this.stream = new MemoryStream(); - this.writer = CreateResourceWriter(this.stream, type); + this.writer = CreateResourceWriter(this.stream, GetResourceType(OpenedFile.FileName)); return this.writer; } - public void Save(string fileName) + public void Save(Stream stream, DesignerResourceService resourceService) { if (this.GetBuffer() != null) { - File.WriteAllBytes(fileName, this.buffer); + stream.Write(buffer, 0, buffer.Length); + if (IsNewFile) { + resourceService.AddFileToProject(this); + IsNewFile = false; + } } } } #endregion - enum ResourceType { - 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 Resources + public void Load(OpenedFile file, Stream stream) { - get { - return resources; - } - set { - resources = value; - } + resourceByFile[file].Load(stream); } - public IDesignerHost Host { - get { - return host; - } - set { - host = value; - } + + public void Save(OpenedFile file, Stream stream) + { + resourceByFile[file].Save(stream, this); } - - 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) { if (ProjectService.OpenSolution != null && formFileName != null) @@ -168,77 +242,33 @@ namespace ICSharpCode.FormsDesigner.Services return null; } - #region System.ComponentModel.Design.IResourceService interface implementation - public System.Resources.IResourceWriter GetResourceWriter(CultureInfo info) + void AddFileToProject(ResourceStorage storage) { - 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); - 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 + string resourceFileName = storage.OpenedFile.FileName; + string formFileName = viewContent.PrimaryFileName; + IProject project = GetProject(formFileName); + + // Add this resource file to the project + if (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); + FileService.FireFileCreated(resourceFileName); - public void Save(string formFileName) - { - this.formFileName = formFileName; - 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(); - } + 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 static string CalcResourceFileName(string formFileName, string cultureName) + + static string CalcResourceFileName(string formFileName, string cultureName) { StringBuilder resourceFileName = null; IProject project = GetProject(formFileName); @@ -304,16 +334,10 @@ namespace ICSharpCode.FormsDesigner.Services 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) { + if (stream.Length == 0) + return null; if (type == ResourceType.Resources) { return new ResourceReader(stream); } diff --git a/src/AddIns/DisplayBindings/WorkflowDesigner/Project/Src/Services/WorkflowSideTabService.cs b/src/AddIns/DisplayBindings/WorkflowDesigner/Project/Src/Services/WorkflowSideTabService.cs index 2197402746..f2d232c13a 100644 --- a/src/AddIns/DisplayBindings/WorkflowDesigner/Project/Src/Services/WorkflowSideTabService.cs +++ b/src/AddIns/DisplayBindings/WorkflowDesigner/Project/Src/Services/WorkflowSideTabService.cs @@ -122,7 +122,7 @@ namespace WorkflowDesigner } // Attach the handlers. - viewContent.SwitchedTo += ViewContentActivatedEventHandler; + //viewContent.SwitchedTo += ViewContentActivatedEventHandler; viewContent.Disposed += ViewContentDisposedEventHandler; ViewCount++; diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs index 3ded37d691..d12a8d9a0f 100644 --- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs +++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs @@ -133,12 +133,12 @@ namespace ICSharpCode.WpfDesign.AddIn base.Dispose(); } - protected override void OnSwitchedTo(EventArgs e) - { - base.OnSwitchedTo(e); - if (designer != null && designer.DesignContext != null) { - WpfToolbox.Instance.ToolService = designer.DesignContext.Services.Tool; - } - } +// protected override void OnSwitchedTo(EventArgs e) +// { +// base.OnSwitchedTo(e); +// if (designer != null && designer.DesignContext != null) { +// WpfToolbox.Instance.ToolService = designer.DesignContext.Services.Tool; +// } +// } } } diff --git a/src/Main/Base/Project/Src/Gui/AbstractViewContent.cs b/src/Main/Base/Project/Src/Gui/AbstractViewContent.cs index 435e7050c8..ec7ccee51e 100644 --- a/src/Main/Base/Project/Src/Gui/AbstractViewContent.cs +++ b/src/Main/Base/Project/Src/Gui/AbstractViewContent.cs @@ -45,28 +45,6 @@ namespace ICSharpCode.SharpDevelop.Gui this.Files.Add(file); } - public event EventHandler SwitchedTo; - - /// - /// 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 must call base.OnViewActivated if you override this method, otherwise the - /// event will not fire and will not work correctly. - /// - protected virtual void OnSwitchedTo(EventArgs e) - { - if (SwitchedTo != null) { - SwitchedTo(this, e); - } - } - - void IViewContent.OnSwitchedTo() - { - OnSwitchedTo(EventArgs.Empty); - } - public abstract Control Control { get; } diff --git a/src/Main/Base/Project/Src/Gui/IViewContent.cs b/src/Main/Base/Project/Src/Gui/IViewContent.cs index 82b051d215..62c88fa803 100644 --- a/src/Main/Base/Project/Src/Gui/IViewContent.cs +++ b/src/Main/Base/Project/Src/Gui/IViewContent.cs @@ -65,16 +65,6 @@ namespace ICSharpCode.SharpDevelop.Gui get; } - /// - /// 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). - /// - void OnSwitchedTo(); - - event EventHandler SwitchedTo; - /// /// Reinitializes the content. (Re-initializes all add-in tree stuff) /// and redraws the content. diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/FolderNodeCommands.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/FolderNodeCommands.cs index ce3c582f59..933d273eca 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/FolderNodeCommands.cs +++ b/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:Global.CancelButtonText}"); if (res == 1) { + // Link foreach (KeyValuePair pair in fileNames) { string fileName = pair.Key; string relFileName = FileUtility.GetRelativePath(node.Project.Directory, fileName); @@ -229,6 +230,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands return; } if (res == 2) { + // Cancel return; } // only continue for res==0 (Copy) diff --git a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs index 722279021b..c0d10f6d07 100644 --- a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs +++ b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceLayout.cs @@ -619,7 +619,6 @@ namespace ICSharpCode.SharpDevelop.Gui } oldSelectedWindow = newWindow; if (newWindow != null && newWindow.ActiveViewContent != null) { - newWindow.ActiveViewContent.OnSwitchedTo(); newWindow.OnWindowSelected(EventArgs.Empty); } } diff --git a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs index a2111e8880..94f3e389c8 100644 --- a/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs +++ b/src/Main/Base/Project/Src/Gui/Workbench/Layouts/SdiWorkspaceWindow.cs @@ -245,7 +245,6 @@ namespace ICSharpCode.SharpDevelop.Gui this.Controls.Add(viewTabControl); viewTabControl.SelectedIndexChanged += delegate { - this.ActiveViewContent.OnSwitchedTo(); UpdateActiveViewContent(); }; } diff --git a/src/Main/Base/Project/Src/Project/CustomTool.cs b/src/Main/Base/Project/Src/Project/CustomTool.cs index d8fa57c7c3..292354ea89 100644 --- a/src/Main/Base/Project/Src/Project/CustomTool.cs +++ b/src/Main/Base/Project/Src/Project/CustomTool.cs @@ -145,6 +145,7 @@ namespace ICSharpCode.SharpDevelop.Project outputItem.FileName = outputFileName; outputItem.DependentUpon = Path.GetFileName(baseItem.FileName); ProjectService.AddProjectItem(project, outputItem); + FileService.FireFileCreated(outputFileName); project.Save(); ProjectBrowserPad.Instance.ProjectBrowserControl.RefreshView(); } diff --git a/src/Main/Base/Project/Src/Services/File/FileService.cs b/src/Main/Base/Project/Src/Services/File/FileService.cs index b7917202ca..b964fb669c 100644 --- a/src/Main/Base/Project/Src/Services/File/FileService.cs +++ b/src/Main/Base/Project/Src/Services/File/FileService.cs @@ -88,10 +88,10 @@ namespace ICSharpCode.SharpDevelop /// /// Gets or creates an opened file. /// 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 - /// are not sure that views were attached to it. + /// Make sure to attach a view to it, or call CloseIfAllViewsClosed on the OpenedFile to + /// unload the OpenedFile instance if no views were attached to it. /// - internal static OpenedFile GetOrCreateOpenedFile(string fileName) + public static OpenedFile GetOrCreateOpenedFile(string fileName) { if (fileName == null) throw new ArgumentNullException("fileName"); @@ -105,15 +105,16 @@ namespace ICSharpCode.SharpDevelop } /// - /// Attaches the view to the opened file. Creates a new OpenedFile instance if necessary. + /// Creates a new untitled OpenedFile. /// - public static OpenedFile AttachToOpenedFile(string fileName, IViewContent view) + public static OpenedFile CreateUntitledOpenedFile(string defaultName, byte[] content) { - if (view == null) - throw new ArgumentNullException("view"); + if (defaultName == null) + throw new ArgumentNullException("defaultName"); - OpenedFile file = GetOrCreateOpenedFile(fileName); - file.RegisterView(view); + OpenedFile file = new OpenedFile(content); + file.FileName = file.GetHashCode() + "/" + defaultName; + openedFileDict[file.FileName] = file; return file; } @@ -248,13 +249,12 @@ namespace ICSharpCode.SharpDevelop IDisplayBinding binding = DisplayBindingService.GetBindingPerFileName(defaultName); if (binding != null) { - OpenedFile file = new OpenedFile(content); - file.FileName = file.GetHashCode() + "/" + defaultName; - openedFileDict[file.FileName] = file; + OpenedFile file = CreateUntitledOpenedFile(defaultName, content); IViewContent newContent = binding.CreateContentForFile(file); if (newContent == null) { LoggingService.Warn("Created view content was null - DefaultName:" + defaultName); + file.CloseIfAllViewsClosed(); return null; } diff --git a/src/Main/Base/Project/Src/Services/File/OpenedFile.cs b/src/Main/Base/Project/Src/Services/File/OpenedFile.cs index 702452e09f..fe6bcc4dee 100644 --- a/src/Main/Base/Project/Src/Services/File/OpenedFile.cs +++ b/src/Main/Base/Project/Src/Services/File/OpenedFile.cs @@ -48,7 +48,6 @@ namespace ICSharpCode.SharpDevelop /// /// Creates a dummy opened file instance. Use for unit tests only! - /// Do not call UnregisterView or CloseIfAllViewsClosed on the dummy opened file!!! /// public static OpenedFile CreateDummyOpenedFile(string name, bool isUntitled) { @@ -120,6 +119,28 @@ namespace ICSharpCode.SharpDevelop } } + /// + /// 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. + /// + /// + /// 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. + /// + 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) { this.FileName = newFileName; @@ -166,11 +187,18 @@ namespace ICSharpCode.SharpDevelop // /// // public event EventHandler SavedCurrentView; + bool inSaveOperation; + void SaveCurrentViewToStream(Stream stream) { // if (SavingCurrentView != null) // SavingCurrentView(this, EventArgs.Empty); - currentView.Save(this, stream); + inSaveOperation = true; + try { + currentView.Save(this, stream); + } finally { + inSaveOperation = false; + } // if (SavedCurrentView != null) // SavedCurrentView(this, EventArgs.Empty); } @@ -191,7 +219,10 @@ namespace ICSharpCode.SharpDevelop registeredViews.Add(view); - view.SwitchedTo += SwitchedToView; + WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchActiveViewContentChanged; + if (WorkbenchSingleton.Workbench.ActiveViewContent == view) { + SwitchedToView(view); + } #if DEBUG view.Disposed += ViewDisposed; #endif @@ -203,7 +234,7 @@ namespace ICSharpCode.SharpDevelop throw new ArgumentNullException("view"); Debug.Assert(registeredViews.Contains(view)); - view.SwitchedTo -= SwitchedToView; + WorkbenchSingleton.Workbench.ActiveViewContentChanged -= WorkbenchActiveViewContentChanged; #if DEBUG view.Disposed -= ViewDisposed; #endif @@ -249,7 +280,7 @@ namespace ICSharpCode.SharpDevelop if (currentView != view) { if (currentView == null) { - SwitchedToView(view, EventArgs.Empty); + SwitchedToView(view); } else { try { 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 (newView.SupportsSwitchToThisWithoutSaveLoad(this, currentView) || currentView.SupportsSwitchFromThisWithoutSaveLoad(this, newView)) diff --git a/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs b/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs index 24289b7a38..9e9f99d8b2 100644 --- a/src/Main/Base/Project/Src/TextEditor/Commands/ClassBookmarkMenuBuilder.cs +++ b/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); projectItem.FileName = newFileName; ProjectService.AddProjectItem(project, projectItem); + FileService.FireFileCreated(newFileName); project.Save(); ProjectBrowserPad.Instance.ProjectBrowserControl.RefreshView(); } diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs index 8f8c4032b0..3e257e1f3d 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs +++ b/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) { + if (file != PrimaryFile) + throw new ArgumentException("file != PrimaryFile"); + if (!textEditorControl.CanSaveWithCurrentEncoding()) { if (MessageService.AskQuestion("The file cannot be saved with the current encoding " + textEditorControl.Encoding.EncodingName + " without losing data." + @@ -216,6 +219,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor public override void Load(OpenedFile file, Stream stream) { + if (file != PrimaryFile) + throw new ArgumentException("file != PrimaryFile"); + if (!file.IsUntitled) { textEditorControl.IsReadOnly = (File.GetAttributes(file.FileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly; }