diff options
Diffstat (limited to 'main/src/addins')
72 files changed, 6036 insertions, 3279 deletions
diff --git a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs index a4b6937b34..b34a637c1f 100644 --- a/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs +++ b/main/src/addins/MonoDevelop.AssemblyBrowser/MonoDevelop.AssemblyBrowser/AssemblyBrowserWidget.cs @@ -917,31 +917,36 @@ namespace MonoDevelop.AssemblyBrowser internal void Open (string url, AssemblyLoader currentAssembly = null, bool expandNode = true) { - Task.WhenAll (this.definitions.Select (d => d.LoadingTask)).ContinueWith (d => { - // At least one of them failed. - if (d.IsFaulted) { - LoggingService.LogError ("Failed to load assemblies", d.Exception); - - // It's possible the assembly in which the type we're looking for exists - // so try probing for it regardless. - } + try { + Task.WhenAll (this.definitions.Select (d => d.LoadingTask)).ContinueWith (d => { + // At least one of them failed. + if (d.IsFaulted) { + LoggingService.LogError ("Failed to load assemblies", d.Exception); + + // It's possible the assembly in which the type we're looking for exists + // so try probing for it regardless. + } - suspendNavigation = false; - ITreeNavigator nav = SearchMember (url, expandNode); - if (definitions.Count == 0) // we've been disposed - return; - if (nav != null) - return; - try { - if (currentAssembly != null) { - OpenFromAssembly (url, currentAssembly); - } else { - OpenFromAssemblyNames (url); + suspendNavigation = false; + ITreeNavigator nav = SearchMember (url, expandNode); + if (definitions.Count == 0) // we've been disposed + return; + if (nav != null) + return; + try { + if (currentAssembly != null) { + OpenFromAssembly (url, currentAssembly); + } else { + OpenFromAssemblyNames (url); + } + } catch (Exception e) { + LoggingService.LogError ("Error while opening the assembly browser with id:" + url, e); } - } catch (Exception e) { - LoggingService.LogError ("Error while opening the assembly browser with id:" + url, e); - } - }, Runtime.MainTaskScheduler).Ignore (); + }, Runtime.MainTaskScheduler).Ignore (); + } catch (Exception e) { + LoggingService.LogError ("Error while opening assembly :" + url); + MessageService.ShowError (GettextCatalog.GetString ("Error while opening assembly {0}.", url), e); + } } void OpenFromAssembly (string url, AssemblyLoader currentAssembly, bool expandNode = true) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/BreakpointsAndSteppingTests.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/BreakpointsAndSteppingTests.cs new file mode 100644 index 0000000000..8966cc23c5 --- /dev/null +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/BreakpointsAndSteppingTests.cs @@ -0,0 +1,86 @@ +// +// BreakpointStoreTests.cs +// +// Author: +// Greg Munn <gregm@microsoft.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. +using System; +using NUnit.Framework; +using Mono.Debugging.Client; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Mono.Debugging.Tests +{ + [TestFixture] + public class BreakpointStoreTests + { + + [Test] + public async Task WhenStoreModifiedExternallyThenIteratingOverBreakpointsShouldNotThrow () + { + var store = new BreakpointStore (); + + Action<int> threadAddAction = (x) => { + store.Add (new Breakpoint ($"fileName{x}.cs", 10)); + }; + + Action threadEnumerateAction = () => { + foreach (var bk in store.GetBreakpointsAtFile ("fileName1.cs")) { + } + }; + + List<Task> tasks = new List<Task> (); + + for (int i = 0; i < 10; i++) { + tasks.Add (Task.Run (() => { + threadAddAction (i); + })); + + tasks.Add (Task.Run (() => { + threadEnumerateAction (); + })); + } + + foreach (var task in tasks) { + await task; + } + } + + [Test] + public void GetBreakpointsAtFileReturnsCorrectFiles () + { + var store = new BreakpointStore (); + + store.Add (new Breakpoint ("fileName1.cs", 10)); + store.Add (new Breakpoint ("fileName1.cs", 20)); + store.Add (new Breakpoint ("fileName2.cs", 10)); + store.Add (new Breakpoint ("fileName3.cs", 15)); + + int count = 0; + foreach (var bk in store.GetBreakpointsAtFile ("fileName1.cs")) { + count++; + Assert.AreEqual ("fileName1.cs", bk.FileName); + } + + Assert.AreEqual (2, count); + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj index 75a26167f2..6007317a64 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.Tests/MonoDevelop.Debugger.Tests.csproj @@ -22,6 +22,7 @@ <Compile Include="DebugTests.MonoDevelop.cs" /> <Compile Include="TextFile.cs" /> <Compile Include="VsCodeStackFrameTests.cs" /> + <Compile Include="BreakpointsAndSteppingTests.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MonoDevelop.Debugger.csproj"> diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs index 9e7aff8e03..4b307559c2 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger.VSTextView/BreakpointManager.cs @@ -68,13 +68,11 @@ namespace MonoDevelop.Debugger var bps = new List<Breakpoint> (); var needsUpdate = false; - lock (breakpointStore) { - foreach (var breakpoint in breakpointStore.GetBreakpointsAtFile (textDocument.FilePath)) { - if (breakpoint.Line > snapshot.LineCount) - continue; + foreach (var breakpoint in breakpointStore.GetBreakpointsAtFile (textDocument.FilePath)) { + if (breakpoint.Line > snapshot.LineCount) + continue; - bps.Add (breakpoint); - } + bps.Add (breakpoint); } foreach (var breakpoint in bps) { @@ -82,7 +80,7 @@ namespace MonoDevelop.Debugger needsUpdate = true; var line = snapshot.GetLineFromLineNumber (breakpoint.Line - 1); - var position = line.Start.Position + breakpoint.Column; + var position = line.Start.Position + breakpoint.Column - 1; var span = await DebuggingService.GetBreakpointSpanAsync (textDocument, position); if (breakpoints.TryGetValue (breakpoint, out var existingBreakpoint)) { diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs index 40b79833c5..121c4f12fd 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/BreakpointPad.cs @@ -292,8 +292,7 @@ namespace MonoDevelop.Debugger continue; var bp = (BreakEvent) store.GetValue (iter, (int) Columns.Breakpoint); - lock (breakpoints) - breakpoints.Remove (bp); + breakpoints.Remove (bp); deleted = true; } } finally { @@ -421,32 +420,30 @@ namespace MonoDevelop.Debugger store.Clear (); if (breakpoints != null) { - lock (breakpoints) { - foreach (BreakEvent be in breakpoints) { - if (be.NonUserBreakpoint) - continue; - - string hitCount = be.HitCountMode != HitCountMode.None ? be.CurrentHitCount.ToString () : ""; - string traceExp = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.TraceExpression : ""; - string traceVal = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.LastTraceValue : ""; - string name, condition = null; - - if (be is FunctionBreakpoint fb) { - if (fb.ParamTypes != null) - name = fb.FunctionName + "(" + string.Join (", ", fb.ParamTypes) + ")"; - else - name = fb.FunctionName; - } else if (be is Breakpoint bp) { - name = string.Format ("{0}:{1},{2}", bp.FileName, bp.Line, bp.Column); - condition = bp.ConditionExpression; - } else if (be is Catchpoint cp) { - name = cp.ExceptionName; - } else { - name = ""; - } - - store.AppendValues (GetIconId (be), be.Enabled, name, be, condition, traceExp, hitCount, traceVal); + foreach (BreakEvent be in breakpoints) { + if (be.NonUserBreakpoint) + continue; + + string hitCount = be.HitCountMode != HitCountMode.None ? be.CurrentHitCount.ToString () : ""; + string traceExp = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.TraceExpression : ""; + string traceVal = (be.HitAction & HitAction.PrintExpression) != HitAction.None ? be.LastTraceValue : ""; + string name, condition = null; + + if (be is FunctionBreakpoint fb) { + if (fb.ParamTypes != null) + name = fb.FunctionName + "(" + string.Join (", ", fb.ParamTypes) + ")"; + else + name = fb.FunctionName; + } else if (be is Breakpoint bp) { + name = string.Format ("{0}:{1},{2}", bp.FileName, bp.Line, bp.Column); + condition = bp.ConditionExpression; + } else if (be is Catchpoint cp) { + name = cp.ExceptionName; + } else { + name = ""; } + + store.AppendValues (GetIconId (be), be.Enabled, name, be, condition, traceExp, hitCount, traceVal); } } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs index 4b0b795f29..8f519906e9 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebugCommands.cs @@ -322,22 +322,20 @@ namespace MonoDevelop.Debugger { var breakpoints = DebuggingService.Breakpoints; - lock (breakpoints) { - if (!breakpoints.IsReadOnly) { - foreach (var be in breakpoints) { - if (be is Breakpoint bp) { - if (!bp.NonUserBreakpoint) { - info.Enabled = true; - break; - } - } else { + if (!breakpoints.IsReadOnly) { + foreach (var be in breakpoints) { + if (be is Breakpoint bp) { + if (!bp.NonUserBreakpoint) { info.Enabled = true; break; } + } else { + info.Enabled = true; + break; } - } else { - info.Enabled = false; } + } else { + info.Enabled = false; } info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Breakpoints); @@ -355,8 +353,7 @@ namespace MonoDevelop.Debugger var (caretLine, caretColumn) = textView.MDCaretLineAndColumn (); var point = textView.Caret.Position.BufferPosition; - lock (breakpoints) - bp = breakpoints.Toggle (IdeApp.Workbench.ActiveDocument.FileName, caretLine, caretColumn); + bp = breakpoints.Toggle (IdeApp.Workbench.ActiveDocument.FileName, caretLine, caretColumn); // If the breakpoint could not be inserted in the caret location, move the caret // to the real line of the breakpoint, so that if the Toggle command is run again, @@ -381,10 +378,8 @@ namespace MonoDevelop.Debugger { var breakpoints = DebuggingService.Breakpoints; - lock (breakpoints) { - foreach (var bp in breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ())) - bp.Enabled = !bp.Enabled; - } + foreach (var bp in breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ())) + bp.Enabled = !bp.Enabled; } protected override void Update (CommandInfo info) @@ -396,15 +391,13 @@ namespace MonoDevelop.Debugger IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true) != null && IdeApp.Workbench.ActiveDocument.FileName != FilePath.Null && !breakpoints.IsReadOnly) { - lock (breakpoints) { - var bpInLine = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine()); - info.Enabled = bpInLine.Count > 0; - info.Text = GettextCatalog.GetString ("Disable Breakpoint"); - foreach (var bp in bpInLine) { - if (!bp.Enabled) - info.Text = GettextCatalog.GetString ("Enable Breakpoint"); - break; - } + var bpInLine = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine()); + info.Enabled = bpInLine.Count > 0; + info.Text = GettextCatalog.GetString ("Disable Breakpoint"); + foreach (var bp in bpInLine) { + if (!bp.Enabled) + info.Text = GettextCatalog.GetString ("Enable Breakpoint"); + break; } } else { info.Enabled = false; @@ -416,20 +409,18 @@ namespace MonoDevelop.Debugger { protected override void Run () { - var breakpoints = DebuggingService.Breakpoints; + var breakpoints = DebuggingService.Breakpoints.ToList(); bool enable = false; - lock (breakpoints) { - foreach (BreakEvent bp in breakpoints) { - if (!bp.Enabled) { - enable = true; - break; - } + foreach (BreakEvent bp in breakpoints) { + if (!bp.Enabled) { + enable = true; + break; } + } - foreach (BreakEvent bp in breakpoints) { - bp.Enabled = enable; - } + foreach (BreakEvent bp in breakpoints) { + bp.Enabled = enable; } } @@ -437,20 +428,19 @@ namespace MonoDevelop.Debugger { var breakpoints = DebuggingService.Breakpoints; - lock (breakpoints) { - info.Enabled = !breakpoints.IsReadOnly && breakpoints.Count > 0; - bool enable = false; - foreach (BreakEvent bp in breakpoints) { - if (!bp.Enabled) { - enable = true; - break; - } + info.Enabled = !breakpoints.IsReadOnly && breakpoints.Count > 0; + bool enable = false; + foreach (BreakEvent bp in breakpoints) { + if (!bp.Enabled) { + enable = true; + break; } - if (enable) - info.Text = GettextCatalog.GetString ("Enable All Breakpoints"); - else - info.Text = GettextCatalog.GetString ("Disable All Breakpoints"); } + if (enable) + info.Text = GettextCatalog.GetString ("Enable All Breakpoints"); + else + info.Text = GettextCatalog.GetString ("Disable All Breakpoints"); + info.Visible = DebuggingService.IsFeatureSupported (DebuggerFeatures.Breakpoints); } } @@ -475,15 +465,13 @@ namespace MonoDevelop.Debugger { var breakpoints = DebuggingService.Breakpoints; - lock (breakpoints) { - IEnumerable<Breakpoint> brs = breakpoints.GetBreakpointsAtFileLine ( - IdeApp.Workbench.ActiveDocument.FileName, - IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()); + IEnumerable<Breakpoint> brs = breakpoints.GetBreakpointsAtFileLine ( + IdeApp.Workbench.ActiveDocument.FileName, + IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()); - List<Breakpoint> list = new List<Breakpoint> (brs); - foreach (Breakpoint bp in list) - breakpoints.Remove (bp); - } + List<Breakpoint> list = new List<Breakpoint> (brs); + foreach (Breakpoint bp in list) + breakpoints.Remove (bp); } protected override void Update (CommandInfo info) @@ -495,8 +483,7 @@ namespace MonoDevelop.Debugger IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true) != null && IdeApp.Workbench.ActiveDocument.FileName != FilePath.Null && !breakpoints.IsReadOnly) { - lock (breakpoints) - info.Enabled = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()).Count > 0; + info.Enabled = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()).Count > 0; } else { info.Enabled = false; } @@ -511,8 +498,7 @@ namespace MonoDevelop.Debugger if (DebuggingService.ShowBreakpointProperties (ref bp)) { var breakpoints = DebuggingService.Breakpoints; - lock (breakpoints) - breakpoints.Add (bp); + breakpoints.Add (bp); } } @@ -531,8 +517,7 @@ namespace MonoDevelop.Debugger if (DebuggingService.ShowBreakpointProperties (ref bp, BreakpointType.Function)) { var breakpoints = DebuggingService.Breakpoints; - lock (breakpoints) - breakpoints.Add (bp); + breakpoints.Add (bp); } } @@ -551,8 +536,7 @@ namespace MonoDevelop.Debugger if (DebuggingService.ShowBreakpointProperties (ref bp, BreakpointType.Catchpoint)) { var breakpoints = DebuggingService.Breakpoints; - lock (breakpoints) - breakpoints.Add (bp); + breakpoints.Add (bp); } } @@ -632,11 +616,9 @@ namespace MonoDevelop.Debugger var breakpoints = DebuggingService.Breakpoints; IList<Breakpoint> brs; - lock (breakpoints) { - brs = breakpoints.GetBreakpointsAtFileLine ( - IdeApp.Workbench.ActiveDocument.FileName, - IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()); - } + brs = breakpoints.GetBreakpointsAtFileLine ( + IdeApp.Workbench.ActiveDocument.FileName, + IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()); if (brs.Count > 0) { BreakEvent be = brs [0]; @@ -653,8 +635,7 @@ namespace MonoDevelop.Debugger IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true) != null && IdeApp.Workbench.ActiveDocument.FileName != FilePath.Null && !breakpoints.IsReadOnly) { - lock (breakpoints) - info.Enabled = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()).Count > 0; + info.Enabled = breakpoints.GetBreakpointsAtFileLine (IdeApp.Workbench.ActiveDocument.FileName, IdeApp.Workbench.ActiveDocument.GetContent<ITextView> (true).MDCaretLine ()).Count > 0; } else { info.Enabled = false; } diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs index 5ed2950d2e..e9139d5fa0 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/DebuggingService.cs @@ -186,12 +186,10 @@ namespace MonoDevelop.Debugger if (liveUpdate) { var bp = pinnedWatches.CreateLiveUpdateBreakpoint (watch); pinnedWatches.Bind (watch, bp); - lock (breakpoints) - breakpoints.Add(bp); + breakpoints.Add(bp); } else { pinnedWatches.Bind (watch, null); - lock (breakpoints) - breakpoints.Remove (watch.BoundTracer); + breakpoints.Remove (watch.BoundTracer); } } @@ -1347,26 +1345,24 @@ namespace MonoDevelop.Debugger static void OnLineCountChanged (object ob, LineCountEventArgs a) { - lock (breakpoints) { - foreach (var bp in breakpoints.GetBreakpoints ()) { - if (bp.FileName == a.TextFile.Name) { - if (bp.Line > a.LineNumber) { - var startIndex = a.TextFile.GetPositionFromLineColumn (bp.Line, bp.Column); - var endIndex = a.TextFile.GetPositionFromLineColumn (bp.Line + 1, 0) - 1; + foreach (var bp in breakpoints.GetBreakpoints ()) { + if (bp.FileName == a.TextFile.Name) { + if (bp.Line > a.LineNumber) { + var startIndex = a.TextFile.GetPositionFromLineColumn (bp.Line, bp.Column); + var endIndex = a.TextFile.GetPositionFromLineColumn (bp.Line + 1, 0) - 1; - if (endIndex < startIndex) - endIndex = startIndex; + if (endIndex < startIndex) + endIndex = startIndex; - var text = a.TextFile.GetText (startIndex, endIndex); + var text = a.TextFile.GetText (startIndex, endIndex); - // If the line that has the breakpoint is deleted, delete the breakpoint, otherwise update the line #. - if (bp.Line + a.LineCount >= a.LineNumber && !string.IsNullOrWhiteSpace (text)) - breakpoints.UpdateBreakpointLine (bp, bp.Line + a.LineCount); - else - breakpoints.Remove (bp); - } else if (bp.Line == a.LineNumber && a.LineCount < 0) + // If the line that has the breakpoint is deleted, delete the breakpoint, otherwise update the line #. + if (bp.Line + a.LineCount >= a.LineNumber && !string.IsNullOrWhiteSpace (text)) + breakpoints.UpdateBreakpointLine (bp, bp.Line + a.LineCount); + else breakpoints.Remove (bp); - } + } else if (bp.Line == a.LineNumber && a.LineCount < 0) + breakpoints.Remove (bp); } } } @@ -1374,8 +1370,7 @@ namespace MonoDevelop.Debugger static void OnStoreUserPrefs (object s, UserPreferencesEventArgs args) { var baseDir = (args.Item as Solution)?.BaseDirectory; - lock (breakpoints) - args.Properties.SetValue ("MonoDevelop.Ide.DebuggingService.Breakpoints", breakpoints.Save (baseDir)); + args.Properties.SetValue ("MonoDevelop.Ide.DebuggingService.Breakpoints", breakpoints.Save (baseDir)); args.Properties.SetValue ("MonoDevelop.Ide.DebuggingService.PinnedWatches", pinnedWatches); } @@ -1385,27 +1380,23 @@ namespace MonoDevelop.Debugger if (elem != null) { var baseDir = (args.Item as Solution)?.BaseDirectory; - lock (breakpoints) - breakpoints.Load (elem, baseDir); + breakpoints.Load (elem, baseDir); } PinnedWatchStore wstore = args.Properties.GetValue<PinnedWatchStore> ("MonoDevelop.Ide.DebuggingService.PinnedWatches"); if (wstore != null) pinnedWatches.LoadFrom (wstore); - lock (breakpoints) - pinnedWatches.BindAll (breakpoints); + pinnedWatches.BindAll (breakpoints); - lock (breakpoints) - pinnedWatches.SetAllLiveUpdateBreakpoints (breakpoints); + pinnedWatches.SetAllLiveUpdateBreakpoints (breakpoints); return Task.FromResult (true); } static void OnSolutionClosed (object s, EventArgs args) { - lock (breakpoints) - breakpoints.Clear (); + breakpoints.Clear (); } static Microsoft.CodeAnalysis.ISymbol GetLanguageItem (MonoDevelop.Ide.Gui.Document document, SourceLocation sourceLocation, string identifier) diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs index e65c855147..8389942e4c 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Styles.cs @@ -100,7 +100,7 @@ namespace MonoDevelop.Debugger // Shared ObjectValueTreeSelectedTextColor = Ide.Gui.Styles.BaseSelectionTextColor.ToHexString (false); - ObjectValueTreeForegroundTextColor = Ide.Gui.Styles.BaseSelectionTextColor.ToHexString (false); + ObjectValueTreeForegroundTextColor = Ide.Gui.Styles.BaseForegroundColor.ToHexString (false); ObjectValueTreeExternalCodeForegroundTextColor = ExceptionCaughtDialog.ExternalCodeTextColor.ToHexString (false); ObjectValueTreeValueErrorText = Ide.Gui.Styles.WarningForegroundColor; diff --git a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs index 0435aeb74c..fac52ab751 100644 --- a/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs +++ b/main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/ThreadsPad.cs @@ -159,18 +159,21 @@ namespace MonoDevelop.Debugger if (process != null) { //User right-clicked on thread and not process context_menu.Items.Add (new SeparatorContextMenuItem ()); var session = store.GetValue (selected, (int)Columns.Session) as DebuggerSession; - var continueExecution = new ContextMenuItem (GettextCatalog.GetString ("Resume")); - continueExecution.Sensitive = !session.IsRunning; - continueExecution.Clicked += delegate { - session.Continue (); - }; - context_menu.Items.Add (continueExecution); - var pauseExecution = new ContextMenuItem (GettextCatalog.GetString ("Pause")); - pauseExecution.Sensitive = session.IsRunning; - pauseExecution.Clicked += delegate { - session.Stop (); - }; - context_menu.Items.Add (pauseExecution); + + if (session != null) { + var continueExecution = new ContextMenuItem (GettextCatalog.GetString ("Resume")); + continueExecution.Sensitive = !session.IsRunning; + continueExecution.Clicked += delegate { + session.Continue (); + }; + context_menu.Items.Add (continueExecution); + var pauseExecution = new ContextMenuItem (GettextCatalog.GetString ("Pause")); + pauseExecution.Sensitive = session.IsRunning; + pauseExecution.Clicked += delegate { + session.Stop (); + }; + context_menu.Items.Add (pauseExecution); + } } context_menu.Show (this, evt); } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/DependenciesNodeCommandHandler.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/DependenciesNodeCommandHandler.cs new file mode 100644 index 0000000000..b473f188cb --- /dev/null +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/DependenciesNodeCommandHandler.cs @@ -0,0 +1,41 @@ +// +// DependenciesNodeCommandHandler.cs +// +// Author: +// Matt Ward <matt.ward@microsoft.com> +// +// Copyright (c) 2019 Microsoft +// +// 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 MonoDevelop.Ide;
+using MonoDevelop.Ide.Gui.Components; +using MonoDevelop.PackageManagement; + +namespace MonoDevelop.DotNetCore.Commands +{ + class DependenciesNodeCommandHandler : NodeCommandHandler + { + public override void ActivateItem () + { + var runner = new ManagePackagesDialogRunner (); + runner.Run (IdeApp.ProjectOperations.CurrentSelectedProject); + } + } +} diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs index 78ee767357..cf2b31370a 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Commands/PackageDependenciesNodeCommandHandler.cs @@ -24,6 +24,7 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +using MonoDevelop.Ide; using MonoDevelop.Ide.Gui.Components; using MonoDevelop.PackageManagement; @@ -33,8 +34,8 @@ namespace MonoDevelop.DotNetCore.Commands { public override void ActivateItem () { - var runner = new AddPackagesDialogRunner (); - runner.Run (); + var runner = new ManagePackagesDialogRunner (); + runner.Run (IdeApp.ProjectOperations.CurrentSelectedProject); } } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs index 8c00cd2380..107c754e6b 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.NodeBuilders/DependenciesNodeBuilder.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; +using MonoDevelop.DotNetCore.Commands; using MonoDevelop.Ide.Gui.Components; namespace MonoDevelop.DotNetCore.NodeBuilders @@ -40,6 +41,10 @@ namespace MonoDevelop.DotNetCore.NodeBuilders return DependenciesNode.NodeName; } + public override Type CommandHandlerType { + get { return typeof (DependenciesNodeCommandHandler); } + } + public override void BuildNode (ITreeBuilder treeBuilder, object dataObject, NodeInfo nodeInfo) { var node = (DependenciesNode)dataObject; diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs index e3c1a79ef9..df44c28c89 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Templating/DotNetCoreProjectTemplateStringTagProvider.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System;
+using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; @@ -140,16 +141,32 @@ namespace MonoDevelop.DotNetCore.Templating return null; string templatesDirectory = Path.Combine ( - DotNetCoreSdk.SdkRootPath, - dotNetCoreSdk.OriginalString, - "Templates" - ); + DotNetCoreSdk.SdkRootPath, + dotNetCoreSdk.OriginalString, + "Templates" + ); - if (DirectoryExists (templatesDirectory)) { - return templatesDirectory; + if (!DirectoryExists (templatesDirectory)) { + // .NET Core 3.0 Preview 8 and higher place templates in the root dir + // and versioned by runtime, not SDK + var baseTemplatesDir = Path.Combine (Directory.GetParent (DotNetCoreSdk.SdkRootPath).FullName, "templates"); + if (DirectoryExists (baseTemplatesDir)) { + var availableTemplates = new Dictionary<DotNetCoreVersion, string> (); + foreach (var dir in EnumerateDirectories (baseTemplatesDir)) { + if (DotNetCoreVersion.TryParse (Path.GetFileName (dir), out var version)) { + availableTemplates [version] = dir; + } + } + + templatesDirectory = availableTemplates.Keys + .Where (v => v.Major < dotNetCoreSdk.Major || (v.Major == dotNetCoreSdk.Major && v.Minor <= dotNetCoreSdk.Minor)) + .OrderByDescending (v => v) + .Select (v => availableTemplates [v]) + .FirstOrDefault (); + } } - return string.Empty; + return DirectoryExists (templatesDirectory) ? templatesDirectory : string.Empty; } DotNetCoreVersion GetDotNetCoreSdkVersion (DotNetCoreVersion version) @@ -172,5 +189,10 @@ namespace MonoDevelop.DotNetCore.Templating /// Used by unit tests. /// </summary> internal Func<string, IEnumerable<string>> EnumerateFiles = Directory.EnumerateFiles; + + /// <summary> + /// Used by unit tests. + /// </summary> + internal Func<string, IEnumerable<string>> EnumerateDirectories = Directory.EnumerateDirectories; } } diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs index a9720ac747..4053f3f526 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.Tests/MonoDevelop.DotNetCore.Tests/DotNetCoreProjectTemplateStringTagProviderTests.cs @@ -24,9 +24,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -using System;
+using System; using System.Collections.Generic; using System.IO; +using System.Linq; using MonoDevelop.DotNetCore.Templating; using NUnit.Framework; @@ -52,6 +53,7 @@ namespace MonoDevelop.DotNetCore.Tests provider = new DotNetCoreProjectTemplateStringTagProvider (); provider.DirectoryExists = DirectoryExists; provider.EnumerateFiles = EnumerateFiles; + provider.EnumerateDirectories = EnumerateDirectories; } bool DirectoryExists (string directory) @@ -64,6 +66,11 @@ namespace MonoDevelop.DotNetCore.Tests return templateFiles; } + IEnumerable<string> EnumerateDirectories (string directory) + { + return directories.Where (dir => Directory.GetParent (dir).FullName == directory); + } + static string ToNativePath (string filePath) { if (Path.DirectorySeparatorChar == '\\') @@ -77,6 +84,34 @@ namespace MonoDevelop.DotNetCore.Tests return filePath.Replace ('\\', Path.DirectorySeparatorChar); } + protected void DotNetCoreSdksInstalled (string sdkVersion, string templatesVersion, bool globalTemplates) + { + DotNetCoreSdksInstalled (sdkVersion); + if (globalTemplates) { + AddGlobalProjectTemplateFile ( + templatesVersion, + $"microsoft.dotnet.common.projecttemplates.{templatesVersion}.aaa", + $"microsoft.dotnet.common.projecttemplates.{templatesVersion}.nupkg", + $"microsoft.dotnet.test.projecttemplates.{templatesVersion}.aaa", + $"microsoft.dotnet.test.projecttemplates.{templatesVersion}.nupkg", + $"microsoft.dotnet.web.projecttemplates.{templatesVersion}.aaa", + $"microsoft.dotnet.web.projecttemplates.{templatesVersion}.nupkg", + $"microsoft.dotnet.web.spa.projecttemplates.{templatesVersion}.aaa", + $"microsoft.dotnet.web.spa.projecttemplates.{templatesVersion}.nupkg"); + } else { + AddProjectTemplateFile ( + sdkVersion, + $"microsoft.dotnet.common.projecttemplates.{templatesVersion}.aaa", + $"microsoft.dotnet.common.projecttemplates.{templatesVersion}.nupkg", + $"microsoft.dotnet.test.projecttemplates.{templatesVersion}.aaa", + $"microsoft.dotnet.test.projecttemplates.{templatesVersion}.nupkg", + $"microsoft.dotnet.web.projecttemplates.{templatesVersion}.aaa", + $"microsoft.dotnet.web.projecttemplates.{templatesVersion}.nupkg", + $"microsoft.dotnet.web.spa.projecttemplates.{templatesVersion}.aaa", + $"microsoft.dotnet.web.spa.projecttemplates.{templatesVersion}.nupkg"); + } + } + string GetTagValue (string tag) { return provider.GetTagValue (null, tag) as string; @@ -102,6 +137,35 @@ namespace MonoDevelop.DotNetCore.Tests return GetTagValue ($"DotNetCoreSdk.{version}.Templates.Web.Spa.ProjectTemplates.nupkg"); } + string GetExpectedTemplateTagValue (string sdkVersion, string templatesVersion, string filePrefix, bool globalTemplates) + { + if (globalTemplates) { + return Path.Combine ( + Directory.GetParent (sdkRootPath).FullName, + "templates", + templatesVersion, + $"{filePrefix}.{templatesVersion}.nupkg"); + } else { + return Path.Combine ( + sdkRootPath, + sdkVersion, + "Templates", + $"{filePrefix}.{templatesVersion}.nupkg"); + } + } + + void AddGlobalProjectTemplateFile (string sdkVersion, params string [] fileNames) + { + string directory = Path.Combine (Directory.GetParent (sdkRootPath).FullName, "templates"); + directories.Add (directory); + directory = Path.Combine (directory, sdkVersion); + directories.Add (directory); + foreach (string fileName in fileNames) { + string fullPath = Path.Combine (directory, fileName); + templateFiles.Add (fullPath); + } + } + void AddProjectTemplateFile (string sdkVersion, params string[] fileNames) { foreach (string fileName in fileNames) { @@ -129,6 +193,7 @@ namespace MonoDevelop.DotNetCore.Tests Assert.AreEqual (string.Empty, GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.1")); Assert.AreEqual (string.Empty, GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.2")); + Assert.AreEqual (string.Empty, GetDotNetCoreSdkCommonProjectTemplatesTagValue ("3.0")); } [TestCase ("2.1", "2.1.300-preview1-008174")] @@ -142,182 +207,56 @@ namespace MonoDevelop.DotNetCore.Tests Assert.AreEqual (string.Empty, result); } - [Test] - public void NetCore22Installed_CommonProjectTemplates () + [TestCase ("3.0.100-preview8-013592", "3.0.0-preview8-013592", true)] + [TestCase ("3.0.100-preview7-012821", "3.0.2.0.0-preview7.19365.3", false)] + [TestCase ("2.2.100-preview2-009404", "2.2.1.0.2-beta4-20180904-2003790", false)] + [TestCase ("2.1.701", "2.1.1.0.2-beta3", false)] + [TestCase ("2.1.300-preview1-008174", "2.1.1.0.1-beta3-20180215-1392068", false)] + public void NetCoreInstalled_CommonProjectTemplates (string sdkVersion, string templatesVersion, bool globalTemplates) { - DotNetCoreSdksInstalled ("2.2.100-preview2-009404"); - AddProjectTemplateFile ( - "2.2.100-preview2-009404", - "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg", - "microsoft.dotnet.test.projecttemplates.2.2.1.0.2-beta4-20180821-1966911.nupkg", - "microsoft.dotnet.web.projecttemplates.2.2.2.2.0-preview2-35157.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.2.100-preview2-009404", - "Templates", - "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg"); - - string result = GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.2"); - - Assert.AreEqual (expectedResult, result); + DotNetCoreSdksInstalled (sdkVersion, templatesVersion, globalTemplates); + Assert.AreEqual ( + GetExpectedTemplateTagValue (sdkVersion, templatesVersion, "microsoft.dotnet.common.projecttemplates", globalTemplates), + GetDotNetCoreSdkCommonProjectTemplatesTagValue (sdkVersion.Substring (0, 3))); } - [Test] - public void NetCore22Installed_TestProjectTemplates () + [TestCase ("3.0.100-preview8-013592", "3.0.0-preview8-013592", true)] + [TestCase ("3.0.100-preview7-012821", "3.0.1.0.2-beta4.19155.2", false)] + [TestCase ("2.2.100-preview2-009404", "2.2.1.0.2-beta4-20180904-2003790", false)] + [TestCase ("2.1.701", "2.1.1.0.2-beta4-20181009-2100240", false)] + [TestCase ("2.1.300-preview1-008174", "2.1.1.0.1-beta3-20180215-1392068", false)] + public void NetCoreInstalled_TestProjectTemplates (string sdkVersion, string templatesVersion, bool globalTemplates) { - DotNetCoreSdksInstalled ("2.2.100-preview2-009404"); - AddProjectTemplateFile ( - "2.2.100-preview2-009404", - "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg", - "microsoft.dotnet.test.projecttemplates.2.2.1.0.2-beta4-20180821-1966911.nupkg", - "microsoft.dotnet.web.projecttemplates.2.2.2.2.0-preview2-35157.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.2.100-preview2-009404", - "Templates", - "microsoft.dotnet.test.projecttemplates.2.2.1.0.2-beta4-20180821-1966911.nupkg"); - - string result = GetDotNetCoreSdkTestProjectTemplatesTagValue ("2.2"); - - Assert.AreEqual (expectedResult, result); - } - - [Test] - public void NetCore22Installed_WebProjectTemplates () - { - DotNetCoreSdksInstalled ("2.2.100-preview2-009404"); - AddProjectTemplateFile ( - "2.2.100-preview2-009404", - "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg", - "microsoft.dotnet.test.projecttemplates.2.2.1.0.2-beta4-20180821-1966911.nupkg", - "microsoft.dotnet.web.projecttemplates.2.2.2.2.0-preview2-35157.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.2.100-preview2-009404", - "Templates", - "microsoft.dotnet.web.projecttemplates.2.2.2.2.0-preview2-35157.nupkg"); - - string result = GetDotNetCoreSdkWebProjectTemplatesTagValue ("2.2"); - - Assert.AreEqual (expectedResult, result); + DotNetCoreSdksInstalled (sdkVersion, templatesVersion, globalTemplates); + Assert.AreEqual ( + GetExpectedTemplateTagValue (sdkVersion, templatesVersion, "microsoft.dotnet.test.projecttemplates", globalTemplates), + GetDotNetCoreSdkTestProjectTemplatesTagValue (sdkVersion.Substring (0, 3))); } - [Test] - public void NetCore22Installed_MatchingFileWithDifferentExtension_CommonProjectTemplates () + [TestCase ("3.0.100-preview8-013592", "3.0.0-preview8-013592", true)] + [TestCase ("3.0.100-preview7-012821", "3.0.0-preview7.19365.7", false)] + [TestCase ("2.2.100-preview2-009404", "2.2.2.2.0-preview2-35157", false)] + [TestCase ("2.1.701", "2.1.2.1.12", false)] + [TestCase ("2.1.300-preview1-008174", "2.1.2.1.0-preview1-final", false)] + public void NetCoreInstalled_WebProjectTemplates (string sdkVersion, string templatesVersion, bool globalTemplates) { - DotNetCoreSdksInstalled ("2.2.100-preview2-009404"); - AddProjectTemplateFile ( - "2.2.100-preview2-009404", - "microsoft.dotnet.common.projecttemplates.2.0.1.0.0-beta3-20171110-312.aaa", - "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.2.100-preview2-009404", - "Templates", - "microsoft.dotnet.common.projecttemplates.2.2.1.0.2-beta4-20180904-2003790.nupkg"); - - string result = GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.2"); - - Assert.AreEqual (expectedResult, result); + DotNetCoreSdksInstalled (sdkVersion, templatesVersion, globalTemplates); + Assert.AreEqual ( + GetExpectedTemplateTagValue (sdkVersion, templatesVersion, "microsoft.dotnet.web.projecttemplates", globalTemplates), + GetDotNetCoreSdkWebProjectTemplatesTagValue (sdkVersion.Substring (0, 3))); } - [Test] - public void NetCore21Installed_CommonProjectTemplates () + [TestCase ("3.0.100-preview8-013592", "3.0.0-preview8-013592", true)] + [TestCase ("3.0.100-preview7-012821", "3.0.0-preview7.19365.7", false)] + [TestCase ("2.2.100-preview2-009404", "2.2.2.2.0-preview2-35157", false)] + [TestCase ("2.1.701", "2.1.12", false)] + [TestCase ("2.1.300-preview1-008174", "2.1.2.1.0-preview1-final", false)] + public void NetCoreInstalled_SpaWebProjectTemplates (string sdkVersion, string templatesVersion, bool globalTemplates) { - DotNetCoreSdksInstalled ("2.1.300-preview1-008174"); - AddProjectTemplateFile ( - "2.1.300-preview1-008174", - "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg", - "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg", - "microsoft.dotnet.web.projecttemplates.2.1.2.1.0-preview1-final.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.1.300-preview1-008174", - "Templates", - "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg"); - - string result = GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.1"); - - Assert.AreEqual (expectedResult, result); - } - - [Test] - public void NetCore21Installed_TestProjectTemplates () - { - DotNetCoreSdksInstalled ("2.1.300-preview1-008174"); - AddProjectTemplateFile ( - "2.1.300-preview1-008174", - "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg", - "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg", - "microsoft.dotnet.web.projecttemplates.2.1.2.1.0-preview1-final.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.1.300-preview1-008174", - "Templates", - "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg"); - - string result = GetDotNetCoreSdkTestProjectTemplatesTagValue ("2.1"); - - Assert.AreEqual (expectedResult, result); - } - - [Test] - public void NetCore21Installed_WebProjectTemplates () - { - DotNetCoreSdksInstalled ("2.1.300-preview1-008174"); - AddProjectTemplateFile ( - "2.1.300-preview1-008174", - "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg", - "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg", - "microsoft.dotnet.web.projecttemplates.2.1.2.1.0-preview1-final.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.1.300-preview1-008174", - "Templates", - "microsoft.dotnet.web.projecttemplates.2.1.2.1.0-preview1-final.nupkg"); - - string result = GetDotNetCoreSdkWebProjectTemplatesTagValue ("2.1"); - - Assert.AreEqual (expectedResult, result); - } - - [Test] - public void NetCore21Installed_SpaWebProjectTemplates () - { - DotNetCoreSdksInstalled ("2.1.300-preview1-008174"); - AddProjectTemplateFile ( - "2.1.300-preview1-008174", - "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg", - "microsoft.dotnet.test.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg", - "microsoft.dotnet.web.spa.projecttemplates.2.1.2.1.0-preview1-final.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.1.300-preview1-008174", - "Templates", - "microsoft.dotnet.web.spa.projecttemplates.2.1.2.1.0-preview1-final.nupkg"); - - string result = GetDotNetCoreSdkSpaWebProjectTemplatesTagValue ("2.1"); - - Assert.AreEqual (expectedResult, result); - } - - [Test] - public void NetCore21Installed_MatchingFileWithDifferentExtension_CommonProjectTemplates () - { - DotNetCoreSdksInstalled ("2.1.300-preview1-008174"); - AddProjectTemplateFile ( - "2.1.300-preview1-008174", - "microsoft.dotnet.common.projecttemplates.2.0.1.0.0-beta3-20171110-312.aaa", - "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg"); - string expectedResult = Path.Combine ( - sdkRootPath, - "2.1.300-preview1-008174", - "Templates", - "microsoft.dotnet.common.projecttemplates.2.1.1.0.1-beta3-20180215-1392068.nupkg"); - - string result = GetDotNetCoreSdkCommonProjectTemplatesTagValue ("2.1"); - - Assert.AreEqual (expectedResult, result); + DotNetCoreSdksInstalled (sdkVersion, templatesVersion, globalTemplates); + Assert.AreEqual ( + GetExpectedTemplateTagValue (sdkVersion, templatesVersion, "microsoft.dotnet.web.spa.projecttemplates", globalTemplates), + GetDotNetCoreSdkSpaWebProjectTemplatesTagValue (sdkVersion.Substring (0, 3))); } [TestCase ("DotNetCoreSdk.2.1.Templates.Common.ProjectTemplates.txt")] diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj index bb1c502dc0..a79bd177e0 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore.csproj @@ -91,6 +91,7 @@ <Compile Include="MonoDevelop.DotNetCore\FrameworkReference.cs" /> <Compile Include="MonoDevelop.DotNetCore.NodeBuilders\PackageDependencyNodePropertyProvider.cs" /> <Compile Include="MonoDevelop.DotNetCore.NodeBuilders\PackageDependencyNodeDescriptor.cs" /> + <Compile Include="MonoDevelop.DotNetCore.Commands\DependenciesNodeCommandHandler.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\external\mono-addins\Mono.Addins\Mono.Addins.csproj"> diff --git a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs index 4b8f3463ce..24a9ff0849 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs +++ b/main/src/addins/MonoDevelop.DotNetCore/MonoDevelop.DotNetCore/DotNetCoreVersion.cs @@ -26,6 +26,7 @@ using System; using System.IO; +using System.Collections.Generic; using System.Linq; using MonoDevelop.Core; diff --git a/main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml b/main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml index 8e8459640d..32c246959b 100644 --- a/main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml +++ b/main/src/addins/MonoDevelop.DotNetCore/Properties/MonoDevelop.DotNetCore.addin.xml @@ -1214,7 +1214,7 @@ <SeparatorItem id="DependenciesEditReferenceSeparator" /> <CommandItem - id="MonoDevelop.PackageManagement.Commands.AddPackages" _label = "Add _Packages..." /> + id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject" /> <CommandItem id="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInProject" /> <CommandItem @@ -1222,7 +1222,7 @@ </Condition> <Condition id="ItemType" value="MonoDevelop.DotNetCore.NodeBuilders.PackageDependenciesNode"> <CommandItem - id="MonoDevelop.PackageManagement.Commands.AddPackages" _label = "Add _Packages..." /> + id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject" /> <CommandItem id="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInProject" /> <CommandItem @@ -1233,7 +1233,7 @@ value="MonoDevelop.DotNetCore.NodeBuilders.AssemblyDependenciesNode|MonoDevelop.DotNetCore.NodeBuilders.ProjectDependenciesNode"> <CommandItem id="MonoDevelop.Ide.Commands.ProjectCommands.AddReference" - insertbefore="MonoDevelop.PackageManagement.Commands.AddPackages" /> + insertbefore="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject" /> </Condition> <Condition id="ItemType" value="UnknownProject|Solution"> <CommandItem diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs index c16dc31352..1a08dcbb5f 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/AddPackagesHandler.cs @@ -24,16 +24,14 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-using System;
-
namespace MonoDevelop.PackageManagement.Commands
{
internal class AddPackagesHandler : PackagesCommandHandler
{
protected override void Run ()
{
- var runner = new AddPackagesDialogRunner ();
- runner.Run ();
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (GetSelectedDotNetProject ());
}
protected override bool IsEnabled ()
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesHandler.cs new file mode 100644 index 0000000000..91c593b4eb --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesHandler.cs @@ -0,0 +1,48 @@ +// +// ManagePackagesHandler.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://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. + +using System.Linq; +using MonoDevelop.PackageManagement.Commands; + +namespace MonoDevelop.PackageManagement +{ + internal class ManagePackagesHandler : PackagesCommandHandler + { + protected override void Run () + { + var runner = new ManagePackagesDialogRunner (); + runner.Run (); + } + + protected override bool IsEnabled () + { + var solution = GetSelectedSolution (); + return (solution != null) && + solution.GetAllDotNetProjects ().Any (); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesInProjectHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesInProjectHandler.cs new file mode 100644 index 0000000000..583c401cf9 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ManagePackagesInProjectHandler.cs @@ -0,0 +1,44 @@ +// +// ManagePackagesInProjectHandler.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://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. + +using MonoDevelop.PackageManagement.Commands; + +namespace MonoDevelop.PackageManagement +{ + class ManagePackagesInProjectHandler : PackagesCommandHandler + { + protected override bool IsEnabled () + { + return IsDotNetProjectSelected (); + } + + protected override void Run () + { + var runner = new ManagePackagesDialogRunner (); + runner.Run (GetSelectedDotNetProject ()); + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs index b0b0a7b585..a07b239fd0 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Commands/ProjectPackagesFolderNodeCommandHandler.cs @@ -28,9 +28,9 @@ using System; using System.Collections.Generic;
using System.Linq;
using MonoDevelop.Components.Commands;
+using MonoDevelop.Ide; using MonoDevelop.Ide.Gui.Components;
using MonoDevelop.PackageManagement.NodeBuilders;
-using NuGet.ProjectManagement;
namespace MonoDevelop.PackageManagement.Commands
{
@@ -38,8 +38,8 @@ namespace MonoDevelop.PackageManagement.Commands {
public override void ActivateItem ()
{
- var runner = new AddPackagesDialogRunner ();
- runner.Run ();
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (IdeApp.ProjectOperations.CurrentSelectedProject);
}
[CommandUpdateHandler (PackagesFolderNodeCommands.ReinstallAllPackagesInProject)]
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellView.cs index aa6b3111d4..09611a1daa 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellView.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellView.cs @@ -1,340 +1,340 @@ -//
-// PackageCellView.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://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.
-
-using System;
-using MonoDevelop.Core;
-using Xwt;
-using Xwt.Drawing;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class PackageCellView : CanvasCellView
- {
- int packageIdFontSize;
- int packageDescriptionFontSize;
-
- public PackageCellView ()
- {
- CellWidth = 260;
-
- BackgroundColor = Styles.CellBackgroundColor;
- StrongSelectionColor = Styles.CellStrongSelectionColor;
- SelectionColor = Styles.CellSelectionColor;
-
- UseStrongSelectionColor = true;
-
- if (Platform.IsWindows) {
- packageIdFontSize = 10;
- packageDescriptionFontSize = 9;
- } else {
- packageIdFontSize = 12;
- packageDescriptionFontSize = 11;
- }
- }
-
- public IDataField<PackageSearchResultViewModel> PackageField { get; set; }
- public IDataField<Image> ImageField { get; set; }
- public IDataField<bool> HasBackgroundColorField { get; set; }
- public IDataField<double> CheckBoxAlphaField { get; set; }
-
- public double CellWidth { get; set; }
-
- public Color BackgroundColor { get; set; }
- public Color StrongSelectionColor { get; set; }
- public Color SelectionColor { get; set; }
-
- public bool UseStrongSelectionColor { get; set; }
-
- public event EventHandler<PackageCellViewEventArgs> PackageChecked;
-
- protected override void OnDraw (Context ctx, Rectangle cellArea)
- {
- PackageSearchResultViewModel packageViewModel = GetValue (PackageField);
- if (packageViewModel == null) {
- return;
- }
-
- FillCellBackground (ctx);
- UpdateTextColor (ctx);
-
- DrawCheckBox (ctx, packageViewModel, cellArea);
- DrawPackageImage (ctx, cellArea);
-
- double packageIdWidth = cellArea.Width - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
-
- // Package download count.
- if (packageViewModel.HasDownloadCount) {
- var downloadCountTextLayout = new TextLayout ();
- downloadCountTextLayout.Text = packageViewModel.GetDownloadCountOrVersionDisplayText ();
- Size size = downloadCountTextLayout.GetSize ();
- Point location = new Point (cellArea.Right - packageDescriptionPadding.Right, cellArea.Top + packageDescriptionPadding.Top);
- Point downloadLocation = location.Offset (-size.Width, 0);
- ctx.DrawTextLayout (downloadCountTextLayout, downloadLocation);
-
- packageIdWidth = downloadLocation.X - cellArea.Left - packageIdRightHandPaddingWidth - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
- }
-
- // Package Id.
- // Use the package id and not the package title to prevent a pango crash if the title
- // contains Chinese characters.
- var packageIdTextLayout = new TextLayout ();
- packageIdTextLayout.Font = packageIdTextLayout.Font.WithSize (packageIdFontSize);
- packageIdTextLayout.Markup = packageViewModel.GetIdMarkup ();
- packageIdTextLayout.Trimming = TextTrimming.WordElipsis;
- Size packageIdTextSize = packageIdTextLayout.GetSize ();
- packageIdTextLayout.Width = packageIdWidth;
- ctx.DrawTextLayout (
- packageIdTextLayout,
- cellArea.Left + packageDescriptionPadding.Left + packageDescriptionLeftOffset,
- cellArea.Top + packageDescriptionPadding.Top);
-
- // Package description.
- var descriptionTextLayout = new TextLayout ();
- descriptionTextLayout.Font = descriptionTextLayout.Font.WithSize (packageDescriptionFontSize);
- descriptionTextLayout.Width = cellArea.Width - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset;
- descriptionTextLayout.Height = cellArea.Height - packageIdTextSize.Height - packageDescriptionPadding.VerticalSpacing;
- descriptionTextLayout.Text = packageViewModel.Summary;
- descriptionTextLayout.Trimming = TextTrimming.Word;
-
- ctx.DrawTextLayout (
- descriptionTextLayout,
- cellArea.Left + packageDescriptionPadding.Left + packageDescriptionLeftOffset,
- cellArea.Top + packageIdTextSize.Height + packageDescriptionPaddingHeight + packageDescriptionPadding.Top);
- }
-
- void UpdateTextColor (Context ctx)
- {
- if (UseStrongSelectionColor && Selected) {
- ctx.SetColor (Styles.CellTextSelectionColor);
- } else {
- ctx.SetColor (Styles.CellTextColor);
- }
- }
-
- void FillCellBackground (Context ctx)
- {
- if (Selected) {
- FillCellBackground (ctx, GetSelectedColor ());
- } else if (IsBackgroundColorFieldSet ()) {
- FillCellBackground (ctx, BackgroundColor);
- }
- }
-
- Color GetSelectedColor ()
- {
- if (UseStrongSelectionColor) {
- return StrongSelectionColor;
- }
- return SelectionColor;
- }
-
- bool IsBackgroundColorFieldSet ()
- {
- return GetValue (HasBackgroundColorField, false);
- }
-
- void FillCellBackground (Context ctx, Color color)
- {
- ctx.Rectangle (BackgroundBounds);
- ctx.SetColor (color);
- ctx.Fill ();
- }
-
- void DrawCheckBox (Context ctx, PackageSearchResultViewModel packageViewModel, Rectangle cellArea)
- {
- CreateCheckboxImages ();
-
- Image image = GetCheckBoxImage (packageViewModel.IsChecked);
- double alpha = GetCheckBoxImageAlpha ();
- ctx.DrawImage (
- image,
- cellArea.Left + checkBoxPadding.Left,
- cellArea.Top + ((cellArea.Height - checkBoxImageSize.Height - 2) / 2),
- alpha);
- }
-
- void CreateCheckboxImages ()
- {
- if (whiteCheckedCheckBoxImage != null)
- return;
-
- var widget = Toolkit.CurrentEngine.GetNativeWidget (ParentWidget);
- var checkbox = new PackageCellViewCheckBox (ParentWidget.ParentWindow.Screen.ScaleFactor);
- checkbox.Container = (Gtk.Widget)widget;
- checkbox.Size = (int)checkBoxImageSize.Width + 1;
-
- // White checkbox.
- whiteUncheckedCheckBoxImage = checkbox.CreateImage ();
- checkbox.Active = true;
- whiteCheckedCheckBoxImage = checkbox.CreateImage ();
-
- // Odd numbered checkbox.
- checkbox.BackgroundColor = BackgroundColor;
- checkedCheckBoxWithBackgroundColorImage = checkbox.CreateImage ();
- checkbox.Active = false;
- uncheckedCheckBoxWithBackgroundColorImage = checkbox.CreateImage ();
-
- // Grey check box.
- checkbox.BackgroundColor = SelectionColor;
- greyUncheckedCheckBoxImage = checkbox.CreateImage ();
- checkbox.Active = true;
- greyCheckedCheckBoxImage = checkbox.CreateImage ();
-
- // Blue check box.
- checkbox.BackgroundColor = StrongSelectionColor;
- blueCheckedCheckBoxImage = checkbox.CreateImage ();
- checkbox.Active = false;
- blueUncheckedCheckBoxImage = checkbox.CreateImage ();
- }
-
- double GetCheckBoxImageAlpha ()
- {
- return GetValue (CheckBoxAlphaField, 1);
- }
-
- Image GetCheckBoxImage (bool checkBoxActive)
- {
- if (Selected && UseStrongSelectionColor && checkBoxActive) {
- return blueCheckedCheckBoxImage;
- } else if (Selected && checkBoxActive) {
- return greyCheckedCheckBoxImage;
- } else if (Selected && UseStrongSelectionColor) {
- return blueUncheckedCheckBoxImage;
- } else if (Selected) {
- return greyUncheckedCheckBoxImage;
- } else if (checkBoxActive && IsBackgroundColorFieldSet ()) {
- return checkedCheckBoxWithBackgroundColorImage;
- } else if (checkBoxActive) {
- return whiteCheckedCheckBoxImage;
- } else if (IsBackgroundColorFieldSet ()) {
- return uncheckedCheckBoxWithBackgroundColorImage;
- } else {
- return whiteUncheckedCheckBoxImage;
- }
- }
-
- void DrawPackageImage (Context ctx, Rectangle cellArea)
- {
- Image image = GetValue (ImageField);
-
- if (image == null) {
- image = defaultPackageImage;
- }
-
- if (Selected)
- image = image.WithStyles ("sel");
-
- if (PackageImageNeedsResizing (image)) {
- Point imageLocation = GetPackageImageLocation (maxPackageImageSize, cellArea);
- ctx.DrawImage (
- image,
- cellArea.Left + packageImagePadding.Left + checkBoxAreaWidth + imageLocation.X,
- Math.Round( cellArea.Top + packageImagePadding.Top + imageLocation.Y),
- maxPackageImageSize.Width,
- maxPackageImageSize.Height);
- } else {
- Point imageLocation = GetPackageImageLocation (image.Size, cellArea);
- ctx.DrawImage (
- image,
- cellArea.Left + packageImagePadding.Left + checkBoxAreaWidth + imageLocation.X,
- Math.Round (cellArea.Top + packageImagePadding.Top + imageLocation.Y));
- }
- }
-
- bool PackageImageNeedsResizing (Image image)
- {
- return (image.Width > maxPackageImageSize.Width) || (image.Height > maxPackageImageSize.Height);
- }
-
- Point GetPackageImageLocation (Size imageSize, Rectangle cellArea)
- {
- double width = (packageImageAreaWidth - imageSize.Width) / 2;
- double height = (cellArea.Height - imageSize.Height - packageImagePadding.Bottom) / 2;
- return new Point (width, height);
- }
-
+// +// PackageCellView.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://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. + +using System; +using MonoDevelop.Core; +using Xwt; +using Xwt.Drawing; + +namespace MonoDevelop.PackageManagement +{ + internal class ManagePackagesCellView : CanvasCellView + { + int packageIdFontSize; + int packageDescriptionFontSize; + + public ManagePackagesCellView () + { + CellWidth = 260; + + BackgroundColor = Styles.CellBackgroundColor; + StrongSelectionColor = Styles.CellStrongSelectionColor; + SelectionColor = Styles.CellSelectionColor; + + UseStrongSelectionColor = true; + + if (Platform.IsWindows) { + packageIdFontSize = 10; + packageDescriptionFontSize = 9; + } else { + packageIdFontSize = 12; + packageDescriptionFontSize = 11; + } + } + + public IDataField<ManagePackagesSearchResultViewModel> PackageField { get; set; } + public IDataField<Image> ImageField { get; set; } + public IDataField<bool> HasBackgroundColorField { get; set; } + public IDataField<double> CheckBoxAlphaField { get; set; } + + public double CellWidth { get; set; } + + public Color BackgroundColor { get; set; } + public Color StrongSelectionColor { get; set; } + public Color SelectionColor { get; set; } + + public bool UseStrongSelectionColor { get; set; } + + public event EventHandler<ManagePackagesCellViewEventArgs> PackageChecked; + + protected override void OnDraw (Context ctx, Rectangle cellArea) + { + ManagePackagesSearchResultViewModel packageViewModel = GetValue (PackageField); + if (packageViewModel == null) { + return; + } + + FillCellBackground (ctx); + UpdateTextColor (ctx); + + DrawCheckBox (ctx, packageViewModel, cellArea); + DrawPackageImage (ctx, cellArea); + + double packageIdWidth = cellArea.Width - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset; + + // Package download count. + if (packageViewModel.HasDownloadCount) { + var downloadCountTextLayout = new TextLayout (); + downloadCountTextLayout.Text = packageViewModel.GetDownloadCountOrVersionDisplayText (); + Size size = downloadCountTextLayout.GetSize (); + Point location = new Point (cellArea.Right - packageDescriptionPadding.Right, cellArea.Top + packageDescriptionPadding.Top); + Point downloadLocation = location.Offset (-size.Width, 0); + ctx.DrawTextLayout (downloadCountTextLayout, downloadLocation); + + packageIdWidth = downloadLocation.X - cellArea.Left - packageIdRightHandPaddingWidth - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset; + } + + // Package Id. + // Use the package id and not the package title to prevent a pango crash if the title + // contains Chinese characters. + var packageIdTextLayout = new TextLayout (); + packageIdTextLayout.Font = packageIdTextLayout.Font.WithSize (packageIdFontSize); + packageIdTextLayout.Markup = packageViewModel.GetIdMarkup (); + packageIdTextLayout.Trimming = TextTrimming.WordElipsis; + Size packageIdTextSize = packageIdTextLayout.GetSize (); + packageIdTextLayout.Width = packageIdWidth; + ctx.DrawTextLayout ( + packageIdTextLayout, + cellArea.Left + packageDescriptionPadding.Left + packageDescriptionLeftOffset, + cellArea.Top + packageDescriptionPadding.Top); + + // Package description. + var descriptionTextLayout = new TextLayout (); + descriptionTextLayout.Font = descriptionTextLayout.Font.WithSize (packageDescriptionFontSize); + descriptionTextLayout.Width = cellArea.Width - packageDescriptionPadding.HorizontalSpacing - packageDescriptionLeftOffset; + descriptionTextLayout.Height = cellArea.Height - packageIdTextSize.Height - packageDescriptionPadding.VerticalSpacing; + descriptionTextLayout.Text = packageViewModel.Summary; + descriptionTextLayout.Trimming = TextTrimming.Word; + + ctx.DrawTextLayout ( + descriptionTextLayout, + cellArea.Left + packageDescriptionPadding.Left + packageDescriptionLeftOffset, + cellArea.Top + packageIdTextSize.Height + packageDescriptionPaddingHeight + packageDescriptionPadding.Top); + } + + void UpdateTextColor (Context ctx) + { + if (Selected) { + ctx.SetColor (Styles.CellTextSelectionColor); + } else { + ctx.SetColor (Styles.CellTextColor); + } + } + + void FillCellBackground (Context ctx) + { + if (Selected) { + FillCellBackground (ctx, GetSelectedColor ()); + } else if (IsBackgroundColorFieldSet ()) { + FillCellBackground (ctx, BackgroundColor); + } + } + + Color GetSelectedColor () + { + if (UseStrongSelectionColor) { + return StrongSelectionColor; + } + return SelectionColor; + } + + bool IsBackgroundColorFieldSet () + { + return GetValue (HasBackgroundColorField, false); + } + + void FillCellBackground (Context ctx, Color color) + { + ctx.Rectangle (BackgroundBounds); + ctx.SetColor (color); + ctx.Fill (); + } + + void DrawCheckBox (Context ctx, ManagePackagesSearchResultViewModel packageViewModel, Rectangle cellArea) + { + CreateCheckboxImages (); + + Image image = GetCheckBoxImage (packageViewModel.IsChecked); + double alpha = GetCheckBoxImageAlpha (); + ctx.DrawImage ( + image, + cellArea.Left + checkBoxPadding.Left, + cellArea.Top + ((cellArea.Height - checkBoxImageSize.Height - 2) / 2), + alpha); + } + + void CreateCheckboxImages () + { + if (whiteCheckedCheckBoxImage != null) + return; + + var widget = Toolkit.CurrentEngine.GetNativeWidget (ParentWidget); + var checkbox = new ManagePackagesCellViewCheckBox (ParentWidget.ParentWindow.Screen.ScaleFactor); + checkbox.Container = (Gtk.Widget)widget; + checkbox.Size = (int)checkBoxImageSize.Width + 1; + + // White checkbox. + whiteUncheckedCheckBoxImage = checkbox.CreateImage (); + checkbox.Active = true; + whiteCheckedCheckBoxImage = checkbox.CreateImage (); + + // Odd numbered checkbox. + checkbox.BackgroundColor = BackgroundColor; + checkedCheckBoxWithBackgroundColorImage = checkbox.CreateImage (); + checkbox.Active = false; + uncheckedCheckBoxWithBackgroundColorImage = checkbox.CreateImage (); + + // Grey check box. + checkbox.BackgroundColor = SelectionColor; + greyUncheckedCheckBoxImage = checkbox.CreateImage (); + checkbox.Active = true; + greyCheckedCheckBoxImage = checkbox.CreateImage (); + + // Blue check box. + checkbox.BackgroundColor = StrongSelectionColor; + blueCheckedCheckBoxImage = checkbox.CreateImage (); + checkbox.Active = false; + blueUncheckedCheckBoxImage = checkbox.CreateImage (); + } + + double GetCheckBoxImageAlpha () + { + return GetValue (CheckBoxAlphaField, 1); + } + + Image GetCheckBoxImage (bool checkBoxActive) + { + if (Selected && UseStrongSelectionColor && checkBoxActive) { + return blueCheckedCheckBoxImage; + } else if (Selected && checkBoxActive) { + return greyCheckedCheckBoxImage; + } else if (Selected && UseStrongSelectionColor) { + return blueUncheckedCheckBoxImage; + } else if (Selected) { + return greyUncheckedCheckBoxImage; + } else if (checkBoxActive && IsBackgroundColorFieldSet ()) { + return checkedCheckBoxWithBackgroundColorImage; + } else if (checkBoxActive) { + return whiteCheckedCheckBoxImage; + } else if (IsBackgroundColorFieldSet ()) { + return uncheckedCheckBoxWithBackgroundColorImage; + } else { + return whiteUncheckedCheckBoxImage; + } + } + + void DrawPackageImage (Context ctx, Rectangle cellArea) + { + Image image = GetValue (ImageField); + + if (image == null) { + image = defaultPackageImage; + } + + if (Selected) + image = image.WithStyles ("sel"); + + if (PackageImageNeedsResizing (image)) { + Point imageLocation = GetPackageImageLocation (maxPackageImageSize, cellArea); + ctx.DrawImage ( + image, + cellArea.Left + packageImagePadding.Left + checkBoxAreaWidth + imageLocation.X, + Math.Round( cellArea.Top + packageImagePadding.Top + imageLocation.Y), + maxPackageImageSize.Width, + maxPackageImageSize.Height); + } else { + Point imageLocation = GetPackageImageLocation (image.Size, cellArea); + ctx.DrawImage ( + image, + cellArea.Left + packageImagePadding.Left + checkBoxAreaWidth + imageLocation.X, + Math.Round (cellArea.Top + packageImagePadding.Top + imageLocation.Y)); + } + } + + bool PackageImageNeedsResizing (Image image) + { + return (image.Width > maxPackageImageSize.Width) || (image.Height > maxPackageImageSize.Height); + } + + Point GetPackageImageLocation (Size imageSize, Rectangle cellArea) + { + double width = (packageImageAreaWidth - imageSize.Width) / 2; + double height = (cellArea.Height - imageSize.Height - packageImagePadding.Bottom) / 2; + return new Point (width, height); + } + protected override Size OnGetRequiredSize (SizeConstraint widthConstraint)
- {
- var layout = new TextLayout ();
- layout.Text = "W";
- layout.Font = layout.Font.WithSize (packageDescriptionFontSize);
- Size size = layout.GetSize ();
- return new Size (CellWidth, size.Height * linesDisplayedCount + packageDescriptionPaddingHeight + packageDescriptionPadding.VerticalSpacing);
- }
-
- protected override void OnButtonPressed (ButtonEventArgs args)
- {
- PackageSearchResultViewModel packageViewModel = GetValue (PackageField);
- if (packageViewModel == null) {
- base.OnButtonPressed (args);
- return;
- }
-
- double x = args.X - Bounds.X;
- double y = args.Y - Bounds.Y;
-
- if (checkBoxImageClickableRectangle.Contains (x, y)) {
- packageViewModel.IsChecked = !packageViewModel.IsChecked;
- OnPackageChecked (packageViewModel);
- }
- }
-
- void OnPackageChecked (PackageSearchResultViewModel packageViewModel)
- {
- if (PackageChecked != null) {
- PackageChecked (this, new PackageCellViewEventArgs (packageViewModel));
- }
- }
-
- const int packageDescriptionPaddingHeight = 5;
- const int packageIdRightHandPaddingWidth = 5;
- const int linesDisplayedCount = 4;
-
- const int checkBoxAreaWidth = 36;
- const int packageImageAreaWidth = 54;
- const int packageDescriptionLeftOffset = checkBoxAreaWidth + packageImageAreaWidth + 8;
-
- WidgetSpacing packageDescriptionPadding = new WidgetSpacing (5, 5, 5, 10);
- WidgetSpacing packageImagePadding = new WidgetSpacing (0, 0, 0, 5);
- WidgetSpacing checkBoxPadding = new WidgetSpacing (10, 0, 0, 10);
-
- Size maxPackageImageSize = new Size (48, 48);
- Size checkBoxImageSize = new Size (16, 16);
- Rectangle checkBoxImageClickableRectangle = new Rectangle (0, 10, 40, 50);
-
- Image whiteCheckedCheckBoxImage;
- Image whiteUncheckedCheckBoxImage;
- Image greyCheckedCheckBoxImage;
- Image greyUncheckedCheckBoxImage;
- Image blueCheckedCheckBoxImage;
- Image blueUncheckedCheckBoxImage;
- Image checkedCheckBoxWithBackgroundColorImage;
- Image uncheckedCheckBoxWithBackgroundColorImage;
-
- static readonly Image defaultPackageImage = Image.FromResource (typeof(PackageCellView), "package-48.png");
- }
-}
-
+ { + var layout = new TextLayout (); + layout.Text = "W"; + layout.Font = layout.Font.WithSize (packageDescriptionFontSize); + Size size = layout.GetSize (); + return new Size (CellWidth, size.Height * linesDisplayedCount + packageDescriptionPaddingHeight + packageDescriptionPadding.VerticalSpacing); + } + + protected override void OnButtonPressed (ButtonEventArgs args) + { + ManagePackagesSearchResultViewModel packageViewModel = GetValue (PackageField); + if (packageViewModel == null) { + base.OnButtonPressed (args); + return; + } + + double x = args.X - Bounds.X; + double y = args.Y - Bounds.Y; + + if (checkBoxImageClickableRectangle.Contains (x, y)) { + packageViewModel.IsChecked = !packageViewModel.IsChecked; + OnPackageChecked (packageViewModel); + } + } + + void OnPackageChecked (ManagePackagesSearchResultViewModel packageViewModel) + { + if (PackageChecked != null) { + PackageChecked (this, new ManagePackagesCellViewEventArgs (packageViewModel)); + } + } + + const int packageDescriptionPaddingHeight = 5; + const int packageIdRightHandPaddingWidth = 5; + const int linesDisplayedCount = 4; + + const int checkBoxAreaWidth = 36; + const int packageImageAreaWidth = 54; + const int packageDescriptionLeftOffset = checkBoxAreaWidth + packageImageAreaWidth + 8; + + WidgetSpacing packageDescriptionPadding = new WidgetSpacing (5, 5, 5, 10); + WidgetSpacing packageImagePadding = new WidgetSpacing (0, 0, 0, 5); + WidgetSpacing checkBoxPadding = new WidgetSpacing (10, 0, 0, 10); + + Size maxPackageImageSize = new Size (48, 48); + Size checkBoxImageSize = new Size (16, 16); + Rectangle checkBoxImageClickableRectangle = new Rectangle (0, 10, 40, 50); + + Image whiteCheckedCheckBoxImage; + Image whiteUncheckedCheckBoxImage; + Image greyCheckedCheckBoxImage; + Image greyUncheckedCheckBoxImage; + Image blueCheckedCheckBoxImage; + Image blueUncheckedCheckBoxImage; + Image checkedCheckBoxWithBackgroundColorImage; + Image uncheckedCheckBoxWithBackgroundColorImage; + + static readonly Image defaultPackageImage = Image.FromResource (typeof(ManagePackagesCellView), "package-48.png"); + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewCheckBox.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewCheckBox.cs index 5e0277c98d..c137669b79 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewCheckBox.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewCheckBox.cs @@ -1,49 +1,49 @@ -//
-// PackageCellViewCheckBox.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://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.
-
+// +// ManagePackagesCellViewCheckBox.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://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. + using System;
using MonoDevelop.Components;
using Gtk;
namespace MonoDevelop.PackageManagement
{
- internal class PackageCellViewCheckBox
+ internal class ManagePackagesCellViewCheckBox
{
static int indicatorSize;
static int indicatorSpacing;
double scaleFactor;
- static PackageCellViewCheckBox ()
+ static ManagePackagesCellViewCheckBox ()
{
var cb = new Gtk.CheckButton ();
indicatorSize = (int) cb.StyleGetProperty ("indicator-size");
indicatorSpacing = (int) cb.StyleGetProperty ("indicator-spacing");
}
- public PackageCellViewCheckBox (double scaleFactor)
+ public ManagePackagesCellViewCheckBox (double scaleFactor)
{
this.scaleFactor = scaleFactor;
Size = indicatorSize;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewEventArgs.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewEventArgs.cs index 20e7920ec9..ae50585266 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/PackageCellViewEventArgs.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesCellViewEventArgs.cs @@ -1,41 +1,40 @@ -//
-// PackageCellViewEventArgs.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://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.
-
-using System;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class PackageCellViewEventArgs : EventArgs
- {
- public PackageCellViewEventArgs (PackageSearchResultViewModel packageViewModel)
- {
- PackageViewModel = packageViewModel;
- }
-
- public PackageSearchResultViewModel PackageViewModel { get; private set; }
- }
-}
-
+// +// PackageCellViewEventArgs.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://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. + +using System; + +namespace MonoDevelop.PackageManagement +{ + internal class ManagePackagesCellViewEventArgs : EventArgs + { + public ManagePackagesCellViewEventArgs (ManagePackagesSearchResultViewModel packageViewModel) + { + PackageViewModel = packageViewModel; + } + + public ManagePackagesSearchResultViewModel PackageViewModel { get; } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.UI.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs index eda980a15c..c47a39aaf4 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.UI.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.UI.cs @@ -1,377 +1,476 @@ -//
-// AddPackagesDialog.UI.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://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.
-
-using System;
-using ExtendedTitleBarDialog = MonoDevelop.Components.ExtendedTitleBarDialog;
-using Mono.Unix;
-using MonoDevelop.Core;
-using MonoDevelop.Ide;
-using Xwt;
-using Xwt.Drawing;
-
-namespace MonoDevelop.PackageManagement
-{
- internal partial class AddPackagesDialog : ExtendedTitleBarDialog
- {
- ComboBox packageSourceComboBox;
- SearchTextEntry packageSearchEntry;
- ListView packagesListView;
- VBox packageInfoVBox;
- Label packageNameLabel;
- LinkLabel packageIdLink;
- Label packageDescription;
- Label packageAuthor;
- Label packagePublishedDate;
- Label packageDownloads;
- LinkLabel packageLicenseLink;
- LinkLabel packageProjectPageLink;
- Label packageDependenciesList;
- HBox packageDependenciesHBox;
- HBox packageDependenciesListHBox;
- Label packageDependenciesNoneLabel;
- CheckBox showPrereleaseCheckBox;
- Label packageId;
- Button addPackagesButton;
- FrameBox loadingSpinnerFrame;
- HBox errorMessageHBox;
- Label errorMessageLabel;
- Label loadingSpinnerLabel;
- FrameBox noPackagesFoundFrame;
- ComboBox packageVersionComboBox;
- HBox packageVersionsHBox;
- int packageInfoFontSize = 11;
-
- void Build ()
- {
- Title = Catalog.GetString ("Add Packages");
- Width = 820;
- Height = 520;
- Padding = new WidgetSpacing ();
-
- if (Platform.IsWindows) {
- packageInfoFontSize = 9;
- }
-
- // Top part of dialog:
- // Package sources and search.
- var topHBox = new HBox ();
- topHBox.Margin = new WidgetSpacing (8, 5, 6, 5);
-
- packageSourceComboBox = new ComboBox ();
- packageSourceComboBox.Name = "packageSourceComboBox";
- packageSourceComboBox.MinWidth = 200;
- topHBox.PackStart (packageSourceComboBox);
-
- packageSearchEntry = new SearchTextEntry ();
- packageSearchEntry.Name = "addPackagesDialogSearchEntry";
- packageSearchEntry.WidthRequest = 187;
- topHBox.PackEnd (packageSearchEntry);
-
- this.HeaderContent = topHBox;
-
- // Middle of dialog:
- // Packages and package information.
- var mainVBox = new VBox ();
- Content = mainVBox;
-
- var middleHBox = new HBox ();
- middleHBox.Spacing = 0;
- var middleFrame = new FrameBox ();
- middleFrame.Content = middleHBox;
- middleFrame.BorderWidth = new WidgetSpacing (0, 0, 0, 1);
- middleFrame.BorderColor = Styles.LineBorderColor;
- mainVBox.PackStart (middleFrame, true, true);
-
- // Error information.
- var packagesListVBox = new VBox ();
- packagesListVBox.Spacing = 0;
- errorMessageHBox = new HBox ();
- errorMessageHBox.Margin = new WidgetSpacing ();
- errorMessageHBox.BackgroundColor = Styles.ErrorBackgroundColor;
- errorMessageHBox.Visible = false;
- var errorImage = new ImageView ();
- errorImage.Margin = new WidgetSpacing (10, 0, 0, 0);
- errorImage.Image = ImageService.GetIcon (MonoDevelop.Ide.Gui.Stock.Warning, Gtk.IconSize.Menu);
- errorImage.HorizontalPlacement = WidgetPlacement.End;
- errorMessageHBox.PackStart (errorImage);
- errorMessageLabel = new Label ();
- errorMessageLabel.TextColor = Styles.ErrorForegroundColor;
- errorMessageLabel.Margin = new WidgetSpacing (5, 5, 5, 5);
- errorMessageLabel.Wrap = WrapMode.Word;
- errorMessageHBox.PackStart (errorMessageLabel, true);
- packagesListVBox.PackStart (errorMessageHBox);
-
- // Packages list.
- middleHBox.PackStart (packagesListVBox, true, true);
- packagesListView = new ListView ();
- packagesListView.BorderVisible = false;
- packagesListView.HeadersVisible = false;
- packagesListVBox.PackStart (packagesListView, true, true);
-
- // Loading spinner.
- var loadingSpinnerHBox = new HBox ();
- loadingSpinnerHBox.HorizontalPlacement = WidgetPlacement.Center;
- var loadingSpinner = new Spinner ();
- loadingSpinner.Animate = true;
- loadingSpinner.MinWidth = 20;
- loadingSpinnerHBox.PackStart (loadingSpinner);
-
- loadingSpinnerLabel = new Label ();
- loadingSpinnerLabel.Text = Catalog.GetString ("Loading package list...");
- loadingSpinnerHBox.PackEnd (loadingSpinnerLabel);
-
- loadingSpinnerFrame = new FrameBox ();
- loadingSpinnerFrame.Visible = false;
- loadingSpinnerFrame.BackgroundColor = Styles.BackgroundColor;
- loadingSpinnerFrame.Content = loadingSpinnerHBox;
- loadingSpinnerFrame.BorderWidth = new WidgetSpacing ();
- packagesListVBox.PackStart (loadingSpinnerFrame, true, true);
-
- // No packages found label.
- var noPackagesFoundHBox = new HBox ();
- noPackagesFoundHBox.HorizontalPlacement = WidgetPlacement.Center;
-
- var noPackagesFoundLabel = new Label ();
- noPackagesFoundLabel.Text = Catalog.GetString ("No matching packages found.");
- noPackagesFoundHBox.PackEnd (noPackagesFoundLabel);
-
- noPackagesFoundFrame = new FrameBox ();
- noPackagesFoundFrame.Visible = false;
- noPackagesFoundFrame.BackgroundColor = Styles.BackgroundColor;
- noPackagesFoundFrame.Content = noPackagesFoundHBox;
- noPackagesFoundFrame.BorderWidth = new WidgetSpacing ();
- packagesListVBox.PackStart (noPackagesFoundFrame, true, true);
-
- // Package information
- packageInfoVBox = new VBox ();
- var packageInfoFrame = new FrameBox ();
- packageInfoFrame.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageInfoFrame.BorderWidth = new WidgetSpacing ();
- packageInfoFrame.Content = packageInfoVBox;
- packageInfoVBox.Margin = new WidgetSpacing (15, 12, 15, 12);
- var packageInfoContainerVBox = new VBox ();
- packageInfoContainerVBox.WidthRequest = 240;
- packageInfoContainerVBox.PackStart (packageInfoFrame, true, true);
-
- var packageInfoScrollView = new ScrollView ();
- packageInfoScrollView.BorderVisible = false;
- packageInfoScrollView.HorizontalScrollPolicy = ScrollPolicy.Never;
- packageInfoScrollView.Content = packageInfoContainerVBox;
- packageInfoScrollView.BackgroundColor = Styles.PackageInfoBackgroundColor;
- var packageInfoScrollViewFrame = new FrameBox ();
- packageInfoScrollViewFrame.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageInfoScrollViewFrame.BorderWidth = new WidgetSpacing (1, 0, 0, 0);
- packageInfoScrollViewFrame.BorderColor = Styles.LineBorderColor;
- packageInfoScrollViewFrame.Content = packageInfoScrollView;
-
- // Package name and version.
- var packageNameHBox = new HBox ();
- packageInfoVBox.PackStart (packageNameHBox);
-
- packageNameLabel = new Label ();
- packageNameLabel.Ellipsize = EllipsizeMode.End;
- Font packageInfoSmallFont = packageNameLabel.Font.WithSize (packageInfoFontSize);
- Font packageInfoBoldFont = packageInfoSmallFont.WithWeight (FontWeight.Bold);
- packageNameLabel.Font = packageInfoSmallFont;
- packageNameHBox.PackStart (packageNameLabel, true);
-
- // Package description.
- packageDescription = new Label ();
- packageDescription.Wrap = WrapMode.Word;
- packageDescription.Font = packageNameLabel.Font.WithSize (packageInfoFontSize);
- packageDescription.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageInfoVBox.PackStart (packageDescription);
-
- // Package id.
- var packageIdHBox = new HBox ();
- packageIdHBox.MarginTop = 7;
- packageInfoVBox.PackStart (packageIdHBox);
-
- var packageIdLabel = new Label ();
+// +// ManagePackagesDialog.UI.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://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. + +using ExtendedTitleBarDialog = MonoDevelop.Components.ExtendedTitleBarDialog; +using InformationPopoverWidget = MonoDevelop.Components.InformationPopoverWidget; +using System; +using MonoDevelop.Core; +using MonoDevelop.Ide; +using Xwt; +using Xwt.Drawing; + +namespace MonoDevelop.PackageManagement +{ + internal partial class ManagePackagesDialog : ExtendedTitleBarDialog + { + ComboBox packageSourceComboBox; + SearchTextEntry packageSearchEntry; + ListView packagesListView; + VBox packageInfoVBox; + HBox packageNameHBox; + Label packageNameLabel; + LinkLabel packageIdLink; + Label packageDescription; + Label packageAuthor; + Label packagePublishedDate; + Label packageDownloads; + LinkLabel packageLicenseLink; + LinkLabel packageProjectPageLink; + Label packageDependenciesList; + HBox packageDependenciesHBox; + HBox packageDependenciesListHBox; + Label packageDependenciesNoneLabel; + CheckBox showPrereleaseCheckBox; + Label packageId; + Button addPackagesButton; + FrameBox loadingSpinnerFrame; + HBox errorMessageHBox; + Label errorMessageLabel; + Label loadingSpinnerLabel; + FrameBox noPackagesFoundFrame; + ComboBox packageVersionComboBox; + HBox packageVersionsHBox; + Label packageVersionsLabel; + Label browseLabel; + Label installedLabel; + Label updatesLabel; + Label consolidateLabel; + VBox projectsListViewVBox; + Label projectsListViewLabel; + ListView projectsListView; + HBox currentPackageVersionHBox; + Label currentPackageVersionLabel; + Label currentPackageVersion; + InformationPopoverWidget currentPackageVersionInfoPopoverWidget; + Button closeButton; + int packageInfoFontSize = 11; + + void Build () + { + Title = GettextCatalog.GetString ("Manage NuGet Packages – Solution"); + Width = 840; + Height = 528; + Padding = new WidgetSpacing (); + + if (Platform.IsWindows) { + packageInfoFontSize = 9; + } + + // Top part of dialog: + // Package sources and search. + var topHBox = new HBox (); + topHBox.Margin = new WidgetSpacing (8, 5, 6, 5); + + packageSourceComboBox = new ComboBox (); + packageSourceComboBox.Name = "packageSourceComboBox"; + packageSourceComboBox.MinWidth = 200; + topHBox.PackStart (packageSourceComboBox); + + int tabLabelMinWidth = 60; + browseLabel = new Label (); + browseLabel.Text = GettextCatalog.GetString ("Browse"); + browseLabel.Tag = browseLabel.Text; + browseLabel.MinWidth = tabLabelMinWidth; + browseLabel.MarginLeft = 10; + topHBox.PackStart (browseLabel); + + installedLabel = new Label (); + installedLabel.Text = GettextCatalog.GetString ("Installed"); + installedLabel.Tag = installedLabel.Text; + installedLabel.MinWidth = tabLabelMinWidth; + topHBox.PackStart (installedLabel); + + updatesLabel = new Label (); + updatesLabel.Text = GettextCatalog.GetString ("Updates"); + updatesLabel.Tag = updatesLabel.Text; + updatesLabel.MinWidth = tabLabelMinWidth; + topHBox.PackStart (updatesLabel); + + consolidateLabel = new Label (); + consolidateLabel.Text = GettextCatalog.GetString ("Consolidate"); + consolidateLabel.Tag = consolidateLabel.Text; + consolidateLabel.MinWidth = tabLabelMinWidth; + topHBox.PackStart (consolidateLabel); + + packageSearchEntry = new SearchTextEntry (); + packageSearchEntry.Name = "managePackagesDialogSearchEntry"; + packageSearchEntry.WidthRequest = 187; + topHBox.PackEnd (packageSearchEntry); + + this.HeaderContent = topHBox; + + // Middle of dialog: + // Packages and package information. + var mainVBox = new VBox (); + Content = mainVBox; + + var middleHBox = new HBox (); + middleHBox.Spacing = 0; + var middleFrame = new FrameBox (); + middleFrame.Content = middleHBox; + middleFrame.BorderWidth = new WidgetSpacing (0, 0, 0, 1); + middleFrame.BorderColor = Styles.LineBorderColor; + mainVBox.PackStart (middleFrame, true, true); + + // Error information. + var packagesListVBox = new VBox (); + packagesListVBox.Spacing = 0; + errorMessageHBox = new HBox (); + errorMessageHBox.Margin = new WidgetSpacing (); + errorMessageHBox.BackgroundColor = Styles.ErrorBackgroundColor; + errorMessageHBox.Visible = false; + var errorImage = new ImageView (); + errorImage.Margin = new WidgetSpacing (10, 0, 0, 0); + errorImage.Image = ImageService.GetIcon (MonoDevelop.Ide.Gui.Stock.Warning, Gtk.IconSize.Menu); + errorImage.HorizontalPlacement = WidgetPlacement.End; + errorMessageHBox.PackStart (errorImage); + errorMessageLabel = new Label (); + errorMessageLabel.TextColor = Styles.ErrorForegroundColor; + errorMessageLabel.Margin = new WidgetSpacing (5, 5, 5, 5); + errorMessageLabel.Wrap = WrapMode.Word; + errorMessageHBox.PackStart (errorMessageLabel, true); + packagesListVBox.PackStart (errorMessageHBox); + + // Packages list. + middleHBox.PackStart (packagesListVBox, true, true); + packagesListView = new ListView (); + packagesListView.BorderVisible = false; + packagesListView.HeadersVisible = false; + packagesListVBox.PackStart (packagesListView, true, true); + + // Loading spinner. + var loadingSpinnerHBox = new HBox (); + loadingSpinnerHBox.HorizontalPlacement = WidgetPlacement.Center; + var loadingSpinner = new Spinner (); + loadingSpinner.Animate = true; + loadingSpinner.MinWidth = 20; + loadingSpinnerHBox.PackStart (loadingSpinner); + + loadingSpinnerLabel = new Label (); + loadingSpinnerLabel.Text = GettextCatalog.GetString ("Loading package list..."); + loadingSpinnerHBox.PackEnd (loadingSpinnerLabel); + + loadingSpinnerFrame = new FrameBox (); + loadingSpinnerFrame.Visible = false; + loadingSpinnerFrame.BackgroundColor = Styles.BackgroundColor; + loadingSpinnerFrame.Content = loadingSpinnerHBox; + loadingSpinnerFrame.BorderWidth = new WidgetSpacing (); + packagesListVBox.PackStart (loadingSpinnerFrame, true, true); + + // No packages found label. + var noPackagesFoundHBox = new HBox (); + noPackagesFoundHBox.HorizontalPlacement = WidgetPlacement.Center; + + var noPackagesFoundLabel = new Label (); + noPackagesFoundLabel.Text = GettextCatalog.GetString ("No matching packages found."); + noPackagesFoundHBox.PackEnd (noPackagesFoundLabel); + + noPackagesFoundFrame = new FrameBox (); + noPackagesFoundFrame.Visible = false; + noPackagesFoundFrame.BackgroundColor = Styles.BackgroundColor; + noPackagesFoundFrame.Content = noPackagesFoundHBox; + noPackagesFoundFrame.BorderWidth = new WidgetSpacing (); + packagesListVBox.PackStart (noPackagesFoundFrame, true, true); + + // Package information + packageInfoVBox = new VBox (); + var packageInfoFrame = new FrameBox (); + packageInfoFrame.BackgroundColor = Styles.PackageInfoBackgroundColor; + packageInfoFrame.BorderWidth = new WidgetSpacing (); + packageInfoFrame.Content = packageInfoVBox; + packageInfoVBox.Margin = new WidgetSpacing (15, 12, 15, 12); + var packageInfoContainerVBox = new VBox (); + packageInfoContainerVBox.WidthRequest = 328; + packageInfoContainerVBox.PackStart (packageInfoFrame, true, true); + + var packageInfoScrollView = new ScrollView (); + packageInfoScrollView.BorderVisible = false; + packageInfoScrollView.HorizontalScrollPolicy = ScrollPolicy.Never; + packageInfoScrollView.Content = packageInfoContainerVBox; + packageInfoScrollView.BackgroundColor = Styles.PackageInfoBackgroundColor; + var packageInfoScrollViewFrame = new FrameBox (); + packageInfoScrollViewFrame.BackgroundColor = Styles.PackageInfoBackgroundColor; + packageInfoScrollViewFrame.BorderWidth = new WidgetSpacing (1, 0, 0, 0); + packageInfoScrollViewFrame.BorderColor = Styles.LineBorderColor; + packageInfoScrollViewFrame.Content = packageInfoScrollView; + + // Package name and version. + packageNameHBox = new HBox (); + packageInfoVBox.PackStart (packageNameHBox); + + packageNameLabel = new Label (); + packageNameLabel.Ellipsize = EllipsizeMode.End; + Font packageInfoSmallFont = packageNameLabel.Font.WithSize (packageInfoFontSize); + Font packageInfoBoldFont = packageInfoSmallFont.WithWeight (FontWeight.Bold); + packageNameLabel.Font = packageInfoSmallFont; + packageNameHBox.PackStart (packageNameLabel, true); + + // Projects list view label. + projectsListViewLabel = new Label (); + projectsListViewLabel.Wrap = WrapMode.Word; + projectsListViewLabel.BackgroundColor = Styles.PackageInfoBackgroundColor; + packageInfoVBox.PackStart (projectsListViewLabel); + + // Projects list view. + projectsListViewVBox = new VBox (); + projectsListViewVBox.Margin = new WidgetSpacing (); + packageInfoVBox.PackStart (projectsListViewVBox, true, true); + + // Package description. + packageDescription = new Label (); + packageDescription.Wrap = WrapMode.Word; + packageDescription.Font = packageNameLabel.Font.WithSize (packageInfoFontSize); + packageDescription.BackgroundColor = Styles.PackageInfoBackgroundColor; + packageInfoVBox.PackStart (packageDescription); + + // Package id. + var packageIdHBox = new HBox (); + packageIdHBox.MarginTop = 7; + packageInfoVBox.PackStart (packageIdHBox); + + var packageIdLabel = new Label (); packageIdLabel.Font = packageInfoBoldFont;
- packageIdLabel.Text = Catalog.GetString ("Id");
- packageIdHBox.PackStart (packageIdLabel);
-
- packageId = new Label ();
- packageId.Ellipsize = EllipsizeMode.End;
- packageId.TextAlignment = Alignment.End;
- packageId.Font = packageInfoSmallFont;
- packageIdLink = new LinkLabel ();
- packageIdLink.Ellipsize = EllipsizeMode.End;
- packageIdLink.TextAlignment = Alignment.End;
- packageIdLink.Font = packageInfoSmallFont;
- packageIdHBox.PackEnd (packageIdLink, true);
- packageIdHBox.PackEnd (packageId, true);
-
- // Package author
- var packageAuthorHBox = new HBox ();
- packageInfoVBox.PackStart (packageAuthorHBox);
-
- var packageAuthorLabel = new Label ();
- packageAuthorLabel.Text = Catalog.GetString ("Author");
- packageAuthorLabel.Font = packageInfoBoldFont;
- packageAuthorHBox.PackStart (packageAuthorLabel);
-
- packageAuthor = new Label ();
- packageAuthor.TextAlignment = Alignment.End;
- packageAuthor.Ellipsize = EllipsizeMode.End;
- packageAuthor.Font = packageInfoSmallFont;
- packageAuthorHBox.PackEnd (packageAuthor, true);
-
- // Package published
- var packagePublishedHBox = new HBox ();
- packageInfoVBox.PackStart (packagePublishedHBox);
-
- var packagePublishedLabel = new Label ();
- packagePublishedLabel.Text = Catalog.GetString ("Published");
- packagePublishedLabel.Font = packageInfoBoldFont;
- packagePublishedHBox.PackStart (packagePublishedLabel);
-
- packagePublishedDate = new Label ();
- packagePublishedDate.Font = packageInfoSmallFont;
- packagePublishedHBox.PackEnd (packagePublishedDate);
-
- // Package downloads
- var packageDownloadsHBox = new HBox ();
- packageInfoVBox.PackStart (packageDownloadsHBox);
-
- var packageDownloadsLabel = new Label ();
- packageDownloadsLabel.Text = Catalog.GetString ("Downloads");
- packageDownloadsLabel.Font = packageInfoBoldFont;
- packageDownloadsHBox.PackStart (packageDownloadsLabel);
-
- packageDownloads = new Label ();
- packageDownloads.Font = packageInfoSmallFont;
- packageDownloadsHBox.PackEnd (packageDownloads);
-
- // Package license.
- var packageLicenseHBox = new HBox ();
- packageInfoVBox.PackStart (packageLicenseHBox);
-
- var packageLicenseLabel = new Label ();
- packageLicenseLabel.Text = Catalog.GetString ("License");
+ packageIdLabel.Text = GettextCatalog.GetString ("Id"); + packageIdHBox.PackStart (packageIdLabel); + + packageId = new Label (); + packageId.Ellipsize = EllipsizeMode.End; + packageId.TextAlignment = Alignment.End; + packageId.Font = packageInfoSmallFont; + packageIdLink = new LinkLabel (); + packageIdLink.Ellipsize = EllipsizeMode.End; + packageIdLink.TextAlignment = Alignment.End; + packageIdLink.Font = packageInfoSmallFont; + packageIdHBox.PackEnd (packageIdLink, true); + packageIdHBox.PackEnd (packageId, true); + + // Package author + var packageAuthorHBox = new HBox (); + packageInfoVBox.PackStart (packageAuthorHBox); + + var packageAuthorLabel = new Label (); + packageAuthorLabel.Text = GettextCatalog.GetString ("Author"); + packageAuthorLabel.Font = packageInfoBoldFont; + packageAuthorHBox.PackStart (packageAuthorLabel); + + packageAuthor = new Label (); + packageAuthor.TextAlignment = Alignment.End; + packageAuthor.Ellipsize = EllipsizeMode.End; + packageAuthor.Font = packageInfoSmallFont; + packageAuthorHBox.PackEnd (packageAuthor, true); + + // Package published + var packagePublishedHBox = new HBox (); + packageInfoVBox.PackStart (packagePublishedHBox); + + var packagePublishedLabel = new Label (); + packagePublishedLabel.Text = GettextCatalog.GetString ("Published"); + packagePublishedLabel.Font = packageInfoBoldFont; + packagePublishedHBox.PackStart (packagePublishedLabel); + + packagePublishedDate = new Label (); + packagePublishedDate.Font = packageInfoSmallFont; + packagePublishedHBox.PackEnd (packagePublishedDate); + + // Package downloads + var packageDownloadsHBox = new HBox (); + packageInfoVBox.PackStart (packageDownloadsHBox); + + var packageDownloadsLabel = new Label (); + packageDownloadsLabel.Text = GettextCatalog.GetString ("Downloads"); + packageDownloadsLabel.Font = packageInfoBoldFont; + packageDownloadsHBox.PackStart (packageDownloadsLabel); + + packageDownloads = new Label (); + packageDownloads.Font = packageInfoSmallFont; + packageDownloadsHBox.PackEnd (packageDownloads); + + // Package license. + var packageLicenseHBox = new HBox (); + packageInfoVBox.PackStart (packageLicenseHBox); + + var packageLicenseLabel = new Label (); + packageLicenseLabel.Text = GettextCatalog.GetString ("License");
packageLicenseLabel.Font = packageInfoBoldFont;
- packageLicenseHBox.PackStart (packageLicenseLabel);
-
- packageLicenseLink = new LinkLabel ();
- packageLicenseLink.Text = Catalog.GetString ("View License");
- packageLicenseLink.Font = packageInfoSmallFont;
- packageLicenseHBox.PackEnd (packageLicenseLink);
-
- // Package project page.
- var packageProjectPageHBox = new HBox ();
- packageInfoVBox.PackStart (packageProjectPageHBox);
-
- var packageProjectPageLabel = new Label ();
- packageProjectPageLabel.Text = Catalog.GetString ("Project Page");
- packageProjectPageLabel.Font = packageInfoBoldFont;
- packageProjectPageHBox.PackStart (packageProjectPageLabel);
-
- packageProjectPageLink = new LinkLabel ();
- packageProjectPageLink.Text = Catalog.GetString ("Visit Page");
- packageProjectPageLink.Font = packageInfoSmallFont;
- packageProjectPageHBox.PackEnd (packageProjectPageLink);
-
- // Package dependencies
- packageDependenciesHBox = new HBox ();
- packageInfoVBox.PackStart (packageDependenciesHBox);
-
- var packageDependenciesLabel = new Label ();
- packageDependenciesLabel.Text = Catalog.GetString ("Dependencies");
- packageDependenciesLabel.Font = packageInfoBoldFont;
- packageDependenciesHBox.PackStart (packageDependenciesLabel);
-
- packageDependenciesNoneLabel = new Label ();
- packageDependenciesNoneLabel.Text = Catalog.GetString ("None");
- packageDependenciesNoneLabel.Font = packageInfoSmallFont;
- packageDependenciesHBox.PackEnd (packageDependenciesNoneLabel);
-
- // Package dependencies list.
- packageDependenciesListHBox = new HBox ();
- packageDependenciesListHBox.Visible = false;
- packageInfoVBox.PackStart (packageDependenciesListHBox);
-
- packageDependenciesList = new Label ();
- packageDependenciesList.Wrap = WrapMode.WordAndCharacter;
- packageDependenciesList.Margin = new WidgetSpacing (5);
- packageDependenciesList.Font = packageInfoSmallFont;
- packageDependenciesListHBox.PackStart (packageDependenciesList, true);
-
- // Package versions.
- packageVersionsHBox = new HBox ();
- packageVersionsHBox.Visible = false;
- packageVersionsHBox.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageVersionsHBox.Margin = new WidgetSpacing (15, 0, 15, 12);
- var packageVersionsLabel = new Label ();
- packageVersionsLabel.Font = packageInfoBoldFont;
- packageVersionsLabel.Text = Catalog.GetString ("Version");
- packageVersionsHBox.PackStart (packageVersionsLabel);
-
- packageVersionComboBox = new ComboBox ();
- packageVersionComboBox.Name = "packageVersionComboBox";
- packageVersionsHBox.Spacing = 15;
- packageVersionsHBox.PackStart (packageVersionComboBox, true, true);
-
- var packageInfoAndVersionsVBox = new VBox ();
- packageInfoAndVersionsVBox.Margin = new WidgetSpacing ();
- packageInfoAndVersionsVBox.BackgroundColor = Styles.PackageInfoBackgroundColor;
- packageInfoAndVersionsVBox.PackStart (packageInfoScrollViewFrame, true, true);
- packageInfoAndVersionsVBox.PackStart (packageVersionsHBox, false, false);
- middleHBox.PackEnd (packageInfoAndVersionsVBox);
-
- // Bottom part of dialog:
- // Show pre-release packages and Close/Add to Project buttons.
- var bottomHBox = new HBox ();
- bottomHBox.Margin = new WidgetSpacing (8, 5, 14, 10);
- bottomHBox.Spacing = 5;
- mainVBox.PackStart (bottomHBox);
-
- showPrereleaseCheckBox = new CheckBox ();
- showPrereleaseCheckBox.Name = "addPackagesDialogShowPreReleaseCheckBox";
- showPrereleaseCheckBox.Label = Catalog.GetString ("Show pre-release packages");
- bottomHBox.PackStart (showPrereleaseCheckBox);
-
- addPackagesButton = new Button ();
- addPackagesButton.Name = "addPackagesDialogAddPackageButton";
- addPackagesButton.MinWidth = 120;
- addPackagesButton.MinHeight = 25;
- addPackagesButton.Label = Catalog.GetString ("Add Package");
- bottomHBox.PackEnd (addPackagesButton);
-
- var closeButton = new Button ();
- closeButton.Name = "addPackagesDialogCloseButton";
- closeButton.MinWidth = 120;
- closeButton.MinHeight = 25;
- closeButton.Label = Catalog.GetString ("Close");
- closeButton.Clicked += (sender, e) => Close ();
- bottomHBox.PackEnd (closeButton);
-
- packageSearchEntry.SetFocus ();
- packageInfoVBox.Visible = false;
- }
- }
-}
-
+ packageLicenseHBox.PackStart (packageLicenseLabel); + + packageLicenseLink = new LinkLabel (); + packageLicenseLink.Text = GettextCatalog.GetString ("View License"); + packageLicenseLink.Font = packageInfoSmallFont; + packageLicenseHBox.PackEnd (packageLicenseLink); + + // Package project page. + var packageProjectPageHBox = new HBox (); + packageInfoVBox.PackStart (packageProjectPageHBox); + + var packageProjectPageLabel = new Label (); + packageProjectPageLabel.Text = GettextCatalog.GetString ("Project Page"); + packageProjectPageLabel.Font = packageInfoBoldFont; + packageProjectPageHBox.PackStart (packageProjectPageLabel); + + packageProjectPageLink = new LinkLabel (); + packageProjectPageLink.Text = GettextCatalog.GetString ("Visit Page"); + packageProjectPageLink.Font = packageInfoSmallFont; + packageProjectPageHBox.PackEnd (packageProjectPageLink); + + // Package dependencies + packageDependenciesHBox = new HBox (); + packageInfoVBox.PackStart (packageDependenciesHBox); + + var packageDependenciesLabel = new Label (); + packageDependenciesLabel.Text = GettextCatalog.GetString ("Dependencies"); + packageDependenciesLabel.Font = packageInfoBoldFont; + packageDependenciesHBox.PackStart (packageDependenciesLabel); + + packageDependenciesNoneLabel = new Label (); + packageDependenciesNoneLabel.Text = GettextCatalog.GetString ("None"); + packageDependenciesNoneLabel.Font = packageInfoSmallFont; + packageDependenciesHBox.PackEnd (packageDependenciesNoneLabel); + + // Package dependencies list. + packageDependenciesListHBox = new HBox (); + packageDependenciesListHBox.Visible = false; + packageInfoVBox.PackStart (packageDependenciesListHBox); + + packageDependenciesList = new Label (); + packageDependenciesList.Wrap = WrapMode.WordAndCharacter; + packageDependenciesList.Margin = new WidgetSpacing (5); + packageDependenciesList.Font = packageInfoSmallFont; + packageDependenciesListHBox.PackStart (packageDependenciesList, true); + + // Current package version. + currentPackageVersionHBox = new HBox (); + currentPackageVersionHBox.Spacing = 15; + currentPackageVersionHBox.Visible = false; + currentPackageVersionHBox.BackgroundColor = Styles.PackageInfoBackgroundColor; + currentPackageVersionHBox.Margin = new WidgetSpacing (15, 0, 15, 0); + currentPackageVersionLabel = new Label (); + currentPackageVersionLabel.BoundsChanged += PackageVersionLabelBoundsChanged; + currentPackageVersionLabel.Font = packageInfoSmallFont; + currentPackageVersionLabel.Text = GettextCatalog.GetString ("Current Version:"); + currentPackageVersionLabel.TextAlignment = Alignment.End; + currentPackageVersionHBox.PackStart (currentPackageVersionLabel); + + var currentPackageVersionWithInfoPopoverHBox = new HBox (); + currentPackageVersionWithInfoPopoverHBox.Margin = new WidgetSpacing (); + currentPackageVersionWithInfoPopoverHBox.Spacing = 0; + + currentPackageVersion = new Label (); + currentPackageVersion.Font = packageInfoSmallFont; + currentPackageVersionWithInfoPopoverHBox.PackStart (currentPackageVersion); + + currentPackageVersionInfoPopoverWidget = new InformationPopoverWidget (); + currentPackageVersionInfoPopoverWidget.Severity = Ide.Tasks.TaskSeverity.Information; + currentPackageVersionInfoPopoverWidget.Margin = new WidgetSpacing (5, 0, 0, 2); + currentPackageVersionWithInfoPopoverHBox.PackStart (currentPackageVersionInfoPopoverWidget); + + currentPackageVersionHBox.PackStart (currentPackageVersionWithInfoPopoverHBox); + + // Package versions. + packageVersionsHBox = new HBox (); + packageVersionsHBox.Visible = false; + packageVersionsHBox.BackgroundColor = Styles.PackageInfoBackgroundColor; + packageVersionsHBox.Margin = new WidgetSpacing (15, 0, 15, 12); + packageVersionsLabel = new Label (); + packageVersionsLabel.Font = packageInfoSmallFont; + packageVersionsLabel.Text = GettextCatalog.GetString ("New Version:"); + packageVersionsLabel.TextAlignment = Alignment.End; + packageVersionsHBox.PackStart (packageVersionsLabel); + + packageVersionComboBox = new ComboBox (); + packageVersionComboBox.Name = "packageVersionComboBox"; + packageVersionsHBox.Spacing = 15; + packageVersionsHBox.PackStart (packageVersionComboBox, true, true); + + var packageInfoAndVersionsVBox = new VBox (); + packageInfoAndVersionsVBox.Margin = new WidgetSpacing (); + packageInfoAndVersionsVBox.BackgroundColor = Styles.PackageInfoBackgroundColor; + packageInfoAndVersionsVBox.PackStart (packageInfoScrollViewFrame, true, true); + packageInfoAndVersionsVBox.PackStart (currentPackageVersionHBox, false, false); + packageInfoAndVersionsVBox.PackStart (packageVersionsHBox, false, false); + middleHBox.PackEnd (packageInfoAndVersionsVBox); + + // Bottom part of dialog: + // Show pre-release packages and Close/Add to Project buttons. + var bottomHBox = new HBox (); + bottomHBox.Margin = new WidgetSpacing (8, 5, 14, 10); + bottomHBox.Spacing = 5; + mainVBox.PackStart (bottomHBox); + + showPrereleaseCheckBox = new CheckBox (); + showPrereleaseCheckBox.Name = "managePackagesDialogShowPreReleaseCheckBox"; + showPrereleaseCheckBox.Label = GettextCatalog.GetString ("Show pre-release packages"); + bottomHBox.PackStart (showPrereleaseCheckBox); + + addPackagesButton = new Button (); + addPackagesButton.Name = "managePackagesDialogAddPackageButton"; + addPackagesButton.MinWidth = 120; + addPackagesButton.MinHeight = 25; + addPackagesButton.Label = GettextCatalog.GetString ("Add Package"); + bottomHBox.PackEnd (addPackagesButton); + + closeButton = new Button (); + closeButton.Name = "managePackagesDialogCloseButton"; + closeButton.MinWidth = 120; + closeButton.MinHeight = 25; + closeButton.Label = GettextCatalog.GetString ("Close"); + bottomHBox.PackEnd (closeButton); + + packageSearchEntry.SetFocus (); + packageInfoVBox.Visible = false; + } + + double? maxPackageVersionLabelWidth; + + void PackageVersionLabelBoundsChanged (object sender, EventArgs e) + { + if (!viewModel.IsUpdatesPageSelected) + return; + + double currentPackageVersionLabelWidth = currentPackageVersionLabel.Size.Width; + double packageVersionsLabelWidth = packageVersionsLabel.Size.Width; + + if (currentPackageVersionLabelWidth > packageVersionsLabelWidth) { + packageVersionsLabel.WidthRequest = currentPackageVersionLabelWidth; + maxPackageVersionLabelWidth = currentPackageVersionLabelWidth; + } else if (packageVersionsLabelWidth > currentPackageVersionLabelWidth) { + currentPackageVersionLabel.WidthRequest = packageVersionsLabelWidth; + maxPackageVersionLabelWidth = packageVersionsLabelWidth; + } + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs index d6e867e140..2cf875404d 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialog.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialog.cs @@ -1,822 +1,1200 @@ -//
-// AddPackagesDialog.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://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.
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using Mono.Unix;
-using MonoDevelop.Core;
-using MonoDevelop.Ide;
-using MonoDevelop.Projects;
-using NuGet.Versioning;
-using Xwt;
-using Xwt.Drawing;
-using PropertyChangedEventArgs = System.ComponentModel.PropertyChangedEventArgs;
-
-namespace MonoDevelop.PackageManagement
-{
- internal partial class AddPackagesDialog
- {
- IBackgroundPackageActionRunner backgroundActionRunner;
- AllPackagesViewModel viewModel;
- List<SourceRepositoryViewModel> packageSources;
- DataField<bool> packageHasBackgroundColorField = new DataField<bool> ();
- DataField<PackageSearchResultViewModel> packageViewModelField = new DataField<PackageSearchResultViewModel> ();
- DataField<Image> packageImageField = new DataField<Image> ();
- DataField<double> packageCheckBoxAlphaField = new DataField<double> ();
- const double packageCheckBoxSemiTransarentAlpha = 0.6;
- ListStore packageStore;
- PackageCellView packageCellView;
- TimeSpan searchDelayTimeSpan = TimeSpan.FromMilliseconds (500);
- IDisposable searchTimer;
- SourceRepositoryViewModel dummyPackageSourceRepresentingConfigureSettingsItem =
- new SourceRepositoryViewModel (Catalog.GetString ("Configure Sources..."));
- ImageLoader imageLoader = new ImageLoader ();
- bool loadingMessageVisible;
- bool ignorePackageVersionChanges;
- const string IncludePrereleaseUserPreferenceName = "NuGet.AddPackagesDialog.IncludePrerelease";
- TimeSpan populatePackageVersionsDelayTimeSpan = TimeSpan.FromMilliseconds (500);
- int packageVersionsAddedCount;
- IDisposable populatePackageVersionsTimer;
- const int MaxVersionsToPopulate = 100;
-
- public AddPackagesDialog (AllPackagesViewModel viewModel, string initialSearch = null)
- : this (
- viewModel,
- initialSearch,
- PackageManagementServices.BackgroundPackageActionRunner)
- {
- }
-
- public AddPackagesDialog (
- AllPackagesViewModel viewModel,
- string initialSearch,
- IBackgroundPackageActionRunner backgroundActionRunner)
- {
- this.viewModel = viewModel;
- this.backgroundActionRunner = backgroundActionRunner;
-
- Build ();
-
- UpdatePackageSearchEntryWithInitialText (initialSearch);
-
- InitializeListView ();
- UpdateAddPackagesButton ();
- ShowLoadingMessage ();
- LoadViewModel (initialSearch);
-
- this.showPrereleaseCheckBox.Clicked += ShowPrereleaseCheckBoxClicked;
- this.packageSourceComboBox.SelectionChanged += PackageSourceChanged;
- this.addPackagesButton.Clicked += AddPackagesButtonClicked;
- this.packageSearchEntry.Changed += PackageSearchEntryChanged;
- this.packageSearchEntry.Activated += PackageSearchEntryActivated;
- this.packageVersionComboBox.SelectionChanged += PackageVersionChanged;
- imageLoader.Loaded += ImageLoaded;
- }
-
- public bool ShowPreferencesForPackageSources { get; private set; }
-
- protected override void Dispose (bool disposing)
- {
- imageLoader.Loaded -= ImageLoaded;
- imageLoader.Dispose ();
-
- RemoveSelectedPackagePropertyChangedEventHandler ();
- viewModel.PropertyChanged -= ViewModelPropertyChanged;
- viewModel.Dispose ();
- DisposeExistingTimer ();
- DisposePopulatePackageVersionsTimer ();
- packageStore.Clear ();
- viewModel = null;
- base.Dispose (disposing);
- }
-
- void UpdatePackageSearchEntryWithInitialText (string initialSearch)
- {
- packageSearchEntry.Text = initialSearch;
- if (!String.IsNullOrEmpty (initialSearch)) {
- packageSearchEntry.CursorPosition = initialSearch.Length;
- }
- }
-
- public string SearchText {
- get { return packageSearchEntry.Text; }
- }
-
- void InitializeListView ()
- {
- packageStore = new ListStore (packageHasBackgroundColorField, packageCheckBoxAlphaField, packageImageField, packageViewModelField);
- packagesListView.DataSource = packageStore;
-
- AddPackageCellViewToListView ();
-
- packagesListView.SelectionChanged += PackagesListViewSelectionChanged;
- packagesListView.RowActivated += PackagesListRowActivated;
- packagesListView.VerticalScrollControl.ValueChanged += PackagesListViewScrollValueChanged;
- }
-
- void AddPackageCellViewToListView ()
- {
- packageCellView = new PackageCellView {
- PackageField = packageViewModelField,
- HasBackgroundColorField = packageHasBackgroundColorField,
- CheckBoxAlphaField = packageCheckBoxAlphaField,
- ImageField = packageImageField,
- CellWidth = 535
- };
- var textColumn = new ListViewColumn ("Package", packageCellView);
- packagesListView.Columns.Add (textColumn);
-
- packageCellView.PackageChecked += PackageCellViewPackageChecked;
- }
-
- void ShowLoadingMessage ()
- {
- UpdateSpinnerLabel ();
- noPackagesFoundFrame.Visible = false;
- packagesListView.Visible = false;
- loadingSpinnerFrame.Visible = true;
- loadingMessageVisible = true;
- }
-
- void HideLoadingMessage ()
- {
- loadingSpinnerFrame.Visible = false;
- packagesListView.Visible = true;
- noPackagesFoundFrame.Visible = false;
- loadingMessageVisible = false;
- }
-
- void UpdateSpinnerLabel ()
- {
- if (String.IsNullOrWhiteSpace (packageSearchEntry.Text)) {
- loadingSpinnerLabel.Text = Catalog.GetString ("Loading package list...");
- } else {
- loadingSpinnerLabel.Text = Catalog.GetString ("Searching packages...");
- }
- }
-
- void ShowNoPackagesFoundMessage ()
- {
- if (!String.IsNullOrWhiteSpace (packageSearchEntry.Text)) {
- packagesListView.Visible = false;
- noPackagesFoundFrame.Visible = true;
- }
- }
-
- void ShowPrereleaseCheckBoxClicked (object sender, EventArgs e)
- {
- viewModel.IncludePrerelease = !viewModel.IncludePrerelease;
-
- SaveIncludePrereleaseUserPreference ();
- }
-
- void SaveIncludePrereleaseUserPreference ()
- {
- Solution solution = IdeApp.ProjectOperations.CurrentSelectedSolution;
- if (solution != null) {
- if (viewModel.IncludePrerelease) {
- solution.UserProperties.SetValue (IncludePrereleaseUserPreferenceName, viewModel.IncludePrerelease);
- } else {
- solution.UserProperties.RemoveValue (IncludePrereleaseUserPreferenceName);
- }
- solution.SaveUserProperties ();
- }
- }
-
- bool GetIncludePrereleaseUserPreference ()
- {
- Solution solution = IdeApp.ProjectOperations.CurrentSelectedSolution;
- if (solution != null) {
- return solution.UserProperties.GetValue (IncludePrereleaseUserPreferenceName, false);
- }
-
- return false;
- }
-
- void LoadViewModel (string initialSearch)
- {
- viewModel.SearchTerms = initialSearch;
-
- viewModel.IncludePrerelease = GetIncludePrereleaseUserPreference ();
- showPrereleaseCheckBox.Active = viewModel.IncludePrerelease;
-
- ClearSelectedPackageInformation ();
- PopulatePackageSources ();
- viewModel.PropertyChanged += ViewModelPropertyChanged;
-
- if (viewModel.SelectedPackageSource != null) {
- viewModel.ReadPackages ();
- } else {
- HideLoadingMessage ();
- }
- }
-
- void ClearSelectedPackageInformation ()
- {
- this.packageInfoVBox.Visible = false;
- this.packageVersionsHBox.Visible = false;
- }
-
- void RemoveSelectedPackagePropertyChangedEventHandler ()
- {
- if (viewModel.SelectedPackage != null) {
- viewModel.SelectedPackage.PropertyChanged -= SelectedPackageViewModelChanged;
- viewModel.SelectedPackage = null;
- }
- }
-
- List<SourceRepositoryViewModel> PackageSources {
- get {
- if (packageSources == null) {
- packageSources = viewModel.PackageSources.ToList ();
- }
- return packageSources;
- }
- }
-
- void PopulatePackageSources ()
- {
- foreach (SourceRepositoryViewModel packageSource in PackageSources) {
- AddPackageSourceToComboBox (packageSource);
- }
-
- AddPackageSourceToComboBox (dummyPackageSourceRepresentingConfigureSettingsItem);
-
- packageSourceComboBox.SelectedItem = viewModel.SelectedPackageSource;
- }
-
- void AddPackageSourceToComboBox (SourceRepositoryViewModel packageSource)
- {
- packageSourceComboBox.Items.Add (packageSource, packageSource.Name);
- }
-
- void PackageSourceChanged (object sender, EventArgs e)
- {
- var selectedPackageSource = (SourceRepositoryViewModel)packageSourceComboBox.SelectedItem;
- if (selectedPackageSource == dummyPackageSourceRepresentingConfigureSettingsItem) {
- ShowPreferencesForPackageSources = true;
- Close ();
- } else {
- viewModel.SelectedPackageSource = selectedPackageSource;
- }
- }
-
- void PackagesListViewSelectionChanged (object sender, EventArgs e)
- {
- try {
- ShowSelectedPackage ();
- } catch (Exception ex) {
- LoggingService.LogError ("Error showing selected package.", ex);
- ShowErrorMessage (ex.Message);
- }
- }
-
- void ShowSelectedPackage ()
- {
- RemoveSelectedPackagePropertyChangedEventHandler ();
-
- PackageSearchResultViewModel packageViewModel = GetSelectedPackageViewModel ();
- if (packageViewModel != null) {
- ShowPackageInformation (packageViewModel);
- } else {
- ClearSelectedPackageInformation ();
- }
- viewModel.SelectedPackage = packageViewModel;
- UpdateAddPackagesButton ();
- }
-
- PackageSearchResultViewModel GetSelectedPackageViewModel ()
- {
- if (packagesListView.SelectedRow != -1) {
- return packageStore.GetValue (packagesListView.SelectedRow, packageViewModelField);
- }
- return null;
- }
-
- void ShowPackageInformation (PackageSearchResultViewModel packageViewModel)
- {
- // Use the package id and not the package title to prevent a pango crash if the title
- // contains Chinese characters.
- this.packageNameLabel.Markup = packageViewModel.GetIdMarkup ();
- this.packageAuthor.Text = packageViewModel.Author;
- this.packagePublishedDate.Text = packageViewModel.GetLastPublishedDisplayText ();
- this.packageDownloads.Text = packageViewModel.GetDownloadCountDisplayText ();
- this.packageDescription.Text = packageViewModel.Description;
- this.packageId.Text = packageViewModel.Id;
- this.packageId.Visible = packageViewModel.HasNoGalleryUrl;
- ShowUri (this.packageIdLink, packageViewModel.GalleryUrl, packageViewModel.Id);
- ShowUri (this.packageProjectPageLink, packageViewModel.ProjectUrl);
- ShowUri (this.packageLicenseLink, packageViewModel.LicenseUrl);
-
- PopulatePackageDependencies (packageViewModel);
-
- PopulatePackageVersions (packageViewModel);
-
- this.packageInfoVBox.Visible = true;
- this.packageVersionsHBox.Visible = true;
-
- packageViewModel.PropertyChanged += SelectedPackageViewModelChanged;
- viewModel.LoadPackageMetadata (packageViewModel);
- }
- - void ShowUri (LinkLabel linkLabel, Uri uri, string label)
- {
- linkLabel.Text = label;
- ShowUri (linkLabel, uri);
- }
-
- void ShowUri (LinkLabel linkLabel, Uri uri)
- {
- if (uri == null) {
- linkLabel.Visible = false;
- } else {
- linkLabel.Visible = true;
- linkLabel.Uri = uri;
- }
- }
-
- void ViewModelPropertyChanged (object sender, PropertyChangedEventArgs e)
- {
- try {
- ShowPackages ();
- } catch (Exception ex) {
- LoggingService.LogError ("Error showing packages.", ex);
- ShowErrorMessage (ex.Message);
- }
- }
-
- void ShowPackages ()
- {
- if (viewModel.HasError) {
- ShowErrorMessage (viewModel.ErrorMessage);
- } else {
- ClearErrorMessage ();
- }
-
- if (viewModel.IsLoadingNextPage) {
- // Show spinner?
- } else if (viewModel.IsReadingPackages) {
- ClearPackages ();
- } else {
- HideLoadingMessage ();
- }
-
- if (!viewModel.IsLoadingNextPage) {
- AppendPackagesToListView ();
- }
-
- UpdateAddPackagesButton ();
- }
-
- void ClearPackages ()
- {
- packageStore.Clear ();
- ResetPackagesListViewScroll ();
- UpdatePackageListViewSelectionColor ();
- ShowLoadingMessage ();
- ShrinkImageCache ();
- DisposePopulatePackageVersionsTimer ();
- }
-
- void ResetPackagesListViewScroll ()
- {
- packagesListView.VerticalScrollControl.Value = 0;
- }
-
- void ShowErrorMessage (string message)
- {
- errorMessageLabel.Text = message;
- errorMessageHBox.Visible = true;
- }
-
- void ClearErrorMessage ()
- {
- errorMessageHBox.Visible = false;
- errorMessageLabel.Text = "";
- }
-
- void ShrinkImageCache ()
- {
- imageLoader.ShrinkImageCache ();
- }
-
- void AppendPackagesToListView ()
- {
- bool packagesListViewWasEmpty = (packageStore.RowCount == 0);
-
- for (int row = packageStore.RowCount; row < viewModel.PackageViewModels.Count; ++row) {
- PackageSearchResultViewModel packageViewModel = viewModel.PackageViewModels [row];
- AppendPackageToListView (packageViewModel);
- LoadPackageImage (row, packageViewModel);
- }
-
- if (packagesListViewWasEmpty && (packageStore.RowCount > 0)) {
- packagesListView.SelectRow (0);
- }
-
- if (!viewModel.IsReadingPackages && (packageStore.RowCount == 0)) {
- ShowNoPackagesFoundMessage ();
- }
- }
-
- void AppendPackageToListView (PackageSearchResultViewModel packageViewModel)
- {
- int row = packageStore.AddRow ();
- packageStore.SetValue (row, packageHasBackgroundColorField, IsOddRow (row));
- packageStore.SetValue (row, packageCheckBoxAlphaField, GetPackageCheckBoxAlpha ());
- packageStore.SetValue (row, packageViewModelField, packageViewModel);
- }
-
- void LoadPackageImage (int row, PackageSearchResultViewModel packageViewModel)
- {
- if (packageViewModel.HasIconUrl) {
- imageLoader.LoadFrom (packageViewModel.IconUrl, row);
- }
- }
-
- bool IsOddRow (int row)
- {
- return (row % 2) == 0;
- }
-
- double GetPackageCheckBoxAlpha ()
- {
- if (PackagesCheckedCount == 0) {
- return packageCheckBoxSemiTransarentAlpha;
- }
- return 1;
- }
-
- void ImageLoaded (object sender, ImageLoadedEventArgs e)
- {
- if (!e.HasError) {
- int row = (int)e.State;
- if (IsValidRowAndUrl (row, e.Uri)) {
- packageStore.SetValue (row, packageImageField, e.Image);
- }
- }
- }
-
- bool IsValidRowAndUrl (int row, Uri uri)
- {
- if (row < packageStore.RowCount) {
- PackageSearchResultViewModel packageViewModel = packageStore.GetValue (row, packageViewModelField);
- if (packageViewModel != null) {
- return uri == packageViewModel.IconUrl;
- }
- }
- return false;
- }
-
- void AddPackagesButtonClicked (object sender, EventArgs e)
- {
- try {
- List<IPackageAction> packageActions = CreateInstallPackageActionsForSelectedPackages ();
- InstallPackages (packageActions);
- } catch (Exception ex) {
- LoggingService.LogError ("Adding packages failed.", ex);
- ShowErrorMessage (ex.Message);
- }
- }
-
- void InstallPackages (List<IPackageAction> packageActions)
- {
- if (packageActions.Count > 0) {
- ProgressMonitorStatusMessage progressMessage = GetProgressMonitorStatusMessages (packageActions);
- backgroundActionRunner.Run (progressMessage, packageActions);
-
- viewModel.OnInstallingSelectedPackages ();
- Close ();
- }
- }
-
- List<IPackageAction> CreateInstallPackageActionsForSelectedPackages ()
- {
- List<PackageSearchResultViewModel> packageViewModels = GetSelectedPackageViewModels ();
- if (packageViewModels.Count > 0) {
- return CreateInstallPackageActions (packageViewModels);
- }
- return new List<IPackageAction> ();
- }
-
- ProgressMonitorStatusMessage GetProgressMonitorStatusMessages (List<IPackageAction> packageActions)
- {
- if (packageActions.Count == 1) {
- string packageId = packageActions.OfType<INuGetPackageAction> ().First ().PackageId;
- if (OlderPackageInstalledThanPackageSelected ()) {
- return ProgressMonitorStatusMessageFactory.CreateUpdatingSinglePackageMessage (packageId);
- }
- return ProgressMonitorStatusMessageFactory.CreateInstallingSinglePackageMessage (packageId);
- }
- return ProgressMonitorStatusMessageFactory.CreateInstallingMultiplePackagesMessage (packageActions.Count);
- }
-
- List<PackageSearchResultViewModel> GetSelectedPackageViewModels ()
- {
- List<PackageSearchResultViewModel> packageViewModels = viewModel.CheckedPackageViewModels.ToList ();
- if (packageViewModels.Count > 0) {
- return packageViewModels;
- }
-
- PackageSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel ();
- if (selectedPackageViewModel != null) {
- packageViewModels.Add (selectedPackageViewModel);
- }
- return packageViewModels;
- }
-
- List<IPackageAction> CreateInstallPackageActions (IEnumerable<PackageSearchResultViewModel> packageViewModels)
- {
- return packageViewModels.Select (packageViewModel => viewModel.CreateInstallPackageAction (packageViewModel)).ToList ();
- }
-
- void PackageSearchEntryChanged (object sender, EventArgs e)
- {
- ClearErrorMessage ();
- ClearPackages ();
- UpdateAddPackagesButton ();
- SearchAfterDelay ();
- }
-
- void SearchAfterDelay ()
- {
- DisposeExistingTimer ();
- searchTimer = Application.TimeoutInvoke (searchDelayTimeSpan, Search);
- }
-
- void DisposeExistingTimer ()
- {
- if (searchTimer != null) {
- searchTimer.Dispose ();
- }
- }
-
- bool Search ()
- {
- viewModel.SearchTerms = this.packageSearchEntry.Text;
- viewModel.Search ();
-
- return false;
- }
-
- void PackagesListRowActivated (object sender, ListViewRowEventArgs e)
- {
- if (PackagesCheckedCount > 0) {
- AddPackagesButtonClicked (sender, e);
- } else {
- PackageSearchResultViewModel packageViewModel = packageStore.GetValue (e.RowIndex, packageViewModelField);
- InstallPackage (packageViewModel);
- }
- }
-
- void InstallPackage (PackageSearchResultViewModel packageViewModel)
- {
- try {
- if (packageViewModel != null) {
- List<IPackageAction> packageActions = CreateInstallPackageActions (
- new PackageSearchResultViewModel [] { packageViewModel });
- InstallPackages (packageActions);
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Installing package failed.", ex);
- ShowErrorMessage (ex.Message);
- }
- }
-
- void PackageSearchEntryActivated (object sender, EventArgs e)
- {
- if (loadingMessageVisible)
- return;
-
- if (PackagesCheckedCount > 0) {
- AddPackagesButtonClicked (sender, e);
- } else {
- PackageSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel ();
- InstallPackage (selectedPackageViewModel);
- }
- }
-
- void PackagesListViewScrollValueChanged (object sender, EventArgs e)
- {
- if (viewModel.IsLoadingNextPage) {
- return;
- }
-
- if (IsScrollBarNearEnd (packagesListView.VerticalScrollControl)) {
- if (viewModel.HasNextPage) {
- viewModel.ShowNextPage ();
- }
- }
- }
-
- bool IsScrollBarNearEnd (ScrollControl scrollControl)
- {
- double currentValue = scrollControl.Value;
- double maxValue = scrollControl.UpperValue;
- double pageSize = scrollControl.PageSize;
-
- return (currentValue / (maxValue - pageSize)) > 0.7;
- }
-
- void PackageCellViewPackageChecked (object sender, PackageCellViewEventArgs e)
- {
- UpdateAddPackagesButton ();
- UpdatePackageListViewSelectionColor ();
- UpdatePackageListViewCheckBoxAlpha ();
- }
-
- void UpdateAddPackagesButton ()
- {
- string label = Catalog.GetPluralString ("Add Package", "Add Packages", GetPackagesCountForAddPackagesButtonLabel ());
- if (PackagesCheckedCount <= 1 && OlderPackageInstalledThanPackageSelected ()) {
- label = Catalog.GetString ("Update Package");
- }
- addPackagesButton.Label = label;
- addPackagesButton.Sensitive = IsAddPackagesButtonEnabled ();
- }
-
- int GetPackagesCountForAddPackagesButtonLabel ()
- {
- if (PackagesCheckedCount > 1)
- return PackagesCheckedCount;
-
- return 1;
- }
-
- void UpdatePackageListViewSelectionColor ()
- {
- packageCellView.UseStrongSelectionColor = (PackagesCheckedCount == 0);
- }
-
- void UpdatePackageListViewCheckBoxAlpha ()
- {
- if (PackagesCheckedCount > 1)
- return;
-
- double alpha = GetPackageCheckBoxAlpha ();
- for (int row = 0; row < packageStore.RowCount; ++row) {
- packageStore.SetValue (row, packageCheckBoxAlphaField, alpha);
- }
- }
-
- bool OlderPackageInstalledThanPackageSelected ()
- {
- if (PackagesCheckedCount != 0) {
- return false;
- }
-
- PackageSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel ();
- if (selectedPackageViewModel != null) {
- return selectedPackageViewModel.IsOlderPackageInstalled ();
- }
- return false;
- }
-
- bool IsAddPackagesButtonEnabled ()
- {
- return !loadingMessageVisible && IsAtLeastOnePackageSelected ();
- }
-
- bool IsAtLeastOnePackageSelected ()
- {
- return (PackagesCheckedCount) >= 1 || (packagesListView.SelectedRow != -1);
- }
-
- int PackagesCheckedCount {
- get { return viewModel.CheckedPackageViewModels.Count; }
- }
-
- void SelectedPackageViewModelChanged (object sender, PropertyChangedEventArgs e)
- {
- try {
- if (e.PropertyName == "Versions") {
- PopulatePackageVersions (viewModel.SelectedPackage);
- } else {
- packagePublishedDate.Text = viewModel.SelectedPackage.GetLastPublishedDisplayText ();
- PopulatePackageDependencies (viewModel.SelectedPackage);
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Error loading package versions.", ex);
- }
- }
-
- void PopulatePackageVersions (PackageSearchResultViewModel packageViewModel)
- {
- DisposePopulatePackageVersionsTimer ();
-
- ignorePackageVersionChanges = true;
- try {
- packageVersionComboBox.Items.Clear ();
- if (packageViewModel.Versions.Any ()) {
- int count = 0;
- foreach (NuGetVersion version in packageViewModel.Versions) {
- count++;
- if (count > MaxVersionsToPopulate) {
- packageVersionsAddedCount = count - 1;
- if (version >= packageViewModel.SelectedVersion) {
- AddPackageVersionToComboBox (packageViewModel.SelectedVersion);
- }
- PopulatePackageVersionsAfterDelay ();
- break;
- }
- AddPackageVersionToComboBox (version);
- }
- } else {
- AddPackageVersionToComboBox (packageViewModel.Version);
- }
- packageVersionComboBox.SelectedItem = packageViewModel.SelectedVersion;
- } finally {
- ignorePackageVersionChanges = false;
- }
- }
-
- void AddPackageVersionToComboBox (NuGetVersion version)
- {
- packageVersionComboBox.Items.Add (version, version.ToString ());
- }
-
- void PackageVersionChanged (object sender, EventArgs e)
- {
- if (ignorePackageVersionChanges || viewModel.SelectedPackage == null)
- return;
-
- viewModel.SelectedPackage.SelectedVersion = (NuGetVersion)packageVersionComboBox.SelectedItem;
- UpdateAddPackagesButton ();
- }
-
- void PopulatePackageDependencies (PackageSearchResultViewModel packageViewModel)
- {
- if (packageViewModel.IsDependencyInformationAvailable) {
- this.packageDependenciesHBox.Visible = true;
- this.packageDependenciesListHBox.Visible = packageViewModel.HasDependencies;
- this.packageDependenciesNoneLabel.Visible = !packageViewModel.HasDependencies;
- this.packageDependenciesList.Text = packageViewModel.GetPackageDependenciesDisplayText ();
- } else {
- this.packageDependenciesHBox.Visible = false;
- this.packageDependenciesListHBox.Visible = false;
- this.packageDependenciesNoneLabel.Visible = false;
- this.packageDependenciesList.Text = String.Empty;
- }
- }
-
- void PopulatePackageVersionsAfterDelay ()
- {
- populatePackageVersionsTimer = Application.TimeoutInvoke (populatePackageVersionsDelayTimeSpan, PopulateMorePackageVersions);
- }
-
- void DisposePopulatePackageVersionsTimer ()
- {
- if (populatePackageVersionsTimer != null) {
- populatePackageVersionsTimer.Dispose ();
- populatePackageVersionsTimer = null;
- }
- }
-
- bool PopulateMorePackageVersions ()
- {
- PackageSearchResultViewModel packageViewModel = viewModel?.SelectedPackage;
- if (populatePackageVersionsTimer == null || packageViewModel == null) {
- return false;
- }
-
- int count = 0;
- foreach (NuGetVersion version in packageViewModel.Versions.Skip (packageVersionsAddedCount)) {
- count++;
-
- if (count > MaxVersionsToPopulate) {
- packageVersionsAddedCount += count - 1;
- return true;
- }
-
- AddPackageVersionToComboBox (version);
- }
-
- return false;
- }
- }
+// +// ManagePackagesDialog.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://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. + +using System; +using System.Collections.Generic; +using System.Linq; +using MonoDevelop.Core; +using MonoDevelop.Ide; +using MonoDevelop.Projects; +using NuGet.Versioning; +using Xwt; +using Xwt.Drawing; +using PropertyChangedEventArgs = System.ComponentModel.PropertyChangedEventArgs; + +namespace MonoDevelop.PackageManagement +{ + internal partial class ManagePackagesDialog + { + IBackgroundPackageActionRunner backgroundActionRunner; + ManagePackagesViewModel viewModel; + List<SourceRepositoryViewModel> packageSources; + DataField<bool> packageHasBackgroundColorField = new DataField<bool> (); + DataField<ManagePackagesSearchResultViewModel> packageViewModelField = new DataField<ManagePackagesSearchResultViewModel> (); + DataField<Image> packageImageField = new DataField<Image> (); + DataField<double> packageCheckBoxAlphaField = new DataField<double> (); + const double packageCheckBoxSemiTransarentAlpha = 0.6; + ListStore packageStore; + ManagePackagesCellView packageCellView; + TimeSpan searchDelayTimeSpan = TimeSpan.FromMilliseconds (500); + IDisposable searchTimer; + SourceRepositoryViewModel dummyPackageSourceRepresentingConfigureSettingsItem = + new SourceRepositoryViewModel (GettextCatalog.GetString ("Configure Sources...")); + ImageLoader imageLoader = new ImageLoader (); + bool loadingMessageVisible; + bool ignorePackageVersionChanges; + const string IncludePrereleaseUserPreferenceName = "NuGet.AddPackagesDialog.IncludePrerelease"; + TimeSpan populatePackageVersionsDelayTimeSpan = TimeSpan.FromMilliseconds (500); + int packageVersionsAddedCount; + IDisposable populatePackageVersionsTimer; + const int MaxVersionsToPopulate = 100; + DataField<bool> projectCheckedField; + DataField<string> projectNameField; + DataField<string> packageVersionField; + DataField<ManageProjectViewModel> projectField; + CheckBoxCellView projectCheckBoxCellView; + ListStore projectStore; + + public ManagePackagesDialog (ManagePackagesViewModel viewModel, string initialSearch = null) + : this ( + viewModel, + initialSearch, + PackageManagementServices.BackgroundPackageActionRunner) + { + } + + public ManagePackagesDialog ( + ManagePackagesViewModel viewModel, + string initialSearch, + IBackgroundPackageActionRunner backgroundActionRunner) + { + this.viewModel = viewModel; + this.backgroundActionRunner = backgroundActionRunner; + + Build (); + + consolidateLabel.Visible = viewModel.IsManagingSolution; + UpdateDialogTitle (); + UpdatePackageSearchEntryWithInitialText (initialSearch); + UpdatePackageResultsPageLabels (); + + InitializeListView (); + UpdateAddPackagesButton (); + ShowLoadingMessage (); + LoadViewModel (initialSearch); + + closeButton.Clicked += CloseButtonClicked; + this.showPrereleaseCheckBox.Clicked += ShowPrereleaseCheckBoxClicked; + this.packageSourceComboBox.SelectionChanged += PackageSourceChanged; + this.addPackagesButton.Clicked += AddPackagesButtonClicked; + this.packageSearchEntry.Changed += PackageSearchEntryChanged; + this.packageSearchEntry.Activated += PackageSearchEntryActivated; + this.packageVersionComboBox.SelectionChanged += PackageVersionChanged; + imageLoader.Loaded += ImageLoaded; + + browseLabel.ButtonPressed += BrowseLabelButtonPressed; + installedLabel.ButtonPressed += InstalledLabelButtonPressed; + updatesLabel.ButtonPressed += UpdatesLabelButtonPressed; + consolidateLabel.ButtonPressed += ConsolidateLabelButtonPressed; + } + + public bool ShowPreferencesForPackageSources { get; private set; } + + protected override void Dispose (bool disposing) + { + closeButton.Clicked -= CloseButtonClicked; + currentPackageVersionLabel.BoundsChanged -= PackageVersionLabelBoundsChanged; + + imageLoader.Loaded -= ImageLoaded; + imageLoader.Dispose (); + + RemoveSelectedPackagePropertyChangedEventHandler (); + viewModel.PropertyChanged -= ViewModelPropertyChanged; + viewModel.Dispose (); + DisposeExistingTimer (); + DisposePopulatePackageVersionsTimer (); + packageStore.Clear (); + projectStore?.Clear (); + viewModel = null; + + base.Dispose (disposing); + } + + void UpdateDialogTitle () + { + if (viewModel.IsManagingSolution) + return; + + Title = GettextCatalog.GetString ("Manage NuGet Packages – {0}", viewModel.Project.Name); + } + + void UpdatePackageSearchEntryWithInitialText (string initialSearch) + { + packageSearchEntry.Text = initialSearch; + if (!String.IsNullOrEmpty (initialSearch)) { + packageSearchEntry.CursorPosition = initialSearch.Length; + } + } + + public string SearchText { + get { return packageSearchEntry.Text; } + } + + void InitializeListView () + { + packageStore = new ListStore (packageHasBackgroundColorField, packageCheckBoxAlphaField, packageImageField, packageViewModelField); + packagesListView.DataSource = packageStore; + + AddPackageCellViewToListView (); + + packagesListView.SelectionChanged += PackagesListViewSelectionChanged; + packagesListView.RowActivated += PackagesListRowActivated; + packagesListView.VerticalScrollControl.ValueChanged += PackagesListViewScrollValueChanged; + } + + void AddPackageCellViewToListView () + { + packageCellView = new ManagePackagesCellView { + PackageField = packageViewModelField, + HasBackgroundColorField = packageHasBackgroundColorField, + CheckBoxAlphaField = packageCheckBoxAlphaField, + ImageField = packageImageField, + CellWidth = 467 + }; + var textColumn = new ListViewColumn ("Package", packageCellView); + packagesListView.Columns.Add (textColumn); + + packageCellView.PackageChecked += PackageCellViewPackageChecked; + } + + void InitializeProjectsListView () + { + projectStore?.Clear (); + + // Recreate the list view each time. This is a workaround for the + // list view not displaying items on re-populating if it has been sorted. + if (projectsListView != null) { + projectsListViewVBox.Remove (projectsListView); + projectsListView.Dispose (); + } + + projectStore?.Dispose (); + + projectCheckedField = new DataField<bool> (); + projectNameField = new DataField<string> (); + packageVersionField = new DataField<string> (); + projectField = new DataField<ManageProjectViewModel> (); + projectStore = new ListStore (projectCheckedField, projectNameField, packageVersionField, projectField); + + projectsListView = new ListView (); + projectsListView.DataSource = projectStore; + + // Selected project check box column. + if (projectCheckBoxCellView != null) + projectCheckBoxCellView.Toggled -= ProjectCheckBoxCellViewToggled; + projectCheckBoxCellView = new CheckBoxCellView (); + projectCheckBoxCellView.ActiveField = projectCheckedField; + projectCheckBoxCellView.Editable = true; + projectCheckBoxCellView.Toggled += ProjectCheckBoxCellViewToggled; + var column = new ListViewColumn (string.Empty, projectCheckBoxCellView); + projectsListView.Columns.Add (column); + + // Project column. + var textCellView = new TextCellView (); + textCellView.TextField = projectNameField; + column = new ListViewColumn (GettextCatalog.GetString ("Project"), textCellView) { + CanResize = true, + SortDataField = projectNameField + }; + projectsListView.Columns.Add (column); + + // Package version column + textCellView = new TextCellView (); + textCellView.TextField = packageVersionField; + column = new ListViewColumn (GettextCatalog.GetString ("Version"), textCellView) { + CanResize = true, + SortDataField = packageVersionField + }; + projectsListView.Columns.Add (column); + + // Add list view to dialog. + projectsListViewVBox.PackStart (projectsListView, true, true); + } + + void ShowLoadingMessage () + { + UpdateSpinnerLabel (); + noPackagesFoundFrame.Visible = false; + packagesListView.Visible = false; + loadingSpinnerFrame.Visible = true; + loadingMessageVisible = true; + } + + void HideLoadingMessage () + { + loadingSpinnerFrame.Visible = false; + packagesListView.Visible = true; + noPackagesFoundFrame.Visible = false; + loadingMessageVisible = false; + } + + void UpdateSpinnerLabel () + { + if (String.IsNullOrWhiteSpace (packageSearchEntry.Text)) { + loadingSpinnerLabel.Text = GettextCatalog.GetString ("Loading package list..."); + } else { + loadingSpinnerLabel.Text = GettextCatalog.GetString ("Searching packages..."); + } + } + + void ShowNoPackagesFoundMessage () + { + if (!String.IsNullOrWhiteSpace (packageSearchEntry.Text)) { + packagesListView.Visible = false; + noPackagesFoundFrame.Visible = true; + } + } + + void CloseButtonClicked (object sender, EventArgs e) + { + Close (); + } + + void ShowPrereleaseCheckBoxClicked (object sender, EventArgs e) + { + viewModel.IncludePrerelease = !viewModel.IncludePrerelease; + + SaveIncludePrereleaseUserPreference (); + } + + void SaveIncludePrereleaseUserPreference () + { + Solution solution = IdeApp.ProjectOperations.CurrentSelectedSolution; + if (solution != null) { + if (viewModel.IncludePrerelease) { + solution.UserProperties.SetValue (IncludePrereleaseUserPreferenceName, viewModel.IncludePrerelease); + } else { + solution.UserProperties.RemoveValue (IncludePrereleaseUserPreferenceName); + } + solution.SaveUserProperties (); + } + } + + bool GetIncludePrereleaseUserPreference () + { + Solution solution = IdeApp.ProjectOperations.CurrentSelectedSolution; + if (solution != null) { + return solution.UserProperties.GetValue (IncludePrereleaseUserPreferenceName, false); + } + + return false; + } + + void LoadViewModel (string initialSearch) + { + viewModel.SearchTerms = initialSearch; + + viewModel.IncludePrerelease = GetIncludePrereleaseUserPreference (); + showPrereleaseCheckBox.Active = viewModel.IncludePrerelease; + + ClearSelectedPackageInformation (); + PopulatePackageSources (); + viewModel.PropertyChanged += ViewModelPropertyChanged; + + if (viewModel.SelectedPackageSource != null) { + viewModel.ReadPackages (); + } else { + HideLoadingMessage (); + } + } + + void ClearSelectedPackageInformation () + { + this.packageInfoVBox.Visible = false; + this.currentPackageVersionHBox.Visible = false; + this.packageVersionsHBox.Visible = false; + projectStore?.Clear (); + } + + void RemoveSelectedPackagePropertyChangedEventHandler () + { + if (viewModel.SelectedPackage != null) { + viewModel.SelectedPackage.PropertyChanged -= SelectedPackageViewModelChanged; + viewModel.SelectedPackage = null; + } + } + + List<SourceRepositoryViewModel> PackageSources { + get { + if (packageSources == null) { + packageSources = viewModel.PackageSources.ToList (); + } + return packageSources; + } + } + + void PopulatePackageSources () + { + foreach (SourceRepositoryViewModel packageSource in PackageSources) { + AddPackageSourceToComboBox (packageSource); + } + + AddPackageSourceToComboBox (dummyPackageSourceRepresentingConfigureSettingsItem); + + packageSourceComboBox.SelectedItem = viewModel.SelectedPackageSource; + } + + void AddPackageSourceToComboBox (SourceRepositoryViewModel packageSource) + { + packageSourceComboBox.Items.Add (packageSource, packageSource.Name); + } + + void PackageSourceChanged (object sender, EventArgs e) + { + var selectedPackageSource = (SourceRepositoryViewModel)packageSourceComboBox.SelectedItem; + if (selectedPackageSource == dummyPackageSourceRepresentingConfigureSettingsItem) { + ShowPreferencesForPackageSources = true; + Close (); + } else { + viewModel.SelectedPackageSource = selectedPackageSource; + } + } + + void PackagesListViewSelectionChanged (object sender, EventArgs e) + { + try { + ShowSelectedPackage (); + } catch (Exception ex) { + LoggingService.LogError ("Error showing selected package.", ex); + ShowErrorMessage (ex.Message); + } + } + + void ShowSelectedPackage () + { + RemoveSelectedPackagePropertyChangedEventHandler (); + + ManagePackagesSearchResultViewModel packageViewModel = GetSelectedPackageViewModel (); + viewModel.SelectedPackage = packageViewModel; + if (packageViewModel != null) { + ShowPackageInformation (packageViewModel); + } else { + ClearSelectedPackageInformation (); + } + UpdateAddPackagesButton (); + } + + ManagePackagesSearchResultViewModel GetSelectedPackageViewModel () + { + if (packagesListView.SelectedRow != -1) { + return packageStore.GetValue (packagesListView.SelectedRow, packageViewModelField); + } + return null; + } + + void ShowPackageInformation (ManagePackagesSearchResultViewModel packageViewModel) + { + bool consolidate = viewModel.IsConsolidatePageSelected; + + if (consolidate) { + projectsListViewLabel.Text = GettextCatalog.GetString ("Select projects and a version for a consolidation."); + } else { + // Use the package id and not the package title to prevent a pango crash if the title + // contains Chinese characters. + this.packageNameLabel.Markup = packageViewModel.GetIdMarkup (); + this.packageAuthor.Text = packageViewModel.Author; + this.packagePublishedDate.Text = packageViewModel.GetLastPublishedDisplayText (); + this.packageDownloads.Text = packageViewModel.GetDownloadCountDisplayText (); + this.packageDescription.Text = packageViewModel.Description; + this.packageId.Text = packageViewModel.Id; + this.packageId.Visible = packageViewModel.HasNoGalleryUrl; + ShowUri (this.packageIdLink, packageViewModel.GalleryUrl, packageViewModel.Id); + ShowUri (this.packageProjectPageLink, packageViewModel.ProjectUrl); + ShowUri (this.packageLicenseLink, packageViewModel.LicenseUrl); + + PopulatePackageDependencies (packageViewModel); + } + + if (viewModel.IsInstalledPageSelected) { + packageVersionsLabel.WidthRequest = -1; + currentPackageVersionHBox.Visible = false; + packageVersionsHBox.Visible = false; + } else if (viewModel.IsUpdatesPageSelected) { + PopulatePackageVersions (packageViewModel); + ShowCurrentPackageVersion (packageViewModel); + packageVersionsHBox.Visible = true; + } else { + packageVersionsLabel.WidthRequest = -1; + currentPackageVersionHBox.Visible = false; + PopulatePackageVersions (packageViewModel); + packageVersionsHBox.Visible = true; + } + + foreach (Widget child in packageInfoVBox.Children) { + child.Visible = !consolidate; + } + + if (consolidate) { + PopulateProjectList (); + } else { + projectStore?.Clear (); + } + + projectsListViewLabel.Visible = consolidate; + projectsListViewVBox.Visible = consolidate; + this.packageInfoVBox.Visible = true; + + packageViewModel.PropertyChanged += SelectedPackageViewModelChanged; + viewModel.LoadPackageMetadata (packageViewModel); + } + + void ShowCurrentPackageVersion (ManagePackagesSearchResultViewModel packageViewModel) + { + if (maxPackageVersionLabelWidth.HasValue) { + currentPackageVersionLabel.WidthRequest = maxPackageVersionLabelWidth.Value; + packageVersionsLabel.WidthRequest = maxPackageVersionLabelWidth.Value; + } + + currentPackageVersion.Text = packageViewModel.GetCurrentPackageVersionText (); + + currentPackageVersionInfoPopoverWidget.Message = packageViewModel.GetCurrentPackageVersionAdditionalText (); + currentPackageVersionInfoPopoverWidget.Visible = !string.IsNullOrEmpty (currentPackageVersionInfoPopoverWidget.Message); + + currentPackageVersionHBox.Visible = !string.IsNullOrEmpty (currentPackageVersion.Text); + } + + void ShowUri (LinkLabel linkLabel, Uri uri, string label) + { + linkLabel.Text = label; + ShowUri (linkLabel, uri); + } + + void ShowUri (LinkLabel linkLabel, Uri uri) + { + if (uri == null) { + linkLabel.Visible = false; + } else { + linkLabel.Visible = true; + linkLabel.Uri = uri; + } + } + + void ViewModelPropertyChanged (object sender, PropertyChangedEventArgs e) + { + try { + ShowPackages (); + } catch (Exception ex) { + LoggingService.LogError ("Error showing packages.", ex); + ShowErrorMessage (ex.Message); + } + } + + void ShowPackages () + { + if (viewModel.HasError) { + ShowErrorMessage (viewModel.ErrorMessage); + } else { + ClearErrorMessage (); + } + + if (viewModel.IsLoadingNextPage) { + // Show spinner? + } else if (viewModel.IsReadingPackages) { + ClearPackages (); + } else { + HideLoadingMessage (); + } + + if (!viewModel.IsLoadingNextPage) { + AppendPackagesToListView (); + } + + UpdateAddPackagesButton (); + } + + void ClearPackages () + { + packageStore.Clear (); + ResetPackagesListViewScroll (); + UpdatePackageListViewSelectionColor (); + ShowLoadingMessage (); + ShrinkImageCache (); + DisposePopulatePackageVersionsTimer (); + } + + void ResetPackagesListViewScroll () + { + packagesListView.VerticalScrollControl.Value = 0; + } + + void ShowErrorMessage (string message) + { + errorMessageLabel.Text = message; + errorMessageHBox.Visible = true; + } + + void ClearErrorMessage () + { + errorMessageHBox.Visible = false; + errorMessageLabel.Text = ""; + } + + void ShrinkImageCache () + { + imageLoader.ShrinkImageCache (); + } + + void AppendPackagesToListView () + { + bool packagesListViewWasEmpty = (packageStore.RowCount == 0); + + for (int row = packageStore.RowCount; row < viewModel.PackageViewModels.Count; ++row) { + ManagePackagesSearchResultViewModel packageViewModel = viewModel.PackageViewModels [row]; + AppendPackageToListView (packageViewModel); + LoadPackageImage (row, packageViewModel); + } + + if (packagesListViewWasEmpty && (packageStore.RowCount > 0)) { + packagesListView.SelectRow (0); + } + + if (!viewModel.IsReadingPackages && (packageStore.RowCount == 0)) { + ShowNoPackagesFoundMessage (); + } + } + + void AppendPackageToListView (ManagePackagesSearchResultViewModel packageViewModel) + { + int row = packageStore.AddRow (); + packageStore.SetValue (row, packageHasBackgroundColorField, IsOddRow (row)); + packageStore.SetValue (row, packageCheckBoxAlphaField, GetPackageCheckBoxAlpha ()); + packageStore.SetValue (row, packageViewModelField, packageViewModel); + } + + void LoadPackageImage (int row, ManagePackagesSearchResultViewModel packageViewModel) + { + if (packageViewModel.HasIconUrl) { + imageLoader.LoadFrom (packageViewModel.IconUrl, row); + } + } + + static bool IsOddRow (int row) + { + return (row % 2) == 0; + } + + double GetPackageCheckBoxAlpha () + { + if (PackagesCheckedCount == 0) { + return packageCheckBoxSemiTransarentAlpha; + } + return 1; + } + + void ImageLoaded (object sender, ImageLoadedEventArgs e) + { + if (!e.HasError) { + int row = (int)e.State; + if (IsValidRowAndUrl (row, e.Uri)) { + packageStore.SetValue (row, packageImageField, e.Image); + } + } + } + + bool IsValidRowAndUrl (int row, Uri uri) + { + if (row < packageStore.RowCount) { + ManagePackagesSearchResultViewModel packageViewModel = packageStore.GetValue (row, packageViewModelField); + if (packageViewModel != null) { + return uri == packageViewModel.IconUrl; + } + } + return false; + } + + void AddPackagesButtonClicked (object sender, EventArgs e) + { + try { + if (viewModel.IsConsolidatePageSelected) { + List<ManagePackagesSearchResultViewModel> packageViewModels = GetSelectedPackageViewModels (); + List<IPackageAction> packageActions = viewModel.CreateConsolidatePackageActions (packageViewModels); + RunPackageActions (packageActions); + } else { + var projects = SelectProjects ().ToList (); + if (projects.Any ()) { + List<IPackageAction> packageActions = CreatePackageActionsForSelectedPackages (projects); + RunPackageActions (packageActions); + } + } + } catch (Exception ex) { + LoggingService.LogError ("Adding packages failed.", ex); + ShowErrorMessage (ex.Message); + } + } + + IEnumerable<IDotNetProject> SelectProjects () + { + return SelectProjects (GetSelectedPackageViewModels ()); + } + + IEnumerable<IDotNetProject> SelectProjects (ManagePackagesSearchResultViewModel packageViewModel) + { + return SelectProjects (new [] { packageViewModel }); + } + + IEnumerable<IDotNetProject> SelectProjects (IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels) + { + if (!viewModel.IsManagingSolution) + return viewModel.DotNetProjects; + + var selectProjectsViewModel = new SelectProjectsViewModel ( + GetFilteredDotNetProjectsToSelect (packageViewModels), + GetPackagesCountForAddPackagesButtonLabel (), + viewModel.PageSelected); + + using (var dialog = new SelectProjectsDialog (selectProjectsViewModel)) { + Command result = dialog.ShowWithParent (); + if (result == Command.Ok) { + return dialog.GetSelectedProjects (); + } else { + return Enumerable.Empty<IDotNetProject> (); + } + } + } + + /// <summary> + /// Remove projects that do not make sense based on the currently selected filter. + /// If we are on the Installed page that do not include any projects that do not have + /// the selected NuGet package installed. + /// </summary> + IEnumerable<IDotNetProject> GetFilteredDotNetProjectsToSelect (IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels) + { + if (viewModel.PageSelected != ManagePackagesPage.Browse) { + var packageIds = packageViewModels.Select (pvm => pvm.Id).ToList (); + return viewModel.GetDotNetProjectsToSelect (packageIds); + } + + return viewModel.DotNetProjects; + } + + void RunPackageActions (List<IPackageAction> packageActions) + { + if (packageActions.Count > 0) { + ProgressMonitorStatusMessage progressMessage = GetProgressMonitorStatusMessages (packageActions); + backgroundActionRunner.Run (progressMessage, packageActions); + + if (viewModel.PageSelected == ManagePackagesPage.Browse) { + viewModel.OnInstallingSelectedPackages (); + } + Close (); + } + } + + List<IPackageAction> CreatePackageActionsForSelectedPackages (IEnumerable<IDotNetProject> selectedProjects) + { + List<ManagePackagesSearchResultViewModel> packageViewModels = GetSelectedPackageViewModels (); + if (packageViewModels.Count > 0) { + return viewModel.CreatePackageActions (packageViewModels, selectedProjects); + } + return new List<IPackageAction> (); + } + + ProgressMonitorStatusMessage GetProgressMonitorStatusMessages (List<IPackageAction> packageActions) + { + if (viewModel.PageSelected == ManagePackagesPage.Browse) { + return GetProgressMonitorInstallMessages (packageActions); + } else if (viewModel.PageSelected == ManagePackagesPage.Installed) { + return GetProgressMonitorUninstallMessages (packageActions); + } else if (viewModel.PageSelected == ManagePackagesPage.Updates) { + return GetProgressMonitorUpdateMessages (packageActions); + } else if (viewModel.PageSelected == ManagePackagesPage.Consolidate) { + return GetProgressMonitorConsolidateMessages (packageActions); + } + return null; + } + + ProgressMonitorStatusMessage GetProgressMonitorInstallMessages (List<IPackageAction> packageActions) + { + if (packageActions.Count == 1) { + string packageId = packageActions.Cast<INuGetPackageAction> ().First ().PackageId; + if (OlderPackageInstalledThanPackageSelected ()) { + return ProgressMonitorStatusMessageFactory.CreateUpdatingSinglePackageMessage (packageId); + } + return ProgressMonitorStatusMessageFactory.CreateInstallingSinglePackageMessage (packageId); + } + return ProgressMonitorStatusMessageFactory.CreateInstallingMultiplePackagesMessage (packageActions.Count); + } + + static ProgressMonitorStatusMessage GetProgressMonitorUninstallMessages (List<IPackageAction> packageActions) + { + int count = packageActions.Count; + if (count == 1) { + string packageId = packageActions.Cast<INuGetPackageAction> ().First ().PackageId; + return ProgressMonitorStatusMessageFactory.CreateRemoveSinglePackageMessage (packageId); + } + + return new ProgressMonitorStatusMessage ( + GettextCatalog.GetString ("Removing {0} packages...", count), + GettextCatalog.GetString ("{0} packages successfully removed.", count), + GettextCatalog.GetString ("Could not remove packages."), + GettextCatalog.GetString ("{0} packages removed with warnings.", count) + ); + } + + static ProgressMonitorStatusMessage GetProgressMonitorUpdateMessages (List<IPackageAction> packageActions) + { + int count = packageActions.Count; + if (count == 1) { + string packageId = packageActions.Cast<INuGetPackageAction> ().First ().PackageId; + return ProgressMonitorStatusMessageFactory.CreateUpdatingSinglePackageMessage (packageId); + } + + return new ProgressMonitorStatusMessage ( + GettextCatalog.GetString ("Updating {0} packages...", count), + GettextCatalog.GetString ("{0} packages successfully updated.", count), + GettextCatalog.GetString ("Could not update packages."), + GettextCatalog.GetString ("{0} packages updated with warnings.", count) + ); + } + + static ProgressMonitorStatusMessage GetProgressMonitorConsolidateMessages (List<IPackageAction> packageActions) + { + int count = packageActions.Count; + if (count == 1) { + string packageId = packageActions.Cast<INuGetPackageAction> ().First ().PackageId; + return new ProgressMonitorStatusMessage ( + GettextCatalog.GetString ("Consolidating {0}...", packageId), + GettextCatalog.GetString ("{0} successfully consolidated.", packageId), + GettextCatalog.GetString ("Could not consolidate {0}.", packageId), + GettextCatalog.GetString ("{0} consolidated with warnings.", packageId) + ); + } + + return new ProgressMonitorStatusMessage ( + GettextCatalog.GetString ("Consolidating {0} packages...", count), + GettextCatalog.GetString ("{0} packages successfully consolidated.", count), + GettextCatalog.GetString ("Could not consolidate packages."), + GettextCatalog.GetString ("{0} packages consolidated with warnings.", count) + ); + } + + List<ManagePackagesSearchResultViewModel> GetSelectedPackageViewModels () + { + List<ManagePackagesSearchResultViewModel> packageViewModels = viewModel.CheckedPackageViewModels.ToList (); + if (packageViewModels.Count > 0) { + return packageViewModels; + } + + ManagePackagesSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel (); + if (selectedPackageViewModel != null) { + packageViewModels.Add (selectedPackageViewModel); + } + return packageViewModels; + } + + void PackageSearchEntryChanged (object sender, EventArgs e) + { + ClearErrorMessage (); + ClearPackages (); + UpdateAddPackagesButton (); + SearchAfterDelay (); + } + + void SearchAfterDelay () + { + DisposeExistingTimer (); + searchTimer = Application.TimeoutInvoke (searchDelayTimeSpan, Search); + } + + void DisposeExistingTimer () + { + if (searchTimer != null) { + searchTimer.Dispose (); + } + } + + bool Search () + { + viewModel.SearchTerms = this.packageSearchEntry.Text; + viewModel.Search (); + + return false; + } + + void PackagesListRowActivated (object sender, ListViewRowEventArgs e) + { + if (PackagesCheckedCount > 0) { + AddPackagesButtonClicked (sender, e); + } else { + ManagePackagesSearchResultViewModel packageViewModel = packageStore.GetValue (e.RowIndex, packageViewModelField); + ManagePackage (packageViewModel); + } + } + + void ManagePackage (ManagePackagesSearchResultViewModel packageViewModel) + { + try { + if (packageViewModel != null) { + if (viewModel.IsConsolidatePageSelected) { + List<IPackageAction> packageActions = viewModel.CreateConsolidatePackageActions ( + new ManagePackagesSearchResultViewModel [] { packageViewModel } + ); + RunPackageActions (packageActions); + } else { + var projects = SelectProjects (packageViewModel).ToList (); + if (!projects.Any ()) + return; + + List<IPackageAction> packageActions = viewModel.CreatePackageActions ( + new ManagePackagesSearchResultViewModel [] { packageViewModel }, + projects); + RunPackageActions (packageActions); + } + } + } catch (Exception ex) { + LoggingService.LogInternalError ("ManagePackage failed.", ex); + ShowErrorMessage (ex.Message); + } + } + + void PackageSearchEntryActivated (object sender, EventArgs e) + { + if (loadingMessageVisible) + return; + + if (PackagesCheckedCount > 0) { + AddPackagesButtonClicked (sender, e); + } else { + ManagePackagesSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel (); + ManagePackage (selectedPackageViewModel); + } + } + + void PackagesListViewScrollValueChanged (object sender, EventArgs e) + { + if (viewModel.IsLoadingNextPage) { + return; + } + + if (IsScrollBarNearEnd (packagesListView.VerticalScrollControl)) { + if (viewModel.HasNextPage) { + viewModel.ShowNextPage (); + } + } + } + + bool IsScrollBarNearEnd (ScrollControl scrollControl) + { + double currentValue = scrollControl.Value; + double maxValue = scrollControl.UpperValue; + double pageSize = scrollControl.PageSize; + + return (currentValue / (maxValue - pageSize)) > 0.7; + } + + void PackageCellViewPackageChecked (object sender, ManagePackagesCellViewEventArgs e) + { + UpdateAddPackagesButton (); + UpdatePackageListViewSelectionColor (); + UpdatePackageListViewCheckBoxAlpha (); + } + + void UpdateAddPackagesButton () + { + addPackagesButton.Label = GetAddPackagesButtonLabel (); + addPackagesButton.Sensitive = IsAddPackagesButtonEnabled (); + } + + string GetAddPackagesButtonLabel () + { + int packagesSelectedCount = GetPackagesCountForAddPackagesButtonLabel (); + if (viewModel.PageSelected == ManagePackagesPage.Browse) { + string label = GettextCatalog.GetPluralString ("Add Package", "Add Packages", packagesSelectedCount); + if (PackagesCheckedCount <= 1 && OlderPackageInstalledThanPackageSelected ()) { + label = GettextCatalog.GetString ("Update Package"); + } + return label; + } else if (viewModel.PageSelected == ManagePackagesPage.Installed) { + return GettextCatalog.GetPluralString ("Uninstall Package", "Uninstall Packages", packagesSelectedCount); + } else if (viewModel.PageSelected == ManagePackagesPage.Updates) { + return GettextCatalog.GetPluralString ("Update Package", "Update Packages", packagesSelectedCount); + } else if (viewModel.PageSelected == ManagePackagesPage.Consolidate) { + return GettextCatalog.GetPluralString ("Consolidate Package", "Consolidate Packages", packagesSelectedCount); + } + + throw new NotImplementedException ("Unknown package results page"); + } + + int GetPackagesCountForAddPackagesButtonLabel () + { + if (PackagesCheckedCount > 1) + return PackagesCheckedCount; + + return 1; + } + + void UpdatePackageListViewSelectionColor () + { + packageCellView.UseStrongSelectionColor = (PackagesCheckedCount == 0); + } + + void UpdatePackageListViewCheckBoxAlpha () + { + if (PackagesCheckedCount > 1) + return; + + double alpha = GetPackageCheckBoxAlpha (); + for (int row = 0; row < packageStore.RowCount; ++row) { + packageStore.SetValue (row, packageCheckBoxAlphaField, alpha); + } + } + + bool OlderPackageInstalledThanPackageSelected () + { + if (PackagesCheckedCount != 0) { + return false; + } + + ManagePackagesSearchResultViewModel selectedPackageViewModel = GetSelectedPackageViewModel (); + if (selectedPackageViewModel != null) { + return selectedPackageViewModel.IsOlderPackageInstalled (); + } + return false; + } + + bool IsAddPackagesButtonEnabled () + { + if (loadingMessageVisible) + return false; + + if (!IsAtLeastOnePackageSelected ()) + return false; + + if (viewModel.IsConsolidatePageSelected) + return viewModel.CanConsolidate (); + + return true; + } + + bool IsAtLeastOnePackageSelected () + { + return (PackagesCheckedCount) >= 1 || (packagesListView.SelectedRow != -1); + } + + int PackagesCheckedCount { + get { return viewModel.CheckedPackageViewModels.Count; } + } + + void SelectedPackageViewModelChanged (object sender, PropertyChangedEventArgs e) + { + try { + if (e.PropertyName == "Versions") { + PopulatePackageVersions (viewModel.SelectedPackage); + } else { + if (!viewModel.IsConsolidatePageSelected) { + packagePublishedDate.Text = viewModel.SelectedPackage.GetLastPublishedDisplayText (); + PopulatePackageDependencies (viewModel.SelectedPackage); + } + } + } catch (Exception ex) { + LoggingService.LogError ("Error loading package versions.", ex); + } + } + + void PopulatePackageVersions (ManagePackagesSearchResultViewModel packageViewModel) + { + DisposePopulatePackageVersionsTimer (); + + ignorePackageVersionChanges = true; + try { + packageVersionComboBox.Items.Clear (); + if (packageViewModel.Versions.Any ()) { + NuGetVersion latestStableVersion = packageViewModel.Versions.FirstOrDefault (v => !v.IsPrerelease); + int count = 0; + foreach (NuGetVersion version in packageViewModel.Versions) { + count++; + if (count > MaxVersionsToPopulate) { + packageVersionsAddedCount = count - 1; + if (version >= packageViewModel.SelectedVersion) { + AddPackageVersionToComboBox (packageViewModel.SelectedVersion); + } + PopulatePackageVersionsAfterDelay (); + break; + } + AddPackageVersionToComboBox (version, latestStableVersion == version); + } + } else { + AddPackageVersionToComboBox (packageViewModel.Version); + } + packageVersionComboBox.SelectedItem = packageViewModel.SelectedVersion; + } finally { + ignorePackageVersionChanges = false; + } + } + + void AddPackageVersionToComboBox (NuGetVersion version, bool latestStable = false) + { + string versionLabel = version.ToString (); + if (latestStable) + versionLabel += " " + GettextCatalog.GetString ("(latest stable)"); + packageVersionComboBox.Items.Add (version, versionLabel); + } + + void PackageVersionChanged (object sender, EventArgs e) + { + if (ignorePackageVersionChanges || viewModel.SelectedPackage == null) + return; + + viewModel.SelectedPackage.SelectedVersion = (NuGetVersion)packageVersionComboBox.SelectedItem; + UpdateAddPackagesButton (); + } + + void PopulatePackageDependencies (ManagePackagesSearchResultViewModel packageViewModel) + { + if (packageViewModel.IsDependencyInformationAvailable) { + this.packageDependenciesHBox.Visible = true; + this.packageDependenciesListHBox.Visible = packageViewModel.HasDependencies; + this.packageDependenciesNoneLabel.Visible = !packageViewModel.HasDependencies; + this.packageDependenciesList.Text = packageViewModel.GetPackageDependenciesDisplayText (); + } else { + this.packageDependenciesHBox.Visible = false; + this.packageDependenciesListHBox.Visible = false; + this.packageDependenciesNoneLabel.Visible = false; + this.packageDependenciesList.Text = String.Empty; + } + } + + void PopulatePackageVersionsAfterDelay () + { + populatePackageVersionsTimer = Application.TimeoutInvoke (populatePackageVersionsDelayTimeSpan, PopulateMorePackageVersions); + } + + void DisposePopulatePackageVersionsTimer () + { + if (populatePackageVersionsTimer != null) { + populatePackageVersionsTimer.Dispose (); + populatePackageVersionsTimer = null; + } + } + + bool PopulateMorePackageVersions () + { + ManagePackagesSearchResultViewModel packageViewModel = viewModel?.SelectedPackage; + if (populatePackageVersionsTimer == null || packageViewModel == null) { + return false; + } + + int count = 0; + foreach (NuGetVersion version in packageViewModel.Versions.Skip (packageVersionsAddedCount)) { + count++; + + if (count > MaxVersionsToPopulate) { + packageVersionsAddedCount += count - 1; + return true; + } + + AddPackageVersionToComboBox (version); + } + + return false; + } + + void UpdatePackageResultsPageLabels () + { + UpdatePackageResultsLabel (ManagePackagesPage.Browse, browseLabel); + UpdatePackageResultsLabel (ManagePackagesPage.Installed, installedLabel); + UpdatePackageResultsLabel (ManagePackagesPage.Updates, updatesLabel); + UpdatePackageResultsLabel (ManagePackagesPage.Consolidate, consolidateLabel); + } + + void UpdatePackageResultsLabel (ManagePackagesPage page, Label label) + { + string text = (string)label.Tag; + if (page == viewModel.PageSelected) { + label.Markup = string.Format ("<b><u>{0}</u></b>", text); + } else { + label.Markup = text; + } + } + + void BrowseLabelButtonPressed (object sender, ButtonEventArgs e) + { + viewModel.PageSelected = ManagePackagesPage.Browse; + OnPackageResultsPageSelected (); + } + + void InstalledLabelButtonPressed (object sender, ButtonEventArgs e) + { + viewModel.PageSelected = ManagePackagesPage.Installed; + OnPackageResultsPageSelected (); + } + + void UpdatesLabelButtonPressed (object sender, ButtonEventArgs e) + { + viewModel.PageSelected = ManagePackagesPage.Updates; + OnPackageResultsPageSelected (); + } + + void ConsolidateLabelButtonPressed (object sender, ButtonEventArgs e) + { + viewModel.PageSelected = ManagePackagesPage.Consolidate; + OnPackageResultsPageSelected (); + } + + void OnPackageResultsPageSelected () + { + UpdatePackageResultsPageLabels (); + ClearErrorMessage (); + ClearPackages (); + UpdateAddPackagesButton (); + Search (); + } + + void PopulateProjectList () + { + InitializeProjectsListView (); + + foreach (ManageProjectViewModel project in viewModel.ProjectViewModels) { + int row = projectStore.AddRow (); + projectStore.SetValues ( + row, + projectCheckedField, + project.IsChecked, + projectNameField, + project.ProjectName, + packageVersionField, + project.PackageVersion, + projectField, + project); + } + } + + void ProjectCheckBoxCellViewToggled (object sender, WidgetEventArgs e) + { + int row = projectsListView.CurrentEventRow; + if (row == -1) + return; + + ManageProjectViewModel selectedProject = projectStore.GetValue (row, projectField); + if (selectedProject == null) + return; + + selectedProject.IsChecked = !selectedProject.IsChecked; + + UpdateAddPackagesButton (); + } + } }
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs index 8551dfafcd..e766df17e2 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/AddPackagesDialogRunner.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/ManagePackagesDialogRunner.cs @@ -1,78 +1,85 @@ -//
-// AddPackagesDialogRunner.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2014 Xamarin Inc. (http://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.
-
-using System;
-using MonoDevelop.Ide;
-using MonoDevelop.Core;
-using MonoDevelop.Projects;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class AddPackagesDialogRunner
- {
- static RecentNuGetPackagesRepository recentPackagesRepository = new RecentNuGetPackagesRepository ();
-
- public void Run (string initialSearch = null)
- {
- Run (null, initialSearch);
- }
-
- public void Run (DotNetProject project, string initialSearch = null)
- {
- try {
- PackageManagementCredentialService.Reset ();
- bool configurePackageSources = false;
- do {
- using (AddPackagesDialog dialog = CreateDialog (project, initialSearch)) {
- dialog.ShowWithParent ();
- configurePackageSources = dialog.ShowPreferencesForPackageSources;
- initialSearch = dialog.SearchText;
- }
- if (configurePackageSources) {
- ShowPreferencesForPackageSources ();
- }
- } while (configurePackageSources);
-
- } catch (Exception ex) {
- LoggingService.LogInternalError (ex);
- }
- }
-
- AddPackagesDialog CreateDialog (DotNetProject project, string initialSearch)
- {
- var viewModel = AllPackagesViewModel.Create (project, recentPackagesRepository);
- return new AddPackagesDialog (
- viewModel,
- initialSearch);
- }
-
- void ShowPreferencesForPackageSources ()
- {
- IdeApp.Workbench.ShowGlobalPreferencesDialog (null, "PackageSources");
- }
- }
-}
-
+// +// ManagePackagesDialogRunner.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://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. + +using System; +using MonoDevelop.Ide; +using MonoDevelop.Core; +using MonoDevelop.Projects; + +namespace MonoDevelop.PackageManagement +{ + internal class ManagePackagesDialogRunner + { + static RecentManagedNuGetPackagesRepository recentPackagesRepository = new RecentManagedNuGetPackagesRepository (); + + public void Run (IDotNetProject project = null, string initialSearch = null) + { + try { + bool configurePackageSources = false; + do { + using (ManagePackagesDialog dialog = CreateDialog (initialSearch, project)) { + dialog.ShowWithParent (); + configurePackageSources = dialog.ShowPreferencesForPackageSources; + initialSearch = dialog.SearchText; + } + if (configurePackageSources) { + ShowPreferencesForPackageSources (); + } + } while (configurePackageSources); + + } catch (Exception ex) { + LoggingService.LogInternalError (ex); + } + } + + public void Run (Project project, string initialSearch = null) + { + Run (CreateDotNetProjectProxy (project), initialSearch); + } + + IDotNetProject CreateDotNetProjectProxy (Project project) + { + if (project is DotNetProject dotNetProject) + return new DotNetProjectProxy (dotNetProject); + + return null; + } + + ManagePackagesDialog CreateDialog (string initialSearch, IDotNetProject project) + { + var viewModel = ManagePackagesViewModel.Create (recentPackagesRepository, project); + return new ManagePackagesDialog ( + viewModel, + initialSearch); + } + + void ShowPreferencesForPackageSources () + { + IdeApp.Workbench.ShowGlobalPreferencesDialog (null, "PackageSources"); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.UI.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.UI.cs new file mode 100644 index 0000000000..3a707ee2e6 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.UI.cs @@ -0,0 +1,117 @@ +// +// SelectProjectsDialog.UI.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2014 Xamarin Inc. (http://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. + +using System; +using System.Collections.Generic; +using System.Linq; +using MonoDevelop.Core; +using Xwt; + +namespace MonoDevelop.PackageManagement +{ + partial class SelectProjectsDialog : Dialog + { + Label topLabel; + VBox projectsListView; + DialogButton okButton; + List<CheckBox> checkBoxes = new List<CheckBox> (); + + void Build () + { + Title = GettextCatalog.GetString ("Select Projects"); + Width = 420; + Height = 330; + Padding = 20; + + var mainVBox = new VBox (); + Content = mainVBox; + + topLabel = new Label (); + topLabel.Wrap = WrapMode.Word; + mainVBox.PackStart (topLabel); + + projectsListView = new VBox (); + + var projectsListScrollView = new ScrollView (projectsListView); + projectsListScrollView.HorizontalScrollPolicy = ScrollPolicy.Never; + projectsListScrollView.VerticalScrollPolicy = ScrollPolicy.Automatic; + projectsListScrollView.BorderVisible = false; + projectsListScrollView.BackgroundColor = Ide.Gui.Styles.BackgroundColor; + projectsListScrollView.Content = projectsListView; + + mainVBox.PackStart (projectsListScrollView, true, true); + + var cancelButton = new DialogButton (Command.Cancel); + Buttons.Add (cancelButton); + + okButton = new DialogButton (Command.Ok); + okButton.Sensitive = false; + Buttons.Add (okButton); + } + + void AddProject (SelectedProjectViewModel project) + { + var hbox = new HBox (); + hbox.Tag = project; + + var checkBox = new CheckBox (); + checkBox.Label = project.Name; + checkBox.Tag = project; + checkBox.Active = project.IsSelected; + checkBox.Clicked += ProjectCheckBoxClicked; + hbox.PackStart (checkBox); + + checkBoxes.Add (checkBox); + + projectsListView.PackStart (hbox); + } + + void ProjectCheckBoxClicked (object sender, EventArgs e) + { + var checkBox = (CheckBox)sender; + var project = (SelectedProjectViewModel)checkBox.Tag; + project.IsSelected = checkBox.Active; + + UpdateOkButtonSensitivity (); + } + + void UpdateOkButtonSensitivity () + { + okButton.Sensitive = viewModel.GetSelectedProjects ().Any (); + } + + protected override void Dispose (bool disposing) + { + base.Dispose (disposing); + + if (disposing) { + foreach (CheckBox checkBox in checkBoxes) { + checkBox.Clicked -= ProjectCheckBoxClicked; + } + } + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.cs new file mode 100644 index 0000000000..0c8003b5b8 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Gui/SelectProjectsDialog.cs @@ -0,0 +1,107 @@ +// +// ManagePackagesDialog.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://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. + +using System.Collections.Generic; +using System.Linq; +using MonoDevelop.Core; + +namespace MonoDevelop.PackageManagement +{ + partial class SelectProjectsDialog + { + SelectProjectsViewModel viewModel; + + public SelectProjectsDialog (SelectProjectsViewModel viewModel) + { + this.viewModel = viewModel; + + Build (); + + UpdateTopLabel (viewModel.Projects.Count ()); + + AddProjects (); + } + + public IEnumerable<IDotNetProject> GetSelectedProjects () + { + return viewModel.GetSelectedProjects (); + } + + void UpdateTopLabel (int projectsCount) + { + if (viewModel.IsAddingSinglePackage) { + topLabel.Text = GettextCatalog.GetPluralString ( + "Add the package to the project:", + "Add the package to the projects:", + projectsCount); + } else if (viewModel.IsAddingMultiplePackages) { + topLabel.Text = GettextCatalog.GetPluralString ( + "Add the packages to the project:", + "Add the packages to the projects:", + projectsCount); + } else if (viewModel.IsRemovingSinglePackage) { + topLabel.Text = GettextCatalog.GetPluralString ( + "Remove the package from the project:", + "Remove the package from the projects:", + projectsCount); + } else if (viewModel.IsRemovingMultiplePackages) { + topLabel.Text = GettextCatalog.GetPluralString ( + "Remove the packages from the project:", + "Remove the packages from the projects:", + projectsCount); + } else if (viewModel.IsUpdatingSinglePackage) { + topLabel.Text = GettextCatalog.GetPluralString ( + "Update the package in the project:", + "Update the package in the projects:", + projectsCount); + } else if (viewModel.IsUpdatingMultiplePackages) { + topLabel.Text = GettextCatalog.GetPluralString ( + "Update the packages in the project:", + "Update the packages in the projects:", + projectsCount); + } else if (viewModel.IsConsolidatingSinglePackage) { + topLabel.Text = GettextCatalog.GetPluralString ( + "Consolidate the package in the project:", + "Consolidate the package in the projects:", + projectsCount); + } else if (viewModel.IsConsolidatingMultiplePackages) { + topLabel.Text = GettextCatalog.GetPluralString ( + "Consolidate the packages in the project:", + "Consolidate the packages in the projects:", + projectsCount); + } + } + + void AddProjects () + { + foreach (SelectedProjectViewModel project in viewModel.Projects) { + AddProject (project); + } + + UpdateOkButtonSensitivity (); + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs index 03b3924ef9..8bf2b74441 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Refactoring/NuGetPackageServicesProxy.cs @@ -191,7 +191,7 @@ namespace MonoDevelop.PackageManagement.Refactoring Runtime.RunInMainThread (delegate { var project = IdeApp.Workbench.ActiveDocument?.Owner as DotNetProject; if (project != null) { - var runner = new AddPackagesDialogRunner (); + var runner = new ManagePackagesDialogRunner (); runner.Run (project, packageName); } }); diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs index c981095f4e..2e289c0ef5 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/FakeSolution.cs @@ -83,12 +83,8 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public IDotNetProject ResolveProject (ProjectReference projectReference)
{
- if (OnResolveProject != null)
- return OnResolveProject (projectReference);
return Projects.FirstOrDefault (project => project.Name == projectReference.Include);
}
-
- public Func<ProjectReference, IDotNetProject> OnResolveProject;
}
}
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageSearchResultViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesSearchResultViewModel.cs index caeec5e53e..10bb57199d 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestablePackageSearchResultViewModel.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesSearchResultViewModel.cs @@ -1,5 +1,5 @@ // -// TestablePackageSearchResultViewModel.cs +// TestableManagePackagesSearchResultViewModel.cs // // Author: // Matt Ward <matt.ward@xamarin.com> @@ -30,12 +30,12 @@ using NuGet.PackageManagement.UI; namespace MonoDevelop.PackageManagement.Tests.Helpers { - class TestablePackageSearchResultViewModel : PackageSearchResultViewModel + class TestableManagePackagesSearchResultViewModel : ManagePackagesSearchResultViewModel { public FakeDotNetProject Project; public FakeSolutionManager SolutionManager; - public TestablePackageSearchResultViewModel ( + public TestableManagePackagesSearchResultViewModel ( PackageItemListViewModel viewModel) : this ( new FakeSolutionManager (), @@ -44,19 +44,19 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers { } - public TestablePackageSearchResultViewModel ( - TestableAllPackagesViewModel parent, + public TestableManagePackagesSearchResultViewModel ( + TestableManagePackagesViewModel parent, PackageItemListViewModel viewModel) : base (parent, viewModel) { } - public TestablePackageSearchResultViewModel ( + public TestableManagePackagesSearchResultViewModel ( FakeSolutionManager solutionManager, FakeDotNetProject project, PackageItemListViewModel viewModel) : this ( - new TestableAllPackagesViewModel (solutionManager, project), + new TestableManagePackagesViewModel (solutionManager, project), viewModel) { SolutionManager = solutionManager; diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableAllPackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesViewModel.cs index 9d2586dcbb..44e8697994 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableAllPackagesViewModel.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.Helpers/TestableManagePackagesViewModel.cs @@ -1,5 +1,5 @@ // -// TestableAllPackagesViewModel.cs +// TestableManagePackagesViewModel.cs // // Author: // Matt Ward <matt.ward@xamarin.com> @@ -25,36 +25,57 @@ // THE SOFTWARE. using System; -using System.Collections.Generic; +using System.IO.IsolatedStorage; using System.Threading; using System.Threading.Tasks; using NuGet.PackageManagement.UI; -using NuGet.Protocol.Core.Types; namespace MonoDevelop.PackageManagement.Tests.Helpers { - class TestableAllPackagesViewModel : AllPackagesViewModel + class TestableManagePackagesViewModel : ManagePackagesViewModel { - public RecentNuGetPackagesRepository RecentPackagesRepository; + public RecentManagedNuGetPackagesRepository RecentPackagesRepository; public FakeNuGetProjectContext FakeNuGetProjectContext; - public TestableAllPackagesViewModel ( + public TestableManagePackagesViewModel ( IMonoDevelopSolutionManager solutionManager, IDotNetProject dotNetProject) : this ( solutionManager, dotNetProject, new FakeNuGetProjectContext (), - new RecentNuGetPackagesRepository ()) + new RecentManagedNuGetPackagesRepository ()) { } - public TestableAllPackagesViewModel ( + public TestableManagePackagesViewModel ( IMonoDevelopSolutionManager solutionManager, IDotNetProject dotNetProject, FakeNuGetProjectContext projectContext, - RecentNuGetPackagesRepository recentPackagesRepository) - : base (solutionManager, dotNetProject, projectContext, recentPackagesRepository) + RecentManagedNuGetPackagesRepository recentPackagesRepository) + : base (solutionManager, dotNetProject.ParentSolution, projectContext, recentPackagesRepository, dotNetProject) + { + FakeNuGetProjectContext = projectContext; + RecentPackagesRepository = recentPackagesRepository; + } + + public TestableManagePackagesViewModel ( + IMonoDevelopSolutionManager solutionManager, + ISolution solution) + : this ( + solutionManager, + solution, + new FakeNuGetProjectContext (), + new RecentManagedNuGetPackagesRepository ()) + { + } + + public TestableManagePackagesViewModel ( + IMonoDevelopSolutionManager solutionManager, + ISolution solution, + FakeNuGetProjectContext projectContext, + RecentManagedNuGetPackagesRepository recentPackagesRepository) + : base (solutionManager, solution, projectContext, recentPackagesRepository, null) { FakeNuGetProjectContext = projectContext; RecentPackagesRepository = recentPackagesRepository; @@ -62,7 +83,7 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public FakePackageFeed PackageFeed = new FakePackageFeed (); - protected override IPackageFeed CreatePackageFeed (IEnumerable<SourceRepository> sourceRepositories) + protected override IPackageFeed CreatePackageFeed (PackageLoadContext context) { return PackageFeed; } @@ -92,9 +113,9 @@ namespace MonoDevelop.PackageManagement.Tests.Helpers public Task GetPackagesInstalledInProjectTask; - protected override Task GetPackagesInstalledInProject () + protected override Task GetPackagesInstalledInProjects () { - GetPackagesInstalledInProjectTask = base.GetPackagesInstalledInProject (); + GetPackagesInstalledInProjectTask = base.GetPackagesInstalledInProjects (); return GetPackagesInstalledInProjectTask; } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj index bbd00cd4ca..560775c805 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests.csproj @@ -44,7 +44,7 @@ <Compile Include="MonoDevelop.PackageManagement.Tests\PackageSourceViewModelTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\RegisteredPackageSourcesViewModelTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\PackageSourceCollectionAssert.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Tests\RecentNuGetPackagesRepositoryTests.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\RecentManagedNuGetPackagesRepositoryTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeSolution.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeProject.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageManagementProjectService.cs" /> @@ -86,17 +86,15 @@ <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProjectAction.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProjectContext.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\NuGetPackageUninstallerTests.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Tests\AllPackagesViewModelTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeSolutionManager.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetProject.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeSourceRepositoryProvider.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakeNuGetSettings.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\FakePackageFeed.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableAllPackagesViewModel.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Tests\PackageSearchResultViewModelTests.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\ManagePackagesSearchResultViewModelTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageMetadataProvider.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageSearchMetadata.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestablePackageSearchResultViewModel.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableManagePackagesSearchResultViewModel.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageMetadataResource.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\FakePackageMetadataResourceProvider.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests\UpdatedNuGetPackagesInWorkspaceTests.cs" /> @@ -154,6 +152,8 @@ <Compile Include="MonoDevelop.PackageManagement.Tests\PackagesCommandHandlerTests.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableRestorePackagesHandler.cs" /> <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableRestorePackagesInProjectHandler.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests\ManagePackagesViewModelTests.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Tests.Helpers\TestableManagePackagesViewModel.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\..\..\core\MonoDevelop.Core\MonoDevelop.Core.csproj"> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageSearchResultViewModelTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesSearchResultViewModelTests.cs index d2a033fe46..dad464ab8f 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/PackageSearchResultViewModelTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesSearchResultViewModelTests.cs @@ -1,5 +1,5 @@ // -// PackageSearchResultViewModelTests.cs +// ManagePackagesSearchResultViewModelTests.cs // // Author: // Matt Ward <matt.ward@xamarin.com> @@ -43,11 +43,11 @@ using NUnit.Framework; namespace MonoDevelop.PackageManagement.Tests { [TestFixture] - public class PackageSearchResultViewModelTests + public class ManagePackagesSearchResultViewModelTests { - TestablePackageSearchResultViewModel viewModel; + TestableManagePackagesSearchResultViewModel viewModel; PackageItemListViewModel packageItemListViewModel; - TestableAllPackagesViewModel parent; + TestableManagePackagesViewModel parent; FakePackageMetadataProvider metadataProvider; List<VersionInfo> packageVersions; FakePackageSearchMetadata packageSearchMetadata; @@ -78,8 +78,8 @@ namespace MonoDevelop.PackageManagement.Tests packageSearchMetadata = metadataProvider.AddPackageMetadata (package.Id, package.Version.ToString ()); var solutionManager = new FakeSolutionManager (); var project = new FakeDotNetProject (); - parent = new TestableAllPackagesViewModel (solutionManager, project); - viewModel = new TestablePackageSearchResultViewModel (parent, packageItemListViewModel); + parent = new TestableManagePackagesViewModel (solutionManager, project); + viewModel = new TestableManagePackagesSearchResultViewModel (parent, packageItemListViewModel); } Task LoadPackageMetadata () @@ -630,5 +630,59 @@ namespace MonoDevelop.PackageManagement.Tests Assert.AreEqual ("1.2-beta1", viewModel.Versions[0].ToString ()); Assert.AreEqual ("1.0-beta2", viewModel.Versions[1].ToString ()); } + + [Test] + public async Task ReadVersions_LatestVersionNotSelectedWhenConsolidating_SelectedVersionChangedToLatestVersion () + { + CreateViewModel (); + viewModel.SelectLatestVersion = true; + AddVersionsToPackageItemListViewModel ("2.0", "1.2.3", "0.2", "0.1"); + + await ReadVersions (); + + Assert.AreEqual (4, viewModel.Versions.Count); + Assert.AreEqual ("2.0", viewModel.Versions [0].ToString ()); + Assert.AreEqual ("1.2.3", viewModel.Versions [1].ToString ()); + Assert.AreEqual ("0.2", viewModel.Versions [2].ToString ()); + Assert.AreEqual ("0.1", viewModel.Versions [3].ToString ()); + Assert.AreEqual ("2.0", viewModel.SelectedVersion.ToString ()); + } + + [Test] + public async Task ReadVersions_LatestVersionNotSelectedWhenNotConsolidating_SelectedVersionNotChanged () + { + CreateViewModel (); + viewModel.SelectLatestVersion = false; + AddVersionsToPackageItemListViewModel ("2.0", "1.2.3", "0.2", "0.1"); + + await ReadVersions (); + + Assert.AreEqual (4, viewModel.Versions.Count); + Assert.AreEqual ("2.0", viewModel.Versions [0].ToString ()); + Assert.AreEqual ("1.2.3", viewModel.Versions [1].ToString ()); + Assert.AreEqual ("0.2", viewModel.Versions [2].ToString ()); + Assert.AreEqual ("0.1", viewModel.Versions [3].ToString ()); + Assert.AreEqual ("1.2.3", viewModel.SelectedVersion.ToString ()); + } + + [Test] + public async Task UpdateFromPreviouslyCheckedViewModel_VersionSelectedWasNotLatestVersion_VersionPreviouslySelectedIsReusedAfterReadingPackages () + { + var package = CreatePackageItemListViewModel (); + package.Version = new NuGetVersion ("1.2.3"); + CreateViewModel (package); + var checkedViewModel = viewModel; + checkedViewModel.IsChecked = true; + package = CreatePackageItemListViewModel (); + package.Version = new NuGetVersion ("1.2.3"); + CreateViewModel (package); + viewModel.SelectLatestVersion = true; + AddVersionsToPackageItemListViewModel ("2.0", "1.2.3", "0.2", "0.1"); + viewModel.UpdateFromPreviouslyCheckedViewModel (checkedViewModel); + await ReadVersions (); + + Assert.IsTrue (viewModel.IsChecked); + Assert.AreEqual ("1.2.3", viewModel.SelectedVersion.ToString ()); + } } }
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AllPackagesViewModelTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesViewModelTests.cs index 5a279f58e9..c4267ab94e 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/AllPackagesViewModelTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/ManagePackagesViewModelTests.cs @@ -1,5 +1,5 @@ // -// AllPackagesViewModelTests.cs +// ManagePackagesViewModelTests.cs // // Author: // Matt Ward <matt.ward@xamarin.com> @@ -31,6 +31,8 @@ using System.Threading.Tasks; using MonoDevelop.PackageManagement.Tests.Helpers; using NuGet.Configuration; using NuGet.PackageManagement.UI; +using NuGet.Packaging; +using NuGet.Packaging.Core; using NuGet.ProjectManagement; using NuGet.Versioning; using NUnit.Framework; @@ -38,28 +40,46 @@ using NUnit.Framework; namespace MonoDevelop.PackageManagement.Tests { [TestFixture] - public class AllPackagesViewModelTests + public class ManagePackagesViewModelTests { - TestableAllPackagesViewModel viewModel; + TestableManagePackagesViewModel viewModel; FakeSolutionManager solutionManager; FakeDotNetProject project; + FakeSolution solution; FakePackageSourceProvider packageSourceProvider; void CreateProject () { + solution = new FakeSolution (); project = new FakeDotNetProject (); + project.ParentSolution = solution; + solution.Projects.Add (project); solutionManager = new FakeSolutionManager (); packageSourceProvider = solutionManager.SourceRepositoryProvider.FakePackageSourceProvider; } + FakeDotNetProject AddProjectToSolution (string name) + { + var newProject = new FakeDotNetProject (); + newProject.Name = name; + solution.Projects.Add (newProject); + return newProject; + } + void CreateViewModel () { - viewModel = new TestableAllPackagesViewModel ( + viewModel = new TestableManagePackagesViewModel ( solutionManager, project); EnsurePackageSourcesLoaded (); } + void CreateViewModelForSolution () + { + viewModel = new TestableManagePackagesViewModel (solutionManager, solution); + EnsurePackageSourcesLoaded (); + } + void EnsurePackageSourcesLoaded () { viewModel.PackageSources.ToList (); @@ -110,29 +130,34 @@ namespace MonoDevelop.PackageManagement.Tests viewModel.SelectedPackageSource = secondPackageSource; } - PackageSearchResultViewModel AddRecentPackage (string packageId, string packageVersion, string packageSource) + ManagePackagesSearchResultViewModel AddRecentPackage (string packageId, string packageVersion, string packageSource) { var searchResultViewModel = CreateRecentPackage (packageId, packageVersion, packageSource); viewModel.RecentPackagesRepository.AddPackage (searchResultViewModel, packageSource); return searchResultViewModel; } - PackageSearchResultViewModel CreateRecentPackage (string packageId, string packageVersion, string packageSource) + ManagePackagesSearchResultViewModel CreateRecentPackage (string packageId, string packageVersion, string packageSource) { - var allPackagesViewModelForRecentPackages = new TestableAllPackagesViewModel ( + var packagesViewModelForRecentPackages = new TestableManagePackagesViewModel ( new FakeSolutionManager (), new FakeDotNetProject ()); var recentPackage = new PackageItemListViewModel { Id = packageId, Version = new NuGetVersion (packageVersion) }; - return new PackageSearchResultViewModel (allPackagesViewModelForRecentPackages, recentPackage); + return new ManagePackagesSearchResultViewModel (packagesViewModelForRecentPackages, recentPackage); } FakeNuGetProject CreateNuGetProjectForProject () { - var nugetProject = new FakeNuGetProject (project); - solutionManager.NuGetProjects[project] = nugetProject; + return CreateNuGetProjectForProject (project); + } + + FakeNuGetProject CreateNuGetProjectForProject (IDotNetProject dotNetProject) + { + var nugetProject = new FakeNuGetProject (dotNetProject); + solutionManager.NuGetProjects [dotNetProject] = nugetProject; return nugetProject; } @@ -1014,6 +1039,7 @@ namespace MonoDevelop.PackageManagement.Tests Assert.AreEqual (1, viewModel.PackageViewModels.Count); Assert.AreEqual ("Recent1", viewModel.PackageViewModels[0].Id); Assert.AreEqual (4, recentPackage.Versions.Count); + Assert.IsFalse (viewModel.PackageViewModels[0].SelectLatestVersion); } [Test] @@ -1031,6 +1057,377 @@ namespace MonoDevelop.PackageManagement.Tests Assert.AreEqual ("All Sources", selectedPackageSource.Name); Assert.IsTrue (selectedPackageSource.IsAggregate); } + + [Test] + public async Task Consolidate_ThreeProjectsDifferentPackageVersionInTwoProjects_ProjectVersionAndSelectionInformationAvailable () + { + CreateProject (); + project.Name = "LibC"; + var nugetProject = CreateNuGetProjectForProject (project); + nugetProject.AddPackageReference ("Test", "0.1"); + + var project2 = AddProjectToSolution ("LibA"); + CreateNuGetProjectForProject (project2); + + var project3 = AddProjectToSolution ("LibB"); + nugetProject = CreateNuGetProjectForProject (project3); + nugetProject.AddPackageReference ("Test", "0.2"); + + AddOnePackageSourceToRegisteredSources (); + CreateViewModelForSolution (); + viewModel.PackageFeed.AddPackage ("Test", "0.2"); + viewModel.PageSelected = ManagePackagesPage.Consolidate; + + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + var package = viewModel.PackageViewModels.Single (); + viewModel.SelectedPackage = package; + Assert.AreEqual ("Test", package.Id); + Assert.AreEqual ("0.2", package.Version.ToString ()); + + Assert.AreEqual (3, viewModel.ProjectViewModels.Count); + + // Checked projects first. + var projectViewModel = viewModel.ProjectViewModels [0]; + Assert.AreEqual ("LibB", projectViewModel.ProjectName); + Assert.AreEqual ("0.2", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [1]; + Assert.AreEqual ("LibC", projectViewModel.ProjectName); + Assert.AreEqual ("0.1", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [2]; + Assert.AreEqual ("LibA", projectViewModel.ProjectName); + Assert.AreEqual ("–", projectViewModel.PackageVersion); + Assert.IsFalse (projectViewModel.IsChecked); + + Assert.IsTrue (viewModel.CanConsolidate ()); + + // Expecting one action since Test 0.2 is already installed in LibB. + var actions = viewModel.CreateConsolidatePackageActions (package).ToList (); + Assert.AreEqual (1, actions.Count); + var action = actions [0] as InstallNuGetPackageAction; + Assert.AreEqual (PackageActionType.Install, action.ActionType); + Assert.AreEqual ("Test", action.PackageId); + Assert.AreEqual ("0.2", action.Version.ToString ()); + Assert.AreEqual ("LibC", action.Project.Name); + + // Check LibA, which does not have the package. + viewModel.ProjectViewModels [2].IsChecked = true; + + // Uncheck LibC. + viewModel.ProjectViewModels [1].IsChecked = false; + + Assert.IsTrue (viewModel.CanConsolidate ()); + + actions = viewModel.CreateConsolidatePackageActions (package).ToList (); + Assert.AreEqual (1, actions.Count); + action = actions [0] as InstallNuGetPackageAction; + Assert.AreEqual (PackageActionType.Install, action.ActionType); + Assert.AreEqual ("Test", action.PackageId); + Assert.AreEqual ("0.2", action.Version.ToString ()); + Assert.AreEqual ("LibA", action.Project.Name); + + // Uncheck all projects. No items checked so cannot consolidate. + viewModel.ProjectViewModels [0].IsChecked = false; + viewModel.ProjectViewModels [1].IsChecked = false; + viewModel.ProjectViewModels [2].IsChecked = false; + Assert.IsFalse (viewModel.CanConsolidate ()); + + // Check LibB which has same package. + viewModel.ProjectViewModels [0].IsChecked = true; + Assert.IsFalse (viewModel.CanConsolidate ()); + + viewModel.SelectedPackage = null; + Assert.AreEqual (0, viewModel.ProjectViewModels.Count); + Assert.IsFalse (viewModel.CanConsolidate ()); + } + + [Test] + public async Task CheckedPackageViewModels_DifferentTabPageSelected_CheckedPackagesCleared () + { + CreateProject (); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("A", "1.2"); + viewModel.PackageFeed.AddPackage ("B", "1.3"); + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + viewModel.PackageViewModels [0].IsChecked = true; + + Assert.AreEqual (2, viewModel.PackageViewModels.Count); + Assert.AreEqual (1, viewModel.CheckedPackageViewModels.Count); + Assert.AreEqual ("A", viewModel.CheckedPackageViewModels [0].Id); + Assert.IsFalse (viewModel.PackageViewModels [0].SelectLatestVersion); + Assert.IsFalse (viewModel.PackageViewModels [1].SelectLatestVersion); + + viewModel.PageSelected = ManagePackagesPage.Consolidate; + + Assert.AreEqual (0, viewModel.CheckedPackageViewModels.Count); + } + + [Test] + public async Task Consolidate_ThreeProjectsTwoPackages_ProjectVersionAndSelectionInformationAvailable () + { + CreateProject (); + project.Name = "LibA"; + var nugetProject = CreateNuGetProjectForProject (project); + nugetProject.AddPackageReference ("Test", "0.1"); + + var project2 = AddProjectToSolution ("LibB"); + nugetProject = CreateNuGetProjectForProject (project2); + nugetProject.AddPackageReference ("Other", "0.1"); + + var project3 = AddProjectToSolution ("LibC"); + nugetProject = CreateNuGetProjectForProject (project3); + nugetProject.AddPackageReference ("Test", "0.2"); + nugetProject.AddPackageReference ("Other", "0.3"); + + AddOnePackageSourceToRegisteredSources (); + CreateViewModelForSolution (); + viewModel.PackageFeed.AddPackage ("Test", "0.2"); + viewModel.PackageFeed.AddPackage ("Other", "0.3"); + viewModel.PageSelected = ManagePackagesPage.Consolidate; + + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + // Select Test package. + var package = viewModel.PackageViewModels [0]; + viewModel.SelectedPackage = package; + + Assert.AreEqual (2, viewModel.PackageViewModels.Count); + Assert.AreEqual ("Test", package.Id); + Assert.AreEqual ("0.2", package.Version.ToString ()); + Assert.IsTrue (package.SelectLatestVersion); + Assert.AreEqual ("Other", viewModel.PackageViewModels [1].Id); + Assert.AreEqual ("0.3", viewModel.PackageViewModels [1].Version.ToString ()); + Assert.IsTrue (viewModel.PackageViewModels [1].SelectLatestVersion); + + Assert.AreEqual (3, viewModel.ProjectViewModels.Count); + + var projectViewModel = viewModel.ProjectViewModels [0]; + Assert.AreEqual ("LibA", projectViewModel.ProjectName); + Assert.AreEqual ("0.1", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [1]; + Assert.AreEqual ("LibC", projectViewModel.ProjectName); + Assert.AreEqual ("0.2", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [2]; + Assert.AreEqual ("LibB", projectViewModel.ProjectName); + Assert.AreEqual ("–", projectViewModel.PackageVersion); + Assert.IsFalse (projectViewModel.IsChecked); + + // Check LibB, Uncheck LibC + viewModel.ProjectViewModels [2].IsChecked = true; + viewModel.ProjectViewModels [1].IsChecked = false; + + // Select Other package + package = viewModel.PackageViewModels [1]; + viewModel.SelectedPackage = package; + + Assert.AreEqual (3, viewModel.ProjectViewModels.Count); + + projectViewModel = viewModel.ProjectViewModels [0]; + Assert.AreEqual ("LibB", projectViewModel.ProjectName); + Assert.AreEqual ("0.1", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [1]; + Assert.AreEqual ("LibC", projectViewModel.ProjectName); + Assert.AreEqual ("0.3", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [2]; + Assert.AreEqual ("LibA", projectViewModel.ProjectName); + Assert.AreEqual ("–", projectViewModel.PackageVersion); + Assert.IsFalse (projectViewModel.IsChecked); + + // Select Test package again. + package = viewModel.PackageViewModels [0]; + viewModel.SelectedPackage = package; + + projectViewModel = viewModel.ProjectViewModels [0]; + Assert.AreEqual ("LibA", projectViewModel.ProjectName); + Assert.AreEqual ("0.1", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [1]; + Assert.AreEqual ("LibC", projectViewModel.ProjectName); + Assert.AreEqual ("0.2", projectViewModel.PackageVersion); + Assert.IsFalse (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [2]; + Assert.AreEqual ("LibB", projectViewModel.ProjectName); + Assert.AreEqual ("–", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + // Check that the cached project information is cleared after selecting a different + // tab and going back to the consolidate tab. + viewModel.PageSelected = ManagePackagesPage.Browse; + viewModel.SelectedPackage = null; + viewModel.PageSelected = ManagePackagesPage.Consolidate; + package = viewModel.PackageViewModels [0]; + viewModel.SelectedPackage = package; + + projectViewModel = viewModel.ProjectViewModels [0]; + Assert.AreEqual ("LibA", projectViewModel.ProjectName); + Assert.AreEqual ("0.1", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [1]; + Assert.AreEqual ("LibC", projectViewModel.ProjectName); + Assert.AreEqual ("0.2", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [2]; + Assert.AreEqual ("LibB", projectViewModel.ProjectName); + Assert.AreEqual ("–", projectViewModel.PackageVersion); + Assert.IsFalse (projectViewModel.IsChecked); + } + + [Test] + public async Task Consolidate_ThreeProjectsTwoPackages_PackagesChecked_CheckedPackagesCanBeConsolidated () + { + CreateProject (); + project.Name = "LibA"; + var nugetProject = CreateNuGetProjectForProject (project); + nugetProject.AddPackageReference ("Test", "0.1"); + + var project2 = AddProjectToSolution ("LibB"); + nugetProject = CreateNuGetProjectForProject (project2); + nugetProject.AddPackageReference ("Other", "0.1"); + + var project3 = AddProjectToSolution ("LibC"); + nugetProject = CreateNuGetProjectForProject (project3); + nugetProject.AddPackageReference ("Test", "0.2"); + nugetProject.AddPackageReference ("Other", "0.3"); + + AddOnePackageSourceToRegisteredSources (); + CreateViewModelForSolution (); + viewModel.PackageFeed.AddPackage ("Test", "0.2"); + viewModel.PackageFeed.AddPackage ("Other", "0.3"); + viewModel.PageSelected = ManagePackagesPage.Consolidate; + + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + // Select Test package. + var package = viewModel.PackageViewModels [0]; + viewModel.SelectedPackage = package; + + Assert.AreEqual (2, viewModel.PackageViewModels.Count); + Assert.AreEqual ("Test", package.Id); + Assert.AreEqual ("0.2", package.Version.ToString ()); + Assert.AreEqual ("Other", viewModel.PackageViewModels [1].Id); + Assert.AreEqual ("0.3", viewModel.PackageViewModels [1].Version.ToString ()); + + // Checked packages first. + var projectViewModel = viewModel.ProjectViewModels [0]; + Assert.AreEqual ("LibA", projectViewModel.ProjectName); + Assert.AreEqual ("0.1", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [1]; + Assert.AreEqual ("LibC", projectViewModel.ProjectName); + Assert.AreEqual ("0.2", projectViewModel.PackageVersion); + Assert.IsTrue (projectViewModel.IsChecked); + + projectViewModel = viewModel.ProjectViewModels [2]; + Assert.AreEqual ("LibB", projectViewModel.ProjectName); + Assert.AreEqual ("–", projectViewModel.PackageVersion); + Assert.IsFalse (projectViewModel.IsChecked); + + viewModel.ProjectViewModels [0].IsChecked = false; + viewModel.ProjectViewModels [1].IsChecked = false; + viewModel.ProjectViewModels [2].IsChecked = false; + + Assert.IsFalse (viewModel.CanConsolidate ()); + + // Select other package, check it, then switch back to + // Test package + package = viewModel.PackageViewModels [1]; + viewModel.SelectedPackage = package; + package.IsChecked = true; + viewModel.SelectedPackage = viewModel.PackageViewModels [0]; + + // Should be able to consolidate since Other package is checked even though + // Test package is selected and cannot be consolidated. + Assert.IsTrue (viewModel.CanConsolidate ()); + + // Check Test package too. + viewModel.SelectedPackage.IsChecked = true; + var actions = viewModel.CreateConsolidatePackageActions (viewModel.PackageViewModels [0]).ToList (); + // Should be no actions since all projects are unchecked for this package. + Assert.AreEqual (0, actions.Count); + + actions = viewModel.CreateConsolidatePackageActions (viewModel.PackageViewModels [1]).ToList (); + var action = actions [0] as InstallNuGetPackageAction; + Assert.AreEqual (1, actions.Count); + Assert.AreEqual ("Other", action.PackageId); + Assert.AreEqual ("0.3", action.Version.ToString ()); + Assert.AreEqual ("LibB", action.Project.Name); + } + + [Test] + public async Task CurrentVersion_OneUpdate_PackageVersionInstalledInProjectReturned () + { + CreateProject (); + var nugetProject = CreateNuGetProjectForProject (project); + nugetProject.AddPackageReference ("Test", "0.1"); + AddOnePackageSourceToRegisteredSources (); + CreateViewModel (); + viewModel.PackageFeed.AddPackage ("Test", "0.2"); + viewModel.PageSelected = ManagePackagesPage.Browse; + + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + var package = viewModel.PackageViewModels.Single (); + Assert.AreEqual ("Test", package.Id); + Assert.AreEqual ("0.2", package.Version.ToString ()); + Assert.AreEqual ("0.1", package.GetCurrentPackageVersionText ()); + Assert.AreEqual (string.Empty, package.GetCurrentPackageVersionAdditionalText ()); + } + + [Test] + public async Task CurrentVersion_DifferentPackageVersionInstalledInProjects_MultipleReturned () + { + CreateProject (); + CreateProject (); + project.Name = "LibC"; + var nugetProject = CreateNuGetProjectForProject (project); + nugetProject.AddPackageReference ("Test", "0.1"); + + var project2 = AddProjectToSolution ("LibA"); + CreateNuGetProjectForProject (project2); + + var project3 = AddProjectToSolution ("LibB"); + nugetProject = CreateNuGetProjectForProject (project3); + nugetProject.AddPackageReference ("Test", "0.2"); + + AddOnePackageSourceToRegisteredSources (); + CreateViewModelForSolution (); + viewModel.PackageFeed.AddPackage ("Test", "0.2"); + + viewModel.PageSelected = ManagePackagesPage.Browse; + + viewModel.ReadPackages (); + await viewModel.ReadPackagesTask; + + string expectedAdditionalText = "LibB: 0.2, LibC: 0.1"; + var package = viewModel.PackageViewModels.Single (); + Assert.AreEqual ("Test", package.Id); + Assert.AreEqual ("0.2", package.Version.ToString ()); + Assert.AreEqual ("Multiple", package.GetCurrentPackageVersionText ()); + Assert.AreEqual (expectedAdditionalText, package.GetCurrentPackageVersionAdditionalText ()); + } } } - diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentNuGetPackagesRepositoryTests.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentManagedNuGetPackagesRepositoryTests.cs index 9bd5595b66..0f327d163a 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentNuGetPackagesRepositoryTests.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.Tests/MonoDevelop.PackageManagement.Tests/RecentManagedNuGetPackagesRepositoryTests.cs @@ -1,5 +1,5 @@ //
-// RecentNuGetPackagesRepositoryTests.cs
+// RecentManagedNuGetPackagesRepositoryTests.cs
//
// Author:
// Matt Ward <matt.ward@xamarin.com>
@@ -33,37 +33,37 @@ using NUnit.Framework; namespace MonoDevelop.PackageManagement.Tests
{
[TestFixture]
- public class RecentNuGetPackagesRepositoryTests
+ public class RecentManagedNuGetPackagesRepositoryTests
{
- RecentNuGetPackagesRepository repository;
+ RecentManagedNuGetPackagesRepository repository;
void CreateRepository ()
{
- repository = new RecentNuGetPackagesRepository ();
+ repository = new RecentManagedNuGetPackagesRepository ();
}
- PackageSearchResultViewModel AddOnePackageToRepository (string id, string packageSource)
+ ManagePackagesSearchResultViewModel AddOnePackageToRepository (string id, string packageSource)
{
var viewModel = CreatePackage (id);
repository.AddPackage (viewModel, packageSource);
return viewModel;
}
- PackageSearchResultViewModel CreatePackage (string id)
+ ManagePackagesSearchResultViewModel CreatePackage (string id)
{
var packageViewModel = new PackageItemListViewModel {
Id = id
};
- return new PackageSearchResultViewModel (null, packageViewModel);
+ return new ManagePackagesSearchResultViewModel (null, packageViewModel);
}
- IEnumerable<PackageSearchResultViewModel> AddTwoDifferentPackagesToRepository (string packageSource)
+ IEnumerable<ManagePackagesSearchResultViewModel> AddTwoDifferentPackagesToRepository (string packageSource)
{
yield return AddOnePackageToRepository ("Test.Package.1", packageSource);
yield return AddOnePackageToRepository ("Test.Package.2", packageSource);
}
- IEnumerable<PackageSearchResultViewModel> AddFourDifferentPackagesToRepository (string packageSource)
+ IEnumerable<ManagePackagesSearchResultViewModel> AddFourDifferentPackagesToRepository (string packageSource)
{
yield return AddOnePackageToRepository ("Test.Package.1", packageSource);
yield return AddOnePackageToRepository ("Test.Package.2", packageSource);
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml index dc351294d4..19c48c6789 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.addin.xml @@ -22,6 +22,18 @@ _label = "Add NuGet _Packages..."
defaultHandler = "MonoDevelop.PackageManagement.Commands.AddPackagesHandler" />
<Command
+ id="MonoDevelop.PackageManagement.Commands.ManagePackages"
+ _description="Manage packages for the solution"
+ _label="_Manage NuGet Packages..."
+ _displayName="Manage Packages (Solution)"
+ defaultHandler="MonoDevelop.PackageManagement.ManagePackagesHandler" />
+ <Command
+ id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject"
+ _description="Manage packages for the project"
+ _label="_Manage NuGet Packages..."
+ _displayName="Manage Packages"
+ defaultHandler="MonoDevelop.PackageManagement.ManagePackagesInProjectHandler" />
+ <Command
id = "MonoDevelop.PackageManagement.Commands.RestorePackages"
_description = "Restore all missing packages in the solution"
_label = "_Restore NuGet Packages"
@@ -65,7 +77,7 @@ <Extension path="/MonoDevelop/Ide/MainMenu/Project">
<SeparatorItem insertafter="MonoDevelop.Ide.Commands.ProjectCommands.AddReference" />
- <CommandItem id="MonoDevelop.PackageManagement.Commands.AddPackages" />
+ <CommandItem id="MonoDevelop.PackageManagement.Commands.ManagePackages" />
<CommandItem id="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInSolution" />
<CommandItem id="MonoDevelop.PackageManagement.Commands.RestorePackages" />
<SeparatorItem />
@@ -73,18 +85,36 @@ <Extension path="/MonoDevelop/Ide/ContextMenu/ProjectPad">
<Condition id="ItemType" value="Solution">
+ <SeparatorItem
+ id="MonoDevelop.PackageManagement.ProjectPad.Separator"
+ insertafter="MonoDevelop.Ide.Commands.ProjectCommands.AddReference"
+ insertbefore="AddSectionEnd" />
+ <CommandItem
+ id="MonoDevelop.PackageManagement.Commands.ManagePackages"
+ insertafter="MonoDevelop.PackageManagement.ProjectPad.Separator"
+ insertbefore="AddSectionEnd" />
<CommandItem
id="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInSolution"
- insertafter="MonoDevelop.PackageManagement.Commands.AddReference"
+ insertafter="MonoDevelop.PackageManagement.Commands.ManagePackagese"
insertbefore="AddSectionEnd" />
<CommandItem
id="MonoDevelop.PackageManagement.Commands.RestorePackages"
insertafter="MonoDevelop.PackageManagement.Commands.UpdateAllPackagesInSolution"
insertbefore="AddSectionEnd" />
</Condition>
+ <Condition id="ItemType" value="DotNetProject">
+ <SeparatorItem
+ id="MonoDevelop.PackageManagement.ProjectPad.Separator"
+ insertafter="MonoDevelop.Ide.Commands.ProjectCommands.AddReference"
+ insertbefore="AddSectionEnd" />
+ <CommandItem
+ id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject"
+ insertafter="MonoDevelop.PackageManagement.ProjectPad.Separator"
+ insertbefore="AddSectionEnd" />
+ </Condition>
<Condition id="ItemType" value="MonoDevelop.PackageManagement.NodeBuilders.ProjectPackagesFolderNode">
<CommandItem
- id="MonoDevelop.PackageManagement.Commands.AddPackages" _label = "Add NuGet _Packages..." />
+ id="MonoDevelop.PackageManagement.Commands.ManagePackagesInProject" />
<CommandItem
id="MonoDevelop.PackageManagement.Commands.PackagesFolderNodeCommands.ReinstallAllPackagesInProject" />
<CommandItem
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj index 6d2e380db0..851b54e052 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement.csproj @@ -102,10 +102,6 @@ <Compile Include="MonoDevelop.PackageManagement.Gui\PackageManagementOptionsPanel.cs" /> <Compile Include="MonoDevelop.PackageManagement.Gui\PackageManagementOptionsWidget.cs" /> <Compile Include="MonoDevelop.PackageManagement.Commands\AddPackagesHandler.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Gui\AddPackagesDialog.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Gui\AddPackagesDialog.UI.cs"> - <DependentUpon>AddPackagesDialog.cs</DependentUpon> - </Compile> <Compile Include="MonoDevelop.PackageManagement\PackageRepositoryNodeExtensions.cs" /> <Compile Include="MonoDevelop.PackageManagement\ProjectTemplateNuGetPackageInstaller.cs" /> <Compile Include="MonoDevelop.PackageManagement\PackageManagementEventsMonitor.cs" /> @@ -127,9 +123,7 @@ <Compile Include="MonoDevelop.PackageManagement\ProgressMonitorStatusMessageFactory.cs" /> <Compile Include="MonoDevelop.PackageManagement\ProgressMonitorStatusMessage.cs" /> <Compile Include="AddinInfo.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Gui\PackageCellView.cs" /> <Compile Include="MonoDevelop.PackageManagement\SearchPackagesSearchCategory.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Gui\AddPackagesDialogRunner.cs" /> <Compile Include="MonoDevelop.PackageManagement.Commands\ProjectPackagesFolderNodeCommandHandler.cs" /> <Compile Include="MonoDevelop.PackageManagement.NodeBuilders\ProjectReferenceNodeBuilderExtension.cs" /> <Compile Include="MonoDevelop.PackageManagement\ProjectReferenceExtensions.cs" /> @@ -142,7 +136,6 @@ <DependentUpon>AddPackageSourceDialog.cs</DependentUpon> </Compile> <Compile Include="MonoDevelop.PackageManagement.Gui\DialogExtensions.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Gui\PackageCellViewEventArgs.cs" /> <Compile Include="MonoDevelop.PackageManagement.Gui\Styles.cs" /> <Compile Include="MonoDevelop.PackageManagement\ImageLoader.cs" /> <Compile Include="MonoDevelop.PackageManagement\ImageLoadedEventArgs.cs" /> @@ -153,7 +146,7 @@ <Compile Include="MonoDevelop.PackageManagement\ImageCache.cs" /> <Compile Include="MonoDevelop.PackageManagement\ProgressMonitorExtensions.cs" /> <Compile Include="MonoDevelop.PackageManagement\PackageListViewTextFormatter.cs" /> - <Compile Include="MonoDevelop.PackageManagement.Gui\PackageCellViewCheckBox.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesCellViewCheckBox.cs" /> <Compile Include="MonoDevelop.PackageManagement\PackageManagementProgressMonitor.cs" /> <Compile Include="MonoDevelop.PackageManagement\ISolution.cs" /> <Compile Include="MonoDevelop.PackageManagement\IProject.cs" /> @@ -197,13 +190,11 @@ <Compile Include="MonoDevelop.PackageManagement\PackageManagementSolutionProjectService.cs" /> <Compile Include="MonoDevelop.PackageManagement\NuGetPackageNewImportsHandler.cs" /> <Compile Include="MonoDevelop.PackageManagement\INuGetPackageNewImportsHandler.cs" /> - <Compile Include="MonoDevelop.PackageManagement\AllPackagesViewModel.cs" /> <Compile Include="MonoDevelop.PackageManagement\SourceRepositoryProvider.cs" /> <Compile Include="NuGet.PackageManagement.UI\SearchResult.cs" /> <Compile Include="NuGet.PackageManagement.UI\PackageItemListViewModel.cs" /> <Compile Include="NuGet.PackageManagement.UI\PackageStatus.cs" /> <Compile Include="NuGet.PackageManagement.UI\DisplayVersion.cs" /> - <Compile Include="MonoDevelop.PackageManagement\PackageSearchResultViewModel.cs" /> <Compile Include="MonoDevelop.PackageManagement\SourceRepositoryViewModel.cs" /> <Compile Include="MonoDevelop.PackageManagement\InstallNuGetPackageAction.cs" /> <Compile Include="MonoDevelop.PackageManagement\MonoDevelopSolutionManager.cs" /> @@ -270,8 +261,6 @@ <Compile Include="NuGet.PackageManagement.UI\IPackageMetadataProvider.cs" /> <Compile Include="NuGet.PackageManagement.UI\DetailControlModel.cs" /> <Compile Include="NuGet.PackageManagement.UI\PackageDetailControlModel.cs" /> - <Compile Include="MonoDevelop.PackageManagement\RecentNuGetPackagesRepository.cs" /> - <Compile Include="MonoDevelop.PackageManagement\PackageSearchResultViewModelComparer.cs" /> <Compile Include="MonoDevelop.PackageManagement\MonoDevelopPackageSourceProvider.cs" /> <Compile Include="MonoDevelop.PackageManagement\SettingsLoader.cs" /> <Compile Include="MonoDevelop.PackageManagement\INuGetPackageManager.cs" /> @@ -347,6 +336,35 @@ <Compile Include="MonoDevelop.PackageManagement\SdkProjectReloadMonitor.cs" /> <Compile Include="MonoDevelop.PackageManagement\SdkProjectBuilderMaintainer.cs" /> <Compile Include="MonoDevelop.PackageManagement\SdkProjectFileRenamedHandler.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Commands\ManagePackagesHandler.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Commands\ManagePackagesInProjectHandler.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesDialog.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesDialog.UI.cs"> + <DependentUpon>ManagePackagesDialog.cs</DependentUpon> + </Compile> + <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesDialogRunner.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Gui\SelectProjectsDialog.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Gui\SelectProjectsDialog.UI.cs"> + <DependentUpon>SelectProjectsDialog.cs</DependentUpon> + </Compile> + <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesCellView.cs" /> + <Compile Include="MonoDevelop.PackageManagement.Gui\ManagePackagesCellViewEventArgs.cs" /> + <Compile Include="MonoDevelop.PackageManagement\ManagedPackagesSearchResultViewModelComparer.cs" /> + <Compile Include="MonoDevelop.PackageManagement\ManagePackagesPage.cs" /> + <Compile Include="MonoDevelop.PackageManagement\ManagePackagesProjectInfo.cs" /> + <Compile Include="MonoDevelop.PackageManagement\ManagePackagesSearchResultViewModel.cs" /> + <Compile Include="MonoDevelop.PackageManagement\ManagePackagesViewModel.cs" /> + <Compile Include="NuGet.PackageManagement.UI\ConsolidatePackageFeed.cs" /> + <Compile Include="NuGet.PackageManagement.UI\InstalledPackageFeed.cs" /> + <Compile Include="NuGet.PackageManagement.UI\PackageCollection.cs" /> + <Compile Include="NuGet.PackageManagement.UI\PackageFeedEnumerator.cs" /> + <Compile Include="NuGet.PackageManagement.UI\PackageSearchMetadataCache.cs" /> + <Compile Include="NuGet.PackageManagement.UI\PlainPackageFeedBase.cs" /> + <Compile Include="NuGet.PackageManagement.UI\UpdatePackageFeed.cs" /> + <Compile Include="MonoDevelop.PackageManagement\SelectedProjectViewModel.cs" /> + <Compile Include="MonoDevelop.PackageManagement\SelectProjectsViewModel.cs" /> + <Compile Include="MonoDevelop.PackageManagement\RecentManagedNuGetPackagesRepository.cs" /> + <Compile Include="MonoDevelop.PackageManagement\ManageProjectViewModel.cs" /> </ItemGroup> <ItemGroup> <EmbeddedResource Include="MonoDevelop.PackageManagement.addin.xml" /> diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs deleted file mode 100644 index f1c5036f80..0000000000 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/AllPackagesViewModel.cs +++ /dev/null @@ -1,608 +0,0 @@ -//
-// AllPackagesViewModel.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2016 Xamarin Inc. (http://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.
-
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using MonoDevelop.Core;
-using MonoDevelop.Ide;
-using MonoDevelop.Projects;
-using NuGet.Configuration;
-using NuGet.PackageManagement;
-using NuGet.PackageManagement.UI;
-using NuGet.Packaging;
-using NuGet.ProjectManagement;
-using NuGet.Protocol.Core.Types;
-using NuGet.Versioning;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class AllPackagesViewModel : ViewModelBase<AllPackagesViewModel>, INuGetUILogger
- {
- SourceRepositoryViewModel selectedPackageSource;
- IPackageSourceProvider packageSourceProvider;
- PackageItemLoader currentLoader;
- CancellationTokenSource cancellationTokenSource;
- List<SourceRepositoryViewModel> packageSources;
- bool includePrerelease;
- bool ignorePackageCheckedChanged;
- IMonoDevelopSolutionManager solutionManager;
- NuGetProject nugetProject;
- IDotNetProject dotNetProject;
- INuGetProjectContext projectContext;
- List<PackageReference> packageReferences = new List<PackageReference> ();
- AggregatePackageSourceErrorMessage aggregateErrorMessage;
- NuGetPackageManager packageManager;
- RecentNuGetPackagesRepository recentPackagesRepository;
-
- public static AllPackagesViewModel Create (RecentNuGetPackagesRepository recentPackagesRepository)
- {
- var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (IdeApp.ProjectOperations.CurrentSelectedSolution);
- var dotNetProject = new DotNetProjectProxy ((DotNetProject)IdeApp.ProjectOperations.CurrentSelectedProject);
- return new AllPackagesViewModel (solutionManager, dotNetProject, recentPackagesRepository);
- }
-
- public static AllPackagesViewModel Create (
- DotNetProject project,
- RecentNuGetPackagesRepository recentPackagesRepository)
- {
- if (project == null)
- return Create (recentPackagesRepository);
-
- var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (project.ParentSolution);
- var dotNetProject = new DotNetProjectProxy (project);
- return new AllPackagesViewModel (solutionManager, dotNetProject, recentPackagesRepository);
- }
-
- public AllPackagesViewModel (
- IMonoDevelopSolutionManager solutionManager,
- IDotNetProject dotNetProject,
- RecentNuGetPackagesRepository recentPackagesRepository)
- : this (
- solutionManager,
- dotNetProject,
- new NuGetProjectContext (solutionManager.Settings),
- recentPackagesRepository)
- {
- }
-
- public AllPackagesViewModel (
- IMonoDevelopSolutionManager solutionManager,
- IDotNetProject dotNetProject,
- INuGetProjectContext projectContext,
- RecentNuGetPackagesRepository recentPackagesRepository)
- {
- this.solutionManager = solutionManager;
- this.dotNetProject = dotNetProject;
- this.projectContext = projectContext;
- this.recentPackagesRepository = recentPackagesRepository;
- PackageViewModels = new ObservableCollection<PackageSearchResultViewModel> ();
- CheckedPackageViewModels = new ObservableCollection<PackageSearchResultViewModel> ();
- ErrorMessage = String.Empty;
-
- packageManager = new NuGetPackageManager (
- solutionManager.CreateSourceRepositoryProvider (),
- solutionManager.Settings,
- solutionManager,
- new DeleteOnRestartManager ()
- );
-
- nugetProject = solutionManager.GetNuGetProject (dotNetProject);
- GetPackagesInstalledInProject ();
- }
-
- public NuGetProject NuGetProject {
- get { return nugetProject; }
- }
-
- public IDotNetProject Project {
- get { return dotNetProject; }
- }
- - public string SearchTerms { get; set; }
-
- public IEnumerable<SourceRepositoryViewModel> PackageSources {
- get {
- if (packageSources == null) {
- packageSources = GetPackageSources ().ToList ();
- }
- return packageSources;
- }
- }
-
- IEnumerable<SourceRepositoryViewModel> GetPackageSources ()
- {
- ISourceRepositoryProvider provider = solutionManager.CreateSourceRepositoryProvider ();
- packageSourceProvider = provider.PackageSourceProvider;
- var repositories = provider.GetRepositories ().ToList ();
-
- if (repositories.Count > 1) {
- yield return new AggregateSourceRepositoryViewModel (repositories);
- }
-
- foreach (SourceRepository repository in repositories) {
- yield return new SourceRepositoryViewModel (repository);
- }
- }
-
- public SourceRepositoryViewModel SelectedPackageSource {
- get {
- if (selectedPackageSource == null) {
- selectedPackageSource = GetActivePackageSource ();
- }
- return selectedPackageSource;
- }
- set {
- if (selectedPackageSource != value) {
- selectedPackageSource = value;
- SaveActivePackageSource ();
- ReadPackages ();
- OnPropertyChanged (null);
- }
- }
- }
- - SourceRepositoryViewModel GetActivePackageSource ()
- {
- if (packageSources == null)
- return null;
-
- if (!String.IsNullOrEmpty (packageSourceProvider.ActivePackageSourceName)) {
- SourceRepositoryViewModel packageSource = packageSources
- .FirstOrDefault (viewModel => String.Equals (viewModel.PackageSource.Name, packageSourceProvider.ActivePackageSourceName, StringComparison.CurrentCultureIgnoreCase));
- if (packageSource != null) {
- return packageSource;
- }
- }
-
- return packageSources.FirstOrDefault (packageSource => !packageSource.IsAggregate);
- }
-
- void SaveActivePackageSource ()
- {
- if (selectedPackageSource == null || packageSourceProvider == null)
- return;
-
- packageSourceProvider.SaveActivePackageSource (selectedPackageSource.PackageSource);
- }
- - public ObservableCollection<PackageSearchResultViewModel> PackageViewModels { get; private set; }
- public ObservableCollection<PackageSearchResultViewModel> CheckedPackageViewModels { get; private set; }
-
- public bool HasError { get; private set; }
- public string ErrorMessage { get; private set; }
-
- public bool IsLoadingNextPage { get; private set; }
- public bool IsReadingPackages { get; private set; }
- public bool HasNextPage { get; private set; }
-
- public bool IncludePrerelease {
- get { return includePrerelease; }
- set {
- if (includePrerelease != value) {
- includePrerelease = value;
- ReadPackages ();
- OnPropertyChanged (null);
- }
- }
- }
-
- public void Dispose()
- {
- OnDispose ();
- CancelReadPackagesTask ();
- IsDisposed = true;
- }
- - protected virtual void OnDispose()
- {
- }
-
- public bool IsDisposed { get; private set; }
-
- public void Search ()
- {
- ReadPackages ();
- OnPropertyChanged (null);
- }
-
- public void ReadPackages ()
- {
- if (SelectedPackageSource == null) {
- return;
- }
-
- HasNextPage = false;
- IsLoadingNextPage = false;
- currentLoader = null;
- StartReadPackagesTask ();
- }
-
- void StartReadPackagesTask (bool clearPackages = true)
- {
- IsReadingPackages = true;
- ClearError ();
- if (clearPackages) {
- CancelReadPackagesTask ();
- ClearPackages ();
- }
- CreateReadPackagesTask ();
- }
-
- void CancelReadPackagesTask()
- {
- if (cancellationTokenSource != null) {
- // Cancel on another thread since CancellationTokenSource.Cancel can sometimes
- // take up to a second on Mono and we do not want to block the UI thread.
- var tokenSource = cancellationTokenSource;
- Task.Run (() => {
- try {
- tokenSource.Cancel ();
- tokenSource.Dispose ();
- } catch (Exception ex) {
- LoggingService.LogError ("Unable to cancel task.", ex);
- }
- });
- cancellationTokenSource = null;
- }
- }
-
- protected virtual Task CreateReadPackagesTask()
- {
- var loader = currentLoader ?? CreatePackageLoader ();
- cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource ();
- return LoadPackagesAsync (loader, cancellationTokenSource.Token)
- .ContinueWith (t => OnPackagesRead (t, loader), TaskScheduler.FromCurrentSynchronizationContext ());
- }
-
- PackageItemLoader CreatePackageLoader ()
- {
- var context = new PackageLoadContext (
- selectedPackageSource.GetSourceRepositories (),
- false,
- nugetProject);
-
- var loader = new PackageItemLoader (
- context,
- CreatePackageFeed (context.SourceRepositories),
- SearchTerms,
- IncludePrerelease
- );
-
- currentLoader = loader;
-
- return loader;
- }
-
- protected virtual IPackageFeed CreatePackageFeed (IEnumerable<SourceRepository> sourceRepositories)
- {
- return new MultiSourcePackageFeed (sourceRepositories, this);
- }
-
- protected virtual Task LoadPackagesAsync (PackageItemLoader loader, CancellationToken token)
- {
- return Task.Run (async () => {
- await loader.LoadNextAsync (null, token);
-
- while (loader.State.LoadingStatus == LoadingStatus.Loading) {
- token.ThrowIfCancellationRequested ();
- await loader.UpdateStateAsync (null, token);
- }
- });
- }
-
- void ClearError ()
- {
- HasError = false;
- ErrorMessage = String.Empty;
- aggregateErrorMessage = new AggregatePackageSourceErrorMessage (GetTotalPackageSources ());
- }
-
- int GetTotalPackageSources ()
- {
- if (selectedPackageSource != null) {
- return selectedPackageSource.GetSourceRepositories ().Count ();
- }
- return 0;
- }
-
- public void ShowNextPage ()
- {
- IsLoadingNextPage = true;
- StartReadPackagesTask (false);
- base.OnPropertyChanged (null);
- }
-
- void OnPackagesRead (Task task, PackageItemLoader loader)
- {
- IsReadingPackages = false;
- IsLoadingNextPage = false;
- if (task.IsFaulted) {
- SaveError (task.Exception);
- } else if (task.IsCanceled || !IsCurrentQuery (loader)) {
- // Ignore.
- return;
- } else {
- SaveAnyWarnings ();
- UpdatePackagesForSelectedPage (loader);
- }
- base.OnPropertyChanged (null);
- }
-
- bool IsCurrentQuery (PackageItemLoader loader)
- {
- return currentLoader == loader;
- }
-
- void SaveError (AggregateException ex)
- {
- HasError = true;
- ErrorMessage = GetErrorMessage (ex);
- LoggingService.LogInfo ("PackagesViewModel error", ex);
- }
-
- string GetErrorMessage (AggregateException ex)
- {
- var errorMessage = new AggregateExceptionErrorMessage (ex);
- return errorMessage.ToString ();
- }
-
- void SaveAnyWarnings ()
- {
- string warning = GetWarningMessage ();
- if (!String.IsNullOrEmpty (warning)) {
- HasError = true;
- ErrorMessage = warning;
- }
- }
-
- protected virtual string GetWarningMessage ()
- {
- return String.Empty;
- }
-
- void UpdatePackagesForSelectedPage (PackageItemLoader loader)
- {
- HasNextPage = loader.State.LoadingStatus == LoadingStatus.Ready;
-
- UpdatePackageViewModels (loader.GetCurrent ());
- }
-
- void UpdatePackageViewModels (IEnumerable<PackageItemListViewModel> newPackageViewModels)
- {
- var packages = ConvertToPackageViewModels (newPackageViewModels).ToList ();
- packages = PrioritizePackages (packages).ToList ();
- - foreach (PackageSearchResultViewModel packageViewModel in packages) {
- PackageViewModels.Add (packageViewModel);
- }
- }
-
- public IEnumerable<PackageSearchResultViewModel> ConvertToPackageViewModels (IEnumerable<PackageItemListViewModel> itemViewModels)
- {
- foreach (PackageItemListViewModel itemViewModel in itemViewModels) {
- PackageSearchResultViewModel packageViewModel = CreatePackageViewModel (itemViewModel);
- UpdatePackageViewModelIfPreviouslyChecked (packageViewModel);
- yield return packageViewModel;
- }
- }
-
- PackageSearchResultViewModel CreatePackageViewModel (PackageItemListViewModel viewModel)
- {
- return new PackageSearchResultViewModel (this, viewModel);
- }
-
- void ClearPackages ()
- {
- PackageViewModels.Clear();
- }
-
- public void OnPackageCheckedChanged (PackageSearchResultViewModel packageViewModel)
- {
- if (ignorePackageCheckedChanged)
- return;
-
- if (packageViewModel.IsChecked) {
- UncheckExistingCheckedPackageWithDifferentVersion (packageViewModel);
- CheckedPackageViewModels.Add (packageViewModel);
- } else {
- CheckedPackageViewModels.Remove (packageViewModel);
- }
- }
-
- void UpdatePackageViewModelIfPreviouslyChecked (PackageSearchResultViewModel packageViewModel)
- {
- ignorePackageCheckedChanged = true;
- try {
- PackageSearchResultViewModel existingPackageViewModel = GetExistingCheckedPackageViewModel (packageViewModel.Id);
- if (existingPackageViewModel != null) {
- packageViewModel.UpdateFromPreviouslyCheckedViewModel (existingPackageViewModel);
- CheckedPackageViewModels.Remove (existingPackageViewModel);
- CheckedPackageViewModels.Add (packageViewModel);
- }
- } finally {
- ignorePackageCheckedChanged = false;
- }
- }
-
- void UncheckExistingCheckedPackageWithDifferentVersion (PackageSearchResultViewModel packageViewModel)
- {
- PackageSearchResultViewModel existingPackageViewModel = GetExistingCheckedPackageViewModel (packageViewModel.Id);
-
- if (existingPackageViewModel != null) {
- CheckedPackageViewModels.Remove (existingPackageViewModel);
- existingPackageViewModel.IsChecked = false;
- }
- }
-
- PackageSearchResultViewModel GetExistingCheckedPackageViewModel (string packageId)
- {
- return CheckedPackageViewModels
- .FirstOrDefault (item => item.Id == packageId);
- }
-
- public IPackageAction CreateInstallPackageAction (PackageSearchResultViewModel packageViewModel)
- {
- return new InstallNuGetPackageAction (
- SelectedPackageSource.GetSourceRepositories (),
- solutionManager,
- dotNetProject,
- projectContext
- ) {
- IncludePrerelease = IncludePrerelease,
- PackageId = packageViewModel.Id,
- Version = packageViewModel.SelectedVersion
- };
- }
-
- public PackageSearchResultViewModel SelectedPackage { get; set; }
-
- public bool IsOlderPackageInstalled (string id, NuGetVersion version)
- {
- return packageReferences.Any (packageReference => IsOlderPackageInstalled (packageReference, id, version));
- }
-
- bool IsOlderPackageInstalled (PackageReference packageReference, string id, NuGetVersion version)
- {
- return packageReference.PackageIdentity.Id == id &&
- packageReference.PackageIdentity.Version < version;
- }
- - protected virtual Task GetPackagesInstalledInProject ()
- {
- return nugetProject
- .GetInstalledPackagesAsync (CancellationToken.None)
- .ContinueWith (task => OnReadInstalledPackages (task), TaskScheduler.FromCurrentSynchronizationContext ());
- }
-
- void OnReadInstalledPackages (Task<IEnumerable<PackageReference>> task)
- {
- try {
- if (task.IsFaulted) {
- LoggingService.LogError ("Unable to read installed packages.", task.Exception);
- } else {
- packageReferences = task.Result.ToList ();
- }
- } catch (Exception ex) {
- LoggingService.LogError ("OnReadInstalledPackages", ex);
- }
- }
-
- void INuGetUILogger.Log (MessageLevel level, string message, params object [] args)
- {
- if (level == MessageLevel.Error) {
- string fullErrorMessage = String.Format (message, args);
- AppendErrorMessage (fullErrorMessage);
- }
- }
-
- void AppendErrorMessage (string message)
- {
- aggregateErrorMessage.AddError (message);
- ErrorMessage = aggregateErrorMessage.ErrorMessage;
- HasError = true;
- OnPropertyChanged (null);
- }
-
- public void LoadPackageMetadata (PackageSearchResultViewModel packageViewModel) - {
- var provider = new MultiSourcePackageMetadataProvider (
- selectedPackageSource.GetSourceRepositories (),
- packageManager.PackagesFolderSourceRepository,
- packageManager.GlobalPackageFolderRepositories,
- new [] { NuGetProject },
- false,
- new NuGet.Common.NullLogger ());
- - packageViewModel.LoadPackageMetadata (provider, cancellationTokenSource.Token); - } - - public void OnInstallingSelectedPackages () - { - try {
- UpdateRecentPackages ();
- } catch (Exception ex) {
- LoggingService.LogError ("Unable to update recent packages", ex);
- } - }
-
- void UpdateRecentPackages ()
- {
- if (SelectedPackageSource == null)
- return;
-
- if (CheckedPackageViewModels.Any ()) {
- foreach (PackageSearchResultViewModel packageViewModel in CheckedPackageViewModels) {
- recentPackagesRepository.AddPackage (packageViewModel, SelectedPackageSource.Name);
- }
- } else {
- recentPackagesRepository.AddPackage (SelectedPackage, SelectedPackageSource.Name);
- }
- }
-
- IEnumerable<PackageSearchResultViewModel> PrioritizePackages (IEnumerable<PackageSearchResultViewModel> packages)
- {
- var recentPackages = GetRecentPackages ().ToList ();
-
- foreach (PackageSearchResultViewModel package in recentPackages) {
- package.Parent = this;
- package.ResetForRedisplay (IncludePrerelease);
- yield return package;
- }
-
- foreach (PackageSearchResultViewModel package in packages) {
- if (!recentPackages.Contains (package, PackageSearchResultViewModelComparer.Instance)) {
- yield return package;
- }
- }
- }
-
- IEnumerable<PackageSearchResultViewModel> GetRecentPackages ()
- {
- if (PackageViewModels.Count == 0 &&
- String.IsNullOrEmpty (SearchTerms) &&
- selectedPackageSource != null) {
- return recentPackagesRepository.GetPackages (SelectedPackageSource.Name)
- .Where (SelectedVersionMatchesIncludePreleaseFilter);
- }
-
- return Enumerable.Empty<PackageSearchResultViewModel> ();
- }
-
- bool SelectedVersionMatchesIncludePreleaseFilter (PackageSearchResultViewModel package)
- {
- if (package.SelectedVersion.IsPrerelease) {
- return IncludePrerelease;
- }
-
- return true;
- }
- }
-}
-
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs index c3d79c8989..25d00c0ccc 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/InstallNuGetPackageAction.cs @@ -226,6 +226,10 @@ namespace MonoDevelop.PackageManagement return Version?.IsPrerelease == true;
}
+ internal IDotNetProject Project { + get { return dotNetProject; } + }
+
public bool IsForProject (DotNetProject project)
{
return dotNetProject.DotNetProject == project;
diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesPage.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesPage.cs new file mode 100644 index 0000000000..3f2f1cd3bb --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesPage.cs @@ -0,0 +1,36 @@ +// +// ManagePackagesPage.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://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. + +namespace MonoDevelop.PackageManagement +{ + enum ManagePackagesPage + { + Browse, + Installed, + Updates, + Consolidate + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesProjectInfo.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesProjectInfo.cs new file mode 100644 index 0000000000..91f32d76b9 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesProjectInfo.cs @@ -0,0 +1,60 @@ +// +// ManagePackagesProjectInfo.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://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. + +using System; +using System.Collections.Generic; +using System.Linq; +using NuGet.Packaging.Core; +using NuGet.Packaging; +using System.Collections.Immutable; + +namespace MonoDevelop.PackageManagement +{ + class ManagePackagesProjectInfo : IComparable<ManagePackagesProjectInfo> + { + readonly ImmutableArray<PackageReference> packages; + + public ManagePackagesProjectInfo (IDotNetProject project, IEnumerable<PackageReference> packages) + { + Project = project; + this.packages = ImmutableArray<PackageReference>.Empty.AddRange (packages); + } + + public IDotNetProject Project { get; } + + public IEnumerable<PackageIdentity> Packages { + get { return packages.Select (p => p.PackageIdentity); } + } + + public int CompareTo (ManagePackagesProjectInfo other) + { + if (other == null) + return 1; + + return string.Compare (Project.Name, other.Project.Name, StringComparison.CurrentCulture); + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesSearchResultViewModel.cs index 2005caeaf0..6aa0d2c97a 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModel.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesSearchResultViewModel.cs @@ -1,453 +1,472 @@ -//
-// PackageSearchResultViewModel.cs
-//
-// Author:
-// Matt Ward <matt.ward@xamarin.com>
-//
-// Copyright (c) 2016 Xamarin Inc. (http://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.
-
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using MonoDevelop.Core;
-using NuGet.Common;
-using NuGet.PackageManagement.UI;
-using NuGet.Packaging.Core;
-using NuGet.Protocol.Core.Types;
-using NuGet.Frameworks;
-using NuGet.Versioning;
-
-namespace MonoDevelop.PackageManagement
-{
- internal class PackageSearchResultViewModel : ViewModelBase<PackageSearchResultViewModel>
- {
- AllPackagesViewModel parent;
- PackageItemListViewModel viewModel;
- PackageDetailControlModel packageDetailModel;
- List<PackageDependencyMetadata> dependencies;
- string summary;
- bool isChecked;
-
- public PackageSearchResultViewModel (
- AllPackagesViewModel parent,
- PackageItemListViewModel viewModel)
- {
- this.parent = parent;
- this.viewModel = viewModel;
-
- Versions = new ObservableCollection<NuGetVersion> ();
- SelectedVersion = Version;
- }
-
- public AllPackagesViewModel Parent {
- get { return parent; }
- set { parent = value; }
- }
-
- public string Id {
- get { return viewModel.Id; }
- }
-
- public NuGetVersion Version {
- get { return viewModel.Version; }
- }
-
- public string Title {
- get { return viewModel.Title; }
- }
-
- public string Name {
- get {
- if (String.IsNullOrEmpty (Title))
- return Id;
-
- return Title;
- }
- }
-
- public bool IsChecked {
- get { return isChecked; }
- set {
- if (value != isChecked) {
- isChecked = value;
- parent.OnPackageCheckedChanged (this);
- }
- }
- }
-
- public bool HasLicenseUrl {
- get { return LicenseUrl != null; }
- }
-
- public Uri LicenseUrl {
- get { return viewModel.LicenseUrl; }
- }
-
- public bool HasProjectUrl {
- get { return ProjectUrl != null; }
- }
-
- public Uri ProjectUrl {
- get { return viewModel.ProjectUrl; }
- }
-
- public bool HasGalleryUrl {
- get { return GalleryUrl != null; }
- }
-
- public bool HasNoGalleryUrl {
- get { return !HasGalleryUrl; }
- }
-
- public Uri GalleryUrl {
- get { return null; }
- //get { return viewModel.GalleryUrl; }
- }
-
- public Uri IconUrl {
- get { return viewModel.IconUrl; }
- }
-
- public bool HasIconUrl {
- get { return IconUrl != null; }
- }
-
- public string Author {
- get { return viewModel.Author; }
- }
-
- public string Summary {
- get {
- if (summary == null) {
- summary = StripNewLinesAndIndentation (GetSummaryOrDescription ());
- }
- return summary;
- }
- }
-
- string GetSummaryOrDescription ()
- {
- if (String.IsNullOrEmpty (viewModel.Summary))
- return viewModel.Description;
- return viewModel.Summary;
- }
-
- string StripNewLinesAndIndentation (string text)
- {
- return PackageListViewTextFormatter.Format (text);
- }
-
- public string Description {
- get { return viewModel.Description; }
- }
-
- public bool HasDownloadCount {
- get { return viewModel.DownloadCount >= 0; }
- }
-
- public string GetIdMarkup ()
- {
- return GetBoldText (Id);
- }
-
- public string GetNameMarkup ()
- {
- return GetBoldText (Name);
- }
-
- static string GetBoldText (string text)
- {
- return String.Format ("<b>{0}</b>", text);
- }
-
- public string GetDownloadCountOrVersionDisplayText ()
- {
- if (ShowVersionInsteadOfDownloadCount) {
- return Version.ToString ();
- }
-
- return GetDownloadCountDisplayText ();
- }
-
- public string GetDownloadCountDisplayText ()
- {
- if (HasDownloadCount) {
- return viewModel.DownloadCount.Value.ToString ("N0");
- }
- return String.Empty;
- }
-
- public bool ShowVersionInsteadOfDownloadCount { get; set; }
-
- public DateTimeOffset? LastPublished {
- get { return viewModel.Published; }
- }
-
- public bool HasLastPublished {
- get { return viewModel.Published.HasValue; }
- }
-
- public string GetLastPublishedDisplayText()
- {
- if (HasLastPublished) {
- return LastPublished.Value.Date.ToShortDateString ();
- }
- return String.Empty;
- }
-
- public NuGetVersion SelectedVersion { get; set; }
- public ObservableCollection<NuGetVersion> Versions { get; private set; }
-
- protected virtual Task ReadVersions (CancellationToken cancellationToken)
- {
- try {
- packageDetailModel = new PackageDetailControlModel (parent.NuGetProject);
- packageDetailModel.SelectedVersion = new DisplayVersion (SelectedVersion, null);
- return ReadVersionsFromPackageDetailControlModel (cancellationToken).ContinueWith (
- task => OnVersionsRead (task),
- TaskScheduler.FromCurrentSynchronizationContext ());
- } catch (Exception ex) {
- LoggingService.LogError ("ReadVersions error.", ex);
- }
- return Task.FromResult (0);
- }
-
- Task ReadVersionsFromPackageDetailControlModel (CancellationToken cancellationToken)
- {
- if (!IsRecentPackage) {
- return packageDetailModel.SetCurrentPackage (viewModel);
- }
-
- return ReadVersionsForRecentPackage (cancellationToken);
- }
-
- async Task ReadVersionsForRecentPackage (CancellationToken cancellationToken)
- {
- var identity = new PackageIdentity (viewModel.Id, viewModel.Version);
- foreach (var sourceRepository in parent.SelectedPackageSource.GetSourceRepositories ()) {
- try {
- var metadata = await sourceRepository.GetPackageMetadataAsync (identity, parent.IncludePrerelease, cancellationToken);
- if (metadata != null) {
- var packageViewModel = CreatePackageItemListViewModel (metadata);
- await packageDetailModel.SetCurrentPackage (packageViewModel);
- return;
- }
- } catch (Exception ex) {
- LoggingService.LogError (
- String.Format ("Unable to get metadata for {0} from source {1}.", identity, sourceRepository.PackageSource.Name),
- ex);
- }
- }
- }
-
- PackageItemListViewModel CreatePackageItemListViewModel (IPackageSearchMetadata metadata)
- {
- return new PackageItemListViewModel {
- Id = metadata.Identity.Id,
- Version = metadata.Identity.Version,
- IconUrl = metadata.IconUrl,
- Author = metadata.Authors,
- DownloadCount = metadata.DownloadCount,
- Summary = metadata.Summary,
- Description = metadata.Description,
- Title = metadata.Title,
- LicenseUrl = metadata.LicenseUrl,
- ProjectUrl = metadata.ProjectUrl,
- Published = metadata.Published,
- Versions = AsyncLazy.New (() => metadata.GetVersionsAsync ())
- };
- }
-
- void OnVersionsRead (Task task)
- {
- try {
- if (task.IsFaulted) {
- LoggingService.LogError ("Failed to read package versions.", task.Exception);
- } else if (task.IsCanceled) {
- // Ignore.
- } else {
- Versions.Clear ();
- foreach (NuGetVersion version in packageDetailModel.AllPackageVersions.OrderByDescending (v => v.Version)) {
- Versions.Add (version);
- }
- OnPropertyChanged (viewModel => viewModel.Versions);
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Failed to read package versions.", ex);
- }
- }
-
- public bool IsOlderPackageInstalled ()
- {
- return parent.IsOlderPackageInstalled (Id, SelectedVersion);
- }
-
- public override bool Equals (object obj)
- {
- var other = obj as PackageSearchResultViewModel;
- if (other == null)
- return false;
- - return StringComparer.OrdinalIgnoreCase.Equals (Id, other.Id);
- }
-
- public override int GetHashCode ()
- {
- return Id.GetHashCode ();
- } - - public void UpdateFromPreviouslyCheckedViewModel (PackageSearchResultViewModel packageViewModel) +// +// ManagedPackagesSearchResultViewModel.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://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. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MonoDevelop.Core; +using NuGet.Common; +using NuGet.PackageManagement.UI; +using NuGet.Packaging.Core; +using NuGet.Protocol.Core.Types; +using NuGet.Frameworks; +using NuGet.Versioning; + +namespace MonoDevelop.PackageManagement +{ + internal class ManagePackagesSearchResultViewModel : ViewModelBase<ManagePackagesSearchResultViewModel> + { + ManagePackagesViewModel parent; + PackageItemListViewModel viewModel; + PackageDetailControlModel packageDetailModel; + PackageDependencyMetadata[] dependencies; + string summary; + bool isChecked; + + public ManagePackagesSearchResultViewModel ( + ManagePackagesViewModel parent, + PackageItemListViewModel viewModel) + { + this.parent = parent; + this.viewModel = viewModel; + + Versions = new ObservableCollection<NuGetVersion> (); + SelectedVersion = Version; + } + + public ManagePackagesViewModel Parent { + get { return parent; } + set { parent = value; } + } + + public string Id { + get { return viewModel.Id; } + } + + public NuGetVersion Version { + get { return viewModel.Version; } + } + + public string Title { + get { return viewModel.Title; } + } + + public string Name { + get { + if (String.IsNullOrEmpty (Title)) + return Id; + + return Title; + } + } + + public bool IsChecked { + get { return isChecked; } + set { + if (value != isChecked) { + isChecked = value; + parent.OnPackageCheckedChanged (this); + } + } + } + + public bool HasLicenseUrl { + get { return LicenseUrl != null; } + } + + public Uri LicenseUrl { + get { return viewModel.LicenseUrl; } + } + + public bool HasProjectUrl { + get { return ProjectUrl != null; } + } + + public Uri ProjectUrl { + get { return viewModel.ProjectUrl; } + } + + public bool HasGalleryUrl { + get { return GalleryUrl != null; } + } + + public bool HasNoGalleryUrl { + get { return !HasGalleryUrl; } + } + + public Uri GalleryUrl { + get { return null; } + //get { return viewModel.GalleryUrl; } + } + + public Uri IconUrl { + get { return viewModel.IconUrl; } + } + + public bool HasIconUrl { + get { return IconUrl != null; } + } + + public string Author { + get { return viewModel.Author; } + } + + public string Summary { + get { + if (summary == null) { + summary = StripNewLinesAndIndentation (GetSummaryOrDescription ()); + } + return summary; + } + } + + string GetSummaryOrDescription () + { + if (String.IsNullOrEmpty (viewModel.Summary)) + return viewModel.Description; + return viewModel.Summary; + } + + string StripNewLinesAndIndentation (string text) + { + return PackageListViewTextFormatter.Format (text); + } + + public string Description { + get { return viewModel.Description; } + } + + public bool HasDownloadCount { + get { return viewModel.DownloadCount >= 0; } + } + + public string GetIdMarkup () + { + return GetBoldText (Id); + } + + public string GetNameMarkup () + { + return GetBoldText (Name); + } + + static string GetBoldText (string text) + { + return String.Format ("<b>{0}</b>", text); + } + + public string GetDownloadCountOrVersionDisplayText () + { + if (ShowVersionInsteadOfDownloadCount) { + return Version.ToString (); + } + + return GetDownloadCountDisplayText (); + } + + public string GetDownloadCountDisplayText () + { + if (HasDownloadCount) { + return viewModel.DownloadCount.Value.ToString ("N0"); + } + return String.Empty; + } + + public bool ShowVersionInsteadOfDownloadCount { get; set; } + + public DateTimeOffset? LastPublished { + get { return viewModel.Published; } + } + + public bool HasLastPublished { + get { return viewModel.Published.HasValue; } + } + + public string GetLastPublishedDisplayText() + { + if (HasLastPublished) { + return LastPublished.Value.Date.ToShortDateString (); + } + return String.Empty; + } + + /// <summary> + /// Consolidating a package should select the latest version. + /// </summary> + internal bool SelectLatestVersion { get; set; } + + public NuGetVersion SelectedVersion { get; set; } + public ObservableCollection<NuGetVersion> Versions { get; private set; } + + protected virtual Task ReadVersions (CancellationToken cancellationToken) { + try { + packageDetailModel = new PackageDetailControlModel (parent.NuGetProjects); + packageDetailModel.SelectedVersion = new DisplayVersion (SelectedVersion, null); + return ReadVersionsFromPackageDetailControlModel (cancellationToken).ContinueWith ( + task => OnVersionsRead (task), + cancellationToken, + TaskContinuationOptions.NotOnCanceled, + TaskScheduler.FromCurrentSynchronizationContext ()); + } catch (Exception ex) { + LoggingService.LogError ("ReadVersions error.", ex); + } + return Task.CompletedTask; + } + + Task ReadVersionsFromPackageDetailControlModel (CancellationToken cancellationToken) + { + if (!IsRecentPackage) { + return packageDetailModel.SetCurrentPackage (viewModel); + } + + return ReadVersionsForRecentPackage (cancellationToken); + } + + async Task ReadVersionsForRecentPackage (CancellationToken cancellationToken) + { + var identity = new PackageIdentity (viewModel.Id, viewModel.Version); + foreach (var sourceRepository in parent.SelectedPackageSource.GetSourceRepositories ()) { + try { + var metadata = await sourceRepository.GetPackageMetadataAsync (identity, parent.IncludePrerelease, cancellationToken); + if (metadata != null) { + var packageViewModel = CreatePackageItemListViewModel (metadata); + await packageDetailModel.SetCurrentPackage (packageViewModel); + return; + } + } catch (Exception ex) { + LoggingService.LogError ( + String.Format ("Unable to get metadata for {0} from source {1}.", identity, sourceRepository.PackageSource.Name), + ex); + } + } + } + + PackageItemListViewModel CreatePackageItemListViewModel (IPackageSearchMetadata metadata) + { + return new PackageItemListViewModel { + Id = metadata.Identity.Id, + Version = metadata.Identity.Version, + IconUrl = metadata.IconUrl, + Author = metadata.Authors, + DownloadCount = metadata.DownloadCount, + Summary = metadata.Summary, + Description = metadata.Description, + Title = metadata.Title, + LicenseUrl = metadata.LicenseUrl, + ProjectUrl = metadata.ProjectUrl, + Published = metadata.Published, + Versions = AsyncLazy.New (() => metadata.GetVersionsAsync ()) + }; + } + + void OnVersionsRead (Task task) + { + try { + if (task.IsFaulted) { + LoggingService.LogError ("Failed to read package versions.", task.Exception); + } else if (task.IsCanceled) { + // Ignore. + } else { + Versions.Clear (); + foreach (NuGetVersion version in packageDetailModel.AllPackageVersions.OrderByDescending (v => v.Version)) { + Versions.Add (version); + } + if (SelectLatestVersion && Versions.Any ()) { + SelectedVersion = Versions [0]; + } + OnPropertyChanged (viewModel => viewModel.Versions); + } + } catch (Exception ex) { + LoggingService.LogError ("Failed to read package versions.", ex); + } + } + + public bool IsOlderPackageInstalled () + { + return parent.IsOlderPackageInstalled (Id, SelectedVersion); + } + + public override bool Equals (object obj) + { + var other = obj as ManagePackagesSearchResultViewModel; + if (other == null) + return false; + + return StringComparer.OrdinalIgnoreCase.Equals (Id, other.Id); + } + + public override int GetHashCode () + { + return Id.GetHashCode (); + } + + public void UpdateFromPreviouslyCheckedViewModel (ManagePackagesSearchResultViewModel packageViewModel) + { + SelectLatestVersion = false; IsChecked = packageViewModel.IsChecked; SelectedVersion = packageViewModel.SelectedVersion; if (SelectedVersion != Version) { Versions.Add (Version); Versions.Add (SelectedVersion); } - }
-
- public void LoadPackageMetadata (IPackageMetadataProvider metadataProvider, CancellationToken cancellationToken)
- {
- if (packageDetailModel != null) {
- return;
- }
-
- if (IsRecentPackage) {
- ReadVersions (cancellationToken).ContinueWith (
- task => LoadPackageMetadataFromPackageDetailModel (metadataProvider, cancellationToken),
- TaskScheduler.FromCurrentSynchronizationContext ());
- } else {
- ReadVersions (cancellationToken);
- LoadPackageMetadataFromPackageDetailModel (metadataProvider, cancellationToken);
- }
- }
- - void LoadPackageMetadataFromPackageDetailModel (IPackageMetadataProvider metadataProvider, CancellationToken cancellationToken)
- {
- try {
- LoadPackageMetadataFromPackageDetailModelAsync (metadataProvider, cancellationToken);
- } catch (Exception ex) {
- LoggingService.LogError ("Error getting detailed package metadata.", ex);
- }
- }
-
- protected virtual Task LoadPackageMetadataFromPackageDetailModelAsync (
- IPackageMetadataProvider metadataProvider,
- CancellationToken cancellationToken)
- {
- return packageDetailModel.LoadPackageMetadaAsync (metadataProvider, cancellationToken).ContinueWith (
- task => OnPackageMetadataLoaded (task),
- TaskScheduler.FromCurrentSynchronizationContext ());
- }
-
- void OnPackageMetadataLoaded (Task task)
- {
- try {
- if (task.IsFaulted) {
- LoggingService.LogError ("Failed to read package metadata.", task.Exception);
- } else if (task.IsCanceled) {
- // Ignore.
- } else {
- var metadata = packageDetailModel?.PackageMetadata;
- if (metadata != null) {
- viewModel.Published = metadata.Published;
- dependencies = GetCompatibleDependencies ().ToList ();
- OnPropertyChanged ("Dependencies");
- }
- }
- } catch (Exception ex) {
- LoggingService.LogError ("Failed to read package metadata.", ex);
- }
- }
-
- public bool HasDependencies {
- get { return CompatibleDependencies.Any (); }
- }
-
- public bool HasNoDependencies {
- get { return !HasDependencies; }
- }
-
- public string GetPackageDependenciesDisplayText ()
- {
- var displayText = new StringBuilder ();
- foreach (PackageDependencyMetadata dependency in CompatibleDependencies) {
- displayText.AppendLine (dependency.ToString ());
- }
- return displayText.ToString ();
- }
-
- IEnumerable<PackageDependencyMetadata> CompatibleDependencies {
- get { return dependencies ?? new List<PackageDependencyMetadata> (); }
- }
-
- IEnumerable<PackageDependencyMetadata> GetCompatibleDependencies ()
- {
- var metadata = packageDetailModel?.PackageMetadata;
- if (metadata?.HasDependencies == true) {
- var projectTargetFramework = new ProjectTargetFramework (parent.Project);
- var targetFramework = NuGetFramework.Parse (projectTargetFramework.TargetFrameworkName.FullName);
-
- foreach (var dependencySet in packageDetailModel.PackageMetadata.DependencySets) {
- if (DefaultCompatibilityProvider.Instance.IsCompatible (targetFramework, dependencySet.TargetFramework)) {
- return dependencySet.Dependencies;
- }
- }
- }
-
- return Enumerable.Empty<PackageDependencyMetadata> ();
- }
-
- public bool IsDependencyInformationAvailable {
- get { return dependencies != null; }
- }
-
- public bool IsRecentPackage { get; set; }
-
- public void ResetDetailedPackageMetadata ()
- {
- packageDetailModel = null;
+ } + + public void LoadPackageMetadata (IPackageMetadataProvider metadataProvider, CancellationToken cancellationToken) + { + if (packageDetailModel != null) { + return; + } + + if (IsRecentPackage) { + ReadVersions (cancellationToken).ContinueWith ( + task => LoadPackageMetadataFromPackageDetailModel (metadataProvider, cancellationToken), + TaskScheduler.FromCurrentSynchronizationContext ()); + } else { + ReadVersions (cancellationToken); + LoadPackageMetadataFromPackageDetailModel (metadataProvider, cancellationToken); + } + } + + void LoadPackageMetadataFromPackageDetailModel (IPackageMetadataProvider metadataProvider, CancellationToken cancellationToken) + { + try { + LoadPackageMetadataFromPackageDetailModelAsync (metadataProvider, cancellationToken); + } catch (Exception ex) { + LoggingService.LogError ("Error getting detailed package metadata.", ex); + } + } + + protected virtual Task LoadPackageMetadataFromPackageDetailModelAsync ( + IPackageMetadataProvider metadataProvider, + CancellationToken cancellationToken) + { + return packageDetailModel.LoadPackageMetadaAsync (metadataProvider, cancellationToken).ContinueWith ( + task => OnPackageMetadataLoaded (task), + TaskScheduler.FromCurrentSynchronizationContext ()); + } + + void OnPackageMetadataLoaded (Task task) + { + try { + if (task.IsFaulted) { + LoggingService.LogError ("Failed to read package metadata.", task.Exception); + } else { + var metadata = packageDetailModel?.PackageMetadata; + if (metadata != null) { + viewModel.Published = metadata.Published; + dependencies = GetCompatibleDependencies ().ToArray (); + OnPropertyChanged ("Dependencies"); + } + } + } catch (Exception ex) { + LoggingService.LogError ("Failed to read package metadata.", ex); + } + } + + public bool HasDependencies { + get { return CompatibleDependencies.Any (); } + } + + public bool HasNoDependencies { + get { return !HasDependencies; } + } + + public string GetPackageDependenciesDisplayText () + { + var displayText = StringBuilderCache.Allocate (); + foreach (PackageDependencyMetadata dependency in CompatibleDependencies) { + displayText.AppendLine (dependency.ToString ()); + } + return StringBuilderCache.ReturnAndFree (displayText); + } + + IEnumerable<PackageDependencyMetadata> CompatibleDependencies { + get { return dependencies ?? Array.Empty<PackageDependencyMetadata> (); } + } + + IEnumerable<PackageDependencyMetadata> GetCompatibleDependencies () + { + var metadata = packageDetailModel?.PackageMetadata; + if (metadata?.HasDependencies == true) { + var projectTargetFramework = new ProjectTargetFramework (parent.Project); + var targetFramework = NuGetFramework.Parse (projectTargetFramework.TargetFrameworkName.FullName); + + foreach (var dependencySet in packageDetailModel.PackageMetadata.DependencySets) { + if (DefaultCompatibilityProvider.Instance.IsCompatible (targetFramework, dependencySet.TargetFramework)) { + return dependencySet.Dependencies; + } + } + } + + return Enumerable.Empty<PackageDependencyMetadata> (); + } + + public bool IsDependencyInformationAvailable { + get { return dependencies != null; } + } + + public bool IsRecentPackage { get; set; } + + public void ResetDetailedPackageMetadata () + { + packageDetailModel = null; } public void ResetForRedisplay (bool includePrereleaseVersions) { - ResetDetailedPackageMetadata ();
- IsChecked = false;
- if (!includePrereleaseVersions) {
- RemovePrereleaseVersions ();
+ ResetDetailedPackageMetadata (); + IsChecked = false; + if (!includePrereleaseVersions) { + RemovePrereleaseVersions (); } } void RemovePrereleaseVersions () { - var prereleaseVersions = Versions.Where (version => version.IsPrerelease).ToArray ();
-
- foreach (NuGetVersion prereleaseVersion in prereleaseVersions) {
- Versions.Remove (prereleaseVersion);
+ var prereleaseVersions = Versions.Where (version => version.IsPrerelease).ToArray (); + + foreach (NuGetVersion prereleaseVersion in prereleaseVersions) { + Versions.Remove (prereleaseVersion); } - }
- }
-}
-
+ } + + public string GetCurrentPackageVersionText () + { + return parent.GetCurrentPackageVersionText (Id); + } + + public string GetCurrentPackageVersionAdditionalText () + { + return parent.GetCurrentPackageVersionAdditionalText (Id); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesViewModel.cs new file mode 100644 index 0000000000..02637c476a --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagePackagesViewModel.cs @@ -0,0 +1,1019 @@ +// +// ManagePackagesViewModel.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://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. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using MonoDevelop.Core; +using MonoDevelop.Ide; +using NuGet.Common; +using NuGet.Configuration; +using NuGet.PackageManagement; +using NuGet.PackageManagement.UI; +using NuGet.Packaging.Core; +using NuGet.ProjectManagement; +using NuGet.Protocol.Core.Types; +using NuGet.Versioning; + +namespace MonoDevelop.PackageManagement +{ + internal class ManagePackagesViewModel : ViewModelBase<ManagePackagesViewModel>, INuGetUILogger + { + SourceRepositoryViewModel selectedPackageSource; + ManagePackagesSearchResultViewModel selectedPackage; + ManagePackagesPage pageSelected; + IPackageSourceProvider packageSourceProvider; + PackageItemLoader currentLoader; + CancellationTokenSource cancellationTokenSource; + List<SourceRepositoryViewModel> packageSources; + bool includePrerelease; + bool ignorePackageCheckedChanged; + IMonoDevelopSolutionManager solutionManager; + List<NuGetProject> nugetProjects; + List<IDotNetProject> dotNetProjects; + INuGetProjectContext projectContext; + AggregatePackageSourceErrorMessage aggregateErrorMessage; + NuGetPackageManager packageManager; + RecentManagedNuGetPackagesRepository recentPackagesRepository; + List<ManagePackagesProjectInfo> projectInformation = new List<ManagePackagesProjectInfo> (); + Dictionary<string, List<ManageProjectViewModel>> cachedProjectViewModels = + new Dictionary<string, List<ManageProjectViewModel>> (StringComparer.OrdinalIgnoreCase); + + public static ManagePackagesViewModel Create ( + RecentManagedNuGetPackagesRepository recentPackagesRepository, + IDotNetProject project) + { + var solutionManager = PackageManagementServices.Workspace.GetSolutionManager (IdeApp.ProjectOperations.CurrentSelectedSolution); + var solution = new SolutionProxy (IdeApp.ProjectOperations.CurrentSelectedSolution); + return new ManagePackagesViewModel (solutionManager, solution, recentPackagesRepository, project); + } + + public ManagePackagesViewModel ( + IMonoDevelopSolutionManager solutionManager, + ISolution solution, + RecentManagedNuGetPackagesRepository recentPackagesRepository, + IDotNetProject project) + : this ( + solutionManager, + solution, + new NuGetProjectContext (solutionManager.Settings), + recentPackagesRepository, + project) + { + } + + public ManagePackagesViewModel ( + IMonoDevelopSolutionManager solutionManager, + ISolution solution, + INuGetProjectContext projectContext, + RecentManagedNuGetPackagesRepository recentPackagesRepository, + IDotNetProject project) + { + this.solutionManager = solutionManager; + this.projectContext = projectContext; + this.recentPackagesRepository = recentPackagesRepository; + IsManagingSolution = project == null; + PackageViewModels = new ObservableCollection<ManagePackagesSearchResultViewModel> (); + CheckedPackageViewModels = new ObservableCollection<ManagePackagesSearchResultViewModel> (); + ProjectViewModels = new ObservableCollection<ManageProjectViewModel> (); + ErrorMessage = String.Empty; + PageSelected = ManagePackagesPage.Browse; + + if (project != null) { + dotNetProjects = new List<IDotNetProject> (); + dotNetProjects.Add (project); + } else { + dotNetProjects = solution.GetAllProjects ().ToList (); + } + + packageManager = new NuGetPackageManager ( + solutionManager.CreateSourceRepositoryProvider (), + solutionManager.Settings, + solutionManager, + new DeleteOnRestartManager () + ); + + nugetProjects = dotNetProjects + .Select (dotNetProject => solutionManager.GetNuGetProject (dotNetProject)) + .ToList (); + + GetPackagesInstalledInProjects ().Ignore (); + } + + public bool IsManagingSolution { get; private set; } + + public IEnumerable<NuGetProject> NuGetProjects { + get { return nugetProjects; } + } + + public IDotNetProject Project { + get { return dotNetProjects[0]; } + } + + public IEnumerable<IDotNetProject> DotNetProjects { + get { return dotNetProjects; } + } + + public string SearchTerms { get; set; } + + public ManagePackagesPage PageSelected { + get { return pageSelected; } + set { + if (pageSelected != value) { + pageSelected = value; + CheckedPackageViewModels.Clear (); + cachedProjectViewModels.Clear (); + } + } + } + + public bool IsConsolidatePageSelected { + get { return PageSelected == ManagePackagesPage.Consolidate; } + } + + public bool IsInstalledPageSelected { + get { return PageSelected == ManagePackagesPage.Installed; } + } + + public bool IsBrowsePageSelected { + get { return PageSelected == ManagePackagesPage.Browse; } + } + + public bool IsUpdatesPageSelected { + get { return PageSelected == ManagePackagesPage.Updates; } + } + + public IEnumerable<SourceRepositoryViewModel> PackageSources { + get { + if (packageSources == null) { + packageSources = GetPackageSources ().ToList (); + } + return packageSources; + } + } + + IEnumerable<SourceRepositoryViewModel> GetPackageSources () + { + ISourceRepositoryProvider provider = solutionManager.CreateSourceRepositoryProvider (); + packageSourceProvider = provider.PackageSourceProvider; + var repositories = provider.GetRepositories ().ToList (); + + if (repositories.Count > 1) { + // All Sources - first package source if there are multiple sources. + yield return new AggregateSourceRepositoryViewModel (repositories); + } + + foreach (SourceRepository repository in repositories) { + yield return new SourceRepositoryViewModel (repository); + } + } + + public SourceRepositoryViewModel SelectedPackageSource { + get { + if (selectedPackageSource == null) { + selectedPackageSource = GetActivePackageSource (); + } + return selectedPackageSource; + } + set { + if (selectedPackageSource != value) { + selectedPackageSource = value; + SaveActivePackageSource (); + ReadPackages (); + OnPropertyChanged (null); + } + } + } + + SourceRepositoryViewModel GetActivePackageSource () + { + if (packageSources == null) + return null; + + if (!String.IsNullOrEmpty (packageSourceProvider.ActivePackageSourceName)) { + SourceRepositoryViewModel packageSource = packageSources + .FirstOrDefault (viewModel => String.Equals (viewModel.PackageSource.Name, packageSourceProvider.ActivePackageSourceName, StringComparison.CurrentCultureIgnoreCase)); + if (packageSource != null) { + return packageSource; + } + } + + return packageSources.FirstOrDefault (packageSource => !packageSource.IsAggregate); + } + + void SaveActivePackageSource () + { + if (selectedPackageSource == null || packageSourceProvider == null) + return; + + packageSourceProvider.SaveActivePackageSource (selectedPackageSource.PackageSource); + } + + public ObservableCollection<ManagePackagesSearchResultViewModel> PackageViewModels { get; private set; } + public ObservableCollection<ManagePackagesSearchResultViewModel> CheckedPackageViewModels { get; private set; } + public ObservableCollection<ManageProjectViewModel> ProjectViewModels { get; private set; } + + public bool HasError { get; private set; } + public string ErrorMessage { get; private set; } + + public bool IsLoadingNextPage { get; private set; } + public bool IsReadingPackages { get; private set; } + public bool HasNextPage { get; private set; } + + public bool IncludePrerelease { + get { return includePrerelease; } + set { + if (includePrerelease != value) { + includePrerelease = value; + ReadPackages (); + OnPropertyChanged (null); + } + } + } + + public void Dispose() + { + OnDispose (); + CancelReadPackagesTask (); + IsDisposed = true; + } + + protected virtual void OnDispose() + { + } + + public bool IsDisposed { get; private set; } + + public void Search () + { + ReadPackages (); + OnPropertyChanged (null); + } + + public void ReadPackages () + { + if (SelectedPackageSource == null) { + return; + } + + HasNextPage = false; + IsLoadingNextPage = false; + currentLoader = null; + StartReadPackagesTask (); + } + + void StartReadPackagesTask (bool clearPackages = true) + { + IsReadingPackages = true; + ClearError (); + if (clearPackages) { + CancelReadPackagesTask (); + ClearPackages (); + } + CreateReadPackagesTask (); + } + + void CancelReadPackagesTask() + { + if (cancellationTokenSource != null) { + // Cancel on another thread since CancellationTokenSource.Cancel can sometimes + // take up to a second on Mono and we do not want to block the UI thread. + var tokenSource = cancellationTokenSource; + Task.Run (() => { + try { + tokenSource.Cancel (); + tokenSource.Dispose (); + } catch (Exception ex) { + LoggingService.LogError ("Unable to cancel task.", ex); + } + }); + cancellationTokenSource = null; + } + } + + protected virtual Task CreateReadPackagesTask() + { + var loader = currentLoader ?? CreatePackageLoader (); + cancellationTokenSource = cancellationTokenSource ?? new CancellationTokenSource (); + return LoadPackagesAsync (loader, cancellationTokenSource.Token) + .ContinueWith (t => OnPackagesRead (t, loader), TaskScheduler.FromCurrentSynchronizationContext ()); + } + + PackageItemLoader CreatePackageLoader () + { + var context = new PackageLoadContext ( + selectedPackageSource.GetSourceRepositories (), + true, + nugetProjects); + + var loader = new PackageItemLoader ( + context, + CreatePackageFeed (context), + SearchTerms, + IncludePrerelease + ); + + currentLoader = loader; + + return loader; + } + + protected virtual IPackageFeed CreatePackageFeed (PackageLoadContext context) + { + if (PageSelected == ManagePackagesPage.Browse) + return new MultiSourcePackageFeed (context.SourceRepositories, this); + + if (PageSelected == ManagePackagesPage.Installed) + return new InstalledPackageFeed (context, CreatePackageMetadataProvider (), new NullLogger ()); + + if (PageSelected == ManagePackagesPage.Updates) { + return new UpdatePackageFeed ( + context, + CreatePackageMetadataProvider (), + new PackageSearchMetadataCache (), + new NullLogger ()); + } + + if (PageSelected == ManagePackagesPage.Consolidate) + return new ConsolidatePackageFeed (context, CreatePackageMetadataProvider (), new NullLogger ()); + + throw new InvalidOperationException ("Unsupported package feed"); + } + + protected virtual Task LoadPackagesAsync (PackageItemLoader loader, CancellationToken token) + { + return Task.Run (async () => { + await loader.LoadNextAsync (null, token); + + while (loader.State.LoadingStatus == LoadingStatus.Loading) { + token.ThrowIfCancellationRequested (); + await loader.UpdateStateAsync (null, token); + } + }); + } + + void ClearError () + { + HasError = false; + ErrorMessage = String.Empty; + aggregateErrorMessage = new AggregatePackageSourceErrorMessage (GetTotalPackageSources ()); + } + + int GetTotalPackageSources () + { + if (selectedPackageSource != null) { + return selectedPackageSource.GetSourceRepositories ().Count (); + } + return 0; + } + + public void ShowNextPage () + { + IsLoadingNextPage = true; + StartReadPackagesTask (false); + base.OnPropertyChanged (null); + } + + void OnPackagesRead (Task task, PackageItemLoader loader) + { + IsReadingPackages = false; + IsLoadingNextPage = false; + if (task.IsFaulted) { + SaveError (task.Exception); + } else if (task.IsCanceled || !IsCurrentQuery (loader)) { + // Ignore. + return; + } else { + SaveAnyWarnings (); + UpdatePackagesForSelectedPage (loader); + } + base.OnPropertyChanged (null); + } + + bool IsCurrentQuery (PackageItemLoader loader) + { + return currentLoader == loader; + } + + void SaveError (AggregateException ex) + { + HasError = true; + ErrorMessage = GetErrorMessage (ex); + LoggingService.LogInfo ("PackagesViewModel error", ex); + } + + string GetErrorMessage (AggregateException ex) + { + var errorMessage = new AggregateExceptionErrorMessage (ex); + return errorMessage.ToString (); + } + + void SaveAnyWarnings () + { + string warning = GetWarningMessage (); + if (!String.IsNullOrEmpty (warning)) { + HasError = true; + ErrorMessage = warning; + } + } + + protected virtual string GetWarningMessage () + { + return String.Empty; + } + + void UpdatePackagesForSelectedPage (PackageItemLoader loader) + { + HasNextPage = loader.State.LoadingStatus == LoadingStatus.Ready; + + UpdatePackageViewModels (loader.GetCurrent ()); + } + + void UpdatePackageViewModels (IEnumerable<PackageItemListViewModel> newPackageViewModels) + { + var packages = PrioritizePackages (ConvertToPackageViewModels (newPackageViewModels)).ToList (); + + foreach (ManagePackagesSearchResultViewModel packageViewModel in packages) { + PackageViewModels.Add (packageViewModel); + } + } + + public IEnumerable<ManagePackagesSearchResultViewModel> ConvertToPackageViewModels (IEnumerable<PackageItemListViewModel> itemViewModels) + { + foreach (PackageItemListViewModel itemViewModel in itemViewModels) { + ManagePackagesSearchResultViewModel packageViewModel = CreatePackageViewModel (itemViewModel); + UpdatePackageViewModelIfPreviouslyChecked (packageViewModel); + yield return packageViewModel; + } + } + + ManagePackagesSearchResultViewModel CreatePackageViewModel (PackageItemListViewModel viewModel) + { + bool showVersion = ShowPackageVersionInsteadOfDownloadCount (); + return new ManagePackagesSearchResultViewModel (this, viewModel) { + ShowVersionInsteadOfDownloadCount = showVersion, + SelectLatestVersion = IsConsolidatePageSelected + }; + } + + bool ShowPackageVersionInsteadOfDownloadCount () + { + return PageSelected != ManagePackagesPage.Browse; + } + + void ClearPackages () + { + PackageViewModels.Clear(); + } + + public void OnPackageCheckedChanged (ManagePackagesSearchResultViewModel packageViewModel) + { + if (ignorePackageCheckedChanged) + return; + + if (packageViewModel.IsChecked) { + UncheckExistingCheckedPackageWithDifferentVersion (packageViewModel); + CheckedPackageViewModels.Add (packageViewModel); + } else { + CheckedPackageViewModels.Remove (packageViewModel); + } + } + + void UpdatePackageViewModelIfPreviouslyChecked (ManagePackagesSearchResultViewModel packageViewModel) + { + ignorePackageCheckedChanged = true; + try { + ManagePackagesSearchResultViewModel existingPackageViewModel = GetExistingCheckedPackageViewModel (packageViewModel.Id); + if (existingPackageViewModel != null) { + packageViewModel.UpdateFromPreviouslyCheckedViewModel (existingPackageViewModel); + CheckedPackageViewModels.Remove (existingPackageViewModel); + CheckedPackageViewModels.Add (packageViewModel); + } + } finally { + ignorePackageCheckedChanged = false; + } + } + + void UncheckExistingCheckedPackageWithDifferentVersion (ManagePackagesSearchResultViewModel packageViewModel) + { + ManagePackagesSearchResultViewModel existingPackageViewModel = GetExistingCheckedPackageViewModel (packageViewModel.Id); + + if (existingPackageViewModel != null) { + CheckedPackageViewModels.Remove (existingPackageViewModel); + existingPackageViewModel.IsChecked = false; + } + } + + ManagePackagesSearchResultViewModel GetExistingCheckedPackageViewModel (string packageId) + { + return CheckedPackageViewModels + .FirstOrDefault (item => item.Id == packageId); + } + + public IEnumerable<IPackageAction> CreateInstallPackageActions ( + ManagePackagesSearchResultViewModel packageViewModel, + IEnumerable<IDotNetProject> projects) + { + bool firstInstall = true; + foreach (IDotNetProject project in projects) { + yield return new InstallNuGetPackageAction ( + SelectedPackageSource.GetSourceRepositories (), + solutionManager, + project, + projectContext + ) { + IncludePrerelease = IncludePrerelease, + PackageId = packageViewModel.Id, + Version = packageViewModel.SelectedVersion, + LicensesMustBeAccepted = firstInstall + }; + + firstInstall = false; + } + } + + public IEnumerable<IPackageAction> CreateUninstallPackageActions ( + ManagePackagesSearchResultViewModel packageViewModel, + IEnumerable<IDotNetProject> projects) + { + foreach (IDotNetProject project in projects) { + if (IsPackageInstalledInProject (project, packageViewModel.Id)) { + yield return new UninstallNuGetPackageAction ( + solutionManager, + project + ) { + PackageId = packageViewModel.Id, + }; + } + } + } + + public IEnumerable<IPackageAction> CreateUpdatePackageActions ( + ManagePackagesSearchResultViewModel packageViewModel, + IEnumerable<IDotNetProject> projects) + { + bool firstInstall = true; + foreach (IDotNetProject project in projects) { + if (IsPackageInstalledInProject (project, packageViewModel.Id)) { + yield return new InstallNuGetPackageAction ( + SelectedPackageSource.GetSourceRepositories (), + solutionManager, + project, + projectContext + ) { + IncludePrerelease = IncludePrerelease, + PackageId = packageViewModel.Id, + Version = packageViewModel.SelectedVersion, + LicensesMustBeAccepted = firstInstall + }; + + firstInstall = false; + } + } + } + + public IEnumerable<IPackageAction> CreateConsolidatePackageActions ( + ManagePackagesSearchResultViewModel packageViewModel) + { + bool firstInstall = true; + foreach (ManageProjectViewModel project in GetProjectViewModelsForPackage (packageViewModel)) { + if (!CanConsolidate (project, packageViewModel)) { + continue; + } + + yield return new InstallNuGetPackageAction ( + SelectedPackageSource.GetSourceRepositories (), + solutionManager, + project.Project, + projectContext + ) { + IncludePrerelease = IncludePrerelease, + PackageId = packageViewModel.Id, + Version = packageViewModel.SelectedVersion, + LicensesMustBeAccepted = firstInstall + }; + + firstInstall = false; + } + } + + public List<IPackageAction> CreatePackageActions ( + IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels, + IEnumerable<IDotNetProject> selectedProjects) + { + if (PageSelected == ManagePackagesPage.Browse) { + return CreatePackageActions (packageViewModels, selectedProjects, CreateInstallPackageActions); + } else if (PageSelected == ManagePackagesPage.Installed) { + return CreatePackageActions (packageViewModels, selectedProjects, CreateUninstallPackageActions); + } else if (PageSelected == ManagePackagesPage.Updates) { + return CreatePackageActions (packageViewModels, selectedProjects, CreateUpdatePackageActions); + } + return null; + } + + List<IPackageAction> CreatePackageActions ( + IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels, + IEnumerable<IDotNetProject> selectedProjects, + Func<ManagePackagesSearchResultViewModel, IEnumerable<IDotNetProject>, IEnumerable<IPackageAction>> transform) + { + var actions = new List<IPackageAction> (); + foreach (var packageViewModel in packageViewModels) { + actions.AddRange (transform (packageViewModel, selectedProjects)); + } + return actions; + } + + public List<IPackageAction> CreateConsolidatePackageActions (IEnumerable<ManagePackagesSearchResultViewModel> packageViewModels) + { + var actions = new List<IPackageAction> (); + foreach (var packageViewModel in packageViewModels) { + actions.AddRange (CreateConsolidatePackageActions (packageViewModel)); + } + return actions; + } + + bool IsPackageInstalledInProject (IDotNetProject project, string packageId) + { + var matchedProjectInfo = projectInformation.FirstOrDefault (p => p.Project == project); + return matchedProjectInfo.Packages.Any (package => StringComparer.OrdinalIgnoreCase.Equals (packageId, package.Id)); + } + + bool CanConsolidate (ManageProjectViewModel projectViewModel, ManagePackagesSearchResultViewModel packageViewModel) + { + if (!projectViewModel.IsChecked) + return false; + + if (IsPackageInstalledInProjectWithSameVersion ( + projectViewModel.ProjectInfo, + packageViewModel.Id, + packageViewModel.SelectedVersion)) { + return false; + } + + return true; + } + + bool IsPackageInstalledInProjectWithSameVersion (ManagePackagesProjectInfo projectInfo, string packageId, NuGetVersion version) + { + var matchPackageId = new PackageIdentity (packageId, version); + return projectInfo.Packages.Any (package => PackageIdentityComparer.Default.Equals (package, matchPackageId)); + } + + public ManagePackagesSearchResultViewModel SelectedPackage { + get { return selectedPackage; } + set { + if (selectedPackage != value) { + selectedPackage = value; + OnSelectedPackageChanged (); + } + } + } + + public bool IsOlderPackageInstalled (string id, NuGetVersion version) + { + foreach (ManagePackagesProjectInfo projectInfo in projectInformation) { + foreach (PackageIdentity package in projectInfo.Packages) { + if (IsOlderPackageInstalled (package, id, version)) { + return true; + } + } + } + return false; + } + + bool IsOlderPackageInstalled (PackageIdentity packageIdentity, string id, NuGetVersion version) + { + return packageIdentity.Id == id && + packageIdentity.Version < version; + } + + protected virtual Task GetPackagesInstalledInProjects () + { + return GetInstalledPackagesProjectInfo () + .ContinueWith (task => OnReadInstalledPackages (task), TaskScheduler.FromCurrentSynchronizationContext ()); + } + + async Task<List<ManagePackagesProjectInfo>> GetInstalledPackagesProjectInfo () + { + var projectInfo = new List<ManagePackagesProjectInfo> (); + for (int i = 0; i < nugetProjects.Count; ++i) { + var nugetProject = nugetProjects[i]; + var packages = await nugetProject.GetInstalledPackagesAsync (CancellationToken.None); + projectInfo.Add (new ManagePackagesProjectInfo (dotNetProjects[i], packages)); + } + projectInfo.Sort (); + return projectInfo; + } + + void OnReadInstalledPackages (Task<List<ManagePackagesProjectInfo>> task) + { + try { + if (task.IsFaulted) { + LoggingService.LogError ("Unable to read installed packages.", task.Exception); + } else { + projectInformation = task.Result; + } + } catch (Exception ex) { + LoggingService.LogError ("OnReadInstalledPackages", ex); + } + } + + void INuGetUILogger.Log (MessageLevel level, string message, params object [] args) + { + if (level == MessageLevel.Error) { + string fullErrorMessage = String.Format (message, args); + AppendErrorMessage (fullErrorMessage); + } + } + + void AppendErrorMessage (string message) + { + aggregateErrorMessage.AddError (message); + ErrorMessage = aggregateErrorMessage.ErrorMessage; + HasError = true; + OnPropertyChanged (null); + } + + public void LoadPackageMetadata (ManagePackagesSearchResultViewModel packageViewModel) + { + IPackageMetadataProvider provider = CreatePackageMetadataProvider (); + + packageViewModel.LoadPackageMetadata (provider, cancellationTokenSource.Token); + } + + IPackageMetadataProvider CreatePackageMetadataProvider () + { + return new MultiSourcePackageMetadataProvider ( + selectedPackageSource.GetSourceRepositories (), + packageManager.PackagesFolderSourceRepository, + packageManager.GlobalPackageFolderRepositories, + nugetProjects.ToArray (), + IsManagingSolution, + new NullLogger ()); + } + + public void OnInstallingSelectedPackages () + { + try { + UpdateRecentPackages (); + } catch (Exception ex) { + LoggingService.LogError ("Unable to update recent packages", ex); + } + } + + void UpdateRecentPackages () + { + if (SelectedPackageSource == null) + return; + + if (CheckedPackageViewModels.Any ()) { + foreach (ManagePackagesSearchResultViewModel packageViewModel in CheckedPackageViewModels) { + recentPackagesRepository.AddPackage (packageViewModel, SelectedPackageSource.Name); + } + } else { + recentPackagesRepository.AddPackage (SelectedPackage, SelectedPackageSource.Name); + } + } + + IEnumerable<ManagePackagesSearchResultViewModel> PrioritizePackages (IEnumerable<ManagePackagesSearchResultViewModel> packages) + { + var recentPackages = GetRecentPackages ().ToList (); + + foreach (ManagePackagesSearchResultViewModel package in recentPackages) { + package.Parent = this; + package.ResetForRedisplay (IncludePrerelease); + yield return package; + } + + foreach (ManagePackagesSearchResultViewModel package in packages) { + if (!recentPackages.Contains (package, ManagedPackagesSearchResultViewModelComparer.Instance)) { + yield return package; + } + } + } + + IEnumerable<ManagePackagesSearchResultViewModel> GetRecentPackages () + { + if (PackageViewModels.Count == 0 && + String.IsNullOrEmpty (SearchTerms) && + selectedPackageSource != null && + PageSelected == ManagePackagesPage.Browse) { + return recentPackagesRepository.GetPackages (SelectedPackageSource.Name) + .Where (SelectedVersionMatchesIncludePreleaseFilter); + } + + return Enumerable.Empty<ManagePackagesSearchResultViewModel> (); + } + + bool SelectedVersionMatchesIncludePreleaseFilter (ManagePackagesSearchResultViewModel package) + { + if (package.SelectedVersion.IsPrerelease) { + return IncludePrerelease; + } + + return true; + } + + public IEnumerable<IDotNetProject> GetDotNetProjectsToSelect (IEnumerable<string> packageIds) + { + if (PageSelected == ManagePackagesPage.Browse) { + return dotNetProjects; + } + + return GetFilteredProjectsToSelect (packageIds); + } + + IEnumerable<IDotNetProject> GetFilteredProjectsToSelect (IEnumerable<string> packageIds) + { + foreach (IDotNetProject project in dotNetProjects) { + foreach (var projectInfo in projectInformation) { + if (projectInfo.Project != project) + continue; + + foreach (PackageIdentity package in projectInfo.Packages) { + foreach (string packageId in packageIds) { + if (StringComparer.OrdinalIgnoreCase.Equals (package.Id, packageId)) { + yield return project; + } + } + } + } + } + } + + void OnSelectedPackageChanged () + { + if (!IsConsolidatePageSelected) { + return; + } + + ProjectViewModels.Clear (); + + if (SelectedPackage == null) { + return; + } + + List<ManageProjectViewModel> projectViewModels; + if (!cachedProjectViewModels.TryGetValue (SelectedPackage.Id, out projectViewModels)) { + projectViewModels = new List<ManageProjectViewModel> (); + var uncheckedProjectViewModels = new List<ManageProjectViewModel> (); + foreach (ManagePackagesProjectInfo projectInfo in projectInformation) { + var projectViewModel = new ManageProjectViewModel (projectInfo, SelectedPackage.Id); + if (projectViewModel.IsChecked) + projectViewModels.Add (projectViewModel); + else + uncheckedProjectViewModels.Add (projectViewModel); + } + // Show projects that have the package installed before the other projects. + projectViewModels.AddRange (uncheckedProjectViewModels); + + cachedProjectViewModels [SelectedPackage.Id] = projectViewModels; + } + + foreach (ManageProjectViewModel projectViewModel in projectViewModels) { + ProjectViewModels.Add (projectViewModel); + } + } + + public bool CanConsolidate () + { + if (!IsConsolidatePageSelected) { + return false; + } + + if (CheckedPackageViewModels.Count == 0) { + return CanConsolidateSelectedPackage (); + } + + return CanConsolidateCheckedPackages (); + } + + bool CanConsolidateSelectedPackage () + { + if (SelectedPackage == null) { + return false; + } + + foreach (ManageProjectViewModel projectViewModel in ProjectViewModels) { + if (CanConsolidate (projectViewModel, SelectedPackage)) { + return true; + } + } + + return false; + } + + bool CanConsolidateCheckedPackages () + { + foreach (ManagePackagesSearchResultViewModel packageViewModel in CheckedPackageViewModels) { + foreach (ManageProjectViewModel projectViewModel in GetProjectViewModelsForPackage (packageViewModel)) { + if (CanConsolidate (projectViewModel, packageViewModel)) { + return true; + } + } + } + + return false; + } + + IEnumerable<ManageProjectViewModel> GetProjectViewModelsForPackage (ManagePackagesSearchResultViewModel packageViewModel) + { + List<ManageProjectViewModel> projectViewModels; + if (cachedProjectViewModels.TryGetValue (packageViewModel.Id, out projectViewModels)) { + return projectViewModels; + } + return Enumerable.Empty<ManageProjectViewModel> (); + } + + public string GetCurrentPackageVersionText (string packageId) + { + PackageIdentity currentPackage = null; + foreach (ManagePackagesProjectInfo projectInfo in projectInformation) { + foreach (PackageIdentity package in projectInfo.Packages) { + if (IsPackageIdMatch (package, packageId)) { + if (currentPackage == null) { + currentPackage = package; + } else { + return GettextCatalog.GetString ("Multiple"); + } + } + } + } + + if (currentPackage != null) { + return currentPackage.Version.ToString (); + } + + return string.Empty; + } + + static bool IsPackageIdMatch (PackageIdentity package, string packageId) + { + return StringComparer.OrdinalIgnoreCase.Equals (package.Id, packageId); + } + + public string GetCurrentPackageVersionAdditionalText (string packageId) + { + if (!IsManagingSolution) + return string.Empty; + + StringBuilder additionalText = null; + (PackageIdentity package, ManagePackagesProjectInfo projectInfo) previousMatch = (null, null); + foreach (ManagePackagesProjectInfo projectInfo in projectInformation) { + PackageIdentity foundPackage = projectInfo.Packages.FirstOrDefault (package => IsPackageIdMatch (package, packageId)); + if (foundPackage != null) { + if (previousMatch.package == null) { + previousMatch.package = foundPackage; + previousMatch.projectInfo = projectInfo; + } else { + if (additionalText == null) { + additionalText = StringBuilderCache.Allocate (); + AppendAdditionalText (additionalText, previousMatch.projectInfo, previousMatch.package); + } + additionalText.Append (", "); + AppendAdditionalText (additionalText, projectInfo, foundPackage); + } + } + } + + if (additionalText != null) { + return StringBuilderCache.ReturnAndFree (additionalText); + } + + return string.Empty; + } + + static void AppendAdditionalText (StringBuilder additionalText, ManagePackagesProjectInfo projectInfo, PackageIdentity foundPackage) + { + additionalText.AppendFormat ("{0}: {1}", projectInfo.Project.Name, foundPackage.Version); + } + } +} + diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManageProjectViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManageProjectViewModel.cs new file mode 100644 index 0000000000..324164fb18 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManageProjectViewModel.cs @@ -0,0 +1,61 @@ +// +// ManageProjectViewModel.cs +// +// Author: +// Matt Ward <matt.ward@microsoft.com> +// +// Copyright (c) 2019 Microsoft +// +// 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.Linq; + +namespace MonoDevelop.PackageManagement +{ + class ManageProjectViewModel + { + public ManageProjectViewModel (ManagePackagesProjectInfo projectInfo, string packageId) + { + ProjectInfo = projectInfo; + + var package = ProjectInfo.Packages.FirstOrDefault (package => StringComparer.OrdinalIgnoreCase.Equals (package.Id, packageId)); + if (package != null) { + IsChecked = true; + PackageVersion = package.Version.ToString (); + } else { + PackageVersion = "–"; + } + } + + public IDotNetProject Project { + get { return ProjectInfo.Project; } + } + + public string ProjectName { + get { return Project.Name; } + } + + public string PackageVersion { get; set; } + + public bool IsChecked { get; set; } + + internal ManagePackagesProjectInfo ProjectInfo { get; set; } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModelComparer.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagedPackagesSearchResultViewModelComparer.cs index 69bb202950..756fdaac9b 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/PackageSearchResultViewModelComparer.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/ManagedPackagesSearchResultViewModelComparer.cs @@ -1,5 +1,5 @@ // -// PackageSearchResultViewModelComparer.cs +// ManagedPackagesSearchResultViewModelComparer.cs // // Author: // Matt Ward <matt.ward@xamarin.com> @@ -29,17 +29,17 @@ using System.Collections.Generic; namespace MonoDevelop.PackageManagement { - class PackageSearchResultViewModelComparer : IEqualityComparer<PackageSearchResultViewModel> + class ManagedPackagesSearchResultViewModelComparer : IEqualityComparer<ManagePackagesSearchResultViewModel> { - public static readonly PackageSearchResultViewModelComparer Instance = - new PackageSearchResultViewModelComparer (); + public static readonly ManagedPackagesSearchResultViewModelComparer Instance = + new ManagedPackagesSearchResultViewModelComparer (); - public bool Equals (PackageSearchResultViewModel x, PackageSearchResultViewModel y) + public bool Equals (ManagePackagesSearchResultViewModel x, ManagePackagesSearchResultViewModel y) { return x.Id.Equals (y.Id, StringComparison.OrdinalIgnoreCase); } - public int GetHashCode (PackageSearchResultViewModel obj) + public int GetHashCode (ManagePackagesSearchResultViewModel obj) { return obj.Id.GetHashCode (); } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentNuGetPackagesRepository.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentManagedNuGetPackagesRepository.cs index 05d7c1b8a3..8833f3cb51 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentNuGetPackagesRepository.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/RecentManagedNuGetPackagesRepository.cs @@ -1,5 +1,5 @@ // -// RecentNuGetPackagesRepository.cs +// RecentManagedNuGetPackagesRepository.cs // // Author: // Matt Ward <matt.ward@xamarin.com> @@ -30,7 +30,7 @@ using System.Linq; namespace MonoDevelop.PackageManagement { - internal class RecentNuGetPackagesRepository + internal class RecentManagedNuGetPackagesRepository { public const int DefaultMaximumPackagesCount = 20; @@ -43,14 +43,14 @@ namespace MonoDevelop.PackageManagement set { maximumPackagesCount = value; } } - public IEnumerable<PackageSearchResultViewModel> GetPackages (string source) + public IEnumerable<ManagePackagesSearchResultViewModel> GetPackages (string source) { return packages .Where (package => String.Equals (package.Source, source, StringComparison.OrdinalIgnoreCase)) .Select (package => package.PackageViewModel); } - public void AddPackage (PackageSearchResultViewModel viewModel, string source) + public void AddPackage (ManagePackagesSearchResultViewModel viewModel, string source) { var package = new RecentPackage (viewModel, source); viewModel.IsRecentPackage = true; @@ -74,7 +74,7 @@ namespace MonoDevelop.PackageManagement bool IsMatch (RecentPackage x, RecentPackage y) { - return PackageSearchResultViewModelComparer.Instance.Equals (x.PackageViewModel, y.PackageViewModel); + return ManagedPackagesSearchResultViewModelComparer.Instance.Equals (x.PackageViewModel, y.PackageViewModel); } void AddPackageAtBeginning (RecentPackage package) @@ -97,13 +97,13 @@ namespace MonoDevelop.PackageManagement class RecentPackage { - public RecentPackage (PackageSearchResultViewModel viewModel, string source) + public RecentPackage (ManagePackagesSearchResultViewModel viewModel, string source) { PackageViewModel = viewModel; Source = source; } - public PackageSearchResultViewModel PackageViewModel { get; set; } + public ManagePackagesSearchResultViewModel PackageViewModel { get; set; } public string Source { get; set; } } } diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs index 95cc768120..cf565f615f 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SearchPackagesSearchCategory.cs @@ -70,8 +70,8 @@ namespace MonoDevelop.PackageManagement public override void Activate () { - var runner = new AddPackagesDialogRunner ();
- runner.Run (pattern.UnparsedPattern);
+ var runner = new ManagePackagesDialogRunner ();
+ runner.Run (IdeApp.ProjectOperations.CurrentSelectedProject, pattern.UnparsedPattern);
}
public override string GetMarkupText (bool selected) diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectProjectsViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectProjectsViewModel.cs new file mode 100644 index 0000000000..c2b00625df --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectProjectsViewModel.cs @@ -0,0 +1,101 @@ +// +// SelectProjectsViewModel.cs +// +// Author: +// Matt Ward <matt.ward@xamarin.com> +// +// Copyright (c) 2016 Xamarin Inc. (http://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. + +using System.Collections.Generic; +using System.Linq; + +namespace MonoDevelop.PackageManagement +{ + class SelectProjectsViewModel + { + readonly List<SelectedProjectViewModel> projects; + + public SelectProjectsViewModel ( + IEnumerable<IDotNetProject> projects, + int packagesCount, + ManagePackagesPage page) + { + this.projects = projects + .OrderBy (project => project.Name) + .Select (project => new SelectedProjectViewModel (project)) + .ToList (); + + if (this.projects.Count == 1) { + this.projects[0].IsSelected = true; + } + + bool multiplePackages = packagesCount > 1; + + switch (page) { + case ManagePackagesPage.Installed: + IsRemovingMultiplePackages = multiplePackages; + IsRemovingSinglePackage = !IsAddingMultiplePackages; + break; + case ManagePackagesPage.Browse: + IsAddingMultiplePackages = multiplePackages; + IsAddingSinglePackage = !IsAddingMultiplePackages; + break; + case ManagePackagesPage.Updates: + IsUpdatingMultiplePackages = multiplePackages; + IsUpdatingSinglePackage = !IsAddingMultiplePackages; + SelectAllProjectsByDefault (); + break; + case ManagePackagesPage.Consolidate: + IsConsolidatingMultiplePackages = multiplePackages; + IsConsolidatingSinglePackage = !IsAddingMultiplePackages; + SelectAllProjectsByDefault (); + break; + } + } + + public IEnumerable<SelectedProjectViewModel> Projects { + get { return projects; } + } + + public bool IsAddingSinglePackage { get; } + public bool IsAddingMultiplePackages { get; } + public bool IsRemovingSinglePackage { get; } + public bool IsRemovingMultiplePackages { get; } + public bool IsUpdatingSinglePackage { get; } + public bool IsUpdatingMultiplePackages { get; } + public bool IsConsolidatingSinglePackage { get; } + public bool IsConsolidatingMultiplePackages { get; } + + public IEnumerable<IDotNetProject> GetSelectedProjects () + { + return projects + .Where (viewModel => viewModel.IsSelected) + .Select (viewModel => viewModel.Project); + } + + void SelectAllProjectsByDefault () + { + foreach (SelectedProjectViewModel project in projects) { + project.IsSelected = true; + } + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectedProjectViewModel.cs b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectedProjectViewModel.cs new file mode 100644 index 0000000000..fa3b0ca585 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/MonoDevelop.PackageManagement/SelectedProjectViewModel.cs @@ -0,0 +1,48 @@ +// +// SelectedProjectViewModel.cs +// +// Author: +// matt <matt.ward@xamarin.com> +// +// Copyright (c) 2016 matt +// +// 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 MonoDevelop.Core; + +namespace MonoDevelop.PackageManagement +{ + class SelectedProjectViewModel + { + public SelectedProjectViewModel (IDotNetProject project) + { + Project = project; + } + + public IDotNetProject Project { get; } + public bool IsSelected { get; set; } + + public string Name { + get { return Project.Name; } + } + + public IconId Icon { + get { return Project.DotNetProject.StockIcon; } + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/ConsolidatePackageFeed.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/ConsolidatePackageFeed.cs new file mode 100644 index 0000000000..5b68f63444 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/ConsolidatePackageFeed.cs @@ -0,0 +1,111 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NuGet.Packaging.Core; +using NuGet.Protocol.Core.Types; + +namespace NuGet.PackageManagement.UI +{ + /// <summary> + /// Package feed facilitating iteration over installed packages needing version consolidation + /// </summary> + internal class ConsolidatePackageFeed : PlainPackageFeedBase + { + IEnumerable<PackageIdentity> _installedPackages; + readonly IPackageMetadataProvider _metadataProvider; + PackageLoadContext _context; + + public ConsolidatePackageFeed ( + PackageLoadContext context, + IPackageMetadataProvider metadataProvider, + Common.ILogger logger) + : this (new PackageIdentity[0], metadataProvider, logger) + { + _context = context; + } + + public ConsolidatePackageFeed ( + IEnumerable<PackageIdentity> installedPackages, + IPackageMetadataProvider metadataProvider, + Common.ILogger logger) + { + if (installedPackages == null) { + throw new ArgumentNullException (nameof (installedPackages)); + } + _installedPackages = installedPackages; + + if (metadataProvider == null) { + throw new ArgumentNullException (nameof (metadataProvider)); + } + _metadataProvider = metadataProvider; + + if (logger == null) { + throw new ArgumentNullException (nameof (logger)); + } + + PageSize = 25; + } + + public override async Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken) + { + var searchToken = continuationToken as FeedSearchContinuationToken; + if (searchToken == null) { + throw new InvalidOperationException ("Invalid token"); + } + + if (_context != null) { + _installedPackages = await _context.GetInstalledPackagesAsync (); + _context = null; + } + + var packagesNeedingConsolidation = _installedPackages + .GroupById () + .Where (g => g.Count () > 1) + .Select (g => new PackageIdentity (g.Key, g.Max ())) + .ToArray (); + + var packages = packagesNeedingConsolidation + .Where (p => p.Id.IndexOf (searchToken.SearchString, StringComparison.OrdinalIgnoreCase) != -1) + .OrderBy (p => p.Id) + .Skip (searchToken.StartIndex) + .Take (PageSize + 1) + .ToArray (); + + var hasMoreItems = packages.Length > PageSize; + if (hasMoreItems) { + packages = packages.Take (packages.Length - 1).ToArray (); + } + + var items = await TaskCombinators.ThrottledAsync ( + packages, + (p, t) => _metadataProvider.GetPackageMetadataAsync (p, searchToken.SearchFilter.IncludePrerelease, t), + cancellationToken); + + var result = SearchResult.FromItems (items.ToArray ()); + + var loadingStatus = hasMoreItems + ? LoadingStatus.Ready + : packages.Length == 0 + ? LoadingStatus.NoItemsFound + : LoadingStatus.NoMoreItems; + result.SourceSearchStatus = new Dictionary<string, LoadingStatus> { + { "Consolidate", loadingStatus } + }; + + if (hasMoreItems) { + result.NextToken = new FeedSearchContinuationToken { + SearchString = searchToken.SearchString, + SearchFilter = searchToken.SearchFilter, + StartIndex = searchToken.StartIndex + packages.Length + }; + } + + return result; + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/InstalledPackageFeed.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/InstalledPackageFeed.cs new file mode 100644 index 0000000000..9bbc222d85 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/InstalledPackageFeed.cs @@ -0,0 +1,119 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NuGet.Packaging.Core; +using NuGet.Protocol.Core.Types; + +namespace NuGet.PackageManagement.UI +{ + /// <summary> + /// Represents a package feed enumerating installed packages. + /// </summary> + internal class InstalledPackageFeed : PlainPackageFeedBase + { + IEnumerable<PackageIdentity> _installedPackages; + readonly IPackageMetadataProvider _metadataProvider; + PackageLoadContext _context; + + public InstalledPackageFeed ( + PackageLoadContext context, + IPackageMetadataProvider metadataProvider, + Common.ILogger logger) + : this (new PackageIdentity[0], metadataProvider, logger) + { + this._context = context; + } + + public InstalledPackageFeed ( + IEnumerable<PackageIdentity> installedPackages, + IPackageMetadataProvider metadataProvider, + Common.ILogger logger) + { + if (installedPackages == null) { + throw new ArgumentNullException (nameof (installedPackages)); + } + _installedPackages = installedPackages; + + if (metadataProvider == null) { + throw new ArgumentNullException (nameof (metadataProvider)); + } + _metadataProvider = metadataProvider; + + if (logger == null) { + throw new ArgumentNullException (nameof (logger)); + } + + PageSize = 25; + } + + public override async Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken) + { + var searchToken = continuationToken as FeedSearchContinuationToken; + if (searchToken == null) { + throw new InvalidOperationException ("Invalid token"); + } + + if (_context != null) { + _installedPackages = await _context.GetInstalledPackagesAsync (); + _context = null; + } + + var packages = _installedPackages + .GetLatest () + .Where (p => p.Id.IndexOf (searchToken.SearchString, StringComparison.OrdinalIgnoreCase) != -1) + .OrderBy (p => p.Id) + .Skip (searchToken.StartIndex) + .Take (PageSize + 1) + .ToArray (); + + var hasMoreItems = packages.Length > PageSize; + if (hasMoreItems) { + packages = packages.Take (packages.Length - 1).ToArray (); + } + + var items = await TaskCombinators.ThrottledAsync ( + packages, + (p, t) => GetPackageMetadataAsync (p, searchToken.SearchFilter.IncludePrerelease, t), + cancellationToken); + + // The packages were originally sorted which is important because we Skip and Take based on that sort + // however the asynchronous execution has randomly reordered the set. So we need to resort. + var result = SearchResult.FromItems (items.OrderBy (p => p.Identity.Id).ToArray ()); + + var loadingStatus = hasMoreItems + ? LoadingStatus.Ready + : packages.Length == 0 + ? LoadingStatus.NoItemsFound + : LoadingStatus.NoMoreItems; + result.SourceSearchStatus = new Dictionary<string, LoadingStatus> { + { "Installed", loadingStatus } + }; + + if (hasMoreItems) { + result.NextToken = new FeedSearchContinuationToken { + SearchString = searchToken.SearchString, + SearchFilter = searchToken.SearchFilter, + StartIndex = searchToken.StartIndex + packages.Length + }; + } + + return result; + } + + async Task<IPackageSearchMetadata> GetPackageMetadataAsync (PackageIdentity identity, bool includePrerelease, CancellationToken cancellationToken) + { + // first we try and load the metadata from a local package + var packageMetadata = await _metadataProvider.GetLocalPackageMetadataAsync (identity, includePrerelease, cancellationToken); + if (packageMetadata == null) { + // and failing that we go to the network + packageMetadata = await _metadataProvider.GetPackageMetadataAsync (identity, includePrerelease, cancellationToken); + } + return packageMetadata; + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageCollection.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageCollection.cs new file mode 100644 index 0000000000..c369377f40 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageCollection.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NuGet.Packaging.Core; +using NuGet.ProjectManagement; +using NuGet.Versioning; + +namespace NuGet.PackageManagement.UI +{ + /// <summary> + /// Wrapper class consolidating common queries against a collection of packages + /// </summary> + internal class PackageCollection : IEnumerable<PackageIdentity> + { + readonly PackageIdentity[] _packages; + readonly ISet<string> _uniqueIds = new HashSet<string> (StringComparer.OrdinalIgnoreCase); + + public PackageCollection (PackageIdentity[] packages) + { + _packages = packages; + _uniqueIds.UnionWith (_packages.Select (p => p.Id)); + } + + public IEnumerator<PackageIdentity> GetEnumerator () + { + return ((IEnumerable<PackageIdentity>)_packages).GetEnumerator (); + } + + IEnumerator IEnumerable.GetEnumerator () + { + return ((IEnumerable<PackageIdentity>)_packages).GetEnumerator (); + } + + public bool ContainsId (string packageId) => _uniqueIds.Contains (packageId); + + public static async Task<PackageCollection> FromProjectsAsync (IEnumerable<NuGetProject> projects, CancellationToken cancellationToken) + { + var tasks = projects + .Select (project => project.GetInstalledPackagesAsync (cancellationToken)); + var packageReferences = await Task.WhenAll (tasks); + var packages = packageReferences + .SelectMany (p => p) + .Where (p => p != null) + .Select (p => p.PackageIdentity) + .Distinct (PackageIdentity.Comparer) + .ToArray (); + + return new PackageCollection (packages); + } + } + + /// <summary> + /// Common package queries implementes as extension methods + /// </summary> + internal static class PackageCollectionExtensions + { + public static NuGetVersion[] GetPackageVersions (this IEnumerable<PackageIdentity> packages, string packageId) + { + return packages + .Where (p => StringComparer.OrdinalIgnoreCase.Equals (p.Id, packageId)) + .Select (p => p.Version) + .ToArray (); + } + + public static IEnumerable<IGrouping<string, NuGetVersion>> GroupById (this IEnumerable<PackageIdentity> packages) + { + return packages + .GroupBy (p => p.Id, p => p.Version, StringComparer.OrdinalIgnoreCase); + } + + public static PackageIdentity[] GetLatest (this IEnumerable<PackageIdentity> packages) + { + return packages + .GroupById () + .Select (g => new PackageIdentity (g.Key, g.MaxOrDefault ())) + .ToArray (); + } + + public static PackageIdentity[] GetEarliest (this IEnumerable<PackageIdentity> packages) + { + return packages + .GroupById () + .Select (g => new PackageIdentity (g.Key, g.MinOrDefault ())) + .ToArray (); + } + } + + internal static class VersionCollectionExtensions + { + public static NuGetVersion MinOrDefault (this IEnumerable<NuGetVersion> versions) + { + return versions + .OrderBy (v => v, VersionComparer.Default) + .FirstOrDefault (); + } + + public static NuGetVersion MaxOrDefault (this IEnumerable<NuGetVersion> versions) + { + return versions + .OrderByDescending (v => v, VersionComparer.Default) + .FirstOrDefault (); + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs index 954558f2f6..89b94c5815 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageDetailControlModel.cs @@ -25,7 +25,7 @@ namespace NuGet.PackageManagement.UI IEnumerable<NuGetProject> nugetProjects) : base(nugetProjects) { - Debug.Assert(nugetProjects.Count() == 1); + //Debug.Assert(nugetProjects.Count() == 1); } //public async override Task SetCurrentPackage( diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageFeedEnumerator.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageFeedEnumerator.cs new file mode 100644 index 0000000000..b52e1f8c8a --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageFeedEnumerator.cs @@ -0,0 +1,119 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NuGet.Protocol.Core.Types; + +namespace NuGet.PackageManagement.UI +{ + internal class PackageFeedEnumerator : IEnumerator<IPackageSearchMetadata>, IDisposable, IEnumerator + { + private readonly IPackageFeed _packageFeed; + private readonly Task<SearchResult<IPackageSearchMetadata>> _startFromTask; + private readonly CancellationToken _cancellationToken; + + private Task<SearchResult<IPackageSearchMetadata>> _searchTask; + private IEnumerator<IPackageSearchMetadata> _current; + + private PackageFeedEnumerator ( + IPackageFeed packageFeed, + Task<SearchResult<IPackageSearchMetadata>> searchTask, + CancellationToken cancellationToken) + { + if (packageFeed == null) { + throw new ArgumentNullException (nameof (packageFeed)); + } + _packageFeed = packageFeed; + + if (searchTask == null) { + throw new ArgumentNullException (nameof (searchTask)); + } + _startFromTask = searchTask; + + _cancellationToken = cancellationToken; + + Reset (); + } + + private PackageFeedEnumerator (PackageFeedEnumerator other) + { + if (other == null) { + throw new ArgumentNullException (nameof (other)); + } + _packageFeed = other._packageFeed; + _startFromTask = other._startFromTask; + _cancellationToken = other._cancellationToken; + + Reset (); + } + + public IPackageSearchMetadata Current => _current.Current; + + object IEnumerator.Current => _current.Current; + + public void Dispose () + { + } + + public bool MoveNext () + { + if (_current.MoveNext ()) { + return true; + } + + LoadNextAsync ().Wait (); + return _current.MoveNext (); + } + + private async Task LoadNextAsync () + { + var searchResult = await _searchTask; + + while (searchResult.RefreshToken != null) { + searchResult = await _packageFeed.RefreshSearchAsync (searchResult.RefreshToken, _cancellationToken); + } + + _current = searchResult.GetEnumerator (); + + if (searchResult.NextToken != null) { + _searchTask = _packageFeed.ContinueSearchAsync (searchResult.NextToken, _cancellationToken); + } else { + _searchTask = Task.FromResult (SearchResult.Empty<IPackageSearchMetadata> ()); + } + } + + public void Reset () + { + _searchTask = _startFromTask; + _current = Enumerable.Empty<IPackageSearchMetadata> ().GetEnumerator (); + } + + public static IEnumerable<IPackageSearchMetadata> Enumerate ( + IPackageFeed packageFeed, + Task<SearchResult<IPackageSearchMetadata>> searchTask, + CancellationToken cancellationToken) + { + var enumerator = new PackageFeedEnumerator (packageFeed, searchTask, cancellationToken); + return new PackageFeedEnumerable (enumerator); + } + + private sealed class PackageFeedEnumerable : IEnumerable<IPackageSearchMetadata> + { + private readonly PackageFeedEnumerator _enumerator; + + public PackageFeedEnumerable (PackageFeedEnumerator enumerator) + { + _enumerator = enumerator; + } + + public IEnumerator<IPackageSearchMetadata> GetEnumerator () => new PackageFeedEnumerator (_enumerator); + + IEnumerator IEnumerable.GetEnumerator () => this.GetEnumerator (); + } + } +} diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs index e69db3cefb..994c60d122 100644 --- a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageLoadContext.cs @@ -14,7 +14,7 @@ namespace NuGet.PackageManagement.UI {
internal class PackageLoadContext
{
- //private readonly Task<PackageCollection> _installedPackagesTask;
+ Task<PackageCollection> installedPackagesTask;
public IEnumerable<SourceRepository> SourceRepositories { get; private set; }
@@ -32,18 +32,18 @@ namespace NuGet.PackageManagement.UI public PackageLoadContext(
IEnumerable<SourceRepository> sourceRepositories,
bool isSolution,
- NuGetProject project)
+ IEnumerable<NuGetProject> projects)
{
SourceRepositories = sourceRepositories;
IsSolution = isSolution;
//PackageManager = uiContext.PackageManager;
- Projects = new [] { project };
+ Projects = projects.ToArray ();
//PackageManagerProviders = uiContext.PackageManagerProviders;
- //_installedPackagesTask = PackageCollection.FromProjectsAsync(Projects, CancellationToken.None);
+ installedPackagesTask = PackageCollection.FromProjectsAsync(Projects, CancellationToken.None);
}
- //public Task<PackageCollection> GetInstalledPackagesAsync() =>_installedPackagesTask;
+ public Task<PackageCollection> GetInstalledPackagesAsync() => installedPackagesTask;
// Returns the list of frameworks that we need to pass to the server during search
public IEnumerable<string> GetSupportedFrameworks()
diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageSearchMetadataCache.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageSearchMetadataCache.cs new file mode 100644 index 0000000000..e61d3dc360 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PackageSearchMetadataCache.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Generic; +using NuGet.Protocol.Core.Types; + +namespace NuGet.PackageManagement.UI +{ + class PackageSearchMetadataCache + { + // Cached Package Metadata + public IReadOnlyList<IPackageSearchMetadata> Packages { get; set; } + + // Remember the IncludePrerelease setting corresponding to the Cached Metadata + public bool IncludePrerelease { get; set; } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PlainPackageFeedBase.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PlainPackageFeedBase.cs new file mode 100644 index 0000000000..360656f33e --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/PlainPackageFeedBase.cs @@ -0,0 +1,36 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading; +using System.Threading.Tasks; +using NuGet.Protocol.Core.Types; + +namespace NuGet.PackageManagement.UI +{ + /// <summary> + /// Shared base implementation of plain package feeds. + /// </summary> + internal abstract class PlainPackageFeedBase : IPackageFeed + { + public int PageSize { get; protected set; } = 100; + + // No, it's not. + public bool IsMultiSource => false; + + public Task<SearchResult<IPackageSearchMetadata>> SearchAsync (string searchText, SearchFilter searchFilter, CancellationToken cancellationToken) + { + var searchToken = new FeedSearchContinuationToken { + SearchString = searchText, + SearchFilter = searchFilter, + StartIndex = 0 + }; + + return ContinueSearchAsync (searchToken, cancellationToken); + } + + public abstract Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken); + + public Task<SearchResult<IPackageSearchMetadata>> RefreshSearchAsync (RefreshToken refreshToken, CancellationToken cancellationToken) + => Task.FromResult (SearchResult.Empty<IPackageSearchMetadata> ()); + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/UpdatePackageFeed.cs b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/UpdatePackageFeed.cs new file mode 100644 index 0000000000..173cee7c64 --- /dev/null +++ b/main/src/addins/MonoDevelop.PackageManagement/NuGet.PackageManagement.UI/UpdatePackageFeed.cs @@ -0,0 +1,121 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using NuGet.Packaging.Core; +using NuGet.Protocol.Core.Types; +using NuGet.Versioning; + +namespace NuGet.PackageManagement.UI +{ + /// <summary> + /// A package feed providing services of package enumeration of installed packages having updated versions in upstream source(s). + /// </summary> + internal class UpdatePackageFeed : PlainPackageFeedBase + { + IEnumerable<PackageIdentity> _installedPackages; + readonly IPackageMetadataProvider _metadataProvider; + readonly PackageSearchMetadataCache _cachedUpdates; + PackageLoadContext _context; + + public UpdatePackageFeed ( + PackageLoadContext context, + IPackageMetadataProvider metadataProvider, + PackageSearchMetadataCache cachedUpdates, + Common.ILogger logger) + : this (new PackageIdentity[0], metadataProvider, cachedUpdates, logger) + { + _context = context; + } + + public UpdatePackageFeed ( + IEnumerable<PackageIdentity> installedPackages, + IPackageMetadataProvider metadataProvider, + PackageSearchMetadataCache cachedUpdates, + Common.ILogger logger) + { + if (installedPackages == null) { + throw new ArgumentNullException (nameof (installedPackages)); + } + _installedPackages = installedPackages; + + if (metadataProvider == null) { + throw new ArgumentNullException (nameof (metadataProvider)); + } + _metadataProvider = metadataProvider; + + _cachedUpdates = cachedUpdates; + + if (logger == null) { + throw new ArgumentNullException (nameof (logger)); + } + } + + public override async Task<SearchResult<IPackageSearchMetadata>> ContinueSearchAsync (ContinuationToken continuationToken, CancellationToken cancellationToken) + { + var searchToken = continuationToken as FeedSearchContinuationToken; + if (searchToken == null) { + throw new InvalidOperationException ("Invalid token"); + } + + var packagesWithUpdates = (_cachedUpdates.Packages != null) && (_cachedUpdates?.IncludePrerelease == searchToken.SearchFilter.IncludePrerelease) + ? + GetPackagesFromCache (searchToken.SearchString) + : + await GetPackagesWithUpdatesAsync (searchToken.SearchString, searchToken.SearchFilter, cancellationToken); + + var items = packagesWithUpdates + .Skip (searchToken.StartIndex) + .ToArray (); + + var result = SearchResult.FromItems (items); + + var loadingStatus = items.Length == 0 + ? LoadingStatus.NoItemsFound + : LoadingStatus.NoMoreItems; + result.SourceSearchStatus = new Dictionary<string, LoadingStatus> { + { "Update", loadingStatus } + }; + + return result; + } + + IEnumerable<IPackageSearchMetadata> GetPackagesFromCache (string searchText) + { + return _cachedUpdates.Packages.Where (p => p.Identity.Id.IndexOf (searchText, StringComparison.OrdinalIgnoreCase) != -1); + } + + async Task<IEnumerable<IPackageSearchMetadata>> GetPackagesWithUpdatesAsync (string searchText, SearchFilter searchFilter, CancellationToken cancellationToken) + { + if (_context != null) { + _installedPackages = await _context.GetInstalledPackagesAsync (); + _context = null; + } + + var packages = _installedPackages + .GetEarliest () + .Where (p => p.Id.IndexOf (searchText, StringComparison.OrdinalIgnoreCase) != -1) + .OrderBy (p => p.Id); + + var latestItems = await TaskCombinators.ThrottledAsync ( + packages, + (p, t) => _metadataProvider.GetLatestPackageMetadataAsync (p, searchFilter.IncludePrerelease, t), + cancellationToken); + + var packagesWithUpdates = packages + .Join (latestItems.Where (i => i != null), + p => p.Id, + m => m.Identity.Id, + (p, m) => new { cv = p.Version, m = m }, + StringComparer.OrdinalIgnoreCase) + .Where (j => VersionComparer.VersionRelease.Compare (j.cv, j.m.Identity.Version) < 0) + .Select (j => j.m); + + return packagesWithUpdates; + } + } +}
\ No newline at end of file diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs index 36398008a6..336df933d5 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.AnalysisCore/Gui/ResultsEditorExtension.cs @@ -76,11 +76,19 @@ namespace MonoDevelop.AnalysisCore.Gui protected override void Initialize () { base.Initialize (); - + if (Editor.Options is DefaultSourceEditorOptions options) + options.Changed += Options_Changed; AnalysisOptions.AnalysisEnabled.Changed += AnalysisOptionsChanged; AnalysisOptionsChanged (null, null); } + void Options_Changed (object sender, EventArgs e) + { + if (DocumentContext == null || !enabled) + return; + UpdateInitialDiagnostics (); + } + void AnalysisOptionsChanged (object sender, EventArgs e) { Enabled = AnalysisOptions.AnalysisEnabled; @@ -91,6 +99,8 @@ namespace MonoDevelop.AnalysisCore.Gui if (disposed) return; enabled = false; + if (Editor.Options is DefaultSourceEditorOptions options) + options.Changed -= Options_Changed; diagService.DiagnosticsUpdated -= OnDiagnosticsUpdated; diagService = null; CancelUpdateTimout (); @@ -154,7 +164,7 @@ namespace MonoDevelop.AnalysisCore.Gui if (!AnalysisOptions.EnableFancyFeatures) return; - var doc = DocumentContext.AnalysisDocument; + var doc = DocumentContext?.AnalysisDocument; if (doc == null || DocumentContext.IsAdHocProject) return; diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs index 75aabfe88a..a630aca56b 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.Refactoring.PackageInstaller/PackageInstallerService.cs @@ -128,6 +128,9 @@ namespace MonoDevelop.Refactoring.PackageInstaller installedPackages.ContainsKey (packageName); } + public bool CanShowManagePackagesDialog () + => true; + public void ShowManagePackagesDialog (string packageName) { PackageServices.ShowManagePackagesDialog (packageName); diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs index 38d4003d5b..30fbbd073e 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor.QuickTasks/QuickTaskOverviewMode.cs @@ -725,20 +725,18 @@ namespace MonoDevelop.SourceEditor.QuickTasks { var breakpointStore = parentStrip.SourceEditorView.Breakpoints; - lock (breakpointStore) { - var breakPoints = breakpointStore.GetBreakpointsAtFile (TextEditor.FileName); + var breakPoints = breakpointStore.GetBreakpointsAtFile (TextEditor.FileName); - if (breakPoints == null) - return; + if (breakPoints == null) + return; - foreach (var point in breakPoints) { - int y = (int)GetYPosition (point.Line); + foreach (var point in breakPoints) { + int y = (int)GetYPosition (point.Line); - cr.SetSourceColor (SyntaxHighlightingService.GetColor (TextEditor.EditorTheme, EditorThemeColors.BreakpointMarker)); - int r = 4; - cr.Rectangle (0, y - r / 2, r, r); - cr.Fill (); - } + cr.SetSourceColor (SyntaxHighlightingService.GetColor (TextEditor.EditorTheme, EditorThemeColors.BreakpointMarker)); + int r = 4; + cr.Rectangle (0, y - r / 2, r, r); + cr.Fill (); } } diff --git a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs index c9407e4dbe..365927bafe 100644 --- a/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs +++ b/main/src/addins/MonoDevelop.SourceEditor2/MonoDevelop.SourceEditor/SourceEditorView.cs @@ -1348,17 +1348,15 @@ namespace MonoDevelop.SourceEditor int i = 0, count = 0; bool mismatch = false; - lock (breakpoints) { - foreach (var bp in breakpoints.GetBreakpointsAtFile (fp.FullPath)) { - count++; - if (i < breakpointSegments.Count) { - int lineNumber = document.OffsetToLineNumber (breakpointSegments [i].TextMarker.Offset); - if (lineNumber != bp.Line) { - mismatch = true; - break; - } - i++; + foreach (var bp in breakpoints.GetBreakpointsAtFile (fp.FullPath)) { + count++; + if (i < breakpointSegments.Count) { + int lineNumber = document.OffsetToLineNumber (breakpointSegments [i].TextMarker.Offset); + if (lineNumber != bp.Line) { + mismatch = true; + break; } + i++; } } @@ -1383,11 +1381,9 @@ namespace MonoDevelop.SourceEditor breakpointSegments.Clear (); - lock (breakpoints) { - foreach (var bp in breakpoints.GetBreakpointsAtFile (fp.FullPath)) { - lineNumbers.Add (bp.Line); - AddBreakpoint (bp); - } + foreach (var bp in breakpoints.GetBreakpointsAtFile (fp.FullPath)) { + lineNumbers.Add (bp.Line); + AddBreakpoint (bp); } foreach (int lineNumber in lineNumbers) { @@ -1506,8 +1502,7 @@ namespace MonoDevelop.SourceEditor int column = TextEditor.Caret.Line == args.LineNumber ? Math.Min (TextEditor.Caret.Column, args.LineSegment.Length) : 1; - lock (breakpoints) - breakpoints.Toggle (Document.FileName, args.LineNumber, column); + breakpoints.Toggle (Document.FileName, args.LineNumber, column); } } } diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml index 3cbda1c2bc..c78c5cae0f 100644 --- a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor.Cocoa/Properties/MonoDevelop.TextEditor.Cocoa.addin.xml @@ -97,8 +97,12 @@ --> <Map id="MonoDevelop.Ide.Commands.SearchCommands.Find" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindCommandArgs" /> <Map id="MonoDevelop.Ide.Commands.SearchCommands.FindNext" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindNextCommandArgs" /> + <Map id="MonoDevelop.Ide.Commands.SearchCommands.FindNextSelection" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindNextLikeSelectionCommandArgs" /> <Map id="MonoDevelop.Ide.Commands.SearchCommands.FindPrevious" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindPreviousCommandArgs" /> + <Map id="MonoDevelop.Ide.Commands.SearchCommands.FindPreviousSelection" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.FindPreviousLikeSelectionCommandArgs" /> <Map id="MonoDevelop.Ide.Commands.SearchCommands.Replace" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.ReplaceCommandArgs" /> + <Map id="MonoDevelop.Ide.Commands.SearchCommands.UseSelectionForReplace" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.ReplaceCommandArgs" /> + <Map id="MonoDevelop.Ide.Commands.SearchCommands.UseSelectionForFind" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.SetSearchStringFromSelectionCommandArgs" /> <Map id="MonoDevelop.Refactoring.Navigate.GotoBaseMember" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.Navigation.GoToBaseMemberCommandArgs" /> <Map id="MonoDevelop.Ide.Commands.SearchCommands.GotoLineNumber" argsType="Microsoft.VisualStudio.Text.Extras.GoToLine.GoToLineCommandArgs" /> </Extension> diff --git a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml index 969f61f267..0e5345b0a0 100644 --- a/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml +++ b/main/src/addins/MonoDevelop.TextEditor/MonoDevelop.TextEditor/Properties/MonoDevelop.TextEditor.addin.xml @@ -146,7 +146,7 @@ <Map id="MonoDevelop.Ide.Commands.TextEditorCommands.ShowCodeTemplateWindow" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.InsertSnippetCommandArgs" /> <Map id="MonoDevelop.Ide.Commands.TextEditorCommands.ShowCodeSurroundingsWindow" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.SurroundWithCommandArgs" /> - <Map id="MonoDevelop.Ide.Commands.TextEditorCommands.GotoMatchingBrace" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.GoToMatchingBraceCommandArgs" /> + <Map id="MonoDevelop.Ide.Commands.TextEditorCommands.GotoMatchingBrace" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.GotoBraceCommandArgs" /> <Map id="MonoDevelop.Ide.Commands.EditCommands.ToggleFolding" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.ToggleOutliningExpansionCommandArgs" /> <Map id="MonoDevelop.Ide.Commands.EditCommands.ToggleAllFoldings" argsType="Microsoft.VisualStudio.Text.Editor.Commanding.Commands.ToggleAllOutliningCommandArgs" /> diff --git a/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml b/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml index 3d0d711c33..0e1bf46362 100644 --- a/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml +++ b/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProject.xpt.xml @@ -32,7 +32,7 @@ </References> <Packages> - <Package ID="NUnit" Version="2.6.4" /> + <Package ID="NUnit" Version="3.12.0" /> </Packages> <Files> diff --git a/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml b/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml index c6aa7ce400..f64fde474b 100644 --- a/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml +++ b/main/src/addins/MonoDevelop.UnitTesting.NUnit/templates/NUnitProjectVBNet.xpt.xml @@ -32,7 +32,7 @@ </References> <Packages> - <Package ID="NUnit" Version="2.6.4" /> + <Package ID="NUnit" Version="3.12.0" /> </Packages> <Files> diff --git a/main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs b/main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs index 317e5d1840..017c404aef 100644 --- a/main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs +++ b/main/src/addins/MonoDeveloperExtensions/MonoMakefileProjectReader.cs @@ -53,12 +53,12 @@ namespace MonoDeveloper public override Task<SolutionItem> LoadSolutionItem (ProgressMonitor monitor, SolutionLoadContext ctx, string fileName, MSBuildFileFormat expectedFormat, string typeGuid, string itemGuid) { - return Task.Run (() => (SolutionItem) ReadFile (fileName, false, monitor)); + return Task.FromResult ((SolutionItem) ReadFile (fileName, false, monitor)); } public override Task<WorkspaceItem> LoadWorkspaceItem (ProgressMonitor monitor, string fileName) { - return Task.Run (() => (WorkspaceItem) ReadFile (fileName, false, monitor)); + return Task.FromResult ((WorkspaceItem) ReadFile (fileName, false, monitor)); } public object ReadFile (FilePath fileName, bool hasParentSolution, ProgressMonitor monitor) diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj index 700e35fb91..9634a9d7df 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl.Git.Tests/MonoDevelop.VersionControl.Git.Tests.csproj @@ -51,6 +51,8 @@ <ProjectReference Include="..\..\..\..\external\libgit2sharp\LibGit2Sharp\LibGit2Sharp.csproj"> <Project>{EE6ED99F-CB12-4683-B055-D28FC7357A34}</Project> <Name>LibGit2Sharp</Name> + <IncludeInPackage>true</IncludeInPackage> + <Private>False</Private> </ProjectReference> <ProjectReference Include="..\..\MonoDevelop.SourceEditor2\MonoDevelop.SourceEditor.csproj"> <Project>{F8F92AA4-A376-4679-A9D4-60E7B7FBF477}</Project> diff --git a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs index f4bfaf9b98..0669b396e5 100644 --- a/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs +++ b/main/src/addins/VersionControl/MonoDevelop.VersionControl/MonoDevelop.VersionControl/DefaultBlameViewHandler.cs @@ -38,10 +38,7 @@ namespace MonoDevelop.VersionControl { public static bool DefaultVCSViewCanHandle (VersionControlItem item, DocumentController controller) { - if (controller == null) - return item.Repository.GetFileIsText (item.Path); - - return controller is TextEditorViewContent || controller.GetContent<ITextBuffer> () != null; + return item.Repository.GetFileIsText (item.Path); } public bool CanHandle (VersionControlItem item, DocumentController controller) => DefaultVCSViewCanHandle (item, controller); diff --git a/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs b/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs index 2ed8162614..d96e660e96 100644 --- a/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs +++ b/main/src/addins/WindowsPlatform/WindowsPlatform/MainToolbar/WPFToolbar.cs @@ -1,4 +1,4 @@ -using MonoDevelop.Components.MainToolbar;
+using MonoDevelop.Components.MainToolbar;
using MonoDevelop.Components.Windows;
using MonoDevelop.Core;
using System;
@@ -25,24 +25,25 @@ namespace WindowsPlatform.MainToolbar public class WPFToolbar : GtkWPFWidget, IMainToolbarView, INotifyPropertyChanged
{
ToolBar toolbar;
+
WPFToolbar (ToolBar toolbar) : base (toolbar)
{
this.toolbar = toolbar;
toolbar.ConfigurationMenu.SelectionChanged += (o, e) => {
- var comboMenu = (ComboMenu<IConfigurationModel>)o;
+ var comboMenu = (ComboMenu<IConfigurationModel>) o;
var newModel = e.Added;
if (newModel == null)
return;
- Runtime.RunInMainThread(() => {
+ Runtime.RunInMainThread (() => {
ActiveConfiguration = newModel;
ConfigurationChanged?.Invoke (o, e);
});
};
toolbar.RunConfigurationMenu.SelectionChanged += (o, e) => {
- var comboMenu = (ComboMenu<IRunConfigurationModel>)o;
+ var comboMenu = (ComboMenu<IRunConfigurationModel>) o;
var newModel = e.Added;
if (newModel == null)
return;
@@ -58,11 +59,11 @@ namespace WindowsPlatform.MainToolbar if (newModel == null)
return;
- using (var mutableModel = newModel.GetMutableModel()) {
- Runtime.RunInMainThread(() => {
+ using (var mutableModel = newModel.GetMutableModel ()) {
+ Runtime.RunInMainThread (() => {
ActiveRuntime = newModel;
- var ea = new MonoDevelop.Components.MainToolbar.HandledEventArgs();
+ var ea = new MonoDevelop.Components.MainToolbar.HandledEventArgs ();
RuntimeChanged?.Invoke (o, ea);
if (ea.Handled)
@@ -80,7 +81,7 @@ namespace WindowsPlatform.MainToolbar if (SearchText == SearchPlaceholderMessage)
return;
- if (SearchEntryChanged != null) + if (SearchEntryChanged != null)
SearchEntryChanged (o, e);
};
@@ -90,9 +91,7 @@ namespace WindowsPlatform.MainToolbar toolbar.SearchBar.SearchText = toolbar.SearchBar.PlaceholderText;
};
- toolbar.SearchBar.SearchBar.GotKeyboardFocus += (o, e) => {
- SearchEntryActivated?.Invoke (o, e);
- };
+ toolbar.SearchBar.SearchBar.GotKeyboardFocus += (o, e) => { SearchEntryActivated?.Invoke (o, e); };
toolbar.SearchBar.SearchBar.SizeChanged += (o, e) => {
if (SearchEntryResized != null)
@@ -100,41 +99,41 @@ namespace WindowsPlatform.MainToolbar };
toolbar.SearchBar.SearchBar.PreviewKeyDown += (o, e) => {
- var ka = new KeyEventArgs(KeyboardUtil.TranslateToXwtKey(e.Key), KeyboardUtil.GetModifiers(), e.IsRepeat, e.Timestamp);
- SendKeyPress(ka);
+ var ka = new KeyEventArgs (KeyboardUtil.TranslateToXwtKey (e.Key), KeyboardUtil.GetModifiers (),
+ e.IsRepeat, e.Timestamp);
+ SendKeyPress (ka);
e.Handled = ka.Handled;
};
- toolbar.SearchBar.ClearIconClicked += (o, e) =>
- {
- SendKeyPress(new KeyEventArgs(Xwt.Key.Escape, KeyboardUtil.GetModifiers(), false, 0));
+ toolbar.SearchBar.ClearIconClicked += (o, e) => {
+ SendKeyPress (new KeyEventArgs (Xwt.Key.Escape, KeyboardUtil.GetModifiers (), false, 0));
};
- }
+ }
- protected override void RepositionWpfWindow()
- {
- int scale = (int)MonoDevelop.Components.GtkWorkarounds.GetScaleFactor(this);
- RepositionWpfWindow (scale, scale);
- } + protected override void RepositionWpfWindow ()
+ {
+ int scale = (int) MonoDevelop.Components.GtkWorkarounds.GetScaleFactor (this);
+ RepositionWpfWindow (scale, scale);
+ }
- void SendKeyPress(KeyEventArgs ka)
+ void SendKeyPress (KeyEventArgs ka)
{
if (SearchEntryKeyPressed != null)
- SearchEntryKeyPressed(this, ka);
+ SearchEntryKeyPressed (this, ka);
}
public WPFToolbar () : this (new ToolBar ())
{
}
-
+
public IConfigurationModel ActiveConfiguration {
get { return toolbar.ConfigurationMenu.Active; }
set { toolbar.ConfigurationMenu.Active = value; }
}
-
+
public IRuntimeModel ActiveRuntime {
- get { return toolbar.RuntimeMenu.Active; }
- set { toolbar.RuntimeMenu.Active = value; }
+ get { return toolbar.RuntimeMenu.Active; }
+ set { toolbar.RuntimeMenu.Active = value; }
}
public IRunConfigurationModel ActiveRunConfiguration {
@@ -143,11 +142,11 @@ namespace WindowsPlatform.MainToolbar }
public bool ButtonBarSensitivity {
- set { toolbar.ButtonBarPanel.IsEnabled = value; }
+ set { toolbar.ButtonBarPanel.IsEnabled = value; }
}
public IEnumerable<IConfigurationModel> ConfigurationModel {
- get { return toolbar.ConfigurationMenu.Model; }
+ get { return toolbar.ConfigurationMenu.Model; }
set { toolbar.ConfigurationMenu.Model = value; }
}
@@ -162,29 +161,26 @@ namespace WindowsPlatform.MainToolbar }
bool configurationPlatformSensitivity;
- public bool ConfigurationPlatformSensitivity {
+
+ public bool ConfigurationPlatformSensitivity {
get { return configurationPlatformSensitivity; }
set {
configurationPlatformSensitivity = value;
- toolbar.ConfigurationMenu.IsEnabled = value && ConfigurationModel.Count() > 1;
- toolbar.RuntimeMenu.IsEnabled = value && RuntimeModel.Count() > 1;
- }
+ toolbar.ConfigurationMenu.IsEnabled = value && ConfigurationModel.Count () > 1;
+ toolbar.RuntimeMenu.IsEnabled = value && RuntimeModel.Count () > 1;
+ }
}
-
+
public bool PlatformSensitivity {
- set {
- toolbar.RuntimeMenu.IsEnabled = value && RuntimeModel.Count() > 1;
- }
+ set { toolbar.RuntimeMenu.IsEnabled = value && RuntimeModel.Count () > 1; }
}
public Gtk.Widget PopupAnchor {
- get {
- return this;
- }
+ get { return this; }
}
public OperationIcon RunButtonIcon {
- set { toolbar.RunButton.Icon = value; }
+ set { toolbar.RunButton.Icon = value; }
}
public bool RunButtonSensitivity {
@@ -195,14 +191,15 @@ namespace WindowsPlatform.MainToolbar public bool RunConfigurationVisible {
get { return toolbar.RunConfigurationMenu.IsVisible; }
set {
- System.Windows.Visibility visible = value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
+ System.Windows.Visibility visible =
+ value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
toolbar.RunConfigurationMenu.Visibility = visible;
toolbar.RunConfigurationSeparator.Visibility = visible;
}
}
public string SearchCategory {
- set {
+ set {
toolbar.SearchBar.SearchText = value;
FocusSearchBar ();
toolbar.SearchBar.SearchBar.Select (value.Length, 0);
@@ -210,18 +207,16 @@ namespace WindowsPlatform.MainToolbar }
public IEnumerable<ISearchMenuModel> SearchMenuItems {
- set {
- toolbar.SearchBar.SearchMenuItems = value;
- }
+ set { toolbar.SearchBar.SearchMenuItems = value; }
}
public string SearchPlaceholderMessage {
get { return toolbar.SearchBar.PlaceholderText; }
- set { toolbar.SearchBar.PlaceholderText = value; }
+ set { toolbar.SearchBar.PlaceholderText = value; }
}
public bool SearchSensivitity {
- set { toolbar.SearchBar.IsEnabled = value; }
+ set { toolbar.SearchBar.IsEnabled = value; }
}
public string SearchText {
@@ -236,7 +231,7 @@ namespace WindowsPlatform.MainToolbar }
public StatusBar StatusBar {
- get { return toolbar.StatusBar; }
+ get { return toolbar.StatusBar; }
}
public event EventHandler ConfigurationChanged;
@@ -245,6 +240,7 @@ namespace WindowsPlatform.MainToolbar public event EventHandler SearchEntryActivated;
public event EventHandler SearchEntryChanged;
public event EventHandler<KeyEventArgs> SearchEntryKeyPressed;
+ public event EventHandler<SearchEntryCommandArgs> PerformCommand;
public event EventHandler SearchEntryLostFocus;
public event EventHandler SearchEntryResized;
@@ -258,27 +254,24 @@ namespace WindowsPlatform.MainToolbar foreach (var item in toolbar.ButtonBarPanel.Children.OfType<IDisposable> ())
item.Dispose ();
- toolbar.ButtonBarPanel.Children.Clear (); - - // Remove empty groups so we know when to put a separator + toolbar.ButtonBarPanel.Children.Clear ();
+
+ // Remove empty groups so we know when to put a separator
var groupList = groups.ToList ();
groupList.RemoveAll ((g) => g.Buttons.Count == 0);
int idx = 0;
int count = groupList.Count;
- var sepStyle = toolbar.FindResource (System.Windows.Controls.ToolBar.SeparatorStyleKey) as System.Windows.Style;
+ var sepStyle =
+ toolbar.FindResource (System.Windows.Controls.ToolBar.SeparatorStyleKey) as System.Windows.Style;
foreach (var buttonGroup in groupList) {
bool needsSeparator = (idx < count - 1);
foreach (var button in buttonGroup.Buttons) {
if (needsSeparator)
toolbar.ButtonBarPanel.Children.Add (new DottedSeparator {
- Margin = new System.Windows.Thickness {
- Left = 3,
- Right = 3,
- },
- UseLayoutRounding = true,
+ Margin = new System.Windows.Thickness {Left = 3, Right = 3,}, UseLayoutRounding = true,
});
toolbar.ButtonBarPanel.Children.Add (new ButtonBarButton (button));
@@ -295,10 +288,10 @@ namespace WindowsPlatform.MainToolbar PropertyChanged (this, new System.ComponentModel.PropertyChangedEventArgs (propName));
}
- public void Focus (Gtk.DirectionType direction, Action<Gtk.DirectionType> exitAction) - { + public void Focus (Gtk.DirectionType direction, Action<Gtk.DirectionType> exitAction)
+ {
FocusSearchBar ();
- exitAction (direction); + exitAction (direction);
}
public void ShowAccessibilityAnnouncement (string message)
@@ -312,7 +305,7 @@ namespace WindowsPlatform.MainToolbar public class NotNullConverter : IValueConverter
{
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ public object Convert (object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null;
}
@@ -321,5 +314,5 @@ namespace WindowsPlatform.MainToolbar {
throw new NotImplementedException ();
}
- }
+ }
}
|