Browse Source

Implemented loading+saving of project+solution preferences.

pull/32/merge
Daniel Grunwald 13 years ago
parent
commit
94e05c3e7f
  1. 2
      src/Main/Base/Project/Dom/SimpleModelCollection.cs
  2. 9
      src/Main/Base/Project/Dom/SynchronizedModelCollection.cs
  3. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  4. 2
      src/Main/Base/Project/Project/ISolution.cs
  5. 4
      src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs
  6. 69
      src/Main/Base/Project/Src/Project/AbstractProject.cs
  7. 19
      src/Main/Base/Project/Src/Project/Behaviors/DefaultProjectBehavior.cs
  8. 21
      src/Main/Base/Project/Src/Project/Behaviors/ProjectBehavior.cs
  9. 34
      src/Main/Base/Project/Src/Project/IProject.cs
  10. 2
      src/Main/Base/Project/Src/Project/ProjectCustomToolOptions.cs
  11. 31
      src/Main/Base/Project/Util/CompositeDisposable.cs
  12. 2
      src/Main/Base/Test/Project/ProjectCustomToolOptionsTests.cs
  13. 2
      src/Main/Base/Test/Utils/ProjectHelper.cs
  14. 2
      src/Main/Core/Project/Src/Services/PropertyService/Properties.cs
  15. 4
      src/Main/Core/Project/Src/Services/PropertyService/PropertyServiceImpl.cs
  16. 4
      src/Main/SharpDevelop/Project/ProjectService.cs
  17. 149
      src/Main/SharpDevelop/Project/Solution.cs
  18. 18
      src/Main/SharpDevelop/Project/SolutionFolder.cs
  19. 2
      src/Main/SharpDevelop/Workbench/AvalonPadContent.cs
  20. 2
      src/Main/SharpDevelop/Workbench/AvalonWorkbenchWindow.cs
  21. 4
      src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs

2
src/Main/Base/Project/Dom/SimpleModelCollection.cs

@ -69,7 +69,7 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -69,7 +69,7 @@ namespace ICSharpCode.SharpDevelop.Dom
handler(removedItems, addedItems);
}
public IDisposable BatchUpdate()
public virtual IDisposable BatchUpdate()
{
if (isWithinBatchOperation)
return null;

9
src/Main/Base/Project/Dom/SynchronizedModelCollection.cs

@ -80,9 +80,12 @@ namespace ICSharpCode.SharpDevelop.Dom @@ -80,9 +80,12 @@ namespace ICSharpCode.SharpDevelop.Dom
IDisposable disposable = underlyingCollection.BatchUpdate();
return new CallbackOnDispose(
delegate {
if (disposable != null)
disposable.Dispose();
Monitor.Exit(syncRoot);
try {
if (disposable != null)
disposable.Dispose();
} finally {
Monitor.Exit(syncRoot);
}
});
}

1
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -236,6 +236,7 @@ @@ -236,6 +236,7 @@
<Compile Include="Src\Project\MSBuildConfigurationOrPlatformNameCollection.cs" />
<Compile Include="Util\AtomicBoolean.cs" />
<Compile Include="Util\ComparerExtensions.cs" />
<Compile Include="Util\CompositeDisposable.cs" />
<Compile Include="Util\CustomThreadPoolTaskScheduler.cs" />
<Compile Include="Util\DebugTimer.cs" />
<Compile Include="Util\DotnetDetection.cs" />

2
src/Main/Base/Project/Project/ISolution.cs

@ -85,7 +85,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -85,7 +85,7 @@ namespace ICSharpCode.SharpDevelop.Project
event EventHandler PreferencesSaving;
/// <summary>
/// Saves the preferences for this solution; and also for any projects within this solution.
/// Saves the preferences for this solution.
/// </summary>
void SavePreferences();

4
src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs

@ -52,9 +52,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -52,9 +52,7 @@ namespace ICSharpCode.SharpDevelop.Gui
void ParserService_LoadSolutionProjectsThreadEnded(object sender, EventArgs e)
{
// refresh the list box contents when parsing has completed
Dispatcher.BeginInvoke(
System.Windows.Threading.DispatcherPriority.Background,
new Action(delegate { textBoxTextChanged(null, null); }));
textBoxTextChanged(null, null);
}
class GotoEntry : IComparable<GotoEntry>

69
src/Main/Base/Project/Src/Project/AbstractProject.cs

@ -11,6 +11,7 @@ using System.Linq; @@ -11,6 +11,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem;
@ -75,21 +76,50 @@ namespace ICSharpCode.SharpDevelop.Project @@ -75,21 +76,50 @@ namespace ICSharpCode.SharpDevelop.Project
}
#endregion
#region IMementoCapable implementation
/// <summary>
/// Saves project preferences (currently opened files, bookmarks etc.) to the
/// a property container.
/// </summary>
public virtual Properties CreateMemento()
#region Preferences
Properties preferences;
public Properties Preferences {
get {
lock (syncRoot) {
if (preferences == null) {
preferences = new Properties(); // in case of errors, use empty properties container
FileName preferencesFile = GetPreferenceFileName(fileName);
if (FileUtility.IsValidPath(preferencesFile) && File.Exists(preferencesFile)) {
try {
preferences = Properties.Load(preferencesFile);
} catch (IOException) {
} catch (UnauthorizedAccessException) {
} catch (XmlException) {
// ignore errors about inaccessible or malformed files
}
}
}
return preferences;
}
}
}
static FileName GetPreferenceFileName(string projectFileName)
{
return GetOrCreateBehavior().CreateMemento();
string directory = Path.Combine(PropertyService.ConfigDirectory, "preferences");
return FileName.Create(Path.Combine(directory,
Path.GetFileName(projectFileName)
+ "." + projectFileName.ToUpperInvariant().GetStableHashCode().ToString("x")
+ ".xml"));
}
public virtual void SetMemento(Properties memento)
public void SavePreferences()
{
// other project data
this.ProjectSpecificProperties = memento.NestedProperties("projectSavedData");
GetOrCreateBehavior().SetMemento(memento);
var p = this.Preferences;
GetOrCreateBehavior().SavePreferences(p);
try {
FileName preferencesFile = GetPreferenceFileName(fileName);
System.IO.Directory.CreateDirectory(preferencesFile.GetParentDirectory());
p.Save(preferencesFile);
} catch (IOException) {
} catch (UnauthorizedAccessException) {
}
}
#endregion
@ -565,6 +595,11 @@ namespace ICSharpCode.SharpDevelop.Project @@ -565,6 +595,11 @@ namespace ICSharpCode.SharpDevelop.Project
GetOrCreateBehavior().ProjectCreationComplete();
}
public virtual void ProjectLoaded()
{
GetOrCreateBehavior().ProjectLoaded();
}
public virtual XElement LoadProjectExtensions(string name)
{
return new XElement(name);
@ -579,18 +614,6 @@ namespace ICSharpCode.SharpDevelop.Project @@ -579,18 +614,6 @@ namespace ICSharpCode.SharpDevelop.Project
return false;
}
Properties projectSpecificProperties = new Properties();
[Browsable(false)]
public Properties ProjectSpecificProperties {
get { return projectSpecificProperties; }
set {
if (value == null)
throw new ArgumentNullException();
projectSpecificProperties = value;
}
}
public virtual string GetDefaultNamespace(string fileName)
{
string relPath = FileUtility.GetRelativePath(this.Directory, Path.GetDirectoryName(fileName));

19
src/Main/Base/Project/Src/Project/Behaviors/DefaultProjectBehavior.cs

@ -76,12 +76,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -76,12 +76,7 @@ namespace ICSharpCode.SharpDevelop.Project
throw new NotSupportedException();
}
/// <summary>
/// Saves project preferences (currently opened files, bookmarks etc.) to the
/// a property container.
/// </summary>
public override Properties CreateMemento()
public override void SavePreferences(Properties preferences)
{
SD.MainThread.VerifyAccess();
@ -94,18 +89,14 @@ namespace ICSharpCode.SharpDevelop.Project @@ -94,18 +89,14 @@ namespace ICSharpCode.SharpDevelop.Project
files.Add(fileName);
}
}
properties.SetList("files", files);
// other project data
properties.SetNestedProperties("projectSavedData", Project.ProjectSpecificProperties.Clone());
return properties;
properties.SetList("openFiles", files);
}
public override void SetMemento(Properties memento)
public override void ProjectLoaded()
{
SD.MainThread.VerifyAccess();
var memento = Project.Preferences;
foreach (var mark in memento.GetList<ICSharpCode.SharpDevelop.Editor.Bookmarks.SDBookmark>("bookmarks")) {
SD.BookmarkManager.AddMark(mark);
}
@ -124,8 +115,6 @@ namespace ICSharpCode.SharpDevelop.Project @@ -124,8 +115,6 @@ namespace ICSharpCode.SharpDevelop.Project
FileService.OpenFile(file);
NavigationService.ResumeLogging();
}));
base.SetMemento(memento);
}
}
}

21
src/Main/Base/Project/Src/Project/Behaviors/ProjectBehavior.cs

@ -87,6 +87,12 @@ namespace ICSharpCode.SharpDevelop.Project @@ -87,6 +87,12 @@ namespace ICSharpCode.SharpDevelop.Project
next.ProjectCreationComplete();
}
public virtual void ProjectLoaded()
{
if (this.next != null)
next.ProjectLoaded();
}
public virtual IEnumerable<CompilerVersion> GetAvailableCompilerVersions()
{
if (this.next != null)
@ -123,17 +129,14 @@ namespace ICSharpCode.SharpDevelop.Project @@ -123,17 +129,14 @@ namespace ICSharpCode.SharpDevelop.Project
next.UpgradeProject(newVersion, newFramework);
}
public virtual Properties CreateMemento()
{
if (this.next != null)
return next.CreateMemento();
throw new InvalidOperationException();
}
public virtual void SetMemento(Properties memento)
/// <summary>
/// Saves project preferences (currently opened files, bookmarks etc.) to the
/// a property container.
/// </summary>
public virtual void SavePreferences(Properties preferences)
{
if (this.next != null)
next.SetMemento(memento);
next.SavePreferences(preferences);
}
public virtual Refactoring.ISymbolSearch PrepareSymbolSearch(IEntity entity)

34
src/Main/Base/Project/Src/Project/IProject.cs

@ -26,7 +26,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -26,7 +26,7 @@ namespace ICSharpCode.SharpDevelop.Project
/// When you implement IProject, you should also implement IProjectItemListProvider and IProjectAllowChangeConfigurations
/// </summary>
public interface IProject
: IBuildable, ISolutionItem, IDisposable, IMementoCapable, IConfigurable
: IBuildable, ISolutionItem, IDisposable, IConfigurable
{
/// <summary>
/// Gets the object used for thread-safe synchronization.
@ -179,8 +179,18 @@ namespace ICSharpCode.SharpDevelop.Project @@ -179,8 +179,18 @@ namespace ICSharpCode.SharpDevelop.Project
/// Gets project specific properties.
/// These are saved in as part of the SharpDevelop configuration in the AppData folder.
/// </summary>
/// <remarks>This property never returns null.</remarks>
Properties ProjectSpecificProperties { get; }
/// <remarks>
/// This property never returns null.
///
/// Use <see cref="LoadProjectExtensions"/> instead to store settings that are for multiple users.
/// </remarks>
Properties Preferences { get; }
/// <summary>
/// Saves the <see cref="Preferences"/> to disk.
/// This method is called by SharpDevelop when the solution is closed.
/// </summary>
void SavePreferences();
/// <summary>
/// Starts the project.
@ -207,13 +217,28 @@ namespace ICSharpCode.SharpDevelop.Project @@ -207,13 +217,28 @@ namespace ICSharpCode.SharpDevelop.Project
/// <summary>
/// Notifies the project that it was succesfully created from a project template.
/// </summary>
/// <remarks>
/// TODO This method is currently called before the project is added to the solution;
/// but we might change that so that it is called later.
/// </remarks>
void ProjectCreationComplete();
/// <summary>
/// Notifies the project that it was loaded in the IDE.
/// This method is called after the whole solution has finished loading; and when existing projects are added to the open solution.
/// It is not called for newly created projects; and not if the solution was loaded in the background
/// (<see cref="IProjectService.LoadSolutionFile"/> vs. <see cref="IProjectService.OpenSolution"/>).
/// </summary>
void ProjectLoaded();
/// <summary>
/// Loads the project extension content with the specified name.
/// </summary>
/// <remarks>
/// Project extensions are custom XML elements that are stored within the .csproj file.
/// They are intended for settings that are not specific to a user/machine.
///
/// Use <see cref="Preferences"/> instead to store per-user settings.
/// </remarks>
XElement LoadProjectExtensions(string name);
@ -222,6 +247,9 @@ namespace ICSharpCode.SharpDevelop.Project @@ -222,6 +247,9 @@ namespace ICSharpCode.SharpDevelop.Project
/// </summary>
/// <remarks>
/// Project extensions are custom XML elements that are stored within the .csproj file.
/// They are intended for settings that are not specific to a user/machine.
///
/// Use <see cref="Preferences"/> instead to store per-user settings.
/// </remarks>
void SaveProjectExtensions(string name, XElement element);

2
src/Main/Base/Project/Src/Project/ProjectCustomToolOptions.cs

@ -14,7 +14,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -14,7 +14,7 @@ namespace ICSharpCode.SharpDevelop.Project
public ProjectCustomToolOptions(IProject project)
{
properties = project.ProjectSpecificProperties.NestedProperties("customTool");
properties = project.Preferences.NestedProperties("customTool");
}
public bool RunCustomToolOnBuild {

31
src/Main/Base/Project/Util/CompositeDisposable.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// IDisposable implementation that disposes multiple disposables.
/// </summary>
public class CompositeDisposable : IDisposable
{
IDisposable[] disposables;
public CompositeDisposable(params IDisposable[] disposables)
{
if (disposables == null)
throw new ArgumentNullException("disposables");
this.disposables = disposables;
}
public void Dispose()
{
foreach (var disposable in disposables) {
if (disposable != null)
disposable.Dispose();
}
}
}
}

2
src/Main/Base/Test/Project/ProjectCustomToolOptionsTests.cs

@ -22,7 +22,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -22,7 +22,7 @@ namespace ICSharpCode.SharpDevelop.Project
{
projectSpecificProperties = new Properties();
project = MockRepository.GenerateStub<IProject>();
project.Stub(p => p.ProjectSpecificProperties).Return(projectSpecificProperties);
project.Stub(p => p.Preferences).Return(projectSpecificProperties);
}
void CreateProjectWithExistingCustomToolProperties(string fileNames)

2
src/Main/Base/Test/Utils/ProjectHelper.cs

@ -25,7 +25,7 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils @@ -25,7 +25,7 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils
.Return(null)
.WhenCalled(mi => mi.ReturnValue = new ImmutableModelCollection<ProjectItem>(ProjectItems));
Project.Stub(p => p.ProjectSpecificProperties).Return(new Properties());
Project.Stub(p => p.Preferences).Return(new Properties());
Project.Stub(p => p.SyncRoot).Return(new Object());
}

2
src/Main/Core/Project/Src/Services/PropertyService/Properties.cs

@ -527,7 +527,7 @@ namespace ICSharpCode.Core @@ -527,7 +527,7 @@ namespace ICSharpCode.Core
#endregion
#region Load/Save
public static Properties Load(string fileName)
public static Properties Load(FileName fileName)
{
return Load(XDocument.Load(fileName).Root);
}

4
src/Main/Core/Project/Src/Services/PropertyService/PropertyServiceImpl.cs

@ -36,7 +36,7 @@ namespace ICSharpCode.Core @@ -36,7 +36,7 @@ namespace ICSharpCode.Core
this.dataDirectory = dataDirectory;
this.propertyFileName = propertiesName + ".xml";
Directory.CreateDirectory(configDirectory);
LoadPropertiesFromStream(Path.Combine(configDirectory, propertyFileName));
LoadPropertiesFromStream(FileName.Create(Path.Combine(configDirectory, propertyFileName)));
}
public string ConfigDirectory {
@ -105,7 +105,7 @@ namespace ICSharpCode.Core @@ -105,7 +105,7 @@ namespace ICSharpCode.Core
properties.Remove(key);
}
bool LoadPropertiesFromStream(string fileName)
bool LoadPropertiesFromStream(FileName fileName)
{
if (!File.Exists(fileName)) {
properties = new Properties();

4
src/Main/SharpDevelop/Project/ProjectService.cs

@ -179,6 +179,8 @@ namespace ICSharpCode.SharpDevelop.Project @@ -179,6 +179,8 @@ namespace ICSharpCode.SharpDevelop.Project
void OnSolutionOpened(ISolution solution)
{
SolutionOpened(this, new SolutionEventArgs(solution));
foreach (var project in solution.Projects)
project.ProjectLoaded();
SD.FileService.RecentOpen.AddRecentProject(solution.FileName);
Project.Converter.UpgradeViewContent.ShowIfRequired(solution);
}
@ -272,6 +274,8 @@ namespace ICSharpCode.SharpDevelop.Project @@ -272,6 +274,8 @@ namespace ICSharpCode.SharpDevelop.Project
if (allowCancel && cancelEventArgs.Cancel)
return false;
foreach (var project in solution.Projects)
project.SavePreferences();
solution.SavePreferences();
if (!SD.Workbench.CloseAllSolutionViews(force: !allowCancel))

149
src/Main/SharpDevelop/Project/Solution.cs

@ -6,6 +6,7 @@ using System.Collections.Generic; @@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Threading;
using System.Xml;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Dom;
@ -26,6 +27,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -26,6 +27,7 @@ namespace ICSharpCode.SharpDevelop.Project
this.fileService = fileService;
this.ConfigurationNames = new SolutionConfigurationOrPlatformNameCollection(this, false);
this.PlatformNames = new SolutionConfigurationOrPlatformNameCollection(this, true);
this.projects = new SynchronizedModelCollection<IProject>(new ProjectModelCollection(this));
this.FileName = fileName;
base.Name = fileName.GetFileNameWithoutExtension();
@ -113,37 +115,45 @@ namespace ICSharpCode.SharpDevelop.Project @@ -113,37 +115,45 @@ namespace ICSharpCode.SharpDevelop.Project
#endregion
#region Project list
IMutableModelCollection<IProject> projects = new SynchronizedModelCollection<IProject>(new SimpleModelCollection<IProject>());
readonly IMutableModelCollection<IProject> projects; // = new SynchronizedModelCollection<IProject>(new ProjectModelCollection(this));
public IModelCollection<IProject> Projects {
get { return projects; }
}
void OnProjectAdded(IProject project)
{
projects.Add(project);
project.ProjectSections.CollectionChanged += OnSolutionSectionCollectionChanged;
OnSolutionSectionCollectionChanged(EmptyList<SolutionSection>.Instance, project.ProjectSections);
if (startupProject == null && AutoDetectStartupProject() == project)
this.StartupProject = project; // when there's no startable project in the solution and one is added, we mark that it as the startup project
}
void OnProjectRemoved(IProject project)
sealed class ProjectModelCollection : SimpleModelCollection<IProject>
{
project.ProjectSections.CollectionChanged -= OnSolutionSectionCollectionChanged;
OnSolutionSectionCollectionChanged(project.ProjectSections, EmptyList<SolutionSection>.Instance);
bool wasStartupProject = (startupProject == project);
if (wasStartupProject)
startupProject = null; // this will force auto-detection on the next property access
projects.Remove(project);
if (wasStartupProject)
StartupProjectChanged(this, EventArgs.Empty);
Solution solution;
public ProjectModelCollection(Solution solution)
{
this.solution = solution;
}
// HACK: ensure the project gets disposed
SD.MainThread.InvokeAsyncAndForget(
delegate {
protected override void OnCollectionChanged(IReadOnlyCollection<IProject> removedItems, IReadOnlyCollection<IProject> addedItems)
{
foreach (var project in addedItems) {
project.ProjectSections.CollectionChanged += solution.OnSolutionSectionCollectionChanged;
solution.OnSolutionSectionCollectionChanged(EmptyList<SolutionSection>.Instance, project.ProjectSections);
}
foreach (var project in removedItems) {
project.ProjectSections.CollectionChanged -= solution.OnSolutionSectionCollectionChanged;
solution.OnSolutionSectionCollectionChanged(project.ProjectSections, EmptyList<SolutionSection>.Instance);
}
// If the startup project was removed, reset that property
bool startupProjectWasRemoved = removedItems.Contains(solution.startupProject);
if (startupProjectWasRemoved)
solution.startupProject = null; // this will force auto-detection on the next property access
base.OnCollectionChanged(removedItems, addedItems);
// After the event is raised; dispose any removed projects.
// Note that this method is only called at the end of a batch update.
// When moving a project from one folder to another, a batch update
// must be used to prevent the project from being disposed.
foreach (var project in removedItems)
project.Dispose();
}, DispatcherPriority.Background);
if (startupProjectWasRemoved || (solution.startupProject == null && addedItems.Contains(solution.AutoDetectStartupProject())))
solution.StartupProjectChanged(this, EventArgs.Empty);
}
}
public IModelCollection<IProject> Projects {
get { return projects; }
}
internal IDisposable ReportBatch()
@ -159,7 +169,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -159,7 +169,7 @@ namespace ICSharpCode.SharpDevelop.Project
ReportRemovedItem(childItem);
}
} else if (oldItem is IProject) {
OnProjectRemoved((IProject)oldItem);
projects.Remove((IProject)oldItem);
}
}
@ -171,7 +181,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -171,7 +181,7 @@ namespace ICSharpCode.SharpDevelop.Project
ReportAddedItem(childItem);
}
} else if (newItem is IProject) {
OnProjectAdded((IProject)newItem);
projects.Add((IProject)newItem);
}
}
#endregion
@ -212,18 +222,32 @@ namespace ICSharpCode.SharpDevelop.Project @@ -212,18 +222,32 @@ namespace ICSharpCode.SharpDevelop.Project
}
#region Preferences
Properties preferences;
Properties preferences = new Properties();
public Properties Preferences {
get { return preferences; }
}
static FileName GetPreferenceFileName(string projectFileName)
{
string directory = Path.Combine(PropertyService.ConfigDirectory, "preferences");
return FileName.Create(Path.Combine(directory,
Path.GetFileName(projectFileName)
+ "." + projectFileName.ToUpperInvariant().GetStableHashCode().ToString("x")
+ ".xml"));
}
internal void LoadPreferences()
{
try {
preferences = new Properties();
} catch (IOException) {
FileName preferencesFile = GetPreferenceFileName(fileName);
if (FileUtility.IsValidPath(preferencesFile) && File.Exists(preferencesFile)) {
try {
preferences = Properties.Load(preferencesFile);
} catch (IOException) {
} catch (UnauthorizedAccessException) {
} catch (XmlException) {
// ignore errors about inaccessible or malformed files
}
}
// Load active configuration from preferences
CreateDefaultConfigurationsIfMissing();
@ -236,26 +260,6 @@ namespace ICSharpCode.SharpDevelop.Project @@ -236,26 +260,6 @@ namespace ICSharpCode.SharpDevelop.Project
}
/*
static Properties LoadSolutionPreferences(string solutionFileName)
{
try {
string file = GetPreferenceFileName(solutionFileName);
if (FileUtility.IsValidPath(file) && File.Exists(file)) {
try {
return Properties.Load(file);
} catch (IOException) {
} catch (UnauthorizedAccessException) {
} catch (XmlException) {
// ignore errors about inaccessible or malformed files
}
}
} catch (Exception ex) {
MessageService.ShowException(ex);
}
return new Properties();
}
static void ApplyConfigurationAndReadProjectPreferences()
{
openSolution.ApplySolutionConfigurationAndPlatformToProjects();
@ -284,39 +288,14 @@ namespace ICSharpCode.SharpDevelop.Project @@ -284,39 +288,14 @@ namespace ICSharpCode.SharpDevelop.Project
preferences.Set("ActiveConfiguration.Configuration", activeConfiguration.Configuration);
preferences.Set("ActiveConfiguration.Platform", activeConfiguration.Platform);
PreferencesSaving(this, EventArgs.Empty);
// TODO: save to disk
/*
string directory = Path.Combine(PropertyService.ConfigDirectory, "preferences");
if (!Directory.Exists(directory)) {
Directory.CreateDirectory(directory);
}
if (SolutionPreferencesSaving != null)
SolutionPreferencesSaving(null, new SolutionEventArgs(openSolution));
Properties memento = openSolution.Preferences.Clone();
string fullFileName = GetPreferenceFileName(openSolution.FileName);
if (FileUtility.IsValidPath(fullFileName)) {
#if DEBUG
memento.Save(fullFileName);
#else
FileUtility.ObservedSave(new NamedFileOperationDelegate(memento.Save), fullFileName, FileErrorPolicy.Inform);
#endif
FileName preferencesFile = GetPreferenceFileName(fileName);
System.IO.Directory.CreateDirectory(preferencesFile.GetParentDirectory());
try {
preferences.Save(preferencesFile);
} catch (IOException) {
} catch (UnauthorizedAccessException) {
}
foreach (IProject project in OpenSolution.Projects) {
memento = project.CreateMemento();
if (memento == null) continue;
fullFileName = GetPreferenceFileName(project.FileName);
if (FileUtility.IsValidPath(fullFileName)) {
#if DEBUG
memento.Save(fullFileName);
#else
FileUtility.ObservedSave(new NamedFileOperationDelegate(memento.Save), fullFileName, FileErrorPolicy.Inform);
#endif
}
}*/
}
#endregion

18
src/Main/SharpDevelop/Project/SolutionFolder.cs

@ -51,6 +51,23 @@ namespace ICSharpCode.SharpDevelop.Project @@ -51,6 +51,23 @@ namespace ICSharpCode.SharpDevelop.Project
throw new ArgumentException("The item already has a parent folder");
}
public override IDisposable BatchUpdate()
{
// This method exists to allow moving a project from one folder to another without
// raising the ISolution.Projects.CollectionChanged event.
// The batch update within OnCollectionChanged() is not sufficient as it is per-folder,
// while we need a batch across multiple folders.
// To allow users to create such a batch update across folders without explicitly exposing solution.ReportBatch()
// in the API; we call ReportBatch() here.
// API consumers should open batches on both the source and target folder,
// Note that the base.BatchUpdate must be disposed first:
// doing so will call OnCollectionChanged() and update ISolution.Projects;
// and only then the solution batch may be disposed.
return new CompositeDisposable(base.BatchUpdate(), folder.parentSolution.ReportBatch());
}
protected override void OnCollectionChanged(IReadOnlyCollection<ISolutionItem> removedItems, IReadOnlyCollection<ISolutionItem> addedItems)
{
using (folder.parentSolution.ReportBatch()) {
@ -110,6 +127,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -110,6 +127,7 @@ namespace ICSharpCode.SharpDevelop.Project
IProject project = ProjectBindingService.LoadProject(loadInfo);
Debug.Assert(project.IdGuid != Guid.Empty);
this.Items.Add(project);
project.ProjectLoaded();
return project;
}

2
src/Main/SharpDevelop/Workbench/AvalonPadContent.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.SharpDevelop.Workbench @@ -83,7 +83,7 @@ namespace ICSharpCode.SharpDevelop.Workbench
if (isFocused) {
IInputElement initialFocus = padInstance.InitiallyFocusedControl as IInputElement;
if (initialFocus != null) {
Dispatcher.BeginInvoke(DispatcherPriority.Background,
Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(delegate { Keyboard.Focus(initialFocus); }));
}
}

2
src/Main/SharpDevelop/Workbench/AvalonWorkbenchWindow.cs

@ -55,7 +55,7 @@ namespace ICSharpCode.SharpDevelop.Workbench @@ -55,7 +55,7 @@ namespace ICSharpCode.SharpDevelop.Workbench
internal static void SetFocus(ManagedContent m, Func<IInputElement> activeChildFunc, bool forceSetFocus = false)
{
m.Dispatcher.BeginInvoke(
DispatcherPriority.Background,
DispatcherPriority.Input,
new Action(
delegate {
// ensure that condition for FocusContent() is still fulfilled

4
src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs

@ -194,12 +194,12 @@ class Test { @@ -194,12 +194,12 @@ class Test {
resolver.Resolve(node);
}
// warm up AvalonEdit (must be done on main thread)
SD.MainThread.InvokeAsync(
SD.MainThread.InvokeAsyncAndForget(
delegate {
object editor;
SD.EditorControlService.CreateEditor(out editor);
LoggingService.Debug("Preload-Thread finished.");
}, DispatcherPriority.Background);
}, DispatcherPriority.ApplicationIdle);
}
#endregion
}

Loading…
Cancel
Save