From a1c667f5f102b9ac1599136c1f0f49787deaaa2d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 16 May 2005 17:45:44 +0000 Subject: [PATCH] Bookmarks (and breakpoints) are saved in the project preferences. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@145 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/Document/BookmarkManager/Bookmark.cs | 22 ++- .../Project/ICSharpCode.SharpDevelop.csproj | 2 +- .../Base/Project/Src/Commands/FileCommands.cs | 2 +- .../Base/Project/Src/Gui/IMementoCapable.cs | 30 ----- .../Src/Gui/Workbench/DefaultWorkbench.cs | 13 +- .../Project/Src/Project/AbstractProject.cs | 23 ++++ src/Main/Base/Project/Src/Project/IProject.cs | 3 +- .../Services/ProjectService/ProjectService.cs | 44 +++++- .../Src/TextEditor/Bookmarks/Bookmark.cs | 2 + .../TextEditor/Bookmarks/BookmarkConverter.cs | 73 ++++++++++ .../TextEditor/Bookmarks/BookmarkManager.cs | 11 ++ .../Bookmarks/Pad/Nodes/BookmarkFolderNode.cs | 30 ++++- .../Bookmarks/Pad/Nodes/BookmarkNode.cs | 32 ++++- .../Core/Project/Src/AddInTree/AddIn/AddIn.cs | 2 +- .../Services/PropertyService/Properties.cs | 127 ++++++++++++++---- 15 files changed, 322 insertions(+), 94 deletions(-) delete mode 100644 src/Main/Base/Project/Src/Gui/IMementoCapable.cs create mode 100644 src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkConverter.cs diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs index 933987fb65..bf32032539 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Document/BookmarkManager/Bookmark.cs @@ -25,7 +25,19 @@ namespace ICSharpCode.TextEditor.Document return document; } set { - document = value; + if (document != value) { + document = value; + OnDocumentChanged(EventArgs.Empty); + } + } + } + + public event EventHandler DocumentChanged; + + protected virtual void OnDocumentChanged(EventArgs e) + { + if (DocumentChanged != null) { + DocumentChanged(this, e); } } @@ -35,8 +47,10 @@ namespace ICSharpCode.TextEditor.Document } set { isEnabled = value; - document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineNumber)); - document.CommitUpdate(); + if (document != null) { + document.RequestUpdate(new TextAreaUpdate(TextAreaUpdateType.SingleLine, lineNumber)); + document.CommitUpdate(); + } } } @@ -80,7 +94,7 @@ namespace ICSharpCode.TextEditor.Document this.lineNumber = lineNumber; this.isEnabled = isEnabled; } - + public virtual void Click(SWF.MouseButtons mouseButtons) { if (mouseButtons == SWF.MouseButtons.Left) { diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 6b33b6e207..077327133f 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -132,7 +132,6 @@ - @@ -662,6 +661,7 @@ Component + diff --git a/src/Main/Base/Project/Src/Commands/FileCommands.cs b/src/Main/Base/Project/Src/Commands/FileCommands.cs index 323a08e38a..91941a81dc 100644 --- a/src/Main/Base/Project/Src/Commands/FileCommands.cs +++ b/src/Main/Base/Project/Src/Commands/FileCommands.cs @@ -67,7 +67,7 @@ namespace ICSharpCode.SharpDevelop.Commands ProjectService.MarkFileDirty(window.ViewContent.FileName); - FileUtility.ObservedSave(new FileOperationDelegate(window.ViewContent.Save), window.ViewContent.FileName); + FileUtility.ObservedSave(new FileOperationDelegate(window.ViewContent.Save), window.ViewContent.FileName, FileErrorPolicy.ProvideAlternative); } } } diff --git a/src/Main/Base/Project/Src/Gui/IMementoCapable.cs b/src/Main/Base/Project/Src/Gui/IMementoCapable.cs deleted file mode 100644 index 02328c0034..0000000000 --- a/src/Main/Base/Project/Src/Gui/IMementoCapable.cs +++ /dev/null @@ -1,30 +0,0 @@ -// -// -// -// -// -// - -using ICSharpCode.Core; - -namespace ICSharpCode.SharpDevelop.Gui -{ - /// - /// This interface flags an object beeing "mementocapable". This means that the - /// state of the object could be saved to an object - /// and set from a object from the same class. - /// This is used to save and restore the state of GUI objects. - /// - public interface IMementoCapable - { - /// - /// Creates a new memento from the state. - /// - Properties CreateMemento(); - - /// - /// Sets the state to the given memento. - /// - void SetMemento(Properties memento); - } -} diff --git a/src/Main/Base/Project/Src/Gui/Workbench/DefaultWorkbench.cs b/src/Main/Base/Project/Src/Gui/Workbench/DefaultWorkbench.cs index abb89823ef..73aba64c08 100644 --- a/src/Main/Base/Project/Src/Gui/Workbench/DefaultWorkbench.cs +++ b/src/Main/Base/Project/Src/Gui/Workbench/DefaultWorkbench.cs @@ -276,7 +276,7 @@ namespace ICSharpCode.SharpDevelop.Gui string fullFileName = Path.Combine(directory, fileName); if (FileUtility.IsValidFileName(fullFileName)) { - FileUtility.ObservedSave(new NamedFileOperationDelegate(memento.Save), fullFileName, FileErrorPolicy.ProvideAlternative); + FileUtility.ObservedSave(new NamedFileOperationDelegate(memento.Save), fullFileName, FileErrorPolicy.Inform); } } @@ -371,8 +371,6 @@ namespace ICSharpCode.SharpDevelop.Gui { base.OnClosing(e); - - ProjectService.SaveSolutionPreferences(); while (WorkbenchSingleton.Workbench.ViewContentCollection.Count > 0) { IViewContent content = WorkbenchSingleton.Workbench.ViewContentCollection[0]; content.WorkbenchWindow.CloseWindow(false); @@ -382,15 +380,6 @@ namespace ICSharpCode.SharpDevelop.Gui } } ProjectService.CloseSolution(); - - // TODO : Dirty Files Dialog - // foreach (IViewContent content in ViewContentCollection) { - // if (content.IsDirty) { - // ICSharpCode.SharpDevelop.Gui.DirtyFilesDialog dfd = new ICSharpCode.SharpDevelop.Gui.DirtyFilesDialog(); - // e.Cancel = dfd.ShowDialog(ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainForm) == DialogResult.Cancel; - // return; - // } - // } } protected override void OnClosed(EventArgs e) diff --git a/src/Main/Base/Project/Src/Project/AbstractProject.cs b/src/Main/Base/Project/Src/Project/AbstractProject.cs index 969c322431..e4f7af11b1 100644 --- a/src/Main/Base/Project/Src/Project/AbstractProject.cs +++ b/src/Main/Base/Project/Src/Project/AbstractProject.cs @@ -362,5 +362,28 @@ namespace ICSharpCode.SharpDevelop.Project { return null; } + + + + /// + /// Saves project preferences (currently opened files, bookmarks etc.) to the + /// a property container. + /// + public virtual Properties CreateMemento() + { + Properties properties = new Properties(); + properties.Set("bookmarks", ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.GetProjectBookmarks(this).ToArray()); + return properties; + } + + /// + /// Loads project preferences (currently opened files, bookmarks etc.). + /// + public virtual void SetMemento(Properties properties) + { + foreach (ICSharpCode.SharpDevelop.Bookmarks.SDBookmark mark in properties.Get("bookmarks", new ICSharpCode.SharpDevelop.Bookmarks.SDBookmark[0])) { + ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.AddMark(mark); + } + } } } diff --git a/src/Main/Base/Project/Src/Project/IProject.cs b/src/Main/Base/Project/Src/Project/IProject.cs index 1485c5f140..5c4556b1c6 100644 --- a/src/Main/Base/Project/Src/Project/IProject.cs +++ b/src/Main/Base/Project/Src/Project/IProject.cs @@ -1,6 +1,7 @@ using System; using System.CodeDom.Compiler; using System.Collections.Generic; +using ICSharpCode.Core; namespace ICSharpCode.SharpDevelop.Project { @@ -11,7 +12,7 @@ namespace ICSharpCode.SharpDevelop.Project Module }; - public interface IProject : ISolutionFolder, IDisposable + public interface IProject : ISolutionFolder, IDisposable, IMementoCapable { PropertyGroup BaseConfiguration { get; diff --git a/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs b/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs index cf6d5ac935..2431d5ad49 100644 --- a/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs +++ b/src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs @@ -137,6 +137,16 @@ namespace ICSharpCode.SharpDevelop.Project { openSolution = Solution.Load(fileName); OnSolutionLoaded(new SolutionEventArgs(openSolution)); + try { + foreach (IProject project in openSolution.Projects) { + string file = GetPreferenceFileName(project); + if (FileUtility.IsValidFileName(file) && File.Exists(file)) { + project.SetMemento(Properties.Load(file)); + } + } + } catch (Exception ex) { + MessageService.ShowError(ex); + } } public static void SaveSolution() @@ -150,9 +160,30 @@ namespace ICSharpCode.SharpDevelop.Project } } + static string GetPreferenceFileName(IProject project) + { + string directory = PropertyService.ConfigDirectory + "preferences"; + string fileName = project.FileName.Substring(3).Replace('/', '.').Replace('\\', '.').Replace(Path.DirectorySeparatorChar, '.'); + string fullFileName = Path.Combine(directory, fileName + ".xml"); + return fullFileName; + } + public static void SaveSolutionPreferences() { - // TODO: + string directory = PropertyService.ConfigDirectory + "preferences"; + if (!Directory.Exists(directory)) { + Directory.CreateDirectory(directory); + } + + foreach (IProject project in OpenSolution.Projects) { + Properties memento = project.CreateMemento(); + if (memento == null) continue; + + string fullFileName = GetPreferenceFileName(project); + if (FileUtility.IsValidFileName(fullFileName)) { + FileUtility.ObservedSave(new NamedFileOperationDelegate(memento.Save), fullFileName, FileErrorPolicy.Inform); + } + } } public static void CloseSolution() @@ -160,6 +191,7 @@ namespace ICSharpCode.SharpDevelop.Project if (openSolution != null) { OnSolutionClosing(new SolutionEventArgs(openSolution)); + SaveSolutionPreferences(); openSolution.Dispose(); openSolution = null; @@ -182,7 +214,7 @@ namespace ICSharpCode.SharpDevelop.Project { project.IsDirty = true; } - + static void OnCurrentProjectChanged(ProjectEventArgs e) { if (CurrentProjectChanged != null) { @@ -218,14 +250,14 @@ namespace ICSharpCode.SharpDevelop.Project } } - static void OnProjectConfigurationChanged(ProjectConfigurationEventArgs e) + static void OnProjectConfigurationChanged(ProjectConfigurationEventArgs e) { if (ProjectConfigurationChanged != null) { ProjectConfigurationChanged(null, e); } } - static void OnSolutionConfigurationChanged(SolutionConfigurationEventArgs e) + static void OnSolutionConfigurationChanged(SolutionConfigurationEventArgs e) { if (SolutionConfigurationChanged != null) { SolutionConfigurationChanged(null, e); @@ -246,7 +278,7 @@ namespace ICSharpCode.SharpDevelop.Project } } - static void OnEndBuild(EventArgs e) + static void OnEndBuild(EventArgs e) { if (EndBuild != null) { EndBuild(null, e); @@ -267,7 +299,7 @@ namespace ICSharpCode.SharpDevelop.Project } } - static void OnSolutionFolderRemoved(SolutionFolderEventArgs e) + static void OnSolutionFolderRemoved(SolutionFolderEventArgs e) { if (SolutionFolderRemoved != null) { SolutionFolderRemoved(null, e); diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/Bookmark.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/Bookmark.cs index 47ba7afba2..62a169713f 100644 --- a/src/Main/Base/Project/Src/TextEditor/Bookmarks/Bookmark.cs +++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/Bookmark.cs @@ -6,6 +6,7 @@ // using System; +using System.ComponentModel; using System.Collections; using System.Collections.Generic; using System.Drawing; @@ -19,6 +20,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks /// /// Description of Bookmark. /// + [TypeConverter(typeof(BookmarkConverter))] public class SDBookmark : Bookmark { string fileName; diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkConverter.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkConverter.cs new file mode 100644 index 0000000000..5baecb2b15 --- /dev/null +++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkConverter.cs @@ -0,0 +1,73 @@ +// +// +// +// +// +// + + +using System; +using System.ComponentModel; +using System.Text; +using System.Globalization; +using ICSharpCode.Core; +using ICSharpCode.TextEditor.Document; + +namespace ICSharpCode.SharpDevelop.Bookmarks +{ + public sealed class BookmarkConverter : 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) + { + if (value is string) { + string[] v = ((string)value).Split('|'); + string fileName = v[1]; + int lineNumber = int.Parse(v[2], culture); + SDBookmark bookmark; + switch (v[0]) { + case "Breakpoint": + bookmark = new Breakpoint(null, fileName, lineNumber).Bookmark; + break; + default: + bookmark = new SDBookmark(fileName, null, lineNumber); + break; + } + bookmark.IsEnabled = bool.Parse(v[3]); + return bookmark; + } else { + return base.ConvertFrom(context, culture, value); + } + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) + { + SDBookmark bookmark = value as SDBookmark; + if (destinationType == typeof(string) && bookmark != null) { + StringBuilder b = new StringBuilder(); + if (bookmark is BreakpointBookmark) { + b.Append("Breakpoint"); + } else { + b.Append("Bookmark"); + } + b.Append('|'); + b.Append(bookmark.FileName); + b.Append('|'); + b.Append(bookmark.LineNumber); + b.Append('|'); + b.Append(bookmark.IsEnabled.ToString()); + return b.ToString(); + } else { + return base.ConvertTo(context, culture, value, destinationType); + } + } + } +} diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkManager.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkManager.cs index a138e04d41..112fd4f03d 100644 --- a/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkManager.cs +++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/BookmarkManager.cs @@ -60,6 +60,17 @@ namespace ICSharpCode.SharpDevelop.Bookmarks } } + public static List GetProjectBookmarks(ICSharpCode.SharpDevelop.Project.IProject project) + { + List projectBookmarks = new List(); + foreach (SDBookmark mark in bookmarks) { + if (mark.FileName != null && project.IsFileInProject(mark.FileName)) { + projectBookmarks.Add(mark); + } + } + return projectBookmarks; + } + public static event BookmarkEventHandler Removed; public static event BookmarkEventHandler Added; } diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkFolderNode.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkFolderNode.cs index 6e19471136..03c8e5beba 100644 --- a/src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkFolderNode.cs +++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkFolderNode.cs @@ -1,4 +1,5 @@ using System; +using System.IO; using System.Drawing; using System.Collections.Generic; using System.Windows.Forms; @@ -15,10 +16,11 @@ namespace ICSharpCode.SharpDevelop.Bookmarks { List marks = new List(); string fileName; + string fileNameText; string occurences; Image icon; - public List Marks { + public List Marks { get { return marks; } @@ -28,6 +30,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks { drawDefault = false; this.fileName = fileName; + fileNameText = Path.GetFileName(fileName) + " in " + Path.GetDirectoryName(fileName); icon = IconService.GetBitmap(IconService.GetImageForFile(fileName)); Nodes.Add(new TreeNode()); } @@ -39,13 +42,13 @@ namespace ICSharpCode.SharpDevelop.Bookmarks } else { occurences = " (" + marks.Count + " bookmarks)"; } - this.Text = fileName + occurences; + this.Text = fileNameText + occurences; } protected override int MeasureItemWidth(DrawTreeNodeEventArgs e) { Graphics g = e.Graphics; - int x = MeasureTextWidth(g, fileName, Font); + int x = MeasureTextWidth(g, fileNameText, Font); x += MeasureTextWidth(g, occurences, ItalicFont); if (icon != null) { x += icon.Width; @@ -60,17 +63,30 @@ namespace ICSharpCode.SharpDevelop.Bookmarks g.DrawImage(icon, x, e.Bounds.Y, icon.Width, icon.Height); x += icon.Width; } - DrawText(g, fileName, Brushes.Black, Font, ref x, e.Bounds.Y); + DrawText(g, fileNameText, Brushes.Black, Font, ref x, e.Bounds.Y); DrawText(g, occurences, Brushes.Gray, ItalicFont, ref x, e.Bounds.Y); } public void AddMark(SDBookmark mark) { - marks.Add(mark); + int index = -1; + for (int i = 0; i < marks.Count; ++i) { + if (mark.LineNumber < marks[i].LineNumber) { + index = i; + break; + } + } + if (index < 0) + marks.Add(mark); + else + marks.Insert(index, mark); if (isInitialized) { BookmarkNode newNode = new BookmarkNode(mark); - Nodes.Add(newNode); + if (index < 0) + Nodes.Add(newNode); + else + Nodes.Insert(index, newNode); newNode.EnsureVisible(); } SetText(); @@ -95,7 +111,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks Nodes.Clear(); if (marks.Count > 0) { IDocument document = marks[0].Document; - if (document.HighlightingStrategy == null) { + if (document != null && document.HighlightingStrategy == null) { document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategyForFile(fileName); } foreach (SDBookmark mark in marks) { diff --git a/src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkNode.cs b/src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkNode.cs index 4b2e7293ea..c257e35206 100644 --- a/src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkNode.cs +++ b/src/Main/Base/Project/Src/TextEditor/Bookmarks/Pad/Nodes/BookmarkNode.cs @@ -37,15 +37,37 @@ namespace ICSharpCode.SharpDevelop.Bookmarks Checked = bookmark.IsEnabled; positionText = "(" + (bookmark.LineNumber + 1) + ") "; - line = bookmark.Document.GetLineSegment(bookmark.LineNumber); - Text = positionText + bookmark.Document.GetText(line); + bookmark.DocumentChanged += BookmarkDocumentChanged; + bookmark.LineNumberChanged += BookmarkLineNumberChanged; + if (bookmark.Document != null) { + line = bookmark.Document.GetLineSegment(bookmark.LineNumber); + Text = positionText + bookmark.Document.GetText(line); + } else { + Text = positionText; + } + } + + void BookmarkDocumentChanged(object sender, EventArgs e) + { + if (bookmark.Document != null) { + line = bookmark.Document.GetLineSegment(bookmark.LineNumber); + Text = positionText + bookmark.Document.GetText(line); + } + } + + void BookmarkLineNumberChanged(object sender, EventArgs e) + { + positionText = "(" + (bookmark.LineNumber + 1) + ") "; + BookmarkDocumentChanged(sender, e); } protected override int MeasureItemWidth(DrawTreeNodeEventArgs e) { Graphics g = e.Graphics; int x = MeasureTextWidth(g, positionText, BoldMonospacedFont); - x += MeasureTextWidth(g, bookmark.Document.GetText(line).Replace("\t", " "), BoldMonospacedFont); + if (line != null) { + x += MeasureTextWidth(g, bookmark.Document.GetText(line).Replace("\t", " "), BoldMonospacedFont); + } return x; } @@ -57,7 +79,9 @@ namespace ICSharpCode.SharpDevelop.Bookmarks spaceSize = g.MeasureString("-", Font, new PointF(0, 0), StringFormat.GenericTypographic); - DrawLine(g, line, e.Bounds.Y, x); + if (line != null) { + DrawLine(g, line, e.Bounds.Y, x); + } } public override void ActivateItem() diff --git a/src/Main/Core/Project/Src/AddInTree/AddIn/AddIn.cs b/src/Main/Core/Project/Src/AddInTree/AddIn/AddIn.cs index a106a14180..092ba332f4 100644 --- a/src/Main/Core/Project/Src/AddInTree/AddIn/AddIn.cs +++ b/src/Main/Core/Project/Src/AddInTree/AddIn/AddIn.cs @@ -23,7 +23,7 @@ namespace ICSharpCode.Core return o; } } - return null; + throw new ArgumentException("Cannot create object: " + className); } public List Runtimes { diff --git a/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs b/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs index cb2ff9212a..b369c74775 100644 --- a/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs +++ b/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs @@ -2,11 +2,31 @@ using System; using System.IO; using System.ComponentModel; using System.Text; +using System.Collections; using System.Collections.Generic; using System.Xml; namespace ICSharpCode.Core { + /// + /// This interface flags an object beeing "mementocapable". This means that the + /// state of the object could be saved to an object + /// and set from a object from the same class. + /// This is used to save and restore the state of GUI objects. + /// + public interface IMementoCapable + { + /// + /// Creates a new memento from the state. + /// + Properties CreateMemento(); + + /// + /// Sets the state to the given memento. + /// + void SetMemento(Properties memento); + } + /// /// Description of PropertyGroup. /// @@ -23,21 +43,6 @@ namespace ICSharpCode.Core } } - public T Get(string property, T defaultValue) - { - if (!properties.ContainsKey(property)) { - properties.Add(property, defaultValue); - return defaultValue; - } - object o = properties[property]; - - if (o is System.String && typeof(T) != typeof(System.String)) { - TypeConverter c = TypeDescriptor.GetConverter(typeof(T)); - return (T)c.ConvertFromInvariantString(o.ToString()); - } - return (T)o; - } - public object Get(string property) { if (!properties.ContainsKey(property)) { @@ -61,7 +66,7 @@ namespace ICSharpCode.Core public bool Contains(string property) { return properties.ContainsKey(property); - } + } public bool Remove(string property) { @@ -71,7 +76,7 @@ namespace ICSharpCode.Core public Properties() { } - + public override string ToString() { StringBuilder sb = new StringBuilder(); @@ -86,7 +91,7 @@ namespace ICSharpCode.Core return sb.ToString(); } - public static Properties ReadFromAttributes(XmlReader reader) + public static Properties ReadFromAttributes(XmlReader reader) { Properties properties = new Properties(); if (reader.HasAttributes) { @@ -118,6 +123,9 @@ namespace ICSharpCode.Core Properties p = new Properties(); p.ReadProperties(reader, "Properties"); properties[propertyName] = p; + } else if (propertyName == "Array") { + propertyName = reader.GetAttribute(0); + properties[propertyName] = ReadArray(reader); } else { properties[propertyName] = reader.HasAttributes ? reader.GetAttribute(0) : null; } @@ -126,23 +134,59 @@ namespace ICSharpCode.Core } } + ArrayList ReadArray(XmlTextReader reader) + { + ArrayList l = new ArrayList(); + while (reader.Read()) { + switch (reader.NodeType) { + case XmlNodeType.EndElement: + if (reader.LocalName == "Array") { + return l; + } + break; + case XmlNodeType.Element: + l.Add(reader.HasAttributes ? reader.GetAttribute(0) : null); + break; + } + } + return l; + } + public void WriteProperties(XmlTextWriter writer) { foreach (KeyValuePair entry in properties) { - - if (entry.Value is Properties) { + object val = entry.Value; + if (val is Properties) { writer.WriteStartElement("Properties"); writer.WriteAttributeString("name", entry.Key); - ((Properties)entry.Value).WriteProperties(writer); + ((Properties)val).WriteProperties(writer); + writer.WriteEndElement(); + } else if (val is Array) { + writer.WriteStartElement("Array"); + writer.WriteAttributeString("name", entry.Key); + foreach (object o in (Array)val) { + writer.WriteStartElement("Element"); + WriteValue(writer, o); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } else { + writer.WriteStartElement(entry.Key); + WriteValue(writer, val); writer.WriteEndElement(); - continue; } - - writer.WriteStartElement(entry.Key); - if (entry.Value != null) { - writer.WriteAttributeString("value", entry.Value.ToString()); + } + } + + void WriteValue(XmlTextWriter writer, object val) + { + if (val != null) { + if (val is string) { + writer.WriteAttributeString("value", val.ToString()); + } else { + TypeConverter c = TypeDescriptor.GetConverter(val.GetType()); + writer.WriteAttributeString("value", c.ConvertToInvariantString(val)); } - writer.WriteEndElement(); } } @@ -184,6 +228,35 @@ namespace ICSharpCode.Core } return null; } + + public T Get(string property, T defaultValue) + { + if (!properties.ContainsKey(property)) { + properties.Add(property, defaultValue); + return defaultValue; + } + object o = properties[property]; + + if (o is string && typeof(T) != typeof(string)) { + TypeConverter c = TypeDescriptor.GetConverter(typeof(T)); + o = c.ConvertFromInvariantString(o.ToString()); + properties[property] = o; // store for future look up + } else if (o is ArrayList && typeof(T).IsArray) { + ArrayList list = (ArrayList)o; + Type elementType = typeof(T).GetElementType(); + Array arr = System.Array.CreateInstance(elementType, list.Count); + TypeConverter c = TypeDescriptor.GetConverter(elementType); + for (int i = 0; i < arr.Length; ++i) { + if (list[i] != null) { + arr.SetValue(c.ConvertFromInvariantString(list[i].ToString()), i); + } + } + o = arr; + properties[property] = o; // store for future look up + } + return (T)o; + } + protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) { if (PropertyChanged != null) {