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 @@ @@ -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 @@ -65,6 +66,10 @@ namespace ICSharpCode.FormsDesigner
}
}
internal new ICollection<OpenedFile> Files {
get { return base.Files; }
}
public IDesignerHost Host {
get {
if (designSurface == null)
@ -110,7 +115,7 @@ namespace ICSharpCode.FormsDesigner @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -352,7 +386,7 @@ namespace ICSharpCode.FormsDesigner
UnloadDesigner();
LoggingService.Info("Unloading form designer finished");
}
*/
*/
public override void Dispose()
{

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

@ -20,30 +20,80 @@ using ICSharpCode.SharpDevelop.Project; @@ -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<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
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;
}
/// <summary>
/// true, if the currently stored resource is not empty.
@ -61,6 +111,8 @@ namespace ICSharpCode.FormsDesigner.Services @@ -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 @@ -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);
}
/// <summary>
/// Returns a new resource reader for this resource based on the most recent
/// version available (either in memory or on disk).
/// </summary>
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;
}
/// <summary>
/// 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.
/// </summary>
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<string, ResourceStorage> 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 @@ -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<string, ResourceStorage> 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 @@ -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);
}

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

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

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

@ -133,12 +133,12 @@ namespace ICSharpCode.WpfDesign.AddIn @@ -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;
// }
// }
}
}

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

@ -45,28 +45,6 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -45,28 +45,6 @@ namespace ICSharpCode.SharpDevelop.Gui
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 {
get;
}

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

@ -65,16 +65,6 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -65,16 +65,6 @@ namespace ICSharpCode.SharpDevelop.Gui
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>
/// Reinitializes the content. (Re-initializes all add-in tree stuff)
/// 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 @@ -212,6 +212,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
"${res:ProjectComponent.ContextMenu.AddExistingFiles.Link}",
"${res:Global.CancelButtonText}");
if (res == 1) {
// Link
foreach (KeyValuePair<string, string> pair in fileNames) {
string fileName = pair.Key;
string relFileName = FileUtility.GetRelativePath(node.Project.Directory, fileName);
@ -229,6 +230,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -229,6 +230,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
return;
}
if (res == 2) {
// Cancel
return;
}
// 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 @@ -619,7 +619,6 @@ namespace ICSharpCode.SharpDevelop.Gui
}
oldSelectedWindow = newWindow;
if (newWindow != null && newWindow.ActiveViewContent != null) {
newWindow.ActiveViewContent.OnSwitchedTo();
newWindow.OnWindowSelected(EventArgs.Empty);
}
}

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

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

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

@ -145,6 +145,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -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();
}

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

@ -88,10 +88,10 @@ namespace ICSharpCode.SharpDevelop @@ -88,10 +88,10 @@ namespace ICSharpCode.SharpDevelop
/// <summary>
/// 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.
/// </summary>
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 @@ -105,15 +105,16 @@ namespace ICSharpCode.SharpDevelop
}
/// <summary>
/// Attaches the view to the opened file. Creates a new OpenedFile instance if necessary.
/// Creates a new untitled OpenedFile.
/// </summary>
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 @@ -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;
}

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

@ -48,7 +48,6 @@ namespace ICSharpCode.SharpDevelop @@ -48,7 +48,6 @@ namespace ICSharpCode.SharpDevelop
/// <summary>
/// Creates a dummy opened file instance. Use for unit tests only!
/// Do not call UnregisterView or CloseIfAllViewsClosed on the dummy opened file!!!
/// </summary>
public static OpenedFile CreateDummyOpenedFile(string name, bool isUntitled)
{
@ -120,6 +119,28 @@ namespace ICSharpCode.SharpDevelop @@ -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)
{
this.FileName = newFileName;
@ -166,11 +187,18 @@ namespace ICSharpCode.SharpDevelop @@ -166,11 +187,18 @@ namespace ICSharpCode.SharpDevelop
// /// </summary>
// 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 @@ -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 @@ -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 @@ -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 @@ -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))

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

@ -182,6 +182,7 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Commands @@ -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();
}

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

@ -203,6 +203,9 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor @@ -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 @@ -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;
}

Loading…
Cancel
Save