Browse Source

Setup infrastructure to save project specific data. Save watch variables. Fix http://bugtracker.sharpdevelop.net/issue/ViewIssue.aspx?id=1509&PROJID=4

4.1
Eusebiu Marcu 14 years ago
parent
commit
53dbd13ee5
  1. 2
      data/resources/StringResources.resx
  2. 92
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
  3. 40
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs
  4. 4
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  5. 15
      src/Main/Base/Project/Src/Project/AbstractProject.cs
  6. 60
      src/Main/Base/Project/Src/Services/ProjectService/SavedData/IProjectSavedData.cs
  7. 54
      src/Main/Base/Project/Src/Services/ProjectService/SavedData/ProjectSavedDataConverter.cs
  8. 81
      src/Main/Base/Project/Src/Services/ProjectService/SavedData/SavedDataManager.cs

2
data/resources/StringResources.resx

@ -5156,7 +5156,7 @@ Goto 'Options-&gt;Visual Style' and change the current language ambience.</value @@ -5156,7 +5156,7 @@ Goto 'Options-&gt;Visual Style' and change the current language ambience.</value
<value>ASP.NET/IIS (Express) worker process ({0}) was not found.</value>
</data>
<data name="ICSharpCode.WepProjectOptionsPanel.NoProjectUrlOrProgramAction" xml:space="preserve">
<value>There's no Project Url specified or external program. Check the web server at Project Properties -&amp;gt; Debug tab.</value>
<value>There's no Project Url specified or external program. Check the web server at Project Properties -&gt; Debug tab.</value>
</data>
<data name="ICSharpCode.WepProjectOptionsPanel.Port" xml:space="preserve">
<value>Server port:</value>

92
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs

@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Input;
@ -13,9 +15,10 @@ using Debugger.AddIn.TreeModel; @@ -13,9 +15,10 @@ using Debugger.AddIn.TreeModel;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Project.SavedData;
using Exception = System.Exception;
using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
@ -58,11 +61,98 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -58,11 +61,98 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
watchList.Drop += watchList_Drop;
watchList.MouseDoubleClick += watchList_DoubleClick;
watchList.KeyUp += watchList_KeyUp;
watchList.WatchItems.CollectionChanged += OnWatchItemsCollectionChanged;
panel.Children.Add(watchList);
panel.KeyUp += new KeyEventHandler(panel_KeyUp);
// wire events that influence the items
LoadSavedNodes();
ProjectService.SolutionClosed += delegate { watchList.WatchItems.Clear(); };
ProjectService.SolutionPreferencesSaving += OnSolutionClosing;
ProjectService.ProjectRemoved += OnProjectRemoved;
ProjectService.ProjectAdded += OnProjectAdded;
ProjectService.SolutionLoaded += delegate { LoadSavedNodes(); };
}
#region Saved nodes
void AddNodes(Func<IProjectSavedData, bool> predicate)
{
if (predicate == null)
throw new ArgumentNullException("predicate");
// get nodes of current projects
List<TextNode> temp = new List<TextNode>();
foreach (var data in SavedDataManager.GetSavedData().Where(predicate)) {
string[] v = data.SavedString.Split('|');
TextNode node = new TextNode(null, v[5], (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), v[7])) { ProjectName = data.ProjectName };
temp.Add(node);
}
// add them to watch list
temp.ForEach(d => { if (!watchList.WatchItems.Contains(d)) watchList.WatchItems.Add(d); } );
}
void LoadSavedNodes()
{
AddNodes(d => d.SavedDataType == ProjectSavedDataType.WatchVariables &&
ProjectService.OpenSolution.Projects.Any(p => p.Name == d.ProjectName));
// remove them temporarilly - they will be saved on exit
SavedDataManager.RemoveAll(d => d.SavedDataType == ProjectSavedDataType.WatchVariables &&
ProjectService.OpenSolution.Projects.Any(p => p.Name == d.ProjectName));
}
void OnSolutionClosing(object sender, SolutionEventArgs e)
{
foreach (var element in watchList.WatchItems) {
SavedDataManager.Add((IProjectSavedData)element);
}
}
void OnProjectAdded(object sender, ProjectEventArgs e)
{
AddNodes(d => d.SavedDataType == ProjectSavedDataType.WatchVariables && e.Project.Name == d.ProjectName);
}
void OnProjectRemoved(object sender, ProjectEventArgs e)
{
if (e.Project == null)
return;
// get the specific nodes from the list
List<TextNode> nodes = new List<TextNode>();
foreach (var element in watchList.WatchItems
.OfType<TextNode>()
.Where(tn => tn.ProjectName == e.Project.Name)) {
nodes.Add(element);
}
// remove nodes from the list
nodes.ForEach(n => watchList.WatchItems.Remove(n));
}
void OnWatchItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add) {
// add to saved data
var data = e.NewItems[0] as IProjectSavedData;
if (data != null)
SavedDataManager.Add(data);
}
if (e.Action == NotifyCollectionChangedAction.Remove) {
// remove from saved data
var data = e.OldItems[0] as IProjectSavedData;
if (data != null)
SavedDataManager.Remove(data);
}
}
#endregion
void panel_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Insert) {

40
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPadModel.cs

@ -2,20 +2,24 @@ @@ -2,20 +2,24 @@
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System;
using System.Collections.Generic;
using System.Text;
using Debugger.AddIn.TreeModel;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Project.SavedData;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class TextNode : TreeNode, ISetText
public class TextNode : TreeNode, ISetText, IProjectSavedData
{
public TextNode(TreeNode parent, string text, SupportedLanguage language)
: base(parent)
{
this.Name = text;
this.Language = language;
if (ProjectService.CurrentProject != null)
ProjectName = ProjectService.CurrentProject.Name;
}
public override bool CanSetText {
@ -37,6 +41,36 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -37,6 +41,36 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
public SupportedLanguage Language { get; set; }
#region IProjectSavedData implementation
string savedString;
public string SavedString {
get {
StringBuilder sb = new StringBuilder();
sb.Append("ProjectName"); sb.Append('|'); sb.Append(ProjectName); sb.Append('|');
sb.Append("ProjectSavedDataType"); sb.Append('|'); sb.Append(SavedDataType); sb.Append('|');
sb.Append("FullName"); sb.Append('|'); sb.Append(FullName); sb.Append('|');
sb.Append("Language"); sb.Append('|'); sb.Append(Language.ToString());
savedString = sb.ToString();
return savedString;
}
set { savedString = value; }
}
public ProjectSavedDataType SavedDataType {
get {
return ProjectSavedDataType.WatchVariables;
}
}
public string ProjectName {
get; internal set;
}
#endregion
}
public class ErrorInfoNode : ICorDebug.InfoNode

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

@ -243,6 +243,9 @@ @@ -243,6 +243,9 @@
<DependentUpon>SelectCulturePanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Src\Services\ProjectService\SavedData\IProjectSavedData.cs" />
<Compile Include="Src\Services\ProjectService\SavedData\ProjectSavedDataConverter.cs" />
<Compile Include="Src\Services\ProjectService\SavedData\SavedDataManager.cs" />
<Compile Include="Src\Gui\Dialogs\OptionPanels\ProjectOptions\WebProjectOptions\WebProjectOptions.cs" />
<Compile Include="Src\Gui\Dialogs\OptionPanels\ProjectOptions\WebProjectOptions\WebProjectOptionsPanel.xaml.cs">
<DependentUpon>WebProjectOptionsPanel.xaml</DependentUpon>
@ -848,6 +851,7 @@ @@ -848,6 +851,7 @@
<Folder Include="Src\Editor\CodeCompletion" />
<Folder Include="Src\Editor\Commands" />
<Folder Include="Src\Editor\Search" />
<Folder Include="Src\Services\ProjectService\SavedData" />
<Folder Include="Src\Gui\Dialogs\OptionPanels\ProjectOptions\WebProjectOptions" />
<Folder Include="Src\Gui\Pads\TaskList" />
<Folder Include="Src\Services\Debugger\Tooltips" />

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

@ -7,12 +7,14 @@ using System.Collections.ObjectModel; @@ -7,12 +7,14 @@ using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Project.SavedData;
namespace ICSharpCode.SharpDevelop.Project
{
@ -71,6 +73,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -71,6 +73,7 @@ namespace ICSharpCode.SharpDevelop.Project
{
WorkbenchSingleton.AssertMainThread();
// breakpoints and files
Properties properties = new Properties();
properties.Set("bookmarks", ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.GetProjectBookmarks(this).ToArray());
List<string> files = new List<string>();
@ -81,10 +84,15 @@ namespace ICSharpCode.SharpDevelop.Project @@ -81,10 +84,15 @@ namespace ICSharpCode.SharpDevelop.Project
}
properties.Set("files", files.ToArray());
// web project properties
var webOptions = WebProjectsOptions.Instance.GetWebProjectOptions(Name);
if (webOptions != null)
properties.Set("WebProjectOptions", webOptions);
// other project data - logic in ProjectSavedDataConverter
properties.Set("projectSavedData_" + Name, SavedDataManager.GetSavedData()
.Where(d => d.ProjectName == Name).ToArray());
return properties;
}
@ -99,7 +107,14 @@ namespace ICSharpCode.SharpDevelop.Project @@ -99,7 +107,14 @@ namespace ICSharpCode.SharpDevelop.Project
filesToOpenAfterSolutionLoad.Add(fileName);
}
// web project properties
WebProjectsOptions.Instance.SetWebProjectOptions(Name, memento.Get("WebProjectOptions", new WebProjectOptions()) as WebProjectOptions);
// other project data - logic in ProjectSavedDataConverter
foreach(var data in memento.Get("projectSavedData_" + Name, new IProjectSavedData[0])
.Where(d => d.ProjectName == Name)) {
SavedDataManager.Add(data);
}
}
#endregion

60
src/Main/Base/Project/Src/Services/ProjectService/SavedData/IProjectSavedData.cs

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
// 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.ComponentModel;
using System.Collections.Generic;
namespace ICSharpCode.SharpDevelop.Project.SavedData
{
public enum ProjectSavedDataType
{
WatchVariables
}
/// <summary>
/// Interface for storing project specific data.
/// When implementing this, one should be carefull when and how
/// the SavedDataManager is used in order to not alter the other data.
/// </summary>
[TypeConverter(typeof(ProjectSavedDataConverter))]
public interface IProjectSavedData
{
/// <summary>
/// Saved data type.
/// </summary>
ProjectSavedDataType SavedDataType { get; }
/// <summary>
/// Saved data.
/// <remarks>The format is: "ProjectName"|{0}|"ProjectSavedDataType"|{1}|(specific data splited by '|').</remarks>
/// </summary>
string SavedString { get; set; }
/// <summary>
/// Gets the project name.
/// </summary>
string ProjectName { get; }
}
/// <summary>
/// Dummy data. Used to map the saved data and exposed to addins where project specific data can exist.
/// </summary>
public sealed class DummyProjectSavedData : IProjectSavedData
{
public ProjectSavedDataType SavedDataType { get; set; }
public string SavedString { get; set; }
public string ProjectName {
get {
if (string.IsNullOrEmpty(SavedString))
return string.Empty;
string[] v = SavedString.Split('|');
return v[1];
}
}
}
}

54
src/Main/Base/Project/Src/Services/ProjectService/SavedData/ProjectSavedDataConverter.cs

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
// 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.ComponentModel;
using System.Globalization;
using System.Text;
namespace ICSharpCode.SharpDevelop.Project.SavedData
{
public sealed class ProjectSavedDataConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string)) {
return true;
} else {
return base.CanConvertFrom(context, sourceType);
}
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
// convert from saved data(string) to objects
if (value is string) {
string[] v = ((string)value).Split('|');
ProjectSavedDataType type = (ProjectSavedDataType)Enum.Parse(typeof(ProjectSavedDataType), v[3]);
var data = new DummyProjectSavedData {
SavedString = (string)value,
SavedDataType = type
};
return data;
} else {
return base.ConvertFrom(context, culture, value);
}
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
// convert objects to saved data(string)
var data = value as IProjectSavedData;
if (destinationType == typeof(string) && data != null) {
switch (data.SavedDataType) {
case ProjectSavedDataType.WatchVariables:
return data.SavedString;
default:
throw new Exception("Invalid value for ProjectSavedDataType");
}
} else {
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
}

81
src/Main/Base/Project/Src/Services/ProjectService/SavedData/SavedDataManager.cs

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
// 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.Concurrent;
using System.Collections.Generic;
namespace ICSharpCode.SharpDevelop.Project.SavedData
{
/// <summary>
/// Stores the project specific data.
/// </summary>
public static class SavedDataManager
{
static readonly List<IProjectSavedData> list;
static object _syncObject = new object();
static SavedDataManager()
{
list = new List<IProjectSavedData>();
ProjectService.SolutionClosed += delegate { list.Clear(); };
}
/// <summary>
/// Gets all saved data.
/// </summary>
/// <returns></returns>
public static List<IProjectSavedData> GetSavedData()
{
return list;
}
/// <summary>
/// Adds a new data.
/// </summary>
/// <param name="data"></param>
public static void Add(IProjectSavedData data)
{
if (data == null)
throw new ArgumentNullException("data");
if (!list.Contains(data)) {
lock (_syncObject) {
if (!list.Contains(data))
list.Add(data);
}
}
}
/// <summary>
/// Removes data.
/// </summary>
/// <param name="data"></param>
public static void Remove(IProjectSavedData data)
{
if (data == null)
throw new ArgumentNullException("data");
if (list.Contains(data)) {
lock (_syncObject) {
if (list.Contains(data))
list.Remove(data);
}
}
}
/// <summary>
/// Removes all data that satisfies a predicate.
/// </summary>
/// <param name="match"></param>
public static void RemoveAll(Predicate<IProjectSavedData> match)
{
if (match == null)
throw new ArgumentNullException("match");
lock (_syncObject) {
list.RemoveAll(match);
}
}
}
}
Loading…
Cancel
Save