diff options
author | Matt Ward <matt.ward@xamarin.com> | 2015-11-19 12:43:19 +0300 |
---|---|---|
committer | Matt Ward <matt.ward@xamarin.com> | 2015-11-19 12:43:19 +0300 |
commit | 3464fad275c48d7c4ffb3602dfcc66afa467b76a (patch) | |
tree | 10db040d0a2cf55165ac8d43dd24b60ca297a887 /main/src/core/MonoDevelop.Ide | |
parent | d94562154c646871e5af85aeb9eca1ece86776f9 (diff) | |
parent | 203ed0aabb6a60c7bb18f3b7b490588ab09cf38e (diff) |
Merge branch 'master' into aspnet-project-wizard
Conflicts:
main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj
main/tests/UnitTests/UnitTests.csproj
Diffstat (limited to 'main/src/core/MonoDevelop.Ide')
87 files changed, 2069 insertions, 533 deletions
diff --git a/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs b/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs index df2563993f..84ab363a6f 100644 --- a/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs +++ b/main/src/core/MonoDevelop.Ide/AssemblyInfo.cs @@ -10,6 +10,7 @@ using System.Runtime.CompilerServices; [assembly: AssemblyCopyright ("LGPL")] [assembly: InternalsVisibleTo("MacPlatform")] +[assembly: InternalsVisibleTo("WindowsPlatform")] [assembly: InternalsVisibleTo("MonoDevelop.Debugger")] [assembly: InternalsVisibleTo("MonoDevelop.DesignerSupport")] [assembly: InternalsVisibleTo("Ide.Tests")] diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml index 1ae62d65bf..3b0e686d93 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Commands.addin.xml @@ -619,15 +619,15 @@ defaultHandler = "MonoDevelop.Ide.Commands.ZoomIn" _label = "_Zoom In" icon = "gtk-zoom-in" - shortcut = "Control|+" - macShortcut = "Meta|+" + shortcut = "Control|+ Control|=" + macShortcut = "Meta|+ Meta|=" _description = "Zooms view in" /> <Command id = "MonoDevelop.Ide.Commands.ViewCommands.ZoomOut" defaultHandler = "MonoDevelop.Ide.Commands.ZoomOut" _label = "Zoom _Out" icon = "gtk-zoom-out" - shortcut = "Control|-" - macShortcut = "Meta|-" + shortcut = "Control|- Control|_" + macShortcut = "Meta|- Meta|_" _description = "Zooms view out" /> <Command id = "MonoDevelop.Ide.Commands.ViewCommands.ZoomReset" defaultHandler = "MonoDevelop.Ide.Commands.ZoomReset" @@ -683,26 +683,37 @@ defaultHandler = "MonoDevelop.Ide.Commands.InstrumentationViewerHandler" _label = "Instrumentation Monitor" /> + <Command id = "MonoDevelop.Ide.Commands.ToolCommands.ToggleSessionRecorder" + defaultHandler = "MonoDevelop.Ide.Commands.ToggleSessionRecorderHandler" + _label = "Start Session Recorder" /> + + <Command id = "MonoDevelop.Ide.Commands.ToolCommands.ReplaySession" + defaultHandler = "MonoDevelop.Ide.Commands.ReplaySessionHandler" + _label = "Replay Session..." /> </Category> <!-- WindowCommands --> <Category _name = "Window" id = "Window"> - <Command id = "MonoDevelop.Ide.Commands.WindowCommands.NextWindow" - defaultHandler = "MonoDevelop.Ide.Commands.NextWindowHandler" - _label = "_Next Window" + <Command id = "MonoDevelop.Ide.Commands.WindowCommands.NextDocument" + defaultHandler = "MonoDevelop.Ide.Commands.NextDocumentHandler" + _label = "_Next Document" icon = "gtk-go-forward" - _description = "Show next window" + _description = "Show next document" shortcut = "Control|Page_Down" macShortcut = "Meta|}" /> - <Command id = "MonoDevelop.Ide.Commands.WindowCommands.PrevWindow" - defaultHandler = "MonoDevelop.Ide.Commands.PrevWindowHandler" - _label = "_Previous Window" + <Command id = "MonoDevelop.Ide.Commands.WindowCommands.PrevDocument" + defaultHandler = "MonoDevelop.Ide.Commands.PrevDocumentHandler" + _label = "_Previous Document" icon = "gtk-go-back" - _description = "Show previous window" + _description = "Show previous document" shortcut = "Control|Page_Up" macShortcut = "Meta|{" /> + <Command id = "MonoDevelop.Ide.Commands.WindowCommands.OpenDocumentList" + defaultHandler = "MonoDevelop.Ide.Commands.OpenDocumentListHandler" + type="radio|array" + _label = "Document List" /> <Command id = "MonoDevelop.Ide.Commands.WindowCommands.OpenWindowList" defaultHandler = "MonoDevelop.Ide.Commands.OpenWindowListHandler" type="radio|array" diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml index e3a7cc997a..28e93193d0 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MainMenu.addin.xml @@ -222,6 +222,10 @@ <CommandItem id = "MonoDevelop.Ide.Commands.ToolCommands.ToolList" /> <CommandItem id = "MonoDevelop.Ide.Commands.ToolCommands.InstrumentationViewer" /> <CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.InsertGuid" /> + <ItemSet id = "SessionRecorder" _label = "Session Recorder" autohide = "true"> + <CommandItem id = "MonoDevelop.Ide.Commands.ToolCommands.ToggleSessionRecorder" /> + <CommandItem id = "MonoDevelop.Ide.Commands.ToolCommands.ReplaySession" /> + </ItemSet> <SeparatorItem id = "OptionsSection" /> <Condition id="Platform" value="windows"> <CommandItem id = "MonoDevelop.Ide.Commands.EditCommands.MonodevelopPreferences" /> @@ -230,8 +234,8 @@ </ItemSet> <ItemSet id = "Window" _label = "_Window"> - <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.NextWindow" /> - <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.PrevWindow" /> + <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.NextDocument" /> + <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.PrevDocument" /> <SeparatorItem id ="NxtPrvSeparator" /> <CommandItem id = "MonoDevelop.Ide.Commands.FileCommands.CloseAllFiles" /> <!-- <SeparatorItem id ="SplitSeparator" /> @@ -241,6 +245,9 @@ <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.SwitchSplitWindow" />--> <SeparatorItem id = "contentSep" /> <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.OpenWindowList" /> + <SeparatorItem id = "windowDocSep" /> + <CommandItem id = "MonoDevelop.Ide.Commands.WindowCommands.OpenDocumentList" /> + <SeparatorItem id = "docMinimizeSep" /> </ItemSet> <ItemSet id = "Help" _label = "_Help"> diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml index 4a4bd5b95a..b27e0cb69b 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/MimeTypes.addin.xml @@ -67,6 +67,11 @@ <MimeType id="text/x-apple-strings" _description="Apple Strings" isText="true"> <File pattern="*.strings" /> </MimeType> + + <MimeType id="text/x-sql" _description="sql files" isText="true"> + <File pattern="*.sql" /> + </MimeType> + <MimeType id="application/json" _description="JSON files" isText="true"> <File pattern="*.json" /> </MimeType> diff --git a/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml b/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml index 2c791534fe..d53bd4470a 100644 --- a/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml +++ b/main/src/core/MonoDevelop.Ide/ExtensionModel/Templates.addin.xml @@ -94,6 +94,11 @@ </Extension> <Extension path="/MonoDevelop/Ide/ProjectTemplateCategories"> + <Category id="multiplat" name="Multi-platform" icon="md-platform-cross-platform"> + <Category id="library" name="Library"> + <Category id="general" name="General" mappedCategories="crossplat/library/general" /> + </Category> + </Category> <Category id="other" name="Other" icon="md-platform-other"> <Category id="net" name=".NET"> <Category id="general" name="General" mappedCategories="C#" /> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs index 34a2429352..0f27272baa 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/ChildrenOperation.cs @@ -30,12 +30,19 @@ namespace MonoDevelop.Components.AutoTest.Operations { public class ChildrenOperation : Operation { + bool recursive; + + public ChildrenOperation (bool recursive = true) + { + this.recursive = recursive; + } + public override List<AppResult> Execute (List<AppResult> resultSet) { List<AppResult> newResultSet = new List<AppResult> (); foreach (var result in resultSet) { - List<AppResult> flattenedChildren = result.Children (); + List<AppResult> flattenedChildren = result.Children (recursive); if (flattenedChildren != null) { newResultSet.AddRange (flattenedChildren); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/SelectedOperation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/SelectedOperation.cs new file mode 100644 index 0000000000..51dfa0444b --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Operations/SelectedOperation.cs @@ -0,0 +1,53 @@ +// +// SelectedOperation.cs +// +// Author: +// Manish Sinha <manish.sinha@xamarin.com> +// +// Copyright (c) 2015 Xamarin Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; + +namespace MonoDevelop.Components.AutoTest.Operations +{ + public class SelectedOperation : Operation + { + public override List<AppResult> Execute (List<AppResult> resultSet) + { + List<AppResult> newResultSet = new List<AppResult> (); + + foreach (var result in resultSet) { + AppResult newResult = result.Selected (); + if (newResult != null) { + newResultSet.Add (newResult); + } + } + + return newResultSet; + } + + public override string ToString () + { + return string.Format ("Selected ()"); + } + } +} + diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs index a0017d32e4..53ec341408 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkNotebookResult.cs @@ -59,6 +59,14 @@ namespace MonoDevelop.Components.AutoTest.Results return null; } + public override AppResult Selected () + { + if (base.Selected () != null) { + return noteBook.CurrentPage == toBeSelected ? this : null; + } + return null; + } + public override bool Select () { if (toBeSelected >= 0) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs index a4a84f8525..bf7a4fd98b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkTreeModelResult.cs @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; using Gtk; +using System.Linq; namespace MonoDevelop.Components.AutoTest.Results { @@ -51,12 +52,25 @@ namespace MonoDevelop.Components.AutoTest.Results Column = column; resultIter = iter; } - + public override AppResult Marked (string mark) { return null; } + public override AppResult Selected () + { + if (!resultIter.HasValue) { + return base.Selected (); + } + + if (base.Selected () != null && ParentWidget is TreeView) { + TreeView treeView = (TreeView)ParentWidget; + return treeView.Selection.IterIsSelected (resultIter.Value) ? this : null; + } + return null; + } + public override AppResult CheckType (Type desiredType) { return null; @@ -64,7 +78,11 @@ namespace MonoDevelop.Components.AutoTest.Results public override AppResult Model (string column) { - return null; + var columnNumber = GetColumnNumber (column, TModel); + if (columnNumber == -1) + return null; + Column = columnNumber; + return this; } bool CheckForText (TreeModel model, TreeIter iter, bool exact) @@ -108,7 +126,16 @@ namespace MonoDevelop.Components.AutoTest.Results return MatchProperty (propertyName, objectToCompare, value); } - return null; + return MatchProperty (propertyName, ParentWidget, value); + } + + public override ObjectProperties Properties () + { + if (resultIter != null && resultIter.HasValue) { + var objectForProperties = TModel.GetValue (resultIter.Value, Column); + return base.GetProperties (objectForProperties); + } + return base.Properties (); } public override List<AppResult> NextSiblings () @@ -131,38 +158,90 @@ namespace MonoDevelop.Components.AutoTest.Results { if (resultIter == null || !resultIter.HasValue) { List<AppResult> children = new List<AppResult> (); - TModel.Foreach ((m, p, i) => { - children.Add (new GtkTreeModelResult (ParentWidget, TModel, Column, i)); - return false; - }); + TreeIter topIter; + if (TModel.GetIterFirst (out topIter)) { + var child = new GtkTreeModelResult (ParentWidget, TModel, Column, topIter); + children.Add (child); + this.FirstChild = child; + child.ParentNode = this; + + if (recursive) { + var topIterChildren = FetchIterChildren (topIter, child, recursive); + child.FirstChild = topIterChildren.FirstOrDefault (); + children.AddRange (topIterChildren); + } + + GtkTreeModelResult previousSibling = child; + while (TModel.IterNext (ref topIter)) { + var nextSibling = new GtkTreeModelResult (ParentWidget, TModel, Column, topIter); + children.Add (nextSibling); + + nextSibling.PreviousSibling = previousSibling; + previousSibling.NextSibling = nextSibling; + nextSibling.ParentNode = this; + + if (recursive) { + var topIterChildren = FetchIterChildren (topIter, nextSibling, recursive); + nextSibling.FirstChild = topIterChildren.FirstOrDefault (); + children.AddRange (topIterChildren); + } + } + } return children; } TreeIter currentIter = (TreeIter) resultIter; - if (!TModel.IterHasChild (currentIter)) + return FetchIterChildren (currentIter, this, recursive); + } + + List<AppResult> FetchIterChildren (TreeIter iter, GtkTreeModelResult result, bool recursive) + { + List<AppResult> newList = new List<AppResult> (); + if (!TModel.IterHasChild (iter)) { - return null; + return newList; } - List<AppResult> newList = new List<AppResult> (); - for (int i = 0; i < TModel.IterNChildren (currentIter); i++) { + GtkTreeModelResult previousSibling = null; + for (int i = 0; i < TModel.IterNChildren (iter); i++) { TreeIter childIter; - if (TModel.IterNthChild (out childIter, currentIter, i)) { - newList.Add (new GtkTreeModelResult (ParentWidget, TModel, Column, childIter)); + if (TModel.IterNthChild (out childIter, iter, i)) { + var child = new GtkTreeModelResult (ParentWidget, TModel, Column, childIter); + + child.ParentNode = this; + child.PreviousSibling = previousSibling; + if (previousSibling != null) + previousSibling.NextSibling = child; + + newList.Add (child); + if (recursive) { + var childrenIter = FetchIterChildren (childIter, child, recursive); + newList.AddRange (childrenIter); + child.FirstChild = childrenIter.FirstOrDefault (); + } + + previousSibling = child; } } + result.FirstChild = newList.FirstOrDefault (); return newList; } public override bool Select () { + base.Select (); + if (!resultIter.HasValue) { return false; } if (ParentWidget is TreeView) { TreeView treeView = (TreeView) ParentWidget; + treeView.Selection.UnselectAll (); + treeView.ExpandRow (TModel.GetPath (resultIter.Value), false); treeView.Selection.SelectIter ((TreeIter) resultIter); + treeView.SetCursor (TModel.GetPath ((TreeIter) resultIter), treeView.Columns [0], false); + } else if (ParentWidget is ComboBox) { ComboBox comboBox = (ComboBox) ParentWidget; comboBox.SetActiveIter ((TreeIter) resultIter); @@ -182,23 +261,15 @@ namespace MonoDevelop.Components.AutoTest.Results return false; } - public override bool TypeKey (char key, string state = "") - { - return false; - } - - public override bool TypeKey (string keyString, string state = "") - { - throw new NotImplementedException (); - } - - public override bool EnterText (string text) - { - return false; - } - public override bool Toggle (bool active) { + if (resultIter.HasValue) { + var modelValue = TModel.GetValue ((TreeIter)resultIter, Column); + if (modelValue is bool) { + TModel.SetValue ((TreeIter)resultIter, Column, active); + return true; + } + } return false; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs index ee0a2ce5d0..50d4f4b082 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/GtkWidgetResult.cs @@ -85,6 +85,11 @@ namespace MonoDevelop.Components.AutoTest.Results return null; } + public override AppResult Selected () + { + return resultWidget.HasFocus ? this : null; + } + public override AppResult CheckType (Type desiredType) { if (resultWidget.GetType () == desiredType || resultWidget.GetType ().IsSubclassOf (desiredType)) { @@ -147,7 +152,7 @@ namespace MonoDevelop.Components.AutoTest.Results return null; } - TreeModel ModelFromWidget (Widget widget) + protected TreeModel ModelFromWidget (Widget widget) { TreeView tv = widget as TreeView; if (tv != null) { @@ -174,25 +179,23 @@ namespace MonoDevelop.Components.AutoTest.Results } // Check if the class has the SemanticModelAttribute + var columnNumber = GetColumnNumber (column, model); + return columnNumber == -1 ? null : new GtkTreeModelResult (resultWidget, model, columnNumber) { SourceQuery = this.SourceQuery }; + } + + protected int GetColumnNumber (string column, TreeModel model) + { Type modelType = model.GetType (); SemanticModelAttribute attr = modelType.GetCustomAttribute<SemanticModelAttribute> (); - if (attr == null) { // Check if the instance has the attributes AttributeCollection attrs = TypeDescriptor.GetAttributes (model); attr = (SemanticModelAttribute)attrs [typeof(SemanticModelAttribute)]; - if (attr == null) { - return null; + return -1; } } - - int columnNumber = Array.IndexOf (attr.ColumnNames, column); - if (columnNumber == -1) { - return null; - } - - return new GtkTreeModelResult (resultWidget, model, columnNumber) { SourceQuery = this.SourceQuery }; + return Array.IndexOf (attr.ColumnNames, column); } public override AppResult Property (string propertyName, object value) @@ -291,7 +294,7 @@ namespace MonoDevelop.Components.AutoTest.Results } } - void RealTypeKey (Gdk.Key key, Gdk.ModifierType state) + internal void RealTypeKey (Gdk.Key key, Gdk.ModifierType state) { SendKeyEvent (resultWidget, (uint)key, state, Gdk.EventType.KeyPress, null); SendKeyEvent (resultWidget, (uint)key, state, Gdk.EventType.KeyRelease, null); @@ -395,6 +398,12 @@ namespace MonoDevelop.Components.AutoTest.Results case "TAB": return Gdk.Key.Tab; + case "BKSP": + return Gdk.Key.BackSpace; + + case "DELETE": + return Gdk.Key.Delete; + default: throw new Exception ("Unknown keystring: " + keyString); } @@ -437,12 +446,13 @@ namespace MonoDevelop.Components.AutoTest.Results return; } - Cairo.Context cr = Gdk.CairoHelper.Create (resultWidget.GdkWindow); - cr.SetSourceRGB (1.0, 0.0, 0.0); + using (var cr = Gdk.CairoHelper.Create (resultWidget.GdkWindow)) { + cr.SetSourceRGB (1.0, 0.0, 0.0); - Gdk.Rectangle allocation = resultWidget.Allocation; - Gdk.CairoHelper.Rectangle (cr, allocation); - cr.Stroke (); + Gdk.Rectangle allocation = resultWidget.Allocation; + Gdk.CairoHelper.Rectangle (cr, allocation); + cr.Stroke (); + } } public override void Flash () diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs index d60b841183..e12c8ab3ed 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/NSObjectResult.cs @@ -26,12 +26,15 @@ #if MAC using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Xml; using AppKit; using Foundation; +using MonoDevelop.Components.MainToolbar; + namespace MonoDevelop.Components.AutoTest.Results { public class NSObjectResult : AppResult @@ -43,6 +46,11 @@ namespace MonoDevelop.Components.AutoTest.Results ResultObject = resultObject; } + public override string ToString () + { + return string.Format ("NSObject: Type: {0}", ResultObject.GetType ().FullName); + } + public override void ToXml (XmlElement element) { AddAttribute (element, "type", ResultObject.GetType ().ToString ()); @@ -69,18 +77,29 @@ namespace MonoDevelop.Components.AutoTest.Results public override AppResult Marked (string mark) { + if (CheckForText (ResultObject.GetType ().FullName, mark, true)) { + return this; + } + if (ResultObject is NSView) { - if (((NSView)ResultObject).Identifier == mark) { + if (CheckForText (((NSView)ResultObject).Identifier, mark, true)) { return this; } + } - if (ResultObject.GetType ().FullName == mark) { + if (ResultObject is NSWindow) { + if (CheckForText (((NSWindow)ResultObject).Title, mark, true)) { return this; } } return null; } + public override AppResult Selected () + { + return null; + } + public override AppResult CheckType (Type desiredType) { if (ResultObject.GetType () == desiredType || ResultObject.GetType ().IsSubclassOf (desiredType)) { @@ -98,6 +117,13 @@ namespace MonoDevelop.Components.AutoTest.Results if (CheckForText (value, text, exact)) { return this; } + + if (ResultObject is NSButton) { + var nsButton = (NSButton)ResultObject; + if (CheckForText (nsButton.Title, text, exact)) { + return this; + } + } } return null; @@ -125,7 +151,7 @@ namespace MonoDevelop.Components.AutoTest.Results public override AppResult Property (string propertyName, object value) { - return (GetPropertyValue (propertyName) == value) ? this : null; + return MatchProperty (propertyName, ResultObject, value); } public override List<AppResult> NextSiblings () @@ -150,7 +176,8 @@ namespace MonoDevelop.Components.AutoTest.Results return false; } - control.PerformClick (null); + using (var nsObj = new NSObject ()) + control.PerformClick (nsObj); return true; } @@ -216,6 +243,55 @@ namespace MonoDevelop.Components.AutoTest.Results { } + +#region MacPlatform.MacIntegration.MainToolbar.SelectorView + public override bool SetActiveConfiguration (string configurationName) + { + Type type = ResultObject.GetType (); + PropertyInfo pinfo = type.GetProperty ("ConfigurationModel"); + if (pinfo == null) { + return false; + } + + IEnumerable<IConfigurationModel> model = (IEnumerable<IConfigurationModel>)pinfo.GetValue (ResultObject, null); + var configuration = model.FirstOrDefault (c => c.DisplayString == configurationName); + if (configuration == null) { + return false; + } + + pinfo = type.GetProperty ("ActiveConfiguration"); + if (pinfo == null) { + return false; + } + + pinfo.SetValue (ResultObject, configuration); + return true; + } + + public override bool SetActiveRuntime (string runtimeName) + { + Type type = ResultObject.GetType (); + PropertyInfo pinfo = type.GetProperty ("RuntimeModel"); + if (pinfo == null) { + return false; + } + + IEnumerable<IRuntimeModel> model = (IEnumerable<IRuntimeModel>)pinfo.GetValue (ResultObject, null); + + var runtime = model.FirstOrDefault (r => r.GetMutableModel ().FullDisplayString == runtimeName); + if (runtime == null) { + return false; + } + + pinfo = type.GetProperty ("ActiveRuntime"); + if (pinfo == null) { + return false; + } + + pinfo.SetValue (ResultObject, runtime); + return true; + } +#endregion } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs index 6657d42cf6..683b697037 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest.Results/ObjectResult.cs @@ -53,6 +53,11 @@ namespace MonoDevelop.Components.AutoTest.Results return null; } + public override AppResult Selected () + { + return null; + } + public override AppResult CheckType (Type desiredType) { return null; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs index 6e9e31a26e..fc08c971db 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppQuery.cs @@ -293,6 +293,12 @@ namespace MonoDevelop.Components.AutoTest return this; } + public AppQuery Selected () + { + operations.Add (new SelectedOperation ()); + return this; + } + public AppQuery Model (string column = null) { operations.Add (new ModelOperation (column)); @@ -335,9 +341,9 @@ namespace MonoDevelop.Components.AutoTest return this; } - public AppQuery Children () + public AppQuery Children (bool recursive = true) { - operations.Add (new ChildrenOperation ()); + operations.Add (new ChildrenOperation (recursive)); return this; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs index e2db5fbac6..20a71e2df5 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AppResult.cs @@ -50,6 +50,7 @@ namespace MonoDevelop.Components.AutoTest // Operations public abstract AppResult Marked (string mark); public abstract AppResult CheckType (Type desiredType); + public abstract AppResult Selected (); public abstract AppResult Text (string text, bool exact); public abstract AppResult Model (string column); public abstract AppResult Property (string propertyName, object value); @@ -62,9 +63,22 @@ namespace MonoDevelop.Components.AutoTest public abstract bool TypeKey (string keyString, string state = ""); public abstract bool EnterText (string text); public abstract bool Toggle (bool active); - public abstract void Flash (); + // More specific actions for complicated widgets + + #region For MacPlatform.MacIntegration.MainToolbar.SelectorView + public virtual bool SetActiveConfiguration (string configurationName) + { + return false; + } + + public virtual bool SetActiveRuntime (string runtimeName) + { + return false; + } + #endregion + // Inspection Operations public abstract ObjectProperties Properties (); public abstract string GetResultType (); @@ -128,27 +142,30 @@ namespace MonoDevelop.Components.AutoTest var properties = resultObject.GetType ().GetProperties ( BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (var property in properties) { - var value = GetPropertyValue (property.Name, resultObject); - AppResult result = null; - - var gtkNotebookValue = value as Gtk.Notebook; - if (gtkNotebookValue != null) - result = new GtkNotebookResult (gtkNotebookValue); - var gtkTreeviewValue = value as Gtk.TreeView; - if (gtkTreeviewValue != null && result == null) - result = new GtkTreeModelResult (gtkTreeviewValue, gtkTreeviewValue.Model, 0); - var gtkWidgetValue = value as Gtk.Widget; - if (gtkWidgetValue != null && result == null) - result = new GtkWidgetResult (gtkWidgetValue); - #if MAC - var nsObjectValue = value as Foundation.NSObject; - if (nsObjectValue != null && result == null) - result = new NSObjectResult (nsObjectValue); - #endif - if (result == null) - result = new ObjectResult (value); - - propertiesObject.Add (property.Name, result, property); + try { + var value = GetPropertyValue (property.Name, resultObject); + AppResult result = null; + + var gtkNotebookValue = value as Gtk.Notebook; + if (gtkNotebookValue != null) + result = new GtkNotebookResult (gtkNotebookValue); + var gtkTreeviewValue = value as Gtk.TreeView; + if (gtkTreeviewValue != null && result == null) + result = new GtkTreeModelResult (gtkTreeviewValue, gtkTreeviewValue.Model, 0); + var gtkWidgetValue = value as Gtk.Widget; + if (gtkWidgetValue != null && result == null) + result = new GtkWidgetResult (gtkWidgetValue); + #if MAC + var nsObjectValue = value as Foundation.NSObject; + if (nsObjectValue != null && result == null) + result = new NSObjectResult (nsObjectValue); + #endif + if (result == null) + result = new ObjectResult (value); + propertiesObject.Add (property.Name, result, property); + } catch (Exception e) { + MonoDevelop.Core.LoggingService.LogInfo ("Failed to fetch property '{0}' on '{1}' with Exception: {2}", property, resultObject, e); + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs index d8d656db72..56047273c4 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestClientSession.cs @@ -65,6 +65,15 @@ namespace MonoDevelop.Components.AutoTest if (file == null) { var binDir = Path.GetDirectoryName (typeof(AutoTestClientSession).Assembly.Location); file = Path.Combine (binDir, "MonoDevelop.exe"); + if (!File.Exists (file)) { + file = Path.Combine (binDir, "XamarinStudio.exe"); + } + } else if (!File.Exists (file)) { + file = file.Replace ("MonoDevelop.exe", "XamarinStudio.exe"); + } + + if (!File.Exists (file)) { + throw new FileNotFoundException (file); } MonoDevelop.Core.Execution.RemotingService.RegisterRemotingChannel (); @@ -77,7 +86,6 @@ namespace MonoDevelop.Components.AutoTest var pi = new ProcessStartInfo (file, args) { UseShellExecute = false }; pi.EnvironmentVariables ["MONO_AUTOTEST_CLIENT"] = sref; - pi.EnvironmentVariables ["GTK_MODULES"] = "gail:atk-bridge"; if (environment != null) foreach (var e in environment) pi.EnvironmentVariables [e.Key] = e.Value; @@ -355,11 +363,31 @@ namespace MonoDevelop.Components.AutoTest } } + public bool SetActiveConfiguration (Func<AppQuery, AppQuery> query, string configuration) + { + AppResult[] results = Query (query); + if (results.Length == 0) { + return false; + } + + return session.SetActiveConfiguration (results [0], configuration); + } + + public bool SetActiveRuntime (Func<AppQuery, AppQuery> query, string runtime) + { + AppResult[] results = Query (query); + if (results.Length == 0) { + return false; + } + + return session.SetActiveRuntime (results [0], runtime); + } + public void RunAndWaitForTimer (Action action, string counterName, int timeout = 20000) { AutoTestSession.TimerCounterContext context = session.CreateNewTimerContext (counterName); action (); - session.WaitForTimerContext (context); + session.WaitForTimerContext (context, timeout); } public XmlDocument ResultsAsXml (AppResult[] results) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs index 7c58a76780..64b48200c2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestService.cs @@ -26,10 +26,16 @@ using System; using MonoDevelop.Components.Commands; +using MonoDevelop.Core; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Remoting; +using System.Diagnostics; using System.Collections.Generic; +using System.Linq; +using System.Xml; +using System.Xml.Linq; +using System.Text; namespace MonoDevelop.Components.AutoTest { @@ -41,6 +47,11 @@ namespace MonoDevelop.Components.AutoTest get { return manager.currentSession; } } + static SessionRecord currentRecordSession; + public static SessionRecord CurrentRecordSession { + get { return currentRecordSession; } + } + public static void Start (CommandManager commandManager, bool publishServer) { AutoTestService.commandManager = commandManager; @@ -65,12 +76,35 @@ namespace MonoDevelop.Components.AutoTest File.WriteAllText (SessionReferenceFile, sref); } } - + + public static void ReplaySessionFromFile (string filename) + { + currentRecordSession = new SessionRecord (commandManager, filename); + currentRecordSession.ReplayEvents (() => { + currentRecordSession = null; + }); + } + public static SessionRecord StartRecordingSession () { - return new SessionRecord (commandManager); + currentRecordSession = new SessionRecord (commandManager); + return currentRecordSession; } - + + public static void StopRecordingSession (string filename = null) + { + if (currentRecordSession == null) { + return; + } + + currentRecordSession.Pause (); + + if (filename != null) { + currentRecordSession.WriteLogToFile (filename); + } + currentRecordSession = null; + } + internal static string SessionReferenceFile { get { return Path.Combine (Path.GetTempPath (), "monodevelop-autotest-objref"); @@ -146,18 +180,104 @@ namespace MonoDevelop.Components.AutoTest { CommandManager commandManager; List<RecordEvent> events = new List<RecordEvent> (); - bool recording; - - public class RecordEvent + enum State { + Idle, + Recording, + Replaying + }; + State state; + + StringBuilder pendingText; + Gdk.ModifierType pendingModifiers = Gdk.ModifierType.None; + + public abstract class RecordEvent { + public abstract XElement ToXML (); + public abstract void ParseXML (XElement element); + public abstract void Replay (AutoTestSession testSession); } public class KeyPressEvent: RecordEvent { public Gdk.Key Key { get; set; } public Gdk.ModifierType Modifiers { get; set; } + + public override XElement ToXML () + { + return new XElement ("event", new XAttribute ("type", "KeyPressEvent"), + new XElement ("key", Key.ToString ()), + new XElement ("modifier", Modifiers.ToString ())); + } + + public override void ParseXML (XElement element) + { + foreach (var e in element.Elements ()) { + if (e.Name == "key") { + Key = (Gdk.Key)Enum.Parse (typeof (Gdk.Key), e.Value); + } else if (e.Name == "modifier") { + Modifiers = (Gdk.ModifierType)Enum.Parse (typeof (Gdk.ModifierType), e.Value); + } + } + } + + public override void Replay (AutoTestSession testSession) + { + // Select the main window and then we can push key events to it. + AppQuery query = testSession.CreateNewQuery (); + AppResult[] results = query.Window ().Marked ("MonoDevelop.Ide.Gui.DefaultWorkbench").Execute (); + if (results.Length == 0) { + return; + } + + testSession.Select (results[0]); + // We need the GtkWidgetResult for the main window as we only have the keys as a Gdk key + if (results [0] is AutoTest.Results.GtkWidgetResult) { + AutoTest.Results.GtkWidgetResult widgetResult = (AutoTest.Results.GtkWidgetResult) results[0]; + widgetResult.RealTypeKey (Key, Modifiers); + } + } } - + + public class StringEvent: RecordEvent + { + internal string Text; + internal Gdk.ModifierType Modifiers { get; set; } + + public override XElement ToXML () + { + return new XElement ("event", new XAttribute ("type", "StringEvent"), + new XElement ("text", Text), + new XElement ("modifier", Modifiers.ToString ())); + } + + public override void ParseXML (XElement element) + { + foreach (var e in element.Elements ()) { + if (e.Name == "text") { + Text = e.Value; + } else if (e.Name == "modifier") { + Modifiers = (Gdk.ModifierType)Enum.Parse (typeof(Gdk.ModifierType), e.Value); + } + } + } + + public override void Replay (AutoTestSession testSession) + { + AppQuery query = testSession.CreateNewQuery (); + AppResult[] results = query.Window ().Marked ("MonoDevelop.Ide.Gui.DefaultWorkbench").Execute (); + if (results.Length == 0) { + return; + } + + testSession.Select (results [0]); + + if (results [0] is AutoTest.Results.GtkWidgetResult) { + AutoTest.Results.GtkWidgetResult widgetResult = (AutoTest.Results.GtkWidgetResult)results [0]; + widgetResult.EnterText (Text); + } + } + } + public class CommandEvent: RecordEvent { public object CommandId { get; set; } @@ -165,6 +285,29 @@ namespace MonoDevelop.Components.AutoTest public bool IsCommandArray { get { return DataItemIndex != -1; } } + + public override XElement ToXML () + { + return new XElement ("event", new XAttribute ("type", "CommandEvent"), + new XElement ("commandID", CommandId.ToString ()), + new XElement ("dataItemIndex", DataItemIndex)); + } + + public override void ParseXML (XElement element) + { + foreach (var e in element.Elements ()) { + if (e.Name == "commandID") { + CommandId = e.Value; + } else if (e.Name == "dataItemIndex") { + DataItemIndex = Convert.ToInt32 (e.Value); + } + } + } + + public override void Replay (AutoTestSession testSession) + { + testSession.ExecuteCommand (CommandId); + } } internal SessionRecord (CommandManager commandManager) @@ -172,39 +315,56 @@ namespace MonoDevelop.Components.AutoTest this.commandManager = commandManager; Resume (); } + + internal SessionRecord (CommandManager commandManager, string logFile) + { + state = State.Idle; + this.commandManager = commandManager; + LoadFromLogFile (logFile); + } public IEnumerable<RecordEvent> Events { get { - if (recording) + if (state == State.Recording) throw new InvalidOperationException ("The record session must be paused before getting the recorded events."); return events; } } public bool IsPaused { - get { return !recording; } + get { return state == State.Idle; } + } + + public bool IsReplaying { + get { return state == State.Replaying; } } public void Pause () { - if (recording) { + if (state == State.Recording) { commandManager.KeyPressed -= HandleCommandManagerKeyPressed; commandManager.CommandActivated -= HandleCommandManagerCommandActivated; - recording = false; + state = State.Idle; } } public void Resume () { - if (!recording) { + if (state == State.Idle) { commandManager.KeyPressed += HandleCommandManagerKeyPressed; commandManager.CommandActivated += HandleCommandManagerCommandActivated; - recording = true; + state = State.Recording; + LoggingService.LogError ("Starting up session recording"); } } void HandleCommandManagerCommandActivated (object sender, CommandActivationEventArgs e) { + if ((string)e.CommandId == "MonoDevelop.Ide.Commands.ToolCommands.ToggleSessionRecorder" || + (string)e.CommandId == "MonoDevelop.Ide.Commands.ToolCommands.ReplaySession") { + return; + } + CommandEvent cme = new CommandEvent () { CommandId = e.CommandId }; cme.DataItemIndex = -1; @@ -219,9 +379,117 @@ namespace MonoDevelop.Components.AutoTest events.Add (cme); } + void CompleteStringEvent (string s, Gdk.ModifierType modifiers) + { + events.Add (new StringEvent { Text = pendingText.ToString (), Modifiers = pendingModifiers }); + pendingText = null; + pendingModifiers = Gdk.ModifierType.None; + } + void HandleCommandManagerKeyPressed (object sender, KeyPressArgs e) { - events.Add (new KeyPressEvent () { Key = e.Key, Modifiers = e.Modifiers }); + uint unicode = Gdk.Keyval.ToUnicode (e.KeyValue); + if (pendingText != null) { + if (pendingModifiers != e.Modifiers || unicode == 0) { + CompleteStringEvent (pendingText.ToString (), pendingModifiers); + } else { + pendingText.Append ((char)unicode); + return; + } + + // If text event has been completed, then we need to reset the pending events + if (unicode != 0) { + pendingText = new StringBuilder (); + pendingText.Append ((char)unicode); + pendingModifiers = e.Modifiers; + } else { + // Don't have a unicode key, so just issue a standard key event + events.Add (new KeyPressEvent { Key = e.Key, Modifiers = e.Modifiers }); + pendingText = null; + pendingModifiers = Gdk.ModifierType.None; + } + } else { + if (unicode == 0) { + events.Add (new KeyPressEvent () { Key = e.Key, Modifiers = e.Modifiers }); + return; + } + + pendingText = new StringBuilder (); + pendingText.Append ((char)unicode); + pendingModifiers = e.Modifiers; + } + } + + public void WriteLogToFile (string filepath) + { + var doc = new XDocument (new XElement ("xs-event-replay-log", + from ev in events + select ev.ToXML ())); + + using (XmlWriter xw = XmlWriter.Create (filepath, new XmlWriterSettings { Indent = true })) { + doc.Save (xw); + } + } + + public bool LoadFromLogFile (string filepath) + { + XDocument doc = XDocument.Load (filepath); + foreach (XElement element in doc.Element("xs-event-replay-log").Elements ()) { + if (element == null) { + continue; + } + + string evType = element.Attribute ("type").Value; + RecordEvent ev = null; + if (evType == "KeyPressEvent") { + ev = new KeyPressEvent (); + } else if (evType == "CommandEvent") { + ev = new CommandEvent (); + } else if (evType == "StringEvent") { + ev = new StringEvent (); + } + + if (ev == null) { + return false; + } + + ev.ParseXML (element); + events.Add (ev); + } + + return true; + } + + public void ReplayEvents (Action completionHandler = null) + { + AutoTestSession testSession = new AutoTestSession (); + Stopwatch sw = new Stopwatch (); + int eventCount = events.Count; + + state = State.Replaying; + + sw.Start (); + // Each spin of the main loop, remove an event from the queue and replay it. + GLib.Idle.Add (() => { + RecordEvent ev = events[0]; + events.RemoveAt (0); + + ev.Replay (testSession); + + if (events.Count > 0) { + return true; + } + + sw.Stop (); + LoggingService.LogInfo ("Time elapsed to replay {0} events: {1}", eventCount, sw.Elapsed); + state = State.Idle; + + if (completionHandler != null) { + completionHandler (); + } + + return false; + }); } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs index 2d35b53b90..a4fb16bb70 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/AutoTestSession.cs @@ -194,6 +194,27 @@ namespace MonoDevelop.Components.AutoTest throw; } }); + #else + Sync (delegate { + try { + using (var bmp = new System.Drawing.Bitmap (System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width, + System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height)) { + using (var g = System.Drawing.Graphics.FromImage(bmp)) + { + g.CopyFromScreen(System.Windows.Forms.Screen.PrimaryScreen.Bounds.X, + System.Windows.Forms.Screen.PrimaryScreen.Bounds.Y, + 0, 0, + bmp.Size, + System.Drawing.CopyPixelOperation.SourceCopy); + } + bmp.Save(screenshotPath); + } + return null; + } catch (Exception e) { + Console.WriteLine (e); + throw; + } + }); #endif } @@ -253,6 +274,8 @@ namespace MonoDevelop.Components.AutoTest if (remaining == null) return res; + else if (res == null) + return null; else return GetValue (res, res.GetType (), remaining); } @@ -302,14 +325,20 @@ namespace MonoDevelop.Components.AutoTest public void ExecuteOnIdle (Action idleFunc, bool wait = true, int timeout = 20000) { + if (DispatchService.IsGuiThread) { + idleFunc (); + return; + } + if (wait == false) { GLib.Idle.Add (() => { idleFunc (); return false; }); + return; } - + syncEvent.Reset (); GLib.Idle.Add (() => { idleFunc (); @@ -324,7 +353,7 @@ namespace MonoDevelop.Components.AutoTest // Executes the query outside of a syncEvent wait so it is safe to call from // inside an ExecuteOnIdleAndWait - AppResult[] ExecuteQueryNoWait (AppQuery query) + internal AppResult[] ExecuteQueryNoWait (AppQuery query) { AppResult[] resultSet = query.Execute (); Sync (() => { @@ -346,7 +375,6 @@ namespace MonoDevelop.Components.AutoTest } catch (TimeoutException e) { throw new TimeoutException (string.Format ("Timeout while executing ExecuteQuery: {0}", query), e); } - return resultSet; } @@ -530,6 +558,36 @@ namespace MonoDevelop.Components.AutoTest } } + public bool SetActiveConfiguration (AppResult result, string configuration) + { + bool success = false; + + try { + ExecuteOnIdle (() => { + success = result.SetActiveConfiguration (configuration); + }); + } catch (TimeoutException e) { + ThrowOperationTimeoutException ("SetActiveConfiguration", result.SourceQuery, result, e); + } + + return success; + } + + public bool SetActiveRuntime (AppResult result, string runtime) + { + bool success = false; + + try { + ExecuteOnIdle (() => { + success = result.SetActiveRuntime (runtime); + }); + } catch (TimeoutException e) { + ThrowOperationTimeoutException ("SetActiveRuntime", result.SourceQuery, result, e); + } + + return success; + } + void ThrowOperationTimeoutException (string operation, string query, AppResult result, Exception innerException) { throw new TimeoutException (string.Format ("Timeout while executing {0}: {1}\n\ton Element: {2}", operation, query, result), innerException); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs index 9fa28fc9c5..84acd89973 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.AutoTest/ObjectProperties.cs @@ -42,8 +42,10 @@ namespace MonoDevelop.Components.AutoTest internal void Add (string propertyName, AppResult propertyValue, PropertyInfo propertyInfo) { - propertyMap.Add (propertyName, propertyValue); - propertyMetaData.Add (propertyName, new PropertyMetadata (propertyInfo)); + if (!propertyMap.ContainsKey (propertyName)) + propertyMap.Add (propertyName, propertyValue); + if (!propertyMetaData.ContainsKey (propertyName)) + propertyMetaData.Add (propertyName, new PropertyMetadata (propertyInfo)); } public ReadOnlyCollection<string> GetPropertyNames () diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs index 205ac7ecfc..12296f22e9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Commands/CommandManager.cs @@ -333,6 +333,12 @@ namespace MonoDevelop.Components.Commands return null; } + // If a modal dialog is running then the menus are disabled, even if the commands are not + // See MDMenuItem::IsGloballyDisabled + if (DesktopService.IsModalDialogRunning ()) { + return ev; + } + var gdkev = MonoDevelop.Components.Mac.GtkMacInterop.ConvertKeyEvent (ev); if (gdkev != null) { if (ProcessKeyEvent (gdkev)) @@ -348,7 +354,7 @@ namespace MonoDevelop.Components.Commands e.RetVal = ProcessKeyEvent (e.Event); } - bool ProcessKeyEvent (Gdk.EventKey ev) + internal bool ProcessKeyEvent (Gdk.EventKey ev) { if (!IsEnabled) return true; @@ -426,7 +432,7 @@ namespace MonoDevelop.Components.Commands void NotifyKeyPressed (Gdk.EventKey ev) { if (KeyPressed != null) - KeyPressed (this, new KeyPressArgs () { Key = ev.Key, Modifiers = ev.State }); + KeyPressed (this, new KeyPressArgs () { Key = ev.Key, KeyValue = ev.KeyValue, Modifiers = ev.State }); } /// <summary> @@ -1166,7 +1172,7 @@ namespace MonoDevelop.Components.Commands return false; commandId = CommandManager.ToCommandId (commandId); - + List<HandlerCallback> handlers = new List<HandlerCallback> (); ActionCommand cmd = null; try { @@ -2602,6 +2608,7 @@ namespace MonoDevelop.Components.Commands public class KeyPressArgs: EventArgs { public Gdk.Key Key { get; internal set; } + public uint KeyValue { get; internal set; } public Gdk.ModifierType Modifiers { get; internal set; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs index c1a7cb5758..c293fd3b81 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/DockNotebook.cs @@ -79,22 +79,16 @@ namespace MonoDevelop.Components.DockNotebook tabStrip.DropDownButton.Sensitive = false; - tabStrip.DropDownButton.MenuCreator = delegate { - Gtk.Menu menu = new Menu (); + tabStrip.DropDownButton.ContextMenuRequested = delegate { + ContextMenu menu = new ContextMenu (); foreach (var tab in pages) { - var mi = new Gtk.ImageMenuItem (""); - menu.Insert (mi, -1); - var label = (Gtk.AccelLabel) mi.Child; - if (tab.Markup != null) - label.Markup = tab.Markup; - else - label.Text = tab.Text; + var item = new ContextMenuItem (tab.Markup ?? tab.Text); var locTab = tab; - mi.Activated += delegate { + item.Clicked += (object sender, ContextMenuItemClickedEventArgs e) => { CurrentTab = locTab; }; + menu.Items.Add (item); } - menu.ShowAll (); return menu; }; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs index 4437cfeff1..90a8668d8e 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.DockNotebook/TabStrip.cs @@ -441,8 +441,10 @@ namespace MonoDevelop.Components.DockNotebook // If the user clicks and drags on the 'x' which closes the current // tab we can end up with a null tab here - if (t == null) + if (t == null) { + TooltipText = null; return base.OnMotionNotifyEvent (evnt); + } SetHighlightedTab (t); var newOver = IsOverCloseButton (t, (int)evnt.X, (int)evnt.Y); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs index 3938cb3d6d..6022b195bc 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockFrame.cs @@ -886,6 +886,8 @@ namespace MonoDevelop.Components.Docking t.Hide (); t.Show (); } + + MonoDevelop.Ide.IdeApp.CommandService.RegisterTopWindow (win); } else { w.Parent = this; w.Size = new Size (width, height); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs index 4aace5dc41..913edeebc1 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Docking/DockItem.cs @@ -327,7 +327,12 @@ namespace MonoDevelop.Components.Docking { if (dockBarItem != null) dockBarItem.Present (Status == DockItemStatus.AutoHide || giveFocus); - else + else if (floatingWindow != null) { + if (giveFocus) + floatingWindow.Present (); + else + floatingWindow.Show (); + } else frame.Present (this, Status == DockItemStatus.AutoHide || giveFocus); } @@ -412,6 +417,7 @@ namespace MonoDevelop.Components.Docking SetRegionStyle (frame.GetRegionStyleForItem (this)); floatingWindow = new DockFloatingWindow ((Window)frame.Toplevel, GetWindowTitle ()); + Ide.IdeApp.CommandService.RegisterTopWindow (floatingWindow); VBox box = new VBox (); box.Show (); @@ -593,7 +599,6 @@ namespace MonoDevelop.Components.Docking { public DockFloatingWindow (Window dockParent, string title) : base (title) { - TypeHint = Gdk.WindowTypeHint.Utility; this.DockParent = dockParent; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs index 9784169415..1451ed1523 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.Extensions/ISelectFileDialog.cs @@ -40,7 +40,19 @@ namespace MonoDevelop.Components.Extensions public interface ISelectFileDialogHandler : IDialogHandler<SelectFileDialogData>
{
} - + + [Flags] + public enum SelectFileDialogAction + { + CreateFolder = 1, + SelectFolder = 2, + Open = 4, + Save = 8, + + FolderFlags = CreateFolder | SelectFolder, + FileFlags = Open | Save + } + /// <summary> /// Data for the ISelectFileDialogHandler implementation /// </summary> @@ -50,7 +62,7 @@ namespace MonoDevelop.Components.Extensions FilterSet = new FileFilterSet (); } internal FileFilterSet FilterSet { get; set; } - public Gtk.FileChooserAction Action { get; set; } + public SelectFileDialogAction Action { get; set; } public IList<SelectFileDialogFilter> Filters { get { return FilterSet.Filters; } } public FilePath CurrentFolder { get; set; } public bool SelectMultiple { get; set; } @@ -107,7 +119,7 @@ namespace MonoDevelop.Components.Extensions /// <summary> /// Action to perform with the file dialog. /// </summary> - public Gtk.FileChooserAction Action { + public SelectFileDialogAction Action { get { return data.Action; } set { data.Action = value; } } @@ -269,7 +281,14 @@ namespace MonoDevelop.Components.Extensions internal void SetDefaultProperties (FileSelector fdiag) { fdiag.Title = Title; - fdiag.Action = Action; + if ((Action & SelectFileDialogAction.CreateFolder) != 0) + fdiag.Action = Gtk.FileChooserAction.CreateFolder; + else if ((Action & SelectFileDialogAction.SelectFolder) != 0) + fdiag.Action = Gtk.FileChooserAction.SelectFolder; + else if ((Action & SelectFileDialogAction.Open) != 0) + fdiag.Action = Gtk.FileChooserAction.Open; + else if ((Action & SelectFileDialogAction.Save) != 0) + fdiag.Action = Gtk.FileChooserAction.Save; fdiag.LocalOnly = true; fdiag.SelectMultiple = SelectMultiple; fdiag.TransientFor = TransientFor; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs index 84e6d44cdb..e381a31c65 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainStatusBarContextImpl.cs @@ -71,6 +71,7 @@ namespace MonoDevelop.Components.MainToolbar public void ShowReady () { statusBar.ShowReady (); + statusBar.SetMessageSourcePad (null); } public void SetMessageSourcePad (Pad pad) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs index 0c2f09ee5c..751ebc8329 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbar.cs @@ -110,19 +110,22 @@ namespace MonoDevelop.Components.MainToolbar return; } - renderer.Visible = runtime.Visible; - renderer.Sensitive = runtime.Enabled; - renderer.Xpad = (uint)(runtime.IsIndented ? 18 : 3); - - if (!runtimeCombo.PopupShown) { - // no need to ident text when the combo dropdown is not showing - if (Platform.IsWindows) - renderer.Xpad = 3; - renderer.Text = runtime.FullDisplayString; - renderer.Attributes = normalAttributes; - } else { - renderer.Text = runtime.DisplayString; - renderer.Attributes = runtime.Notable ? boldAttributes : normalAttributes; + using (var mutableModel = runtime.GetMutableModel ()) { + renderer.Visible = mutableModel.Visible; + renderer.Sensitive = mutableModel.Enabled; + renderer.Xpad = (uint)(runtime.IsIndented ? 18 : 3); + + if (!runtimeCombo.PopupShown) { + // no need to ident text when the combo dropdown is not showing + if (Platform.IsWindows) + renderer.Xpad = 3; + renderer.Text = mutableModel.FullDisplayString; + renderer.Attributes = normalAttributes; + } else { + renderer.Text = mutableModel.DisplayString; + renderer.Attributes = runtime.Notable ? boldAttributes : normalAttributes; + } + } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs index e07e8dd7e3..70ea988491 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarController.cs @@ -341,10 +341,16 @@ namespace MonoDevelop.Components.MainToolbar bool SelectActiveRuntime (ref bool selected, ref ExecutionTarget defaultTarget, ref int defaultIter) { var runtimes = ToolbarView.RuntimeModel.Cast<RuntimeModel> ().ToList (); + string lastRuntimeForProject = currentStartupProject.UserProperties.GetValue<string> ("PreferredExecutionTarget", defaultValue: null); + var activeTarget = IdeApp.Workspace.ActiveExecutionTarget; + var activeTargetId = activeTarget != null ? activeTarget.Id : null; + for (int iter = 0; iter < runtimes.Count; ++iter) { var item = runtimes [iter]; - if (!item.Enabled) - continue; + using (var model = item.GetMutableModel ()) { + if (!model.Enabled) + continue; + } var target = item.ExecutionTarget; if (target == null || !target.Enabled) @@ -354,12 +360,12 @@ namespace MonoDevelop.Components.MainToolbar if (item.HasChildren) continue; - if (defaultTarget == null) { + if (defaultTarget == null || lastRuntimeForProject == target.Id) { defaultTarget = target; defaultIter = iter; } - if (target.Id == IdeApp.Workspace.PreferredActiveExecutionTarget) { + if (target.Id == activeTargetId) { IdeApp.Workspace.ActiveExecutionTarget = target; ToolbarView.ActiveRuntime = ToolbarView.RuntimeModel.ElementAt (iter); UpdateBuildConfiguration (); @@ -367,7 +373,7 @@ namespace MonoDevelop.Components.MainToolbar return true; } - if (target.Equals (IdeApp.Workspace.ActiveExecutionTarget)) { + if (target.Equals (activeTarget)) { ToolbarView.ActiveRuntime = ToolbarView.RuntimeModel.ElementAt (iter); UpdateBuildConfiguration (); selected = true; @@ -395,7 +401,6 @@ namespace MonoDevelop.Components.MainToolbar UpdateBuildConfiguration (); } } - } finally { ignoreRuntimeChangedCount--; } @@ -438,6 +443,9 @@ namespace MonoDevelop.Components.MainToolbar void TrackStartupProject () { if (currentStartupProject != null && ((currentSolution != null && currentStartupProject != currentSolution.StartupItem) || currentSolution == null)) { + var runtime = (RuntimeModel)ToolbarView.ActiveRuntime; + if (runtime != null && runtime.Command == null) + currentStartupProject.UserProperties.SetValue<string> ("PreferredExecutionTarget", runtime.TargetId); currentStartupProject.ExecutionTargetsChanged -= executionTargetsChanged; currentStartupProject.Saved -= HandleUpdateCombos; } @@ -762,8 +770,6 @@ namespace MonoDevelop.Components.MainToolbar public RuntimeModel (MainToolbarController controller, ExecutionTarget target) : this (controller) { ExecutionTarget = target; - Enabled = !(ExecutionTarget is ExecutionTargetGroup); - Visible = true; } public RuntimeModel (MainToolbarController controller, ExecutionTarget target, RuntimeModel parent) : this (controller, target) @@ -785,6 +791,7 @@ namespace MonoDevelop.Components.MainToolbar public IEnumerable<IRuntimeModel> Children { get { return children; } } + public bool Notable { get { return ExecutionTarget != null && ExecutionTarget.Notable; } } @@ -799,16 +806,6 @@ namespace MonoDevelop.Components.MainToolbar set; } - public bool Visible { - get; - private set; - } - - public bool Enabled { - get; - private set; - } - public bool IsSeparator { get { return Command == null && ExecutionTarget == null; } } @@ -818,43 +815,72 @@ namespace MonoDevelop.Components.MainToolbar set; } - public string DisplayString { - get { - if (Command != null) { - var ci = IdeApp.CommandService.GetCommandInfo (Command, new CommandTargetRoute (Controller.lastCommandTarget)); - Visible = ci.Visible; - Enabled = ci.Enabled; - return RemoveUnderline (ci.Text); - } + public bool NotifyActivated () + { + if (Command != null && IdeApp.CommandService.DispatchCommand (Command, CommandSource.ContextMenu)) + return true; + return false; + } + internal string TargetId { + get { if (ExecutionTarget == null) return ""; - - return !HasParent ? ExecutionTarget.FullName : ExecutionTarget.Name; + return ExecutionTarget.Id; } } - public string FullDisplayString { - get { - if (Command != null) { - var ci = IdeApp.CommandService.GetCommandInfo (Command, new CommandTargetRoute (Controller.lastCommandTarget)); - Visible = ci.Visible; - Enabled = ci.Enabled; - return RemoveUnderline (ci.Text); - } + public IRuntimeMutableModel GetMutableModel () + { + return Command != null ? new RuntimeMutableModel (Controller, Command) : new RuntimeMutableModel (ExecutionTarget, HasParent); + } + } - if (ExecutionTarget == null) - return ""; + class RuntimeMutableModel : IRuntimeMutableModel + { + public RuntimeMutableModel (MainToolbarController controller, object command) + { + var ci = IdeApp.CommandService.GetCommandInfo (command, new CommandTargetRoute (controller.lastCommandTarget)); + Visible = ci.Visible; + Enabled = ci.Enabled; + DisplayString = FullDisplayString = RemoveUnderline (ci.Text); + } - return ExecutionTarget.FullName; + public RuntimeMutableModel (ExecutionTarget target, bool hasParent) + { + Enabled = !(target is ExecutionTargetGroup); + Visible = true; + if (target == null) + DisplayString = FullDisplayString = string.Empty; + else { + FullDisplayString = target.FullName; + DisplayString = !hasParent ? target.FullName : target.Name; } } - public bool NotifyActivated () + // Marker so it won't be reused. + public void Dispose () { - if (Command != null && IdeApp.CommandService.DispatchCommand (Command, CommandSource.ContextMenu)) - return true; - return false; + } + + public bool Visible { + get; + private set; + } + + public bool Enabled { + get; + private set; + } + + public string DisplayString { + get; + private set; + } + + public string FullDisplayString { + get; + private set; } static string RemoveUnderline (string s) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs index bdd0036f0d..eb814b067b 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/MainToolbarModels.cs @@ -51,30 +51,6 @@ namespace MonoDevelop.Components.MainToolbar IEnumerable<IRuntimeModel> Children { get; } /// <summary> - /// Gets the display string to be used inside a context menu. - /// </summary> - /// <value>The display string.</value> - string DisplayString { get; } - - /// <summary> - /// Gets the display string to be for selected items. - /// </summary> - /// <value>The full display string.</value> - string FullDisplayString { get; } - - /// <summary> - /// Gets whether the menu item is visible. - /// </summary> - /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value> - bool Visible { get; } - - /// <summary> - /// Gets whether the menu item is enabled. - /// </summary> - /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value> - bool Enabled { get; } - - /// <summary> /// Gets whether the menu item is a separator. /// </summary> /// <value><c>true</c> if this instance is separator; otherwise, <c>false</c>.</value> @@ -100,6 +76,39 @@ namespace MonoDevelop.Components.MainToolbar /// </remarks> /// <value><c>true</c> if this instance has a parent; otherwise, <c>false</c>.</value> bool HasParent { get; } + + /// <summary> + /// Gets the runtime combo item model. + /// </summary> + /// <value>The runtime combo item.</value> + IRuntimeMutableModel GetMutableModel(); + } + + public interface IRuntimeMutableModel : IDisposable + { + /// <summary> + /// Gets the display string to be used inside a context menu. + /// </summary> + /// <value>The display string.</value> + string DisplayString { get; } + + /// <summary> + /// Gets the display string to be for selected items. + /// </summary> + /// <value>The full display string.</value> + string FullDisplayString { get; } + + /// <summary> + /// Gets whether the menu item is visible. + /// </summary> + /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value> + bool Visible { get; } + + /// <summary> + /// Gets whether the menu item is enabled. + /// </summary> + /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value> + bool Enabled { get; } } public interface ISearchMenuModel diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs index c204647762..cd1a9c87e5 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchInSolutionSearchCategory.cs @@ -30,7 +30,7 @@ using MonoDevelop.Core; using ICSharpCode.NRefactory.TypeSystem; using MonoDevelop.Ide.FindInFiles; using System.Linq; -using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide; namespace MonoDevelop.Components.MainToolbar { @@ -42,9 +42,13 @@ namespace MonoDevelop.Components.MainToolbar public override Task<ISearchDataSource> GetResults (SearchPopupSearchPattern searchPattern, int resultsCount, CancellationToken token) { - return Task.Factory.StartNew (delegate { - return (ISearchDataSource)new SearchInSolutionDataSource (searchPattern); - }); + if (IdeApp.ProjectOperations.CurrentSelectedSolution != null) { + return Task.Factory.StartNew (delegate { + return (ISearchDataSource)new SearchInSolutionDataSource (searchPattern); + }); + } + + return Task.FromResult<ISearchDataSource> (default(ISearchDataSource)); } public override bool IsValidTag (string tag) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs index 7deca2de99..b84db63c31 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.MainToolbar/SearchPopupWindow.cs @@ -120,6 +120,7 @@ namespace MonoDevelop.Components.MainToolbar categories.Add (new ProjectSearchCategory (this)); categories.Add (new FileSearchCategory (this)); categories.Add (new CommandSearchCategory (this)); + categories.Add (new SearchInSolutionSearchCategory ()); categories.AddRange (AddinManager.GetExtensionObjects<SearchCategory> ("/MonoDevelop/Ide/SearchCategories")); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs index 23df98afc8..37da6db915 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/FilePathEditor.cs @@ -26,8 +26,9 @@ using System; using System.Linq; -using Gtk; + using MonoDevelop.Core; +using MonoDevelop.Components.Extensions; namespace MonoDevelop.Components.PropertyGrid.PropertyEditors { @@ -41,16 +42,17 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors public override void LaunchDialogue () { var kindAtt = this.Property.Attributes.OfType<FilePathIsFolderAttribute> ().FirstOrDefault (); - FileChooserAction action; + SelectFileDialogAction action; + string title; if (kindAtt == null) { - action = FileChooserAction.Open; + action = SelectFileDialogAction.Open; title = GettextCatalog.GetString ("Select File..."); } else { - action = FileChooserAction.SelectFolder; + action = SelectFileDialogAction.SelectFolder; title = GettextCatalog.GetString ("Select Folder..."); } - var fs = new MonoDevelop.Components.SelectFileDialog (title, action); + var fs = new SelectFileDialog (title, action); if (fs.Run ()) Property.SetValue (Instance, fs.SelectedFile); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs index 7d7d5a0f9b..a553b2d48c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid.Editors/TextEditor.cs @@ -88,6 +88,7 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors // no standard values, so just use an entry else { entry = new Entry (); + entry.IsEditable = !session.Property.IsReadOnly; PackStart (entry, true, true, 0); } @@ -96,9 +97,11 @@ namespace MonoDevelop.Components.PropertyGrid.PropertyEditors entry.HasFrame = false; entry.Changed += TextChanged; entry.FocusOutEvent += FirePendingChangeEvent; + if (!entry.IsEditable) + entry.ModifyText (StateType.Normal, entry.Style.Text (Gtk.StateType.Insensitive)); } - if (entry != null && ShouldShowDialogButton ()) { + if (entry != null && ShouldShowDialogButton () && entry.IsEditable) { var button = new Button ("..."); PackStart (button, false, false, 0); button.Clicked += ButtonClicked; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs index 5f5e6d9e95..b3914cc0ec 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGrid.cs @@ -252,6 +252,10 @@ namespace MonoDevelop.Components.PropertyGrid { if (this.currentObject == obj)
return;
+ if (this.propertyProviders != null) {
+ foreach (var old in this.propertyProviders.OfType<IDisposable> ())
+ old.Dispose ();
+ }
this.currentObject = obj; this.propertyProviders = propertyProviders; UpdateTabs ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs index b8b16247fd..f6e785dec9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components.PropertyGrid/PropertyGridTable.cs @@ -609,7 +609,7 @@ namespace MonoDevelop.Components.PropertyGrid if (row != null && editSession == null) { var bounds = GetInactiveEditorBounds (row); - if (!bounds.IsEmpty && bounds.Contains ((int)evnt.X, (int)evnt.Y) && row.Enabled) { + if (!bounds.IsEmpty && bounds.Contains ((int)evnt.X, (int)evnt.Y)) { StartEditing (row); return true; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs index 52607bf131..1e4f383f88 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsGtk.cs @@ -33,16 +33,38 @@ namespace MonoDevelop.Components { public static void ShowContextMenu (Gtk.Widget parent, Gdk.EventButton evt, ContextMenu menu) { + ShowContextMenu (parent, evt, menu, null); + } + + public static void ShowContextMenu (Gtk.Widget parent, Gdk.EventButton evt, ContextMenu menu, Action closeHandler) + { if (parent == null) throw new ArgumentNullException ("parent"); if (menu == null) throw new ArgumentNullException ("menu"); - var gtkMenu = FromMenu (menu); + var gtkMenu = FromMenu (menu, closeHandler); gtkMenu.ShowAll (); ShowContextMenu (parent, evt, gtkMenu); } + public static void ShowContextMenu (Gtk.Widget parent, int x, int y, ContextMenu menu) + { + ShowContextMenu (parent, x, y, menu, null); + } + + public static void ShowContextMenu (Gtk.Widget parent, int x, int y, ContextMenu menu, Action closeHandler) + { + if (parent == null) + throw new ArgumentNullException ("parent"); + if (menu == null) + throw new ArgumentNullException ("menu"); + + var gtkMenu = FromMenu (menu, closeHandler); + gtkMenu.ShowAll (); + ShowContextMenu (parent, x, y, gtkMenu); + } + public static void ShowContextMenu (Gtk.Widget parent, Gdk.EventButton evt, Gtk.Menu menu) { if (parent == null) @@ -53,6 +75,16 @@ namespace MonoDevelop.Components Mono.TextEditor.GtkWorkarounds.ShowContextMenu (menu, parent, evt); } + public static void ShowContextMenu (Gtk.Widget parent, int x, int y, Gtk.Menu menu) + { + if (parent == null) + throw new ArgumentNullException ("parent"); + if (menu == null) + throw new ArgumentNullException ("menu"); + + Mono.TextEditor.GtkWorkarounds.ShowContextMenu (menu, parent, x, y, parent.Allocation); + } + static Gtk.MenuItem CreateMenuItem (ContextMenuItem item) { if (!item.Visible) @@ -74,7 +106,7 @@ namespace MonoDevelop.Components } if (item.SubMenu != null && item.SubMenu.Items.Count > 0) { - menuItem.Submenu = FromMenu (item.SubMenu); + menuItem.Submenu = FromMenu (item.SubMenu, null); } else { menuItem.Activated += (sender, e) => item.Click (); @@ -100,7 +132,7 @@ namespace MonoDevelop.Components return menuItem; } - static Gtk.Menu FromMenu (ContextMenu menu) + static Gtk.Menu FromMenu (ContextMenu menu, Action closeHandler) { var result = new Gtk.Menu (); @@ -110,6 +142,9 @@ namespace MonoDevelop.Components result.Append (item); } + if (closeHandler != null) { + result.Hidden += (sender, e) => closeHandler (); + } return result; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs index 0b03a1e8a3..3fd766ba13 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/ContextMenuExtensionsMac.cs @@ -67,8 +67,18 @@ namespace MonoDevelop.Components var toplevel = parent.Toplevel as Gtk.Window; var nswindow = MonoDevelop.Components.Mac.GtkMacInterop.GetNSWindow (toplevel); - var titleBarHeight = MonoDevelop.Components.Mac.GtkMacInterop.GetTitleBarHeight (); - var pt = new CoreGraphics.CGPoint (x, nswindow.Frame.Height - y - titleBarHeight - 12); + + int titleBarOffset; + if (toplevel.TypeHint == Gdk.WindowTypeHint.Toolbar && toplevel.Type == Gtk.WindowType.Toplevel && toplevel.Decorated == false) { + // Undecorated toplevel toolbars are used for auto-hide pad windows. Don't add a titlebar offset for them. + titleBarOffset = 0; + } else if (MonoDevelop.Ide.DesktopService.GetIsFullscreen (toplevel)) { + titleBarOffset = 0; + } else { + titleBarOffset = MonoDevelop.Components.Mac.GtkMacInterop.GetTitleBarHeight () + 12; + } + + var pt = new CoreGraphics.CGPoint (x, nswindow.Frame.Height - y - titleBarOffset); var tmp_event = NSEvent.MouseEvent (NSEventType.LeftMouseDown, pt, diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs index a47612b712..83029b1b73 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/FileEntry.cs @@ -28,6 +28,8 @@ using System.ComponentModel; +using MonoDevelop.Components.Extensions; + namespace MonoDevelop.Components { [Category ("MonoDevelop.Components")] @@ -40,7 +42,7 @@ namespace MonoDevelop.Components public FileEntry (string name) : base (name) { - Action = Gtk.FileChooserAction.Open; + Action = SelectFileDialogAction.Open; } protected override string ShowBrowseDialog (string name, string startIn) @@ -57,6 +59,6 @@ namespace MonoDevelop.Components return null; } - public Gtk.FileChooserAction Action { get; set; } + public SelectFileDialogAction Action { get; set; } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs index 6e6aaa468a..50443ef77c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/MenuButton.cs @@ -38,6 +38,7 @@ namespace MonoDevelop.Components public class MenuButton : Button { MenuCreator creator; + ContextMenuCreator contextMenuCreator; Label label; Image image; Arrow arrow; @@ -65,31 +66,57 @@ namespace MonoDevelop.Components { } - + + [Obsolete ("Use ContextMenuRequested")] public MenuCreator MenuCreator { get { return creator; } set { creator = value; } } - + + public ContextMenuCreator ContextMenuRequested { + get { return contextMenuCreator; } + set { contextMenuCreator = value; } + } + + ReliefStyle MenuOpened () + { + isOpen = true; + //make sure the button looks depressed + ReliefStyle oldRelief = this.Relief; + this.Relief = ReliefStyle.Normal; + return oldRelief; + } + + void MenuClosed (ReliefStyle oldRelief) + { + this.Relief = oldRelief; + isOpen = false; + this.State = StateType.Normal; + } + protected override void OnClicked () { base.OnClicked (); - + if (contextMenuCreator != null) { + ContextMenu menu = contextMenuCreator (this); + var oldRelief = MenuOpened (); + + Gdk.Rectangle rect = this.Allocation; + + // Offset the menu by the height of the rect + ContextMenuExtensionsGtk.ShowContextMenu (this, 0, rect.Height, menu, () => MenuClosed (oldRelief)); + return; + } + if (creator != null) { Menu menu = creator (this); if (menu != null) { - isOpen = true; - - //make sure the button looks depressed - ReliefStyle oldRelief = this.Relief; - this.Relief = ReliefStyle.Normal; - + var oldRelief = MenuOpened (); + //clean up after the menu's done menu.Hidden += delegate { - this.Relief = oldRelief ; - isOpen = false; - this.State = StateType.Normal; + MenuClosed (oldRelief); //FIXME: for some reason the menu's children don't get activated if we destroy //directly here, so use a timeout to delay it @@ -153,6 +180,8 @@ namespace MonoDevelop.Components protected override void OnDestroyed () { creator = null; + contextMenuCreator = null; + base.OnDestroyed (); } @@ -186,6 +215,7 @@ namespace MonoDevelop.Components set { label.Markup = value; } } } - + public delegate Menu MenuCreator (MenuButton button); + public delegate ContextMenu ContextMenuCreator (MenuButton button); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs index 8ff221923e..a13f021b63 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/PathBar.cs @@ -479,7 +479,13 @@ namespace MonoDevelop.Components if (menuWidget is Menu) { ((Menu)menuWidget).Popup (null, null, PositionFunc, 0, Gtk.Global.CurrentEventTime); } else { + var window = menuWidget as Gtk.Window; PositionWidget (menuWidget); + + if (window != null) { + window.TransientFor = this.Toplevel as Gtk.Window; + } + menuWidget.ShowAll (); } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs index 45913593b5..58d0b95a2f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFileDialog.cs @@ -23,12 +23,9 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -
-using System; -using Gtk; + using MonoDevelop.Components.Extensions;
-
namespace MonoDevelop.Components
{ /// <summary> @@ -40,11 +37,11 @@ namespace MonoDevelop.Components { } - public SelectFileDialog (string title): this (title, FileChooserAction.Open) + public SelectFileDialog (string title): this (title, SelectFileDialogAction.Open) { } - public SelectFileDialog (string title, Gtk.FileChooserAction action) + public SelectFileDialog (string title, SelectFileDialogAction action) { Title = title; Action = action; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs index a2a253f162..c468bbf9d7 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/SelectFolderDialog.cs @@ -39,14 +39,14 @@ namespace MonoDevelop.Components {
public SelectFolderDialog () { - Action = Gtk.FileChooserAction.SelectFolder; + Action = SelectFileDialogAction.SelectFolder; } - public SelectFolderDialog (string title): this (title, Gtk.FileChooserAction.SelectFolder) + public SelectFolderDialog (string title): this (title, SelectFileDialogAction.SelectFolder) { } - public SelectFolderDialog (string title, Gtk.FileChooserAction action) + public SelectFolderDialog (string title, SelectFileDialogAction action) { Title = title; Action = action; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs index d6c04f907a..f2153678da 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Tabstrip.cs @@ -277,6 +277,7 @@ namespace MonoDevelop.Components this.Label = label; layout = PangoUtil.CreateLayout (parent); layout.SetText (label); + layout.Alignment = Pango.Alignment.Center; layout.GetPixelSize (out w, out h); if (IsSeparator) @@ -335,13 +336,26 @@ namespace MonoDevelop.Components cr.Fill (); } } - + if (Active) cr.SetSourceRGB (1, 1, 1); else cr.SetSourceColor (parent.Style.Text (StateType.Normal).ToCairoColor ()); - cr.MoveTo (rectangle.X + (rectangle.Width - w) / 2, (rectangle.Height - h) / 2); + if (layout.Width != (int)rectangle.Width) + layout.Width = (int)rectangle.Width; + + #if MAC + /* On Cocoa, Pango doesn't render text correctly using layout width/height computation. + * For instance here we need to balance some kind of internal padding by two pixels which + * only happens on Mac. + */ + const int verticalOffset = -2; + #else + const int verticalOffset = 0; + #endif + + cr.MoveTo (rectangle.X + (int)(rectangle.Width / 2), (rectangle.Height - h) / 2 + verticalOffset); Pango.CairoHelper.ShowLayout (cr, layout); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWPFWidget.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWPFWidget.cs new file mode 100644 index 0000000000..10dd3d4b6e --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWPFWidget.cs @@ -0,0 +1,142 @@ +// +// GtkWPFWidget.cs +// +// Author: +// Marius Ungureanu <marius.ungureanu@xamarin.com> +// +// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if WIN32 +using System; +using System.Windows; +using System.Windows.Interop;
+using Gtk;
+using Gdk; + +namespace MonoDevelop.Components.Windows +{ + public class GtkWPFWidget : Widget + { + bool fromGtk; + internal System.Windows.Window wpfWindow { + get; + private set; + } + + public GtkWPFWidget (System.Windows.Controls.Control wpfControl) + { + wpfWindow = new System.Windows.Window {
+ Content = wpfControl,
+ AllowsTransparency = true,
+ WindowStyle = WindowStyle.None,
+ Background = System.Windows.Media.Brushes.Transparent,
+ }; + wpfWindow.PreviewKeyDown += (sender, e) => { + // TODO: Some commands check for toplevels, and this window is not a toplevel. + var key = e.Key == System.Windows.Input.Key.System ? e.SystemKey : e.Key; + e.Handled = Ide.IdeApp.CommandService.ProcessKeyEvent (GtkWin32Interop.ConvertKeyEvent (e.KeyboardDevice.Modifiers, key)); + }; + + wpfWindow.Closed += (sender, e) => {
+ if (fromGtk)
+ return;
+
+ Ide.IdeApp.Exit ();
+ }; + wpfWindow.ShowInTaskbar = false; + WidgetFlags |= WidgetFlags.NoWindow; + } + + void RepositionWpfWindow () + { + int x, y; + + var gtkWnd = Toplevel as Gtk.Window; + int offset = 0; + if (gtkWnd.Decorated) + offset = System.Windows.Forms.SystemInformation.CaptionHeight; + + int root_x, root_y; + gtkWnd.GetPosition (out root_x, out root_y); + if (TranslateCoordinates (Toplevel, root_x, root_y + offset, out x, out y)) { + wpfWindow.Left = x; + wpfWindow.Top = y; + } else { + wpfWindow.Left = Allocation.Left; + wpfWindow.Top = Allocation.Top; + } + wpfWindow.Width = Allocation.Width; + wpfWindow.Height = Allocation.Height; + } + + protected override void OnRealized () + { + base.OnRealized (); + + RepositionWpfWindow (); + } + + protected override void OnSizeAllocated (Gdk.Rectangle allocation) + { + base.OnSizeAllocated (allocation); + + RepositionWpfWindow (); + } + + protected override void OnDestroyed () + { + base.OnDestroyed (); + + fromGtk = true; + wpfWindow.Close (); + } + + protected override void OnShown () + { + base.OnShown (); + + wpfWindow.Show (); + AttachWindow (); + } + + void AttachWindow () + { + IntPtr gtkWindowPtr = GtkWin32Interop.HWndGet (Ide.IdeApp.Workbench.RootWindow.GdkWindow); + IntPtr wpfWindowPtr = new WindowInteropHelper (wpfWindow).Handle; + GtkWin32Interop.SetWindowLongPtr (wpfWindowPtr, (int)GtkWin32Interop.GWLParameter.GWL_HWNDPARENT, gtkWindowPtr); + Ide.IdeApp.Workbench.RootWindow.ConfigureEvent += OnWindowConfigured; + } + + void OnWindowConfigured (object sender, ConfigureEventArgs args) + { + RepositionWpfWindow (); + } + + protected override void OnHidden () + { + base.OnHidden (); + + wpfWindow.Hide (); + Ide.IdeApp.Workbench.RootWindow.ConfigureEvent -= OnWindowConfigured; + } + } +} +#endif diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWin32Interop.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWin32Interop.cs new file mode 100644 index 0000000000..49fcec4936 --- /dev/null +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Components/Windows/GtkWin32Interop.cs @@ -0,0 +1,118 @@ +// +// GtkWin32Interop.cs +// +// Author: +// Marius Ungureanu <marius.ungureanu@xamarin.com> +// +// Copyright (c) 2015 Xamarin, Inc (http://www.xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +#if WIN32 +using System; +using System.Runtime.InteropServices; +using System.Windows.Input; + +namespace MonoDevelop.Components.Windows +{ + public static class GtkWin32Interop + { + internal const string LIBGDK = "libgdk-win32-2.0-0.dll"; + internal const string USER32 = "user32.dll"; + + public enum ExtendedWindowStyles + { + // Hides it from alt-tab. + WS_EX_TOOLWINDOW = 0x80, + } + + public enum GWLParameter + { + // Sets a new extended style. + GWL_EXSTYLE = -20, + + // Sets a new application handle instance. + GWL_HINSTANCE = -6, + + // Sets a new window handle as the parent. + GWL_HWNDPARENT = -8, + + // Sets a new identifier of the window. + GWL_ID = -12, + + // Sets a new window style. + GWL_STYLE = -16, + + // Sets a new user data associated with the window. Initially zero. + GWL_USERDATA = -21, + + // Sets a new address of the window procedure. + GWL_WNDPROC = -4, + } + + [DllImport (LIBGDK, CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr gdk_win32_window_get_impl_hwnd (IntPtr window); + + public static IntPtr HWndGet (Gdk.Window window) + { + return gdk_win32_window_get_impl_hwnd (window.Handle); + } + + [DllImport (USER32, EntryPoint="SetWindowLongPtr")] + static extern IntPtr SetWindowLongPtr64 (IntPtr hWnd, int nIndex, IntPtr dwNewLong); + + [DllImport(USER32, EntryPoint="SetWindowLong")] + static extern IntPtr SetWindowLongPtr32 (IntPtr hWnd, int nIndex, IntPtr dwNewLong); + + public static IntPtr SetWindowLongPtr (IntPtr hWnd, int nIndex, IntPtr dwNewLong) + { + if (IntPtr.Size == 4) + return SetWindowLongPtr32 (hWnd, nIndex, dwNewLong); + return SetWindowLongPtr64 (hWnd, nIndex, dwNewLong); + } + + [DllImport (USER32, EntryPoint="GetWindowLongPtr")] + static extern IntPtr GetWindowLongPtr64 (IntPtr hWnd, int nIndex); + + [DllImport(USER32, EntryPoint="GetWindowLong")] + static extern IntPtr GetWindowLongPtr32 (IntPtr hWnd, int nIndex); + + public static IntPtr GetWindowLongPtr (IntPtr hWnd, int nIndex) + { + if (IntPtr.Size == 4) + return GetWindowLongPtr32 (hWnd, nIndex); + return GetWindowLongPtr64 (hWnd, nIndex); + } + + internal static Gdk.EventKey ConvertKeyEvent (ModifierKeys mod, Key key) + { + var state = Gdk.ModifierType.None; + if ((mod & ModifierKeys.Control) != 0) + state |= Gdk.ModifierType.ControlMask; + if ((mod & ModifierKeys.Shift) != 0) + state |= Gdk.ModifierType.ShiftMask; + if ((mod & ModifierKeys.Windows) != 0) + state |= Gdk.ModifierType.MetaMask; + if ((mod & ModifierKeys.Alt) != 0) + state |= Gdk.ModifierType.Mod1Mask; + + return GtkUtil.CreateKeyEventFromKeyCode ((ushort)KeyInterop.VirtualKeyFromKey (key), state, Gdk.EventType.KeyPress, Ide.IdeApp.Workbench.RootWindow.GdkWindow); + } + } +} +#endif diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs index ab723739b3..80c7f67502 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeCompletion/CompletionWindowManager.cs @@ -92,8 +92,16 @@ namespace MonoDevelop.Ide.CodeCompletion wnd = new CompletionListWindow (); wnd.WordCompleted += HandleWndWordCompleted; } - if (ext != null) + if (ext != null) { wnd.TransientFor = ext.document.Editor.Parent.Toplevel as Gtk.Window; + } else { + var widget = completionWidget as Gtk.Widget; + if (widget != null) { + var window = widget.Toplevel as Gtk.Window; + if (window != null) + wnd.TransientFor = window; + } + } wnd.Extension = ext; try { if (!wnd.ShowListWindow (firstChar, list, completionWidget, completionContext)) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs index cd4b4c4c64..6d78400369 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CodeTemplates/CodeTemplate.cs @@ -431,7 +431,7 @@ namespace MonoDevelop.Ide.CodeTemplates document.Editor.Caret.Location = document.Editor.OffsetToLocation (newoffset) ; var prettyPrinter = CodeFormatterService.GetFormatter (data.MimeType); - if (prettyPrinter != null) { + if (prettyPrinter != null && prettyPrinter.SupportsOnTheFlyFormatting) { int endOffset = template.InsertPosition + template.Code.Length; var oldVersion = data.Version; prettyPrinter.OnTheFlyFormat (document, template.InsertPosition, endOffset); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs index 38d4b566a4..5d460002c9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileCommands.cs @@ -34,10 +34,10 @@ using MonoDevelop.Ide.Gui; using MonoDevelop.Projects; using MonoDevelop.Ide.Gui.Content; using System.IO; -using Gtk; using MonoDevelop.Ide.Projects; using MonoDevelop.Ide.Desktop; using System.Linq; +using MonoDevelop.Components.Extensions; namespace MonoDevelop.Ide.Commands { @@ -79,7 +79,7 @@ namespace MonoDevelop.Ide.Commands { protected override void Run () { - var dlg = new OpenFileDialog (GettextCatalog.GetString ("File to Open"), Gtk.FileChooserAction.Open) { + var dlg = new OpenFileDialog (GettextCatalog.GetString ("File to Open"), SelectFileDialogAction.Open) { TransientFor = IdeApp.Workbench.RootWindow, ShowEncodingSelector = true, ShowViewerSelector = true, @@ -273,8 +273,12 @@ namespace MonoDevelop.Ide.Commands int i = 0; foreach (var ri in files) { - string acceleratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10).ToString() + " " : ""; - var cmd = new CommandInfo (acceleratorKeyPrefix + ri.DisplayName.Replace ("_", "__")) { + string commandText = ri.DisplayName.Replace ("_", "__"); + if (!Platform.IsMac) { + string acceleratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10).ToString() + " " : ""; + commandText = acceleratorKeyPrefix + commandText; + } + var cmd = new CommandInfo (commandText) { Description = GettextCatalog.GetString ("Open {0}", ri.FileName) }; /* Gdk.Pixbuf icon = DesktopService.GetIconForFile (ri.FileName, IconSize.Menu); @@ -347,13 +351,18 @@ namespace MonoDevelop.Ide.Commands LoggingService.LogWarning ("Error building recent solutions list", ex); continue; } - - string acceleratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10).ToString() + " " : ""; + + string commandText = ri.DisplayName.Replace ("_", "__"); + if (!Platform.IsMac) { + string acceleratorKeyPrefix = i < 10 ? "_" + ((i + 1) % 10).ToString() + " " : ""; + commandText = acceleratorKeyPrefix + commandText; + } + string str = GettextCatalog.GetString ("Load solution {0}", ri.ToString ()); if (IdeApp.Workspace.IsOpen) str += " - " + GettextCatalog.GetString ("Hold Control to open in current workspace."); - var cmd = new CommandInfo (acceleratorKeyPrefix + ri.DisplayName.Replace ("_", "__")) { + var cmd = new CommandInfo (commandText) { Icon = icon, Description = str, }; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs index 60c9b06e60..20ace23f75 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/FileTabCommands.cs @@ -35,6 +35,7 @@ using MonoDevelop.Ide.Gui; using MonoDevelop.Ide.Navigation; using MonoDevelop.Core; using System.Linq; +using MonoDevelop.Ide.Gui.Dialogs; namespace MonoDevelop.Ide.Commands { @@ -49,33 +50,46 @@ namespace MonoDevelop.Ide.Commands class CloseAllHandler : CommandHandler { + protected virtual IViewContent GetDocumentException () + { + return null; + } + protected override void Run () { var active = IdeApp.Workbench.ActiveDocument; if (active == null) return; + var activeNotebook = ((SdiWorkspaceWindow)active.Window).TabControl; - foreach (Document doc in IdeApp.Workbench.Documents.ToArray ()) { - var w1 = (SdiWorkspaceWindow) doc.Window; - if (w1.TabControl == activeNotebook) + var except = GetDocumentException (); + + var docs = IdeApp.Workbench.Documents + .Where (doc => ((SdiWorkspaceWindow)doc.Window).TabControl == activeNotebook && (except == null || doc.Window.ViewContent != except)) + .ToArray (); + + var dirtyDialogShown = docs.Count (doc => doc.IsDirty) > 1; + if (dirtyDialogShown) + using (var dlg = new DirtyFilesDialog (docs, closeWorkspace: false, groupByProject: false)) { + dlg.Modal = true; + if (MessageService.ShowCustomDialog (dlg) != (int)Gtk.ResponseType.Ok) + return; + } + + foreach (Document doc in docs) + if (dirtyDialogShown) + doc.Window.CloseWindow (true); + else doc.Close (); - } } } - class CloseAllButThisHandler : CommandHandler + class CloseAllButThisHandler : CloseAllHandler { - protected override void Run () + protected override IViewContent GetDocumentException () { var active = IdeApp.Workbench.ActiveDocument; - if (active == null) - return; - var activeNotebook = ((SdiWorkspaceWindow)active.Window).TabControl; - foreach (Document doc in IdeApp.Workbench.Documents.ToArray ()) { - var w1 = (SdiWorkspaceWindow) doc.Window; - if (w1.TabControl == activeNotebook && doc != active) - doc.Close (); - } + return active == null ? null : active.Window.ViewContent; } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs index ef43552ecf..a121725c3a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ProjectCommands.cs @@ -571,9 +571,11 @@ namespace MonoDevelop.Ide.Commands { protected override void Update (CommandInfo info) { - info.Enabled = (IdeApp.ProjectOperations.CurrentSelectedSolution != null) && - (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted) && - IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllProjects ().Any (p => p.SupportsTarget ("RunCodeAnalysis")); + //TODO: Roslyn, switch back to SupportsTarget check + //info.Enabled = (IdeApp.ProjectOperations.CurrentSelectedSolution != null) && + // (IdeApp.ProjectOperations.CurrentBuildOperation.IsCompleted) && + // IdeApp.ProjectOperations.CurrentSelectedSolution.GetAllProjects ().Any (p => p.SupportsTarget ("RunCodeAnalysis")); + info.Enabled = true; } protected override void Run () @@ -591,7 +593,8 @@ namespace MonoDevelop.Ide.Commands if (IdeApp.Workspace.IsOpen) { var project = IdeApp.ProjectOperations.CurrentSelectedProject; if (project != null) { - info.Enabled = project.SupportsTarget ("RunCodeAnalysis"); + //TODO: Roslyn, switch back to SupportsTarget check + info.Enabled = true;//project.SupportsTarget ("RunCodeAnalysis"); info.Text = GettextCatalog.GetString ("Run Code Analysis on {0}", project.Name.Replace ("_","__")); return; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs index 797e266a66..109d363505 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/ToolsCommands.cs @@ -25,11 +25,11 @@ // // - +using MonoDevelop.Components.AutoTest; using MonoDevelop.Components.Commands; using MonoDevelop.Core; using MonoDevelop.Core.Execution; -using MonoDevelop.Ide.Gui; +using MonoDevelop.Ide.Gui.Dialogs; using System; using MonoDevelop.Ide.Updater; @@ -39,7 +39,9 @@ namespace MonoDevelop.Ide.Commands { AddinManager, ToolList, - InstrumentationViewer + InstrumentationViewer, + ToggleSessionRecorder, + ReplaySession, } internal class AddinManagerHandler : CommandHandler @@ -138,4 +140,59 @@ namespace MonoDevelop.Ide.Commands info.Visible = MonoDevelop.Core.Instrumentation.InstrumentationService.Enabled; } } + + internal class ToggleSessionRecorderHandler : CommandHandler + { + protected override void Run () + { + if (AutoTestService.CurrentRecordSession == null) { + AutoTestService.StartRecordingSession (); + } else { + var selector = new FileSelectorDialog ("Save session as...", Gtk.FileChooserAction.Save); + try { + var result = MessageService.RunCustomDialog (selector, MessageService.RootWindow); + + if (result == (int)Gtk.ResponseType.Cancel) { + return; + } + + AutoTestService.StopRecordingSession (selector.Filename); + } finally { + selector.Destroy (); + } + } + } + + protected override void Update (CommandInfo info) + { + info.Visible = IdeApp.Preferences.EnableAutomatedTesting; + info.Text = AutoTestService.CurrentRecordSession == null ? "Start Session Recorder" : "Stop Session Recorder"; + } + } + + internal class ReplaySessionHandler : CommandHandler + { + protected override void Run () + { + var selector = new FileSelectorDialog ("Open session"); + string filename = null; + try { + var result = MessageService.RunCustomDialog (selector, MessageService.RootWindow); + + if (result == (int)Gtk.ResponseType.Cancel) { + return; + } + + filename = selector.Filename; + } finally { + selector.Destroy (); + } + AutoTestService.ReplaySessionFromFile (filename); + } + + protected override void Update (CommandInfo info) + { + info.Visible = IdeApp.Preferences.EnableAutomatedTesting; + } + } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs index b1ca6d43d4..3f758fce2e 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Commands/WindowCommands.cs @@ -37,8 +37,9 @@ namespace MonoDevelop.Ide.Commands { public enum WindowCommands { - NextWindow, - PrevWindow, + NextDocument, + PrevDocument, + OpenDocumentList, OpenWindowList, SplitWindowVertically, SplitWindowHorizontally, @@ -48,7 +49,7 @@ namespace MonoDevelop.Ide.Commands SwitchPreviousDocument } - internal class NextWindowHandler : CommandHandler + internal class NextDocumentHandler : CommandHandler { protected override void Update (CommandInfo info) { @@ -70,7 +71,7 @@ namespace MonoDevelop.Ide.Commands } } - internal class PrevWindowHandler : CommandHandler + internal class PrevDocumentHandler : CommandHandler { protected override void Update (CommandInfo info) { @@ -91,7 +92,7 @@ namespace MonoDevelop.Ide.Commands } } - internal class OpenWindowListHandler : CommandHandler + internal class OpenDocumentListHandler : CommandHandler { protected override void Update (CommandArrayInfo info) { @@ -103,7 +104,7 @@ namespace MonoDevelop.Ide.Commands commandInfo.Text = document.Window.Title.Replace ("_", "__"); if (document == IdeApp.Workbench.ActiveDocument) commandInfo.Checked = true; - commandInfo.Description = GettextCatalog.GetString ("Activate window '{0}'", commandInfo.Text); + commandInfo.Description = GettextCatalog.GetString ("Activate document '{0}'", commandInfo.Text); if (document.Window.ShowNotification) { commandInfo.UseMarkup = true; commandInfo.Text = "<span foreground=" + '"' + "blue" + '"' + ">" + commandInfo.Text + "</span>"; @@ -129,6 +130,34 @@ namespace MonoDevelop.Ide.Commands } } + internal class OpenWindowListHandler : CommandHandler + { + protected override void Update (CommandArrayInfo info) + { + int i = 0; + foreach (Gtk.Window window in IdeApp.CommandService.TopLevelWindowStack) { + + //Create CommandInfo object + CommandInfo commandInfo = new CommandInfo (); + commandInfo.Text = window.Title.Replace ("_", "__"); + if (window.HasToplevelFocus) + commandInfo.Checked = true; + commandInfo.Description = GettextCatalog.GetString ("Activate window '{0}'", commandInfo.Text); + + //Add menu item + info.Add (commandInfo, window); + + i++; + } + } + + protected override void Run (object dataItem) + { + Window window = (Window)dataItem; + window.Present (); + } + } + internal class SplitWindowVertically : CommandHandler { protected override void Update (CommandInfo info) @@ -223,7 +252,7 @@ namespace MonoDevelop.Ide.Commands { //FIXME: does this option need to exist? if (!PropertyService.Get ("MonoDevelop.Core.Gui.EnableDocumentSwitchDialog", true)) { - IdeApp.CommandService.DispatchCommand (next? WindowCommands.NextWindow : WindowCommands.PrevWindow); + IdeApp.CommandService.DispatchCommand (next? WindowCommands.NextDocument : WindowCommands.PrevDocument); return; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs index d5bc44bb67..8ad57a0cfa 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Desktop/RecentOpen.cs @@ -44,7 +44,7 @@ namespace MonoDevelop.Ide.Desktop const string projGroup = "MonoDevelop Projects"; const string fileGroup = "MonoDevelop Files"; - const int ItemLimit = 10; + const int ItemLimit = 25; public FdoRecentFiles () : this (RecentFileStorage.DefaultPath) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs index 024869101c..51b808b831 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.FindInFiles/FindInFilesDialog.cs @@ -146,8 +146,13 @@ namespace MonoDevelop.Ide.FindInFiles properties = PropertyService.Get ("MonoDevelop.FindReplaceDialogs.SearchOptions", new Properties ()); SetButtonIcon (toggleReplaceInFiles, "gtk-find-and-replace"); SetButtonIcon (toggleFindInFiles, "gtk-find"); - - TransientFor = IdeApp.Workbench.RootWindow; + + // If we have an active floating window, attach the dialog to it. Otherwise use the main IDE window. + var current_toplevel = Gtk.Window.ListToplevels ().FirstOrDefault (x => x.IsActive); + if (current_toplevel is Components.DockNotebook.DockWindow) + TransientFor = current_toplevel; + else + TransientFor = IdeApp.Workbench.RootWindow; toggleReplaceInFiles.Active = showReplace; toggleFindInFiles.Active = !showReplace; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs index 9e0f7e6724..6f22cda97c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/ExtensibleTreeView.cs @@ -195,11 +195,20 @@ namespace MonoDevelop.Ide.Gui.Components tree.MotionNotifyEvent += HandleMotionNotifyEvent; tree.LeaveNotifyEvent += HandleLeaveNotifyEvent; + if (GtkGestures.IsSupported) { + tree.AddGestureMagnifyHandler ((sender, args) => { + Zoom += Zoom * (args.Magnification / 4d); + }); + } + for (int n=3; n<16; n++) { Gtk.Rc.ParseString ("style \"MonoDevelop.ExtensibleTreeView_" + n + "\" {\n GtkTreeView::expander-size = " + n + "\n }\n"); Gtk.Rc.ParseString ("widget \"*.MonoDevelop.ExtensibleTreeView_" + n + "\" style \"MonoDevelop.ExtensibleTreeView_" + n + "\"\n"); } + if (!string.IsNullOrEmpty (Id)) + Zoom = PropertyService.Get<double> ("MonoDevelop.Ide.ExtensibleTreeView.Zoom." + Id, 1d); + this.Add (tree); this.ShowAll (); @@ -244,8 +253,9 @@ namespace MonoDevelop.Ide.Gui.Components var info = (NodeInfo)model.GetValue (it, NodeInfoColumn); var cell = (ZoomableCellRendererPixbuf)renderer; - cell.Image = info.Icon != null && info.Icon != CellRendererImage.NullImage && info.DisabledStyle ? info.Icon.WithAlpha (0.5) : info.Icon; - cell.ImageExpanderOpen = cell.Image; + var img = info.Icon != null && info.Icon != CellRendererImage.NullImage && info.DisabledStyle ? info.Icon.WithAlpha (0.5) : info.Icon; + cell.Image = img; + cell.ImageExpanderOpen = img; cell.ImageExpanderClosed = info.ClosedIcon != null && info.ClosedIcon != CellRendererImage.NullImage && info.DisabledStyle ? info.ClosedIcon.WithAlpha (0.5) : info.ClosedIcon; cell.OverlayBottomLeft = info.OverlayBottomLeft; cell.OverlayBottomRight = info.OverlayBottomRight; @@ -1019,12 +1029,92 @@ namespace MonoDevelop.Ide.Gui.Components public event EventHandler CurrentItemActivated; - [Obsolete ("Not supported anymore")] + #region Zoom + + const double ZOOM_FACTOR = 1.1f; + const int ZOOM_MIN_POW = -4; + const int ZOOM_MAX_POW = 8; + static readonly double ZOOM_MIN = System.Math.Pow (ZOOM_FACTOR, ZOOM_MIN_POW); + static readonly double ZOOM_MAX = System.Math.Pow (ZOOM_FACTOR, ZOOM_MAX_POW); + double zoom; + public double Zoom { - get { return 1d; } - set { } + get { + return zoom; + } + set { + value = System.Math.Min (ZOOM_MAX, System.Math.Max (ZOOM_MIN, value)); + if (value > ZOOM_MAX || value < ZOOM_MIN) + return; + //snap to one, if within 0.001d + if ((System.Math.Abs (value - 1d)) < 0.001d) { + value = 1d; + } + if (zoom != value) { + zoom = value; + OnZoomChanged (value); + } + } } + void OnZoomChanged (double value) + { + pix_render.Zoom = value; + text_render.Zoom = value; + + int expanderSize = (int) (12 * Zoom); + if (expanderSize < 3) expanderSize = 3; + if (expanderSize > 15) expanderSize = 15; + if (expanderSize != 12) + tree.Name = "MonoDevelop.ExtensibleTreeView_" + expanderSize; + else + tree.Name = ""; + tree.ColumnsAutosize (); + if (!string.IsNullOrEmpty (Id)) { + PropertyService.Set ("MonoDevelop.Ide.ExtensibleTreeView.Zoom." + Id, Zoom); + } + } + + [CommandHandler (ViewCommands.ZoomIn)] + public void ZoomIn () + { + int oldPow = (int)System.Math.Round (System.Math.Log (zoom) / System.Math.Log (ZOOM_FACTOR)); + Zoom = System.Math.Pow (ZOOM_FACTOR, oldPow + 1); + } + + [CommandHandler (ViewCommands.ZoomOut)] + public void ZoomOut () + { + int oldPow = (int)System.Math.Round (System.Math.Log (zoom) / System.Math.Log (ZOOM_FACTOR)); + Zoom = System.Math.Pow (ZOOM_FACTOR, oldPow - 1); + } + + [CommandHandler (ViewCommands.ZoomReset)] + public void ZoomReset () + { + Zoom = 1d; + } + + [CommandUpdateHandler (ViewCommands.ZoomIn)] + protected void UpdateZoomIn (CommandInfo cinfo) + { + cinfo.Enabled = zoom < ZOOM_MAX - 0.000001d; + } + + [CommandUpdateHandler (ViewCommands.ZoomOut)] + protected void UpdateZoomOut (CommandInfo cinfo) + { + cinfo.Enabled = zoom > ZOOM_MIN + 0.000001d; + } + + [CommandUpdateHandler (ViewCommands.ZoomReset)] + protected void UpdateZoomReset (CommandInfo cinfo) + { + cinfo.Enabled = zoom != 1d; + } + + #endregion Zoom + [CommandHandler (EditCommands.Copy)] public void CopyCurrentItem () { @@ -1783,7 +1873,9 @@ namespace MonoDevelop.Ide.Gui.Components void ShowPopup (Gdk.EventButton evt) { - var entryset = BuildEntrySet () ?? new CommandEntrySet (); + var entryset = BuildEntrySet (); + if (entryset == null) + return; if (evt == null) { var paths = tree.Selection.GetSelectedRows (); @@ -1950,6 +2042,24 @@ namespace MonoDevelop.Ide.Gui.Components } } + protected override bool OnScrollEvent (Gdk.EventScroll evnt) + { + var modifier = !Platform.IsMac? Gdk.ModifierType.ControlMask + //Mac window manager already uses control-scroll, so use command + //Command might be either meta or mod1, depending on GTK version + : (Gdk.ModifierType.MetaMask | Gdk.ModifierType.Mod1Mask); + + if ((evnt.State & modifier) !=0) { + if (evnt.Direction == Gdk.ScrollDirection.Up) + ZoomIn (); + else if (evnt.Direction == Gdk.ScrollDirection.Down) + ZoomOut (); + + return true; + } + return base.OnScrollEvent (evnt); + } + protected virtual void OnNodeActivated (object sender, Gtk.RowActivatedArgs args) { ActivateCurrentItem (); @@ -2248,6 +2358,7 @@ namespace MonoDevelop.Ide.Gui.Components class CustomCellRendererText: Gtk.CellRendererText { + double zoom; Pango.Layout layout; Pango.FontDescription scaledFont, customFont; @@ -2309,7 +2420,7 @@ namespace MonoDevelop.Ide.Gui.Components if (scaledFont != null) scaledFont.Dispose (); scaledFont = (customFont ?? parent.Style.FontDesc).Copy (); - scaledFont.Size = customFont.Size; + scaledFont.Size = (int)(customFont.Size * Zoom); if (layout != null) layout.FontDescription = scaledFont; } @@ -2455,6 +2566,19 @@ namespace MonoDevelop.Ide.Gui.Components width += (int) StatusIcon.Width + StatusIconSpacing; } + public double Zoom { + get { + return zoom; + } + set { + if (scaledFont != null) { + scaledFont.Dispose (); + scaledFont = null; + } + zoom = value; + } + } + public bool PointerInButton (int px, int py) { return buttonScreenRect.Contains (px, py); @@ -2535,6 +2659,8 @@ namespace MonoDevelop.Ide.Gui.Components class ZoomableCellRendererPixbuf: CellRendererImage { + double zoom = 1f; + Dictionary<Xwt.Drawing.Image,Xwt.Drawing.Image> resizedCache = new Dictionary<Xwt.Drawing.Image, Xwt.Drawing.Image> (); Xwt.Drawing.Image overlayBottomLeft; @@ -2542,6 +2668,17 @@ namespace MonoDevelop.Ide.Gui.Components Xwt.Drawing.Image overlayTopLeft; Xwt.Drawing.Image overlayTopRight; + public double Zoom { + get { return zoom; } + set { + if (zoom != value) { + zoom = value; + resizedCache.Clear (); + Notify ("image"); + } + } + } + public override Xwt.Drawing.Image Image { get { return base.Image; @@ -2616,7 +2753,20 @@ namespace MonoDevelop.Ide.Gui.Components if (value == null || value == CellRendererImage.NullImage) return null; - return value; + if (zoom == 1) + return value; + + Xwt.Drawing.Image resized; + if (resizedCache.TryGetValue (value, out resized)) + return resized; + + int w = (int) (zoom * (double) value.Width); + int h = (int) (zoom * (double) value.Height); + if (w == 0) w = 1; + if (h == 0) h = 1; + resized = value.WithSize (w, h); + resizedCache [value] = resized; + return resized; } public override void GetSize (Gtk.Widget widget, ref Gdk.Rectangle cell_area, out int x_offset, out int y_offset, out int width, out int height) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs index 17a65a2364..9932f93145 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Components/LogView.cs @@ -112,8 +112,11 @@ namespace MonoDevelop.Ide.Gui.Components var clipboard = Clipboard.Get (Gdk.Atom.Intern ("CLIPBOARD", false)); clipboard.Text = text; - clipboard = Clipboard.Get (Gdk.Atom.Intern ("PRIMARY", false)); - clipboard.Text = text; + if (Platform.IsLinux) { + // gtk has different clipboards for CLIPBOARD and PRIMARY only on Linux. + clipboard = Clipboard.Get (Gdk.Atom.Intern ("PRIMARY", false)); + clipboard.Text = text; + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs index 290c2f37a5..85be8e40f3 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/DirtyFilesDialog.cs @@ -1,5 +1,6 @@ using System; using System.Collections; +using System.Collections.Generic; using Gtk; @@ -10,7 +11,6 @@ namespace MonoDevelop.Ide.Gui.Dialogs { internal class DirtyFilesDialog : Gtk.Dialog { - Button btnSaveAndQuit; Button btnQuit; Button btnCancel; @@ -18,21 +18,26 @@ namespace MonoDevelop.Ide.Gui.Dialogs TreeStore tsFiles; CellRendererToggle togRender; CellRendererText textRender; - - public DirtyFilesDialog () : base (GettextCatalog.GetString ("Save Files"), IdeApp.Workbench.RootWindow, DialogFlags.Modal) + + public DirtyFilesDialog () : this (IdeApp.Workbench.Documents, true, true) + { + } + + public DirtyFilesDialog (IReadOnlyList<Document> docs, bool closeWorkspace, bool groupByProject) : + base (GettextCatalog.GetString ("Save Files"), IdeApp.Workbench.RootWindow, DialogFlags.Modal) { tsFiles = new TreeStore (typeof(string), typeof(bool), typeof(SdiWorkspaceWindow), typeof(bool)); tvFiles = new TreeView (tsFiles); TreeIter topCombineIter = TreeIter.Zero; Hashtable projectIters = new Hashtable (); - foreach (Document doc in IdeApp.Workbench.Documents) { + foreach (Document doc in docs) { if (!doc.IsDirty) continue; IViewContent viewcontent = doc.Window.ViewContent; - if (viewcontent.Project != null) { + if (groupByProject && viewcontent.Project != null) { TreeIter projIter = TreeIter.Zero; if (projectIters.ContainsKey (viewcontent.Project)) projIter = (TreeIter)projectIters [viewcontent.Project]; @@ -79,9 +84,9 @@ namespace MonoDevelop.Ide.Gui.Dialogs sc.BorderWidth = 6; this.VBox.PackStart (sc, true, true, 6); - - btnSaveAndQuit = new Button (GettextCatalog.GetString ("_Save and Quit")); - btnQuit = new Button (Gtk.Stock.Quit); + + btnSaveAndQuit = new Button (closeWorkspace ? GettextCatalog.GetString ("_Save and Quit") : GettextCatalog.GetString ("_Save and Close")); + btnQuit = new Button (closeWorkspace ? Gtk.Stock.Quit : Gtk.Stock.Close); btnCancel = new Button (Gtk.Stock.Cancel); btnSaveAndQuit.Clicked += SaveAndQuit; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs index 430502ff21..62e39f17a9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Dialogs/OpenFileDialog.cs @@ -25,12 +25,10 @@ // THE SOFTWARE. using System; -using MonoDevelop.Core; +using System.Text; + using MonoDevelop.Ide.Extensions; using MonoDevelop.Components.Extensions; -using System.Collections.Generic; -using Mono.Addins; -using System.Text; namespace MonoDevelop.Ide.Gui.Dialogs
{ @@ -43,11 +41,11 @@ namespace MonoDevelop.Ide.Gui.Dialogs { } - public OpenFileDialog (string title) : this (title, Gtk.FileChooserAction.Save) + public OpenFileDialog (string title) : this (title, SelectFileDialogAction.Save) { } - public OpenFileDialog (string title, Gtk.FileChooserAction action) + public OpenFileDialog (string title, SelectFileDialogAction action) { Title = title; Action = action; @@ -90,10 +88,20 @@ namespace MonoDevelop.Ide.Gui.Dialogs public FileViewer SelectedViewer { get { return data.SelectedViewer; } } + + Gtk.FileChooserAction GetFileChooserAction () + { + switch (Action) { + case SelectFileDialogAction.CreateFolder: return Gtk.FileChooserAction.CreateFolder; + case SelectFileDialogAction.SelectFolder: return Gtk.FileChooserAction.SelectFolder; + case SelectFileDialogAction.Save: return Gtk.FileChooserAction.Save; + default: return Gtk.FileChooserAction.Open; + } + } protected override bool RunDefault () { - var win = new FileSelectorDialog (Title, Action); + var win = new FileSelectorDialog (Title, GetFileChooserAction ()); win.SelectedEncoding = Encoding != null ? Encoding.CodePage : 0; win.ShowEncodingSelector = ShowEncodingSelector; win.ShowViewerSelector = ShowViewerSelector; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs index 30136aceae..f1754c228c 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.OptionPanels/KeyBindingsPanel.cs @@ -431,25 +431,29 @@ namespace MonoDevelop.Ide.Gui.OptionPanels return; } globalWarningBox.Show (); - conflicButton.MenuCreator = delegate { - Menu menu = new Menu (); + + conflicButton.ContextMenuRequested = delegate { + ContextMenu menu = new ContextMenu (); + bool first = true; + foreach (KeyBindingConflict conf in conflicts) { - if (menu.Children.Length > 0) { - SeparatorMenuItem it = new SeparatorMenuItem (); - it.Show (); - menu.Insert (it, -1); + if (first == false) { + ContextMenuItem item = new SeparatorContextMenuItem (); + menu.Items.Add (item); } + foreach (Command cmd in conf.Commands) { string txt = currentBindings.GetBinding (cmd) + " - " + cmd.Text; - MenuItem item = new MenuItem (txt); + ContextMenuItem item = new ContextMenuItem (txt); Command localCmd = cmd; - item.Activated += delegate { - SelectCommand (localCmd); - }; - item.Show (); - menu.Insert (item, -1); + + item.Clicked += (sender, e) => SelectCommand (localCmd); + + menu.Items.Add (item); + first = false; } } + return menu; }; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs index 0734f172b9..2d9e6c4a76 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/FolderNodeBuilder.cs @@ -90,6 +90,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad { string dir; + if (!file.Visible || file.Flags.HasFlag (ProjectItemFlags.Hidden)) + continue; + if (file.Subtype != Subtype.Directory) { if (file.DependsOnFile != null) continue; @@ -130,6 +133,8 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad foreach (var file in project.Files) { FilePath path; + if (!file.Visible || file.Flags.HasFlag (ProjectItemFlags.Hidden)) + continue; if (file.Subtype != Subtype.Directory) path = file.IsLink ? project.BaseDirectory.Combine (file.ProjectVirtualPath) : file.FilePath; else diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs index ca2204543b..57608e02bb 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFileNodeBuilder.cs @@ -224,60 +224,6 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad return DragOperation.Copy | DragOperation.Move; } - public override bool CanDropNode (object dataObject, DragOperation operation) - { - var target = (ProjectFile) CurrentNode.DataItem; - var pf = dataObject as ProjectFile; - - return pf != null && pf != target && !pf.HasChildren && target.DependsOn == null; - } - - void Drop (ProjectFile pf, DragOperation operation, HashSet<SolutionEntityItem> projectsToSave) - { - var target = (ProjectFile) CurrentNode.DataItem; - var targetDirectory = target.FilePath.ParentDirectory; - - // file dependencies only work if they are in the same physical folder - if (pf.FilePath.ParentDirectory != targetDirectory) { - var targetPath = targetDirectory.Combine (pf.FilePath.FileName); - - // if copying to the same directory, make a copy with a different name - if (targetPath == pf.FilePath) - targetPath = ProjectOperations.GetTargetCopyName (targetPath, false); - - if (File.Exists (targetPath)) - if (!MessageService.Confirm (GettextCatalog.GetString ("The file '{0}' already exists. Do you want to overwrite it?", targetPath.FileName), AlertButton.OverwriteFile)) - return; - - // unlink the project file from its current parent - pf.DependsOn = null; - - projectsToSave.Add (pf.Project); - - bool move = operation == DragOperation.Move; - var opText = move ? GettextCatalog.GetString ("Moving file...") : GettextCatalog.GetString ("Copying file..."); - - using (var monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (opText, Stock.StatusWorking, true)) - IdeApp.ProjectOperations.TransferFiles (monitor, pf.Project, pf.FilePath, target.Project, targetPath, move, true); - - pf = target.Project.Files.GetFile (targetPath); - } - - // the dropped project file now depends on the file it was just dropped onto - pf.DependsOn = target.FilePath.FileName; - projectsToSave.Add (pf.Project); - } - - public override void OnMultipleNodeDrop (object[] dataObjects, DragOperation operation) - { - var projectsToSave = new HashSet<SolutionEntityItem> (); - - foreach (var dataObject in dataObjects) - Drop ((ProjectFile) dataObject, operation, projectsToSave); - - IdeApp.ProjectOperations.Save (projectsToSave); - } - public override bool CanDeleteItem () { return true; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs index 26b22e7047..28c623f1cf 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectFolderNodeBuilder.cs @@ -198,16 +198,16 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad "The Delete option permanently removes the directory and any files it contains from your hard disk. " + "Click Remove from Project if you only want to remove it from your current solution.") }; - question.Buttons.Add (AlertButton.Cancel); question.Buttons.Add (AlertButton.Delete); question.Buttons.Add (removeButton); + question.Buttons.Add (AlertButton.Cancel); var deleteOnlyQuestion = new QuestionMessage () { AllowApplyToAll = folders.Count > 1, SecondaryText = GettextCatalog.GetString ("The directory and any files it contains will be permanently removed from your hard disk. ") }; - deleteOnlyQuestion.Buttons.Add (AlertButton.Cancel); deleteOnlyQuestion.Buttons.Add (AlertButton.Delete); + deleteOnlyQuestion.Buttons.Add (AlertButton.Cancel); foreach (var folder in folders) { var project = folder.Project; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs index b10b6ad8ff..28ac0a8e8a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads.ProjectPad/ProjectNodeBuilder.cs @@ -222,6 +222,9 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad void AddFile (ProjectFile file, Project project) { + if (!file.Visible || file.Flags.HasFlag (ProjectItemFlags.Hidden)) + return; + ITreeBuilder tb = Context.GetTreeBuilder (); if (file.DependsOnFile != null) { @@ -402,9 +405,12 @@ namespace MonoDevelop.Ide.Gui.Pads.ProjectPad public void SetAsStartupProject () { Project project = CurrentNode.DataItem as Project; - project.ParentSolution.SingleStartup = true; project.ParentSolution.StartupItem = project; - IdeApp.ProjectOperations.Save (project.ParentSolution); + if (!project.ParentSolution.SingleStartup) { + project.ParentSolution.SingleStartup = true; + IdeApp.ProjectOperations.Save (project.ParentSolution); + } else + project.ParentSolution.SaveUserProperties (); } public override void DeleteItem () diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs index d5fb26cf09..5ac9296bad 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/ErrorListPad.cs @@ -49,6 +49,7 @@ using MonoDevelop.Ide.Gui.Components; using MonoDevelop.Components.Commands; using MonoDevelop.Ide.Commands; using MonoDevelop.Components; +using System.Linq; namespace MonoDevelop.Ide.Gui.Pads { @@ -125,7 +126,7 @@ namespace MonoDevelop.Ide.Gui.Pads DockItemToolbar toolbar = window.GetToolbar (PositionType.Top); - errorBtn = new ToggleButton (); + errorBtn = new ToggleButton { Name = "toggleErrors" }; errorBtn.Active = (bool)PropertyService.Get (showErrorsPropertyName, true); errorBtn.Image = new Gtk.Image (Stock.Error, Gtk.IconSize.Menu); errorBtn.Image.Show (); @@ -134,7 +135,7 @@ namespace MonoDevelop.Ide.Gui.Pads UpdateErrorsNum(); toolbar.Add (errorBtn); - warnBtn = new ToggleButton (); + warnBtn = new ToggleButton { Name = "toggleWarnings" }; warnBtn.Active = (bool)PropertyService.Get (showWarningsPropertyName, true); warnBtn.Image = new Gtk.Image (Stock.Warning, Gtk.IconSize.Menu); warnBtn.Image.Show (); @@ -143,7 +144,7 @@ namespace MonoDevelop.Ide.Gui.Pads UpdateWarningsNum(); toolbar.Add (warnBtn); - msgBtn = new ToggleButton (); + msgBtn = new ToggleButton { Name = "toggleMessages" }; msgBtn.Active = (bool)PropertyService.Get (showMessagesPropertyName, true); msgBtn.Image = new Gtk.Image (Stock.Information, Gtk.IconSize.Menu); msgBtn.Image.Show (); @@ -154,7 +155,7 @@ namespace MonoDevelop.Ide.Gui.Pads toolbar.Add (new SeparatorToolItem ()); - logBtn = new ToggleButton (); + logBtn = new ToggleButton { Name = "toggleBuildOutput" }; logBtn.Label = GettextCatalog.GetString ("Build Output"); logBtn.Image = ImageService.GetImage ("md-message-log", Gtk.IconSize.Menu); logBtn.Image.Show (); @@ -230,7 +231,7 @@ namespace MonoDevelop.Ide.Gui.Pads control.Add1 (sw); - outputView = new LogView (); + outputView = new LogView { Name = "buildOutput" }; control.Add2 (outputView); Control.ShowAll (); @@ -302,31 +303,20 @@ namespace MonoDevelop.Ide.Gui.Pads void LoadColumnsVisibility () { - string columns = (string)PropertyService.Get ("Monodevelop.ErrorListColumns", "TRUE;TRUE;TRUE;TRUE;TRUE;TRUE;TRUE"); - string[] tokens = columns.Split (new char[] {';'}, StringSplitOptions.RemoveEmptyEntries); - if (tokens.Length == 7 && view != null && view.Columns.Length == 7) - { - for (int i = 0; i < 7; i++) - { + var columns = PropertyService.Get ("Monodevelop.ErrorListColumns", string.Join (";", Enumerable.Repeat ("TRUE", view.Columns.Length))); + var tokens = columns.Split (new [] { ';' }, StringSplitOptions.RemoveEmptyEntries); + if (view.Columns.Length == tokens.Length) { + for (int i = 0; i < tokens.Length; i++) { bool visible; - if (bool.TryParse (tokens[i], out visible)) - view.Columns[i].Visible = visible; + if (bool.TryParse (tokens [i], out visible)) + view.Columns [i].Visible = visible; } } } void StoreColumnsVisibility () { - string columns = String.Format ("{0};{1};{2};{3};{4};{5};{6};{7}", - view.Columns[VisibleColumns.Type].Visible, - view.Columns[VisibleColumns.Marked].Visible, - view.Columns[VisibleColumns.Line].Visible, - view.Columns[VisibleColumns.Description].Visible, - view.Columns[VisibleColumns.File].Visible, - view.Columns[VisibleColumns.Project].Visible, - view.Columns[VisibleColumns.Path].Visible, - view.Columns[VisibleColumns.Category].Visible); - PropertyService.Set ("Monodevelop.ErrorListColumns", columns); + PropertyService.Set ("Monodevelop.ErrorListColumns", string.Join (";", view.Columns.Select (c => c.Visible ? "TRUE" : "FALSE"))); } public void RedrawContent() diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs index 915ae8612a..0eb985da7d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Pads/MonodocTreePad.cs @@ -46,7 +46,7 @@ namespace MonoDevelop.Ide.Gui.Pads ScrolledWindow scroller; TreeIter root_iter; - public HelpTree () : base (GettextCatalog.GetString ("Help"), "md-help") + public HelpTree () : base (GettextCatalog.GetString ("Help"), Stock.Help) { tree_view = new MonoDevelop.Ide.Gui.Components.PadTreeView (); diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs index 58d6768512..82a7646774 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/DefaultWorkbench.cs @@ -1028,7 +1028,8 @@ namespace MonoDevelop.Ide.Gui protected override bool OnConfigureEvent (Gdk.EventConfigure evnt) { SetActiveWidget (Focus); - return base.OnConfigureEvent (evnt); + base.OnConfigureEvent (evnt); + return false; } protected override bool OnFocusInEvent (Gdk.EventFocus evnt) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs index 069845ada8..d3a12756c6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs @@ -52,6 +52,7 @@ using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using System.Text; using System.Collections.ObjectModel; +using MonoDevelop.Components.Extensions; namespace MonoDevelop.Ide.Gui { @@ -414,7 +415,7 @@ namespace MonoDevelop.Ide.Gui } if (filename == null) { - var dlg = new OpenFileDialog (GettextCatalog.GetString ("Save as..."), FileChooserAction.Save) { + var dlg = new OpenFileDialog (GettextCatalog.GetString ("Save as..."), SelectFileDialogAction.Save) { TransientFor = IdeApp.Workbench.RootWindow, Encoding = encoding, ShowEncodingSelector = (tbuffer != null), diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs index 05d64ce084..5e50878b93 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/ProgressMonitors.cs @@ -77,7 +77,7 @@ namespace MonoDevelop.Ide.Gui public IProgressMonitor GetRunProgressMonitor () { - return GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.RunProgramIcon, true, true); + return GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.RunProgramIcon, false, true); } public IProgressMonitor GetToolOutputProgressMonitor (bool bringToFront) @@ -102,7 +102,7 @@ namespace MonoDevelop.Ide.Gui public IConsole CreateConsole (bool closeOnDispose) { - return (IConsole) GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.MessageLog, true, true); + return (IConsole) GetOutputProgressMonitor ("MonoDevelop.Ide.ApplicationOutput", GettextCatalog.GetString ("Application Output"), Stock.MessageLog, false, true); } /******************************/ diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs index 65c7eb0d09..752f262e12 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/StatusProgressMonitor.cs @@ -90,32 +90,28 @@ namespace MonoDevelop.Ide.Gui statusBar.EndProgress (); - if (!IsCancelRequested) { - try { - if (Errors.Count > 0 || Warnings.Count > 0) { - if (Errors.Count > 0) { - statusBar.ShowError (Errors [Errors.Count - 1]); - } else if (SuccessMessages.Count == 0) { - statusBar.ShowWarning (Warnings [Warnings.Count - 1]); - } + try { + if (Errors.Count > 0 || Warnings.Count > 0) { + if (Errors.Count > 0) { + statusBar.ShowError (Errors [Errors.Count - 1]); + } else if (SuccessMessages.Count == 0) { + statusBar.ShowWarning (Warnings [Warnings.Count - 1]); + } - DesktopService.ShowGlobalProgressError (); + DesktopService.ShowGlobalProgressError (); - base.OnCompleted (); - - if (showErrorDialogs) - ShowResultDialog (); - return; - } + base.OnCompleted (); - if (SuccessMessages.Count > 0) - statusBar.ShowMessage (MonoDevelop.Ide.Gui.Stock.StatusSuccess, SuccessMessages [SuccessMessages.Count - 1]); - - } finally { - statusBar.StatusSourcePad = statusSourcePad; - statusBar.Dispose (); + if (!IsCancelRequested && showErrorDialogs) + ShowResultDialog (); + return; } - } else { + + if (SuccessMessages.Count > 0) + statusBar.ShowMessage (MonoDevelop.Ide.Gui.Stock.StatusSuccess, SuccessMessages [SuccessMessages.Count - 1]); + + } finally { + statusBar.StatusSourcePad = statusSourcePad; statusBar.Dispose (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs index 01ea62b0ca..58e4750c86 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Workbench.cs @@ -201,6 +201,14 @@ namespace MonoDevelop.Ide.Gui return false; if (toplevel == RootWindow) return true; + #if WIN32 + var app = System.Windows.Application.Current; + if (app != null) { + var wpfWindow = app.Windows.OfType<System.Windows.Window>().SingleOrDefault (x => x.IsActive); + if (wpfWindow != null) + return true; + } + #endif var dock = toplevel as DockFloatingWindow; return dock != null && dock.DockParent == RootWindow; } @@ -311,6 +319,37 @@ namespace MonoDevelop.Ide.Gui foreach (Document doc in docs) doc.Save (); } + + internal bool SaveAllDirtyFiles () + { + Document[] docs = Documents.Where (doc => doc.IsDirty && doc.Window.ViewContent != null).ToArray (); + if (!docs.Any ()) + return true; + + foreach (Document doc in docs) { + AlertButton result = PromptToSaveChanges (doc); + if (result == AlertButton.Cancel) + return false; + + doc.Save (); + if (doc.IsDirty) { + doc.Select (); + return false; + } + } + return true; + } + + static AlertButton PromptToSaveChanges (Document doc) + { + return MessageService.GenericAlert (MonoDevelop.Ide.Gui.Stock.Warning, + GettextCatalog.GetString ("Save the changes to document '{0}' before creating a new solution?", + doc.Window.ViewContent.IsUntitled + ? doc.Window.ViewContent.UntitledName + : System.IO.Path.GetFileName (doc.FileName)), + "", + AlertButton.Cancel, doc.Window.ViewContent.IsUntitled ? AlertButton.SaveAs : AlertButton.Save); + } public void CloseAllDocuments (bool leaveActiveDocumentOpen) { diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs index a1af09c25c..c8ff32acb6 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Navigation/NavigationHistoryService.cs @@ -349,12 +349,11 @@ namespace MonoDevelop.Ide.Navigation bool closedHistoryChanged = false; foreach (ProjectFileRenamedEventInfo args in e) { foreach (NavigationHistoryItem point in history) { - DocumentNavigationPoint dp = point.NavigationPoint as DocumentNavigationPoint; + var dp = point.NavigationPoint as DocumentNavigationPoint; historyChanged &= (dp != null && dp.HandleRenameEvent (args.OldName, args.NewName)); - } - foreach (NavigationHistoryItem point in history) { - DocumentNavigationPoint cdp = point.NavigationPoint as DocumentNavigationPoint; - closedHistoryChanged &= (cdp != null && cdp.HandleRenameEvent (args.OldName, args.NewName)); + closedHistoryChanged &= (dp != null && dp.HandleRenameEvent (args.OldName, args.NewName)); + if (historyChanged && closedHistoryChanged) + break; } } if (historyChanged) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs index 10a0e87b66..111d928081 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddExternalFileDialog.cs @@ -37,6 +37,7 @@ namespace MonoDevelop.Ide.Projects radioCopy.Active = true; labelTitle.Markup = GettextCatalog.GetString (labelTitle.Text, "<b>" + GLib.Markup.EscapeText (file) + "</b>"); Resizable = false; + buttonOk.GrabFocus (); } public void ShowKeepOption (string dir) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs index 6377843060..512bcf6940 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AddFileDialog.cs @@ -42,7 +42,7 @@ namespace MonoDevelop.Ide.Projects public AddFileDialog (string title)
{ Title = title; - Action = FileChooserAction.Open; + Action = SelectFileDialogAction.Open; data.SelectMultiple = true;
} diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs index 7c53d25e86..4bc2a95b56 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/AssemblyReferencePanel.cs @@ -150,7 +150,7 @@ namespace MonoDevelop.Ide.Projects void HandleClicked (object sender, EventArgs e) { - var dlg = new OpenFileDialog (GettextCatalog.GetString ("Select Assembly"), FileChooserAction.Open); + var dlg = new OpenFileDialog (GettextCatalog.GetString ("Select Assembly"), SelectFileDialogAction.Open); // dlg.AddFilter (GettextCatalog.GetString ("Assemblies"), "*.[Dd][Ll][Ll]", "*.[Ee][Xx][Ee]"); dlg.AddFilter (GettextCatalog.GetString ("Assemblies"), "*.dll", "*.exe"); dlg.CurrentFolder = basePath; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs index 22ec6051b6..c226b12acd 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/DefaultPolicyOptionsDialog.cs @@ -37,6 +37,7 @@ using MonoDevelop.Components; using Gtk; using System.Linq; using MonoDevelop.Projects; +using MonoDevelop.Components.Extensions; namespace MonoDevelop.Ide.Projects { @@ -72,37 +73,44 @@ namespace MonoDevelop.Ide.Projects exportButton = new MenuButton (); exportButton.Label = GettextCatalog.GetString ("Export"); - exportButton.MenuCreator = delegate { - Gtk.Menu menu = new Gtk.Menu (); - MenuItem mi = new MenuItem (GettextCatalog.GetString ("To file...")); - mi.Activated += HandleToFile; - menu.Insert (mi, -1); - mi = new MenuItem (GettextCatalog.GetString ("To project or solution...")); - mi.Activated += HandleToProject; - if (!IdeApp.Workspace.IsOpen) - mi.Sensitive = false; - menu.Insert (mi, -1); - menu.ShowAll (); + exportButton.ContextMenuRequested = delegate { + ContextMenu menu = new ContextMenu (); + + ContextMenuItem item = new ContextMenuItem (GettextCatalog.GetString ("To file...")); + item.Clicked += HandleToFile; + menu.Items.Add (item); + + item = new ContextMenuItem (GettextCatalog.GetString ("To project or solution...")); + item.Clicked += HandleToProject; + if (!IdeApp.Workspace.IsOpen) { + item.Sensitive = false; + } + menu.Items.Add (item); + return menu; }; topBar.PackEnd (exportButton, false, false, 0); newButton = new MenuButton (); newButton.Label = GettextCatalog.GetString ("Add Policy"); - newButton.MenuCreator = delegate { - Gtk.Menu menu = new Gtk.Menu (); - MenuItem mi = new MenuItem (GettextCatalog.GetString ("New policy...")); - mi.Activated += HandleNewButtonClicked; - menu.Insert (mi, -1); - mi = new MenuItem (GettextCatalog.GetString ("From file...")); - mi.Activated += HandleFromFile; - menu.Insert (mi, -1); - mi = new MenuItem (GettextCatalog.GetString ("From project or solution...")); - mi.Activated += HandleFromProject; - if (!IdeApp.Workspace.IsOpen) - mi.Sensitive = false; - menu.Insert (mi, -1); - menu.ShowAll (); + newButton.ContextMenuRequested = delegate { + ContextMenu menu = new ContextMenu (); + + ContextMenuItem item = new ContextMenuItem (GettextCatalog.GetString ("New policy...")); + item.Clicked += HandleNewButtonClicked; + menu.Items.Add (item); + + item = new ContextMenuItem (GettextCatalog.GetString ("From file...")); + item.Clicked += HandleFromFile; + menu.Items.Add (item); + + item = new ContextMenuItem (GettextCatalog.GetString ("From project or solution...")); + item.Clicked += HandleFromProject; + if (!IdeApp.Workspace.IsOpen) { + item.Sensitive = false; + } + menu.Items.Add (item); + return menu; }; topBar.PackEnd (newButton, false, false, 0); @@ -214,7 +222,7 @@ namespace MonoDevelop.Ide.Projects void HandleFromFile (object sender, EventArgs e) { OpenFileDialog dlg = new OpenFileDialog (GettextCatalog.GetString ("Select Policy File")); - dlg.Action = FileChooserAction.Open; + dlg.Action = SelectFileDialogAction.Open; dlg.TransientFor = this; dlg.AddFilter (BrandingService.BrandApplicationName (GettextCatalog.GetString ("MonoDevelop policy files")), "*.mdpolicy"); dlg.AddAllFilesFilter (); @@ -273,7 +281,7 @@ namespace MonoDevelop.Ide.Projects OpenFileDialog dlg = new OpenFileDialog (GettextCatalog.GetString ("Select Policy File")); dlg.TransientFor = this; dlg.InitialFileName = currentSet.Name + ".mdpolicy"; - dlg.Action = FileChooserAction.Save; + dlg.Action = SelectFileDialogAction.Save; dlg.AddFilter (BrandingService.BrandApplicationName (GettextCatalog.GetString ("MonoDevelop policy files")), "*.mdpolicy"); dlg.AddAllFilesFilter (); dlg.CurrentFolder = ExportProjectPolicyDialog.DefaultFileDialogPolicyDir; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs index 4f51bb1f38..3c6412b68f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/ExportProjectPolicyDialog.cs @@ -23,11 +23,13 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. + using System; -using Gtk; + using MonoDevelop.Core; using MonoDevelop.Projects; using MonoDevelop.Projects.Policies; +using MonoDevelop.Components.Extensions; namespace MonoDevelop.Ide.Projects { @@ -41,7 +43,7 @@ namespace MonoDevelop.Ide.Projects this.Build (); this.policyProvider = policyProvider; - fileEntry.Action = FileChooserAction.Save; + fileEntry.Action = SelectFileDialogAction.Save; fileEntry.DefaultPath = DefaultFileDialogPolicyDir; if (policyProvider is SolutionItem) fileEntry.Path = ((SolutionItem)policyProvider).Name + ".mdpolicy"; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs index 3861ff60df..611343c253 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.UI.cs @@ -29,6 +29,7 @@ using Gtk; using MonoDevelop.Components;
using MonoDevelop.Core;
using MonoDevelop.Ide.Templates;
+using Mono.TextEditor;
namespace MonoDevelop.Ide.Projects
{
@@ -72,8 +73,8 @@ namespace MonoDevelop.Ide.Projects void Build ()
{
BorderWidth = 0;
- WidthRequest = 901;
- HeightRequest = 632;
+ WidthRequest = GtkWorkarounds.ConvertToPixelScale (901);
+ HeightRequest = GtkWorkarounds.ConvertToPixelScale (632);
Name = "wizard_dialog";
Title = GettextCatalog.GetString ("New Project");
@@ -84,9 +85,9 @@ namespace MonoDevelop.Ide.Projects projectConfigurationWidget.Name = "projectConfigurationWidget";
// Top banner of dialog.
- var topLabelEventBox = new EventBox ();
+ var topLabelEventBox = new EventBox (); topLabelEventBox.Name = "topLabelEventBox";
- topLabelEventBox.HeightRequest = 52;
+ topLabelEventBox.HeightRequest = GtkWorkarounds.ConvertToPixelScale (52); topLabelEventBox.ModifyBg (StateType.Normal, bannerBackgroundColor);
topLabelEventBox.ModifyFg (StateType.Normal, whiteColor);
topLabelEventBox.BorderWidth = 0;
@@ -130,7 +131,7 @@ namespace MonoDevelop.Ide.Projects var templateCategoriesVBox = new VBox ();
templateCategoriesVBox.Name = "templateCategoriesVBox";
templateCategoriesVBox.BorderWidth = 0;
- templateCategoriesVBox.WidthRequest = 220;
+ templateCategoriesVBox.WidthRequest = GtkWorkarounds.ConvertToPixelScale (220);
var templateCategoriesScrolledWindow = new ScrolledWindow ();
templateCategoriesScrolledWindow.Name = "templateCategoriesScrolledWindow";
templateCategoriesScrolledWindow.HscrollbarPolicy = PolicyType.Never;
@@ -148,9 +149,9 @@ namespace MonoDevelop.Ide.Projects templatesHBox.PackStart (templateCategoriesVBox, false, false, 0);
// Templates.
- var templatesVBox = new VBox ();
+ var templatesVBox = new VBox (); templatesVBox.Name = "templatesVBox";
- templatesVBox.WidthRequest = 400;
+ templatesVBox.WidthRequest = GtkWorkarounds.ConvertToPixelScale (400); templatesHBox.PackStart (templatesVBox, false, false, 0);
var templatesScrolledWindow = new ScrolledWindow ();
templatesScrolledWindow.Name = "templatesScrolledWindow";
@@ -178,23 +179,23 @@ namespace MonoDevelop.Ide.Projects templateEventBox.Add (templateVBox);
// Template large image.
- templateImage = new ImageView ();
+ templateImage = new ImageView (); templateImage.Name = "templateImage";
- templateImage.HeightRequest = 140;
- templateImage.WidthRequest = 240;
+ templateImage.HeightRequest = GtkWorkarounds.ConvertToPixelScale (140);
+ templateImage.WidthRequest = GtkWorkarounds.ConvertToPixelScale (240); templateVBox.PackStart (templateImage, false, false, 10);
// Template description.
- templateNameLabel = new Label ();
+ templateNameLabel = new Label (); templateNameLabel.Name = "templateNameLabel";
- templateNameLabel.WidthRequest = 240;
+ templateNameLabel.WidthRequest = GtkWorkarounds.ConvertToPixelScale (240); templateNameLabel.Wrap = true;
templateNameLabel.Xalign = 0;
templateNameLabel.Markup = MarkupTemplateName ("TemplateName");
templateVBox.PackStart (templateNameLabel, false, false, 0);
- templateDescriptionLabel = new Label ();
+ templateDescriptionLabel = new Label (); templateDescriptionLabel.Name = "templateDescriptionLabel";
- templateDescriptionLabel.WidthRequest = 240;
+ templateDescriptionLabel.WidthRequest = GtkWorkarounds.ConvertToPixelScale (240); templateDescriptionLabel.Wrap = true;
templateDescriptionLabel.Xalign = 0;
templateVBox.PackStart (templateDescriptionLabel, false, false, 0);
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs index 83c534cd30..c4570c668d 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkNewProjectDialogBackend.cs @@ -380,6 +380,8 @@ namespace MonoDevelop.Ide.Projects var currentTemplate = templatesListStore.GetValue (iter, TemplateColumn) as SolutionTemplate;
if (currentTemplate == template) {
templatesTreeView.Selection.SelectIter (iter);
+ TreePath path = templatesListStore.GetPath (iter);
+ templatesTreeView.ScrollToCell (path, null, true, 1, 0);
break;
}
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs index 55f54d1c3e..ed5388bc5a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/GtkTemplateCellRenderer.cs @@ -32,6 +32,7 @@ using Gtk; using MonoDevelop.Components;
using MonoDevelop.Core;
using MonoDevelop.Ide.Templates;
+using Mono.TextEditor;
namespace MonoDevelop.Ide.Projects
{
@@ -118,7 +119,8 @@ namespace MonoDevelop.Ide.Projects SetMarkup (layout, GetSelectedLanguage ());
layout.GetPixelSize (out textWidth, out textHeight);
- languageRect = GetLanguageButtonRectangle (window, widget, cell_area, textHeight, textWidth);
+ double scale = GtkWorkarounds.GetPixelScale ();
+ languageRect = GetLanguageButtonRectangle (window, widget, cell_area, textHeight, textWidth, scale);
DrawTemplateNameText (window, widget, cell_area, iconRect, languageRect, flags);
@@ -126,7 +128,7 @@ namespace MonoDevelop.Ide.Projects SetSourceColor (ctx, LanguageButtonBackgroundColor.ToCairoColor ());
ctx.Fill ();
- int languageTextX = languageRect.X + languageLeftHandPadding;
+ int languageTextX = languageRect.X + GetLanguageLeftHandPadding (scale);
if (!TemplateHasMultipleLanguages ()) {
languageTextX = languageRect.X + (languageRect.Width - textWidth) / 2;
}
@@ -135,14 +137,30 @@ namespace MonoDevelop.Ide.Projects window.DrawLayout (widget.Style.TextGC (StateType.Normal), languageTextX, languageTextY, layout);
if (TemplateHasMultipleLanguages ()) {
- int triangleX = languageTextX + textWidth + languageRightHandPadding;
- int triangleY = languageRect.Y + (languageRect.Height - dropdownTriangleHeight) / 2;
- DrawTriangle (ctx, triangleX, triangleY);
+ int triangleX = languageTextX + textWidth + GetLanguageRightHandPadding (scale);
+ int triangleY = languageRect.Y + (languageRect.Height - ((int)(scale * dropdownTriangleHeight))) / 2;
+ DrawTriangle (ctx, triangleX, triangleY, scale);
}
}
}
}
+ int GetLanguageLeftHandPadding (double scale)
+ {
+ if (Platform.IsWindows && scale > 1.0) {
+ return (int)(scale * (languageLeftHandPadding + 3));
+ }
+ return languageLeftHandPadding;
+ }
+
+ int GetLanguageRightHandPadding (double scale)
+ {
+ if (Platform.IsWindows && scale > 1.0) {
+ return (int)(scale * languageRightHandPadding);
+ }
+ return languageRightHandPadding;
+ }
+
void DrawTemplateCategoryText (Drawable window, Widget widget, Rectangle cell_area, CellRendererState flags)
{
StateType state = GetState (widget, flags);
@@ -233,7 +251,7 @@ namespace MonoDevelop.Ide.Projects layout.SetMarkup (markup);
}
- Rectangle GetLanguageButtonRectangle (Drawable window, Widget widget, Rectangle cell_area, int textHeight, int textWidth)
+ Rectangle GetLanguageButtonRectangle (Drawable window, Widget widget, Rectangle cell_area, int textHeight, int textWidth, double scale)
{
int languageRectangleHeight = cell_area.Height - 8;
int languageRectangleWidth = textWidth + languageLeftHandPadding;
@@ -244,6 +262,8 @@ namespace MonoDevelop.Ide.Projects languageRectangleWidth = Math.Max (languageRectangleWidth, minLanguageRectWidth);
}
+ languageRectangleWidth = (int)(scale * languageRectangleWidth);
+
var dy = (cell_area.Height - languageRectangleHeight) / 2 - 1;
var y = cell_area.Y + dy;
var x = widget.Allocation.Width - languageRectangleWidth - (int)Xpad;
@@ -256,12 +276,15 @@ namespace MonoDevelop.Ide.Projects return Template.AvailableLanguages.Count > 1;
}
- void DrawTriangle (Cairo.Context ctx, int x, int y)
+ void DrawTriangle (Cairo.Context ctx, int x, int y, double scale)
{
+ int width = (int)(scale * dropdownTriangleWidth);
+ int height = (int)(scale * dropdownTriangleHeight);
+
SetSourceColor (ctx, triangleColor.ToCairoColor ());
ctx.MoveTo (x, y);
- ctx.LineTo (x + dropdownTriangleWidth, y);
- ctx.LineTo (x + (dropdownTriangleWidth / 2), y + dropdownTriangleHeight);
+ ctx.LineTo (x + width, y);
+ ctx.LineTo (x + (width / 2), y + height);
ctx.LineTo (x, y);
ctx.Fill ();
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs index 7bbb3a8fd8..4dafab5fa9 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Projects/NewProjectController.cs @@ -57,7 +57,10 @@ namespace MonoDevelop.Ide.Projects const string CreateGitIgnoreFilePropertyName = "Dialogs.NewProjectDialog.CreateGitIgnoreFile";
const string CreateProjectSubDirectoryPropertyName = "MonoDevelop.Core.Gui.Dialogs.NewProjectDialog.AutoCreateProjectSubdir";
const string CreateProjectSubDirectoryInExistingSolutionPropertyName = "Dialogs.NewProjectDialog.AutoCreateProjectSubdirInExistingSolution";
- const string LastSelectedCategoryPropertyName = "Dialogs.NewProjectDialog.LastSelectedCategoryPath";
+ const string NewSolutionLastSelectedCategoryPropertyName = "Dialogs.NewProjectDialog.LastSelectedCategoryPath";
+ const string NewSolutionLastSelectedTemplatePropertyName = "Dialogs.NewProjectDialog.LastSelectedTemplate";
+ const string NewProjectLastSelectedCategoryPropertyName = "Dialogs.NewProjectDialog.AddNewProjectLastSelectedCategoryPath";
+ const string NewProjectLastSelectedTemplatePropertyName = "Dialogs.NewProjectDialog.AddNewProjectLastSelectedTemplate";
const string SelectedLanguagePropertyName = "Dialogs.NewProjectDialog.SelectedLanguage";
List<TemplateCategory> templateCategories;
@@ -90,13 +93,56 @@ namespace MonoDevelop.Ide.Projects string DefaultSelectedCategoryPath {
get {
- return PropertyService.Get<string> (LastSelectedCategoryPropertyName, null);
+ return GetDefaultPropertyValue (NewProjectLastSelectedCategoryPropertyName,
+ NewSolutionLastSelectedCategoryPropertyName);
}
set {
- PropertyService.Set (LastSelectedCategoryPropertyName, value);
+ SetDefaultPropertyValue (NewProjectLastSelectedCategoryPropertyName,
+ NewSolutionLastSelectedCategoryPropertyName,
+ value);
}
}
+ string DefaultSelectedTemplate {
+ get {
+ return GetDefaultPropertyValue (NewProjectLastSelectedTemplatePropertyName,
+ NewSolutionLastSelectedTemplatePropertyName);
+ }
+ set {
+ SetDefaultPropertyValue (NewProjectLastSelectedTemplatePropertyName,
+ NewSolutionLastSelectedTemplatePropertyName,
+ value);
+ }
+ }
+
+ string GetDefaultPropertyValue (string newProjectPropertyName, string newSolutionPropertyName)
+ {
+ if (!IsNewSolution) {
+ string propertyValue = PropertyService.Get<string> (newProjectPropertyName, null);
+ if (!string.IsNullOrEmpty (propertyValue))
+ return propertyValue;
+ }
+ return PropertyService.Get<string> (newSolutionPropertyName, null);
+ }
+
+ void SetDefaultPropertyValue (string newProjectPropertyName, string newSolutionPropertyName, string value)
+ {
+ SolutionTemplateVisibility visibility = GetSelectedTemplateVisibility ();
+ if (IsNewSolution || visibility != SolutionTemplateVisibility.NewProject) {
+ PropertyService.Set (newSolutionPropertyName, value);
+ PropertyService.Set (newProjectPropertyName, null);
+ } else if (visibility == SolutionTemplateVisibility.NewProject) {
+ PropertyService.Set (newProjectPropertyName, value);
+ }
+ }
+
+ SolutionTemplateVisibility GetSelectedTemplateVisibility ()
+ {
+ if (SelectedTemplate != null)
+ return SelectedTemplate.Visibility;
+ return SolutionTemplateVisibility.All;
+ }
+
public bool IsNewSolution {
get { return projectConfiguration.CreateSolution; }
}
@@ -162,8 +208,9 @@ namespace MonoDevelop.Ide.Projects {
UpdateDefaultGitSettings ();
UpdateDefaultCreateProjectDirectorySetting ();
- PropertyService.Set (SelectedLanguagePropertyName, SelectedLanguage);
+ PropertyService.Set (SelectedLanguagePropertyName, GetLanguageForTemplateProcessing ());
DefaultSelectedCategoryPath = GetSelectedCategoryPath ();
+ DefaultSelectedTemplate = GetDefaultSelectedTemplateId ();
}
string GetSelectedCategoryPath ()
@@ -184,6 +231,14 @@ namespace MonoDevelop.Ide.Projects return null;
}
+ string GetDefaultSelectedTemplateId ()
+ {
+ if (SelectedTemplate != null) {
+ return SelectedTemplate.Id;
+ }
+ return null;
+ }
+
void UpdateDefaultCreateProjectDirectorySetting ()
{
if (IsNewSolution) {
@@ -272,7 +327,13 @@ namespace MonoDevelop.Ide.Projects if (SelectedTemplateId != null) {
SelectTemplate (SelectedTemplateId);
} else if (DefaultSelectedCategoryPath != null) {
- SelectFirstTemplateInCategory (DefaultSelectedCategoryPath);
+ if (DefaultSelectedTemplate != null) {
+ SelectTemplateInCategory (DefaultSelectedCategoryPath, DefaultSelectedTemplate);
+ }
+
+ if (SelectedTemplate == null) {
+ SelectFirstTemplateInCategory (DefaultSelectedCategoryPath);
+ }
}
if (SelectedSecondLevelCategory == null) {
@@ -292,6 +353,18 @@ namespace MonoDevelop.Ide.Projects void SelectFirstTemplateInCategory (string categoryPath)
{
+ SelectTemplateInCategory (categoryPath, template => true);
+ }
+
+ void SelectTemplateInCategory (string categoryPath, string templateId)
+ {
+ SelectTemplateInCategory (categoryPath, parentTemplate => {
+ return parentTemplate.GetTemplate (template => template.Id == templateId) != null;
+ });
+ }
+
+ void SelectTemplateInCategory (string categoryPath, Func<SolutionTemplate, bool> isTemplateMatch)
+ {
List<string> parts = new TemplateCategoryPath (categoryPath).GetParts ().ToList ();
if (parts.Count < 2) {
return;
@@ -300,7 +373,7 @@ namespace MonoDevelop.Ide.Projects string topLevelCategoryId = parts [0];
string secondLevelCategoryId = parts [1];
SelectTemplate (
- template => true,
+ isTemplateMatch,
category => category.Id == topLevelCategoryId,
category => category.Id == secondLevelCategoryId);
}
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs index cb0e0ebf53..1742eb86ec 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Templates/ProjectTemplateCategorizer.cs @@ -37,6 +37,7 @@ namespace MonoDevelop.Ide.Templates TemplateCategory defaultCategory;
Dictionary<string, TemplateCategory> mappedCategories = new Dictionary<string, TemplateCategory> ();
Predicate<SolutionTemplate> templateMatch;
+ bool removedEmptyCategories;
public static readonly Predicate<SolutionTemplate> MatchNewProjectTemplates = template => template.IsMatch (SolutionTemplateVisibility.NewProject);
public static readonly Predicate<SolutionTemplate> MatchNewSolutionTemplates = template => template.IsMatch (SolutionTemplateVisibility.NewSolution);
@@ -86,6 +87,11 @@ namespace MonoDevelop.Ide.Templates public IEnumerable<TemplateCategory> GetCategorizedTemplates ()
{
+ if (!removedEmptyCategories) {
+ RemoveEmptyCategories ();
+ removedEmptyCategories = true;
+ }
+
return categories;
}
@@ -99,7 +105,6 @@ namespace MonoDevelop.Ide.Templates LogNoCategoryMatch (template);
}
}
- RemoveEmptyCategories ();
}
IEnumerable<SolutionTemplate> GetFilteredTemplates (IEnumerable<SolutionTemplate> templates)
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs index 4c857af7d9..42d8e0116f 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/CodeGenerationService.cs @@ -115,7 +115,7 @@ namespace MonoDevelop.Ide.TypeSystem var tcs = new TaskCompletionSource<bool>(); if (parentType == null) return tcs.Task; - part = part ?? parentType.Parts.FirstOrDefault (); + part = part ?? FindCurrentPart (parentType); if (part == null) return tcs.Task; var loadedDocument = IdeApp.Workbench.OpenDocument (part.Region.FileName); @@ -160,7 +160,24 @@ namespace MonoDevelop.Ide.TypeSystem return tcs.Task; } - + + public static IUnresolvedTypeDefinition FindCurrentPart (ITypeDefinition type) + { + var active = IdeApp.Workbench.ActiveDocument; + if (active != null) { + var partsInFile = type.Parts.Where (p => p.Region.FileName == active.FileName).ToList (); + + foreach (var p in partsInFile) { + if (p.Region.Contains (active.Editor.Caret.Location)) + return p; + } + if (partsInFile.Count > 0) + return partsInFile[0]; + } + + return type.Parts.FirstOrDefault (); + } + public static Task<bool> InsertMember ( ITypeDefinition parentType, IUnresolvedTypeDefinition part, IUnresolvedMember newMember, bool implementExplicit = false) @@ -168,7 +185,7 @@ namespace MonoDevelop.Ide.TypeSystem var tcs = new TaskCompletionSource<bool>(); if (parentType == null) return tcs.Task; - part = part ?? parentType.Parts.FirstOrDefault (); + part = part ?? FindCurrentPart (parentType); if (part == null) return tcs.Task; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs index 62b696292b..d1cc52adfc 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.TypeSystem/TypeSystemService.cs @@ -160,7 +160,7 @@ namespace MonoDevelop.Ide.TypeSystem public static class TypeSystemService { - const string CurrentVersion = "1.1.8"; + const string CurrentVersion = "1.1.9"; static readonly List<TypeSystemParserNode> parsers; static string[] filesSkippedInParseThread = new string[0]; @@ -674,6 +674,11 @@ namespace MonoDevelop.Ide.TypeSystem throw new Exception ("Too many cache directories"); } + static string EscapeToXml (string txt) + { + return new System.Xml.Linq.XText (txt).ToString (); + } + static string CreateCacheDirectory (FilePath fileName) { CanonicalizePath (ref fileName); @@ -685,7 +690,7 @@ namespace MonoDevelop.Ide.TypeSystem File.WriteAllText ( Path.Combine (cacheDir, "data.xml"), - string.Format ("<DerivedData><File name=\"{0}\" version =\"{1}\"/></DerivedData>", fileName, CurrentVersion) + string.Format ("<DerivedData><File name=\"{0}\" version =\"{1}\"/></DerivedData>", EscapeToXml (fileName), CurrentVersion) ); return cacheDir; @@ -1129,10 +1134,11 @@ namespace MonoDevelop.Ide.TypeSystem public bool WasChanged; [NonSerialized] ICompilation compilation; + object compilationContentLock = new object (); public ICompilation Compilation { get { - lock (updateContentLock) { + lock (compilationContentLock) { if (compilation == null) { compilation = Content.CreateCompilation (); } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj index ce400427d9..20a2a4b437 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.csproj @@ -31,14 +31,14 @@ <Optimize>True</Optimize> <OutputPath>..\..\..\build\bin</OutputPath> <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> + <WarningLevel>3</WarningLevel> <Execution> <Execution clr-version="Net_2_0" /> </Execution> <AllowUnsafeBlocks>True</AllowUnsafeBlocks> <DebugSymbols>true</DebugSymbols> <NoWarn>1591;1573</NoWarn> - <DocumentationFile>..\..\..\build\AddIns\MonoDevelop.Ide.xml</DocumentationFile> + <DocumentationFile>..\..\..\build\bin\MonoDevelop.Ide.xml</DocumentationFile> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMac|AnyCPU' "> <DebugSymbols>true</DebugSymbols> @@ -62,8 +62,38 @@ <OutputPath>..\..\..\build\bin</OutputPath> <DefineConstants>MAC</DefineConstants> <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <DocumentationFile>..\..\..\build\AddIns\MonoDevelop.Ide.xml</DocumentationFile> + <WarningLevel>3</WarningLevel> + <DocumentationFile>..\..\..\build\bin\MonoDevelop.Ide.xml</DocumentationFile> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + <NoWarn>1591;1573</NoWarn> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugWin32|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>..\..\..\build\bin</OutputPath> + <DefineConstants>DEBUG,WIN32</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>3</WarningLevel> + <DocumentationFile>..\..\..\build\bin\MonoDevelop.Ide.xml</DocumentationFile> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <NoWarn>1591;1573</NoWarn> + <Execution> + <Execution clr-version="Net_2_0" /> + </Execution> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseWin32|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>..\..\..\build\bin</OutputPath> + <DefineConstants>WIN32</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>3</WarningLevel> + <DocumentationFile>..\..\..\build\bin\MonoDevelop.Ide.xml</DocumentationFile> <AllowUnsafeBlocks>true</AllowUnsafeBlocks> <Execution> <Execution clr-version="Net_2_0" /> @@ -104,6 +134,11 @@ <Reference Include="Xamarin.Mac" Condition=" '$(Configuration)' == 'DebugMac' Or '$(Configuration)' == 'ReleaseMac' "> <HintPath>..\..\..\external\Xamarin.Mac.dll</HintPath> </Reference> + <Reference Include="System.Windows" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="PresentationCore" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="PresentationFramework" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="WindowsBase" Condition=" '$(Configuration)' == 'DebugWin32' Or '$(Configuration)' == 'ReleaseWin32' " /> + <Reference Include="System.Xaml" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MonoDevelop.Core\MonoDevelop.Core.csproj"> @@ -3379,6 +3414,9 @@ <Compile Include="MonoDevelop.Components.AutoTest\PropertyMetadata.cs" /> <Compile Include="MonoDevelop.Components.AutoTest\ObjectProperties.cs" /> <Compile Include="MonoDevelop.Ide.Templates\TemplateConditionEvaluator.cs" /> + <Compile Include="MonoDevelop.Components.AutoTest.Operations\SelectedOperation.cs" /> + <Compile Include="MonoDevelop.Components\Windows\GtkWPFWidget.cs" /> + <Compile Include="MonoDevelop.Components\Windows\GtkWin32Interop.cs" /> </ItemGroup> <ItemGroup> <None Include="Makefile.am" /> @@ -3423,6 +3461,7 @@ <Folder Include="MonoDevelop.Ide.TextEditing\" /> <Folder Include="MonoDevelop.Components.DockNotebook\" /> <Folder Include="icons\mac\" /> + <Folder Include="MonoDevelop.Components\Windows\" /> </ItemGroup> <ItemGroup> <Content Include="gtkrc.win32"> diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs index 362998e7e6..3a0224a252 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/Ide.cs @@ -295,6 +295,8 @@ namespace MonoDevelop.Ide }; AutoTestService.Start (commandService, Preferences.EnableAutomatedTesting); AutoTestService.NotifyEvent ("MonoDevelop.Ide.IdeStart"); + + Gtk.LinkButton.SetUriHook ((button, uri) => Xwt.Desktop.OpenUrl (uri)); } static void KeyBindingFailed (object sender, KeyBindingFailedEventArgs e) diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs index 9aaca48201..9231b18f8a 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/IdeStartup.cs @@ -219,7 +219,13 @@ namespace MonoDevelop.Ide Counters.Initialization.Trace ("Loading Icons"); //force initialisation before the workbench so that it can register stock icons for GTK before they get requested ImageService.Initialize (); - + + // If we display an error dialog before the main workbench window on OS X then a second application menu is created + // which is then replaced with a second empty Apple menu. + // XBC #33699 + Counters.Initialization.Trace ("Initializing IdeApp"); + IdeApp.Initialize (monitor); + if (errorsList.Count > 0) { using (AddinLoadErrorDialog dlg = new AddinLoadErrorDialog ((AddinError[]) errorsList.ToArray (typeof(AddinError)), false)) { if (!dlg.Run ()) @@ -234,9 +240,6 @@ namespace MonoDevelop.Ide // no alternative for Application.ThreadException? // Application.ThreadException += new ThreadExceptionEventHandler(ShowErrorBox); - Counters.Initialization.Trace ("Initializing IdeApp"); - IdeApp.Initialize (monitor); - // Load requested files Counters.Initialization.Trace ("Opening Files"); @@ -356,7 +359,10 @@ namespace MonoDevelop.Ide gtkrc += "-yosemite"; } } - Environment.SetEnvironmentVariable ("GTK2_RC_FILES", PropertyService.EntryAssemblyPath.Combine (gtkrc)); + + var gtkrcf = PropertyService.EntryAssemblyPath.Combine (gtkrc); + LoggingService.LogInfo ("GTK: Using gtkrc from {0}", gtkrcf); + Environment.SetEnvironmentVariable ("GTK2_RC_FILES", gtkrcf); } } @@ -731,6 +737,10 @@ namespace MonoDevelop.Ide Console.WriteLine (BrandingService.ApplicationName + " " + BuildInfo.VersionLabel); Console.WriteLine ("Options:"); optSet.WriteOptionDescriptions (Console.Out); + const string openFileText = " file.ext;line;column"; + Console.Write (openFileText); + Console.Write (new string (' ', 29 - openFileText.Length)); + Console.WriteLine ("Opens a file at specified integer line and column"); } return opt; diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs index 7956e16a54..748fcccdcd 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/ProjectOperations.cs @@ -53,6 +53,7 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; using System.Text; using MonoDevelop.Ide.TypeSystem; using ICSharpCode.NRefactory.TypeSystem; +using MonoDevelop.Components.Extensions; namespace MonoDevelop.Ide { @@ -622,6 +623,9 @@ namespace MonoDevelop.Ide public void NewSolution (string defaultTemplate) { + if (!IdeApp.Workbench.SaveAllDirtyFiles ()) + return; + var newProjectDialog = new NewProjectDialogController (); newProjectDialog.OpenSolution = true; newProjectDialog.SelectedTemplateId = defaultTemplate; @@ -653,7 +657,7 @@ namespace MonoDevelop.Ide WorkspaceItem res = null; var dlg = new SelectFileDialog () { - Action = Gtk.FileChooserAction.Open, + Action = SelectFileDialogAction.Open, CurrentFolder = parentWorkspace.BaseDirectory, SelectMultiple = false, }; @@ -716,7 +720,7 @@ namespace MonoDevelop.Ide SolutionItem res = null; var dlg = new SelectFileDialog () { - Action = Gtk.FileChooserAction.Open, + Action = SelectFileDialogAction.Open, CurrentFolder = parentFolder.BaseDirectory, SelectMultiple = false, }; @@ -1621,7 +1625,7 @@ namespace MonoDevelop.Ide { var dlg = new SelectFileDialog () { SelectMultiple = true, - Action = Gtk.FileChooserAction.Open, + Action = SelectFileDialogAction.Open, CurrentFolder = folder.BaseDirectory, TransientFor = MessageService.RootWindow, }; @@ -1798,7 +1802,9 @@ namespace MonoDevelop.Ide try { if (!dialogShown || !applyToAll) { - if (MessageService.RunCustomDialog (addExternalDialog) == (int) Gtk.ResponseType.Cancel) { + int response = MessageService.RunCustomDialog (addExternalDialog); + // A dialog emits DeleteEvent rather than Cancel in response to Escape being pressed + if (response == (int) Gtk.ResponseType.Cancel || response == (int) Gtk.ResponseType.DeleteEvent) { project.Files.AddRange (newFileList.Where (f => f != null)); return newFileList; } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs index 7f63bb7925..c18aa74bb2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide/RootWorkspace.cs @@ -52,7 +52,6 @@ namespace MonoDevelop.Ide // IParserDatabase parserDatabase; string activeConfiguration; bool useDefaultRuntime; - string preferredActiveExecutionTarget; ProjectFileEventHandler fileAddedToProjectHandler; ProjectFileEventHandler fileRemovedFromProjectHandler; @@ -153,11 +152,6 @@ namespace MonoDevelop.Ide ActiveExecutionTargetChanged (this, EventArgs.Empty); } - internal string PreferredActiveExecutionTarget { - get { return ActiveExecutionTarget != null ? ActiveExecutionTarget.Id : preferredActiveExecutionTarget; } - set { preferredActiveExecutionTarget = value; } - } - public ConfigurationSelector ActiveConfiguration { get { return new SolutionConfigurationSelector (activeConfiguration); } } @@ -693,7 +687,6 @@ namespace MonoDevelop.Ide try { WorkspaceUserData data = item.UserProperties.GetValue<WorkspaceUserData> ("MonoDevelop.Ide.Workspace"); if (data != null) { - PreferredActiveExecutionTarget = data.PreferredExecutionTarget; ActiveExecutionTarget = null; if (GetConfigurations ().Contains (data.ActiveConfiguration)) @@ -762,8 +755,6 @@ namespace MonoDevelop.Ide WorkspaceUserData data = new WorkspaceUserData (); data.ActiveConfiguration = ActiveConfigurationId; data.ActiveRuntime = UseDefaultRuntime ? null : ActiveRuntime.Id; - if (ActiveExecutionTarget != null) - data.PreferredExecutionTarget = ActiveExecutionTarget.Id; item.UserProperties.SetValue ("MonoDevelop.Ide.Workspace", data); // Allow add-ins to fill-up data @@ -1497,8 +1488,6 @@ namespace MonoDevelop.Ide public string ActiveConfiguration; [ItemProperty] public string ActiveRuntime; - [ItemProperty] - public string PreferredExecutionTarget; } public class ItemUnloadingEventArgs: EventArgs |