diff --git a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/AssignStylesheetCommand.cs b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/AssignStylesheetCommand.cs index 4884afde4c..89cb8cc1c3 100644 --- a/src/AddIns/DisplayBindings/XmlEditor/Project/Src/AssignStylesheetCommand.cs +++ b/src/AddIns/DisplayBindings/XmlEditor/Project/Src/AssignStylesheetCommand.cs @@ -24,8 +24,9 @@ namespace ICSharpCode.XmlEditor string stylesheetFileName = BrowseForStylesheetFile(); // Assign stylesheet. - if (stylesheetFileName != null) + if (stylesheetFileName != null) { xmlView.StylesheetFileName = stylesheetFileName; + } } } @@ -39,21 +40,29 @@ namespace ICSharpCode.XmlEditor AddInTreeNode node = AddInTree.GetTreeNode("/SharpDevelop/Workbench/FileFilter"); if (node != null) { + string xmlFileFilter = GetFileFilter(node, "Xml"); + string allFilesFilter = GetFileFilter(node, "AllFiles"); + string xslFileFilter = GetFileFilter(node, "Xsl"); - string xmlFileFilter = (string)node.BuildChildItem("Xml", null, null); - string allFilesFilter = (string)node.BuildChildItem("AllFiles", null, null); - string xslFileFilter = (string)node.BuildChildItem("Xsl", null, null); - - dialog.Filter = string.Concat(xslFileFilter, "|", xmlFileFilter, "|", allFilesFilter); + dialog.Filter = String.Join("|", xslFileFilter, xmlFileFilter, allFilesFilter); dialog.FilterIndex = 1; } - if (dialog.ShowDialog(ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainWin32Window) == DialogResult.OK) { + if (dialog.ShowDialog(WorkbenchSingleton.MainWin32Window) == DialogResult.OK) { return dialog.FileName; } } return null; } + + static string GetFileFilter(AddInTreeNode node, string filterName) + { + FileFilterDescriptor fileFilter = node.BuildChildItem(filterName, null, null) as FileFilterDescriptor; + if (fileFilter != null) { + return fileFilter.ToString(); + } + return String.Empty; + } } } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/DottedLineMargin.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/DottedLineMargin.cs index d19791d500..97a8871bea 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/DottedLineMargin.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/DottedLineMargin.cs @@ -20,7 +20,7 @@ namespace ICSharpCode.AvalonEdit.Editing /// /// Creates a vertical dotted line to separate the line numbers from the text view. /// - public static UIElement Create(TextEditor editor) + public static UIElement Create() { Line line = new Line { X1 = 0, Y1 = 0, X2 = 0, Y2 = 1, @@ -32,6 +32,17 @@ namespace ICSharpCode.AvalonEdit.Editing Tag = tag }; + return line; + } + + /// + /// Creates a vertical dotted line to separate the line numbers from the text view. + /// + [Obsolete("This method got published accidentally; and will be removed again in a future version. Use the parameterless overload instead.")] + public static UIElement Create(TextEditor editor) + { + Line line = (Line)Create(); + line.SetBinding( Line.StrokeProperty, new Binding("LineNumbersForeground") { Source = editor } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/SelectionMouseHandler.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/SelectionMouseHandler.cs index ab54f946ae..07193d2e79 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/SelectionMouseHandler.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Editing/SelectionMouseHandler.cs @@ -206,6 +206,7 @@ namespace ICSharpCode.AvalonEdit.Editing textArea.Document.UndoStack.EndUndoGroup(); } } + e.Handled = true; } } } catch (Exception ex) { diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs index b8251ed8de..ffc2c3a090 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Folding/FoldingElementGenerator.cs @@ -95,6 +95,20 @@ namespace ICSharpCode.AvalonEdit.Folding } } if (foldedUntil > offset && foldingSection != null) { + // Handle overlapping foldings: if there's another folded folding + // (starting within the foldingSection) that continues after the end of the folded section, + // then we'll extend our fold element to cover that overlapping folding. + bool foundOverlappingFolding; + do { + foundOverlappingFolding = false; + foreach (FoldingSection fs in FoldingManager.GetFoldingsContaining(foldedUntil)) { + if (fs.IsFolded && fs.EndOffset > foldedUntil) { + foldedUntil = fs.EndOffset; + foundOverlappingFolding = true; + } + } + } while (foundOverlappingFolding); + string title = foldingSection.Title; if (string.IsNullOrEmpty(title)) title = "..."; diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/HeightTree.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/HeightTree.cs index 3acc90d67d..19345f2dd1 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/HeightTree.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/HeightTree.cs @@ -58,7 +58,24 @@ namespace ICSharpCode.AvalonEdit.Rendering this.weakLineTracker = null; } - public double DefaultLineHeight { get; set; } + double defaultLineHeight; + + public double DefaultLineHeight { + get { return defaultLineHeight; } + set { + double oldValue = defaultLineHeight; + if (oldValue == value) + return; + defaultLineHeight = value; + // update the stored value in all nodes: + foreach (var node in AllNodes) { + if (node.lineNode.height == oldValue) { + node.lineNode.height = value; + UpdateAugmentedData(node, UpdateAfterChildrenChangeRecursionMode.IfRequired); + } + } + } + } HeightTreeNode GetNode(DocumentLine ls) { @@ -84,7 +101,7 @@ namespace ICSharpCode.AvalonEdit.Rendering HeightTreeNode[] nodes = new HeightTreeNode[document.LineCount]; int lineNumber = 0; foreach (DocumentLine ls in document.Lines) { - nodes[lineNumber++] = new HeightTreeNode(ls, DefaultLineHeight); + nodes[lineNumber++] = new HeightTreeNode(ls, defaultLineHeight); } Debug.Assert(nodes.Length > 0); // now build the corresponding balanced tree @@ -161,7 +178,7 @@ namespace ICSharpCode.AvalonEdit.Rendering HeightTreeNode InsertAfter(HeightTreeNode node, DocumentLine newLine) { - HeightTreeNode newNode = new HeightTreeNode(newLine, DefaultLineHeight); + HeightTreeNode newNode = new HeightTreeNode(newLine, defaultLineHeight); if (node.right == null) { if (node.lineNode.collapsedSections != null) { // we are inserting directly after node - so copy all collapsedSections diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs index d4c4054b2e..1a67c34bdb 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs @@ -1233,18 +1233,15 @@ namespace ICSharpCode.AvalonEdit.Rendering null)) { wideSpaceWidth = Math.Max(1, line.WidthIncludingTrailingWhitespace); - defaultLineHeight = line.Height; + defaultLineHeight = Math.Max(1, line.Height); } } else { wideSpaceWidth = FontSize / 2; defaultLineHeight = FontSize + 3; } - } - - void InvalidateWideSpaceWidthAndDefaultLineHeight() - { - wideSpaceWidth = 0; - defaultLineHeight = 0; + // Update heightTree.DefaultLineHeight, if a document is loaded. + if (heightTree != null) + heightTree.DefaultLineHeight = defaultLineHeight; } static double ValidateVisualOffset(double offset) @@ -1684,20 +1681,29 @@ namespace ICSharpCode.AvalonEdit.Rendering { base.OnPropertyChanged(e); if (TextFormatterFactory.PropertyChangeAffectsTextFormatter(e.Property)) { - RecreateCachedElements(); + // first, create the new text formatter: RecreateTextFormatter(); - InvalidateWideSpaceWidthAndDefaultLineHeight(); + // changing text formatter requires recreating the cached elements + RecreateCachedElements(); + // and we need to re-measure the font metrics: + MeasureWideSpaceWidthAndDefaultLineHeight(); + } else if (e.Property == Control.ForegroundProperty + || e.Property == TextView.NonPrintableCharacterBrushProperty) + { + // changing brushes requires recreating the cached elements + RecreateCachedElements(); + Redraw(); } - if (e.Property == Control.ForegroundProperty - || e.Property == Control.FontFamilyProperty + if (e.Property == Control.FontFamilyProperty || e.Property == Control.FontSizeProperty || e.Property == Control.FontStretchProperty || e.Property == Control.FontStyleProperty - || e.Property == Control.FontWeightProperty - || e.Property == TextView.NonPrintableCharacterBrushProperty) + || e.Property == Control.FontWeightProperty) { + // changing font properties requires recreating cached elements RecreateCachedElements(); - InvalidateWideSpaceWidthAndDefaultLineHeight(); + // and we need to re-measure the font metrics: + MeasureWideSpaceWidthAndDefaultLineHeight(); Redraw(); } } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs index 1e9ca34fc9..90e851851e 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/TextEditor.cs @@ -13,7 +13,9 @@ using System.Windows.Data; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; +using System.Windows.Shapes; using System.Windows.Threading; + using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; using ICSharpCode.AvalonEdit.Highlighting; @@ -470,13 +472,13 @@ namespace ICSharpCode.AvalonEdit TextEditor editor = (TextEditor)d; var leftMargins = editor.TextArea.LeftMargins; if ((bool)e.NewValue) { - var lineNumbers = new LineNumberMargin(); + LineNumberMargin lineNumbers = new LineNumberMargin(); + Line line = (Line)DottedLineMargin.Create(); leftMargins.Insert(0, lineNumbers); - leftMargins.Insert(1, DottedLineMargin.Create(editor)); - lineNumbers.SetBinding(Control.ForegroundProperty, - new Binding("LineNumbersForeground") { - Source = editor - }); + leftMargins.Insert(1, line); + var lineNumbersForeground = new Binding("LineNumbersForeground") { Source = editor }; + line.SetBinding(Line.StrokeProperty, lineNumbersForeground); + lineNumbers.SetBinding(Control.ForegroundProperty, lineNumbersForeground); } else { for (int i = 0; i < leftMargins.Count; i++) { if (leftMargins[i] is LineNumberMargin) { diff --git a/src/Main/Base/Project/Src/Gui/FormLocationHelper.cs b/src/Main/Base/Project/Src/Gui/FormLocationHelper.cs index 5c6a674059..5a9c42e917 100644 --- a/src/Main/Base/Project/Src/Gui/FormLocationHelper.cs +++ b/src/Main/Base/Project/Src/Gui/FormLocationHelper.cs @@ -60,7 +60,7 @@ namespace ICSharpCode.SharpDevelop.Gui }; } - static Rect Validate(Rect bounds) + public static Rect Validate(Rect bounds) { // Check if form is outside the screen and get it back if necessary. // This is important when the user uses multiple screens, a window stores its location diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/FileNode.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/FileNode.cs index c7ed3c8a38..9a45004e58 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/FileNode.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/FileNode.cs @@ -122,7 +122,11 @@ namespace ICSharpCode.SharpDevelop.Project public override void ActivateItem() { - FileService.OpenFile(FileName); + var viewContent = FileService.OpenFile(FileName); + if (fileNodeStatus == FileNodeStatus.Missing && viewContent != null) { + fileNodeStatus = FileNodeStatus.InProject; + SetIcon(); + } } // protected override void Initialize() diff --git a/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs b/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs index 8e18fe4202..01ed0ca426 100644 --- a/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs +++ b/src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs @@ -529,25 +529,36 @@ namespace ICSharpCode.SharpDevelop.Gui } #endregion + System.Windows.WindowState lastNonMinimizedWindowState = System.Windows.WindowState.Normal; + Rect restoreBoundsBeforeClosing; + + protected override void OnStateChanged(EventArgs e) + { + base.OnStateChanged(e); + if (this.WindowState != System.Windows.WindowState.Minimized) + lastNonMinimizedWindowState = this.WindowState; + } + public Properties CreateMemento() { Properties prop = new Properties(); - prop.Set("WindowState", this.WindowState); - if (this.WindowState == System.Windows.WindowState.Normal) { - prop.Set("Left", this.Left); - prop.Set("Top", this.Top); - prop.Set("Width", this.Width); - prop.Set("Height", this.Height); + prop.Set("WindowState", lastNonMinimizedWindowState); + var bounds = this.RestoreBounds; + if (bounds.IsEmpty) bounds = restoreBoundsBeforeClosing; + if (!bounds.IsEmpty) { + prop.Set("Bounds", bounds); } return prop; } public void SetMemento(Properties memento) { - this.Left = memento.Get("Left", 10.0); - this.Top = memento.Get("Top", 10.0); - this.Width = memento.Get("Width", 600.0); - this.Height = memento.Get("Height", 400.0); + Rect bounds = memento.Get("Bounds", new Rect(10, 10, 750, 550)); + bounds = FormLocationHelper.Validate(bounds); + this.Left = bounds.Left; + this.Top = bounds.Top; + this.Width = bounds.Width; + this.Height = bounds.Height; this.WindowState = memento.Get("WindowState", System.Windows.WindowState.Maximized); } @@ -574,6 +585,8 @@ namespace ICSharpCode.SharpDevelop.Gui Project.ProjectService.CloseSolution(); ParserService.StopParserThread(); + restoreBoundsBeforeClosing = this.RestoreBounds; + this.WorkbenchLayout = null; foreach (PadDescriptor padDescriptor in this.PadContentCollection) { diff --git a/src/Main/Base/Project/Src/Project/CustomTool.cs b/src/Main/Base/Project/Src/Project/CustomTool.cs index 9142d32cea..6a150e56a8 100644 --- a/src/Main/Base/Project/Src/Project/CustomTool.cs +++ b/src/Main/Base/Project/Src/Project/CustomTool.cs @@ -99,12 +99,24 @@ namespace ICSharpCode.SharpDevelop.Project } public string GetOutputFileName(FileProjectItem baseItem, string additionalExtension) + { + return GetOutputFileName(baseItem, additionalExtension, true); + } + + public string GetOutputFileName(FileProjectItem baseItem, string additionalExtension, bool isPrimaryOutput) { if (baseItem == null) throw new ArgumentNullException("baseItem"); if (baseItem.Project != project) throw new ArgumentException("baseItem is not from project this CustomToolContext belongs to"); + if (isPrimaryOutput) { + string lastGenOutput = baseItem.GetEvaluatedMetadata("LastGenOutput"); + if (!string.IsNullOrEmpty(lastGenOutput)) { + return Path.Combine(Path.GetDirectoryName(baseItem.FileName), lastGenOutput); + } + } + string newExtension = null; if (project.LanguageProperties.CodeDomProvider != null) { newExtension = project.LanguageProperties.CodeDomProvider.FileExtension; @@ -121,22 +133,55 @@ namespace ICSharpCode.SharpDevelop.Project newExtension = "." + newExtension; } - return Path.ChangeExtension(baseItem.FileName, additionalExtension + newExtension); + string newFileName = Path.ChangeExtension(baseItem.FileName, additionalExtension + newExtension); + int retryIndex = 0; + while (true) { + FileProjectItem item = project.FindFile(newFileName); + // If the file does not exist in the project, we can use that name. + if (item == null) + return newFileName; + // If the file already exists in the project, use it only if it belongs to our base item + if (string.Equals(item.DependentUpon, Path.GetFileName(baseItem.FileName), StringComparison.OrdinalIgnoreCase)) + return newFileName; + // Otherwise, find another free file name + retryIndex++; + newFileName = Path.ChangeExtension(baseItem.FileName, additionalExtension + retryIndex + newExtension); + } } public FileProjectItem EnsureOutputFileIsInProject(FileProjectItem baseItem, string outputFileName) { + return EnsureOutputFileIsInProject(baseItem, outputFileName, true); + } + + public FileProjectItem EnsureOutputFileIsInProject(FileProjectItem baseItem, string outputFileName, bool isPrimaryOutput) + { + if (baseItem == null) + throw new ArgumentNullException("baseItem"); + if (baseItem.Project != project) + throw new ArgumentException("baseItem is not from project this CustomToolContext belongs to"); + WorkbenchSingleton.AssertMainThread(); + bool saveProject = false; + if (isPrimaryOutput) { + if (baseItem.GetEvaluatedMetadata("LastGenOutput") != Path.GetFileName(outputFileName)) { + saveProject = true; + baseItem.SetEvaluatedMetadata("LastGenOutput", Path.GetFileName(outputFileName)); + } + } FileProjectItem outputItem = project.FindFile(outputFileName); if (outputItem == null) { outputItem = new FileProjectItem(project, ItemType.Compile); outputItem.FileName = outputFileName; outputItem.DependentUpon = Path.GetFileName(baseItem.FileName); + outputItem.SetEvaluatedMetadata("AutoGen", "True"); ProjectService.AddProjectItem(project, outputItem); FileService.FireFileCreated(outputFileName, false); - project.Save(); + saveProject = true; ProjectBrowserPad.RefreshViewAsync(); } + if (saveProject) + project.Save(); return outputItem; } @@ -475,7 +520,7 @@ namespace ICSharpCode.SharpDevelop.Project activeToolRun = null; if(toolRuns.Count > 0) { CustomToolRun nextRun = toolRuns.Dequeue(); - if(nextRun != null) { + if(nextRun != null) { RunCustomTool(nextRun); } } diff --git a/src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs b/src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs index 785092d6ea..6d0fa74182 100644 --- a/src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs +++ b/src/Main/ICSharpCode.SharpDevelop.BuildWorker/Program.cs @@ -123,7 +123,12 @@ namespace ICSharpCode.SharpDevelop.BuildWorker Program.Log("In build thread"); bool success = false; try { - success = buildWrapper.DoBuild(currentJob, new ForwardingLogger(this)); + if (File.Exists(currentJob.ProjectFileName)) { + success = buildWrapper.DoBuild(currentJob, new ForwardingLogger(this)); + } else { + success = false; + HostReportEvent(new BuildErrorEventArgs(null, null, currentJob.ProjectFileName, 0, 0, 0, 0, "Project file '" + Path.GetFileName(currentJob.ProjectFileName) + "' not found", null, null)); + } } catch (Exception ex) { host.Writer.Write("ReportException"); host.Writer.Write(ex.ToString()); @@ -297,19 +302,5 @@ namespace ICSharpCode.SharpDevelop.BuildWorker } } #endif - - [Serializable] - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1064:ExceptionsShouldBePublic")] - sealed class BuildCancelException : Exception - { - public BuildCancelException() - { - } - - BuildCancelException(SerializationInfo info, StreamingContext context) - : base(info, context) - { - } - } } }