166 changed files with 12502 additions and 574 deletions
@ -0,0 +1,116 @@
@@ -0,0 +1,116 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00 |
||||
# Visual Studio 2010 |
||||
# SharpDevelop 4.1.0.7222-alpha |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PackageManagement", "Project\PackageManagement.csproj", "{AE4AB0FA-6087-4480-AF37-0FA1452B3DA1}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PackageManagement.Tests", "Test\PackageManagement.Tests.csproj", "{56E98A01-8398-4A08-9578-C7337711A52B}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop", "..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj", "{2748AD25-9C63-4E12-877B-4DCE96FBED54}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core", "..\..\..\Main\Core\Project\ICSharpCode.Core.csproj", "{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvalonDock", "..\..\..\Libraries\AvalonDock\AvalonDock\AvalonDock.csproj", "{87E61430-4243-45F2-B74E-0A4C096CEBF3}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.AvalonEdit", "..\..\..\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj", "{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core.Presentation", "..\..\..\Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj", "{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Core.WinForms", "..\..\..\Main\ICSharpCode.Core.WinForms\ICSharpCode.Core.WinForms.csproj", "{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Dom", "..\..\..\Main\ICSharpCode.SharpDevelop.Dom\Project\ICSharpCode.SharpDevelop.Dom.csproj", "{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.SharpDevelop.Widgets", "..\..\..\Main\ICSharpCode.SharpDevelop.Widgets\Project\ICSharpCode.SharpDevelop.Widgets.csproj", "{8035765F-D51F-4A0C-A746-2FD100E19419}" |
||||
EndProject |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NRefactory", "..\..\..\Libraries\NRefactory\Project\NRefactory.csproj", "{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}" |
||||
EndProject |
||||
Global |
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||
Debug|x86 = Debug|x86 |
||||
Release|x86 = Release|x86 |
||||
Debug|Any CPU = Debug|Any CPU |
||||
Release|Any CPU = Release|Any CPU |
||||
EndGlobalSection |
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||
{AE4AB0FA-6087-4480-AF37-0FA1452B3DA1}.Debug|x86.Build.0 = Debug|x86 |
||||
{AE4AB0FA-6087-4480-AF37-0FA1452B3DA1}.Debug|x86.ActiveCfg = Debug|x86 |
||||
{AE4AB0FA-6087-4480-AF37-0FA1452B3DA1}.Release|x86.Build.0 = Release|x86 |
||||
{AE4AB0FA-6087-4480-AF37-0FA1452B3DA1}.Release|x86.ActiveCfg = Release|x86 |
||||
{56E98A01-8398-4A08-9578-C7337711A52B}.Debug|x86.Build.0 = Debug|x86 |
||||
{56E98A01-8398-4A08-9578-C7337711A52B}.Debug|x86.ActiveCfg = Debug|x86 |
||||
{56E98A01-8398-4A08-9578-C7337711A52B}.Release|x86.Build.0 = Release|x86 |
||||
{56E98A01-8398-4A08-9578-C7337711A52B}.Release|x86.ActiveCfg = Release|x86 |
||||
{2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|x86.Build.0 = Release|Any CPU |
||||
{2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{2748AD25-9C63-4E12-877B-4DCE96FBED54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{2748AD25-9C63-4E12-877B-4DCE96FBED54}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|x86.Build.0 = Release|Any CPU |
||||
{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
{87E61430-4243-45F2-B74E-0A4C096CEBF3}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{87E61430-4243-45F2-B74E-0A4C096CEBF3}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{87E61430-4243-45F2-B74E-0A4C096CEBF3}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{87E61430-4243-45F2-B74E-0A4C096CEBF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{87E61430-4243-45F2-B74E-0A4C096CEBF3}.Release|x86.Build.0 = Release|Any CPU |
||||
{87E61430-4243-45F2-B74E-0A4C096CEBF3}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{87E61430-4243-45F2-B74E-0A4C096CEBF3}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{87E61430-4243-45F2-B74E-0A4C096CEBF3}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|x86.Build.0 = Release|Any CPU |
||||
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Release|x86.Build.0 = Release|Any CPU |
||||
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|x86.Build.0 = Release|Any CPU |
||||
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|x86.Build.0 = Release|Any CPU |
||||
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{924EE450-603D-49C1-A8E5-4AFAA31CE6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
{8035765F-D51F-4A0C-A746-2FD100E19419}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{8035765F-D51F-4A0C-A746-2FD100E19419}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{8035765F-D51F-4A0C-A746-2FD100E19419}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{8035765F-D51F-4A0C-A746-2FD100E19419}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{8035765F-D51F-4A0C-A746-2FD100E19419}.Release|x86.Build.0 = Release|Any CPU |
||||
{8035765F-D51F-4A0C-A746-2FD100E19419}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{8035765F-D51F-4A0C-A746-2FD100E19419}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{8035765F-D51F-4A0C-A746-2FD100E19419}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|x86.Build.0 = Debug|Any CPU |
||||
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|x86.ActiveCfg = Debug|Any CPU |
||||
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|x86.Build.0 = Release|Any CPU |
||||
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|x86.ActiveCfg = Release|Any CPU |
||||
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|Any CPU.Build.0 = Release|Any CPU |
||||
{3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}.Release|Any CPU.ActiveCfg = Release|Any CPU |
||||
EndGlobalSection |
||||
EndGlobal |
Binary file not shown.
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?> |
||||
<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
||||
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> |
||||
<id>AvalonEdit.Sample</id> |
||||
<version>4.0.0.7070</version> |
||||
<authors>Daniel Grunwald</authors> |
||||
<owners>SharpDevelop</owners> |
||||
<licenseUrl>http://www.opensource.org/licenses/mit-license.php</licenseUrl> |
||||
<projectUrl>http://www.avalonedit.net</projectUrl> |
||||
<iconUrl>http://community.sharpdevelop.net/blogs/mattward/SharpDevelop.png</iconUrl> |
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance> |
||||
<description>Sample code for AvalonEdit the WPF-based text editor used in SharpDevelop 4.0.</description> |
||||
<summary>Sample code for AvalonEdit the WPF-based text editor used in SharpDevelop 4.0.</summary> |
||||
<language>en-US</language> |
||||
<dependencies> |
||||
<dependency id="AvalonEdit" version="4.0.0.7070" /> |
||||
</dependencies> |
||||
</metadata> |
||||
</package> |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2009 Daniel Grunwald |
||||
// |
||||
// 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 ICSharpCode.AvalonEdit.Document; |
||||
using ICSharpCode.AvalonEdit.Folding; |
||||
|
||||
namespace $rootnamespace$.AvalonEdit.Sample |
||||
{ |
||||
/// <summary> |
||||
/// Allows producing foldings from a document based on braces. |
||||
/// </summary> |
||||
public class BraceFoldingStrategy : AbstractFoldingStrategy |
||||
{ |
||||
/// <summary> |
||||
/// Gets/Sets the opening brace. The default value is '{'. |
||||
/// </summary> |
||||
public char OpeningBrace { get; set; } |
||||
|
||||
/// <summary> |
||||
/// Gets/Sets the closing brace. The default value is '}'. |
||||
/// </summary> |
||||
public char ClosingBrace { get; set; } |
||||
|
||||
/// <summary> |
||||
/// Creates a new BraceFoldingStrategy. |
||||
/// </summary> |
||||
public BraceFoldingStrategy() |
||||
{ |
||||
this.OpeningBrace = '{'; |
||||
this.ClosingBrace = '}'; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Create <see cref="NewFolding"/>s for the specified document. |
||||
/// </summary> |
||||
public override IEnumerable<NewFolding> CreateNewFoldings(TextDocument document, out int firstErrorOffset) |
||||
{ |
||||
firstErrorOffset = -1; |
||||
return CreateNewFoldings(document); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Create <see cref="NewFolding"/>s for the specified document. |
||||
/// </summary> |
||||
public IEnumerable<NewFolding> CreateNewFoldings(ITextSource document) |
||||
{ |
||||
List<NewFolding> newFoldings = new List<NewFolding>(); |
||||
|
||||
Stack<int> startOffsets = new Stack<int>(); |
||||
int lastNewLineOffset = 0; |
||||
char openingBrace = this.OpeningBrace; |
||||
char closingBrace = this.ClosingBrace; |
||||
for (int i = 0; i < document.TextLength; i++) { |
||||
char c = document.GetCharAt(i); |
||||
if (c == openingBrace) { |
||||
startOffsets.Push(i); |
||||
} else if (c == closingBrace && startOffsets.Count > 0) { |
||||
int startOffset = startOffsets.Pop(); |
||||
// don't fold if opening and closing brace are on the same line |
||||
if (startOffset < lastNewLineOffset) { |
||||
newFoldings.Add(new NewFolding(startOffset, i + 1)); |
||||
} |
||||
} else if (c == '\n' || c == '\r') { |
||||
lastNewLineOffset = i + 1; |
||||
} |
||||
} |
||||
newFoldings.Sort((a,b) => a.StartOffset.CompareTo(b.StartOffset)); |
||||
return newFoldings; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,60 @@
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2009 Daniel Grunwald |
||||
// |
||||
// 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.Windows; |
||||
using System.Windows.Media; |
||||
|
||||
using ICSharpCode.AvalonEdit.Document; |
||||
using ICSharpCode.AvalonEdit.Rendering; |
||||
|
||||
namespace $rootnamespace$.AvalonEdit.Sample |
||||
{ |
||||
/// <summary> |
||||
/// Finds the word 'AvalonEdit' and makes it bold and italic. |
||||
/// </summary> |
||||
public class ColorizeAvalonEdit : DocumentColorizingTransformer |
||||
{ |
||||
protected override void ColorizeLine(DocumentLine line) |
||||
{ |
||||
int lineStartOffset = line.Offset; |
||||
string text = CurrentContext.Document.GetText(line); |
||||
int start = 0; |
||||
int index; |
||||
while ((index = text.IndexOf("AvalonEdit", start)) >= 0) { |
||||
base.ChangeLinePart( |
||||
lineStartOffset + index, // startOffset |
||||
lineStartOffset + index + 10, // endOffset |
||||
(VisualLineElement element) => { |
||||
// This lambda gets called once for every VisualLineElement |
||||
// between the specified offsets. |
||||
Typeface tf = element.TextRunProperties.Typeface; |
||||
// Replace the typeface with a modified version of |
||||
// the same typeface |
||||
element.TextRunProperties.SetTypeface(new Typeface( |
||||
tf.FontFamily, |
||||
FontStyles.Italic, |
||||
FontWeights.Bold, |
||||
tf.Stretch |
||||
)); |
||||
}); |
||||
start = index + 1; // search for next occurrence |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0"?> |
||||
<SyntaxDefinition name="Custom Highlighting" xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"> |
||||
<Color name="Comment" foreground="Green" /> |
||||
<Color name="String" foreground="Blue" /> |
||||
|
||||
<!-- This is the main ruleset. --> |
||||
<RuleSet> |
||||
<Span color="Comment" begin="//" /> |
||||
<Span color="Comment" multiline="true" begin="/\*" end="\*/" /> |
||||
|
||||
<Span color="String"> |
||||
<Begin>"</Begin> |
||||
<End>"</End> |
||||
<RuleSet> |
||||
<!-- nested span for escape sequences --> |
||||
<Span begin="\\" end="." /> |
||||
</RuleSet> |
||||
</Span> |
||||
|
||||
<Keywords fontWeight="bold" foreground="Blue"> |
||||
<Word>if</Word> |
||||
<Word>else</Word> |
||||
<!-- ... --> |
||||
</Keywords> |
||||
|
||||
<Keywords fontWeight="bold" fontStyle="italic" foreground="Red"> |
||||
<Word>AvalonEdit</Word> |
||||
</Keywords> |
||||
|
||||
<!-- Digits --> |
||||
<Rule foreground="DarkBlue"> |
||||
\b0[xX][0-9a-fA-F]+ # hex number |
||||
| \b |
||||
( \d+(\.[0-9]+)? #number with optional floating point |
||||
| \.[0-9]+ #or just starting with floating point |
||||
) |
||||
([eE][+-]?[0-9]+)? # optional exponent |
||||
</Rule> |
||||
</RuleSet> |
||||
</SyntaxDefinition> |
@ -0,0 +1,110 @@
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2009 Daniel Grunwald |
||||
// |
||||
// 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.IO; |
||||
using System.Text.RegularExpressions; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Media; |
||||
using System.Windows.Media.Imaging; |
||||
|
||||
using ICSharpCode.AvalonEdit.Document; |
||||
using ICSharpCode.AvalonEdit.Rendering; |
||||
|
||||
namespace $rootnamespace$.AvalonEdit.Sample |
||||
{ |
||||
/// <summary> |
||||
/// This class can be used to embed images inside AvalonEdit like this: <img src="Images/Save.png"/> |
||||
/// </summary> |
||||
public class ImageElementGenerator : VisualLineElementGenerator |
||||
{ |
||||
readonly static Regex imageRegex = new Regex(@"<img src=""([\.\/\w\d]+)""/?>", |
||||
RegexOptions.IgnoreCase); |
||||
readonly string basePath; |
||||
|
||||
public ImageElementGenerator(string basePath) |
||||
{ |
||||
if (basePath == null) |
||||
throw new ArgumentNullException("basePath"); |
||||
this.basePath = basePath; |
||||
} |
||||
|
||||
Match FindMatch(int startOffset) |
||||
{ |
||||
// fetch the end offset of the VisualLine being generated |
||||
int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset; |
||||
TextDocument document = CurrentContext.Document; |
||||
string relevantText = document.GetText(startOffset, endOffset - startOffset); |
||||
return imageRegex.Match(relevantText); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Gets the first offset >= startOffset where the generator wants to construct |
||||
/// an element. |
||||
/// Return -1 to signal no interest. |
||||
/// </summary> |
||||
public override int GetFirstInterestedOffset(int startOffset) |
||||
{ |
||||
Match m = FindMatch(startOffset); |
||||
return m.Success ? (startOffset + m.Index) : -1; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Constructs an element at the specified offset. |
||||
/// May return null if no element should be constructed. |
||||
/// </summary> |
||||
public override VisualLineElement ConstructElement(int offset) |
||||
{ |
||||
Match m = FindMatch(offset); |
||||
// check whether there's a match exactly at offset |
||||
if (m.Success && m.Index == 0) { |
||||
BitmapImage bitmap = LoadBitmap(m.Groups[1].Value); |
||||
if (bitmap != null) { |
||||
Image image = new Image(); |
||||
image.Source = bitmap; |
||||
image.Width = bitmap.PixelWidth; |
||||
image.Height = bitmap.PixelHeight; |
||||
// Pass the length of the match to the 'documentLength' parameter |
||||
// of InlineObjectElement. |
||||
return new InlineObjectElement(m.Length, image); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
BitmapImage LoadBitmap(string fileName) |
||||
{ |
||||
// TODO: add some kind of cache to avoid reloading the image whenever the |
||||
// VisualLine is reconstructed |
||||
try { |
||||
string fullFileName = Path.Combine(basePath, fileName); |
||||
if (File.Exists(fullFileName)) { |
||||
BitmapImage bitmap = new BitmapImage(new Uri(fullFileName)); |
||||
bitmap.Freeze(); |
||||
return bitmap; |
||||
} |
||||
} catch (ArgumentException) { |
||||
// invalid filename syntax |
||||
} catch (IOException) { |
||||
// other IO error |
||||
} |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2009 Daniel Grunwald |
||||
// |
||||
// 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 ICSharpCode.AvalonEdit.CodeCompletion; |
||||
using ICSharpCode.AvalonEdit.Document; |
||||
using ICSharpCode.AvalonEdit.Editing; |
||||
|
||||
namespace $rootnamespace$.AvalonEdit.Sample |
||||
{ |
||||
/// <summary> |
||||
/// Implements AvalonEdit ICompletionData interface to provide the entries in the completion drop down. |
||||
/// </summary> |
||||
public class MyCompletionData : ICompletionData |
||||
{ |
||||
public MyCompletionData(string text) |
||||
{ |
||||
this.Text = text; |
||||
} |
||||
|
||||
public System.Windows.Media.ImageSource Image { |
||||
get { return null; } |
||||
} |
||||
|
||||
public string Text { get; private set; } |
||||
|
||||
// Use this property if you want to show a fancy UIElement in the drop down list. |
||||
public object Content { |
||||
get { return this.Text; } |
||||
} |
||||
|
||||
public object Description { |
||||
get { return "Description for " + this.Text; } |
||||
} |
||||
|
||||
public double Priority { get { return 0; } } |
||||
|
||||
public void Complete(TextArea textArea, ISegment completionSegment, EventArgs insertionRequestEventArgs) |
||||
{ |
||||
textArea.Document.Replace(completionSegment, this.Text); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,186 @@
@@ -0,0 +1,186 @@
|
||||
// Copyright (c) 2009 Daniel Grunwald |
||||
// |
||||
// 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.IO; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
using System.Windows.Input; |
||||
using System.Windows.Threading; |
||||
using System.Xml; |
||||
|
||||
using ICSharpCode.AvalonEdit.CodeCompletion; |
||||
using ICSharpCode.AvalonEdit.Folding; |
||||
using ICSharpCode.AvalonEdit.Highlighting; |
||||
using Microsoft.Win32; |
||||
|
||||
namespace $rootnamespace$.AvalonEdit.Sample |
||||
{ |
||||
/// <summary> |
||||
/// Interaction logic for Window1.xaml |
||||
/// </summary> |
||||
public partial class Window1 : Window |
||||
{ |
||||
public Window1() |
||||
{ |
||||
InitializeComponent(); |
||||
propertyGridComboBox.SelectedIndex = 2; |
||||
|
||||
//textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#"); |
||||
//textEditor.SyntaxHighlighting = customHighlighting; |
||||
// initial highlighting now set by XAML |
||||
|
||||
textEditor.TextArea.TextEntering += textEditor_TextArea_TextEntering; |
||||
textEditor.TextArea.TextEntered += textEditor_TextArea_TextEntered; |
||||
|
||||
DispatcherTimer foldingUpdateTimer = new DispatcherTimer(); |
||||
foldingUpdateTimer.Interval = TimeSpan.FromSeconds(2); |
||||
foldingUpdateTimer.Tick += foldingUpdateTimer_Tick; |
||||
foldingUpdateTimer.Start(); |
||||
} |
||||
|
||||
string currentFileName; |
||||
|
||||
void openFileClick(object sender, RoutedEventArgs e) |
||||
{ |
||||
OpenFileDialog dlg = new OpenFileDialog(); |
||||
dlg.CheckFileExists = true; |
||||
if (dlg.ShowDialog() ?? false) { |
||||
currentFileName = dlg.FileName; |
||||
textEditor.Load(currentFileName); |
||||
textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(currentFileName)); |
||||
} |
||||
} |
||||
|
||||
void saveFileClick(object sender, EventArgs e) |
||||
{ |
||||
if (currentFileName == null) { |
||||
SaveFileDialog dlg = new SaveFileDialog(); |
||||
dlg.DefaultExt = ".txt"; |
||||
if (dlg.ShowDialog() ?? false) { |
||||
currentFileName = dlg.FileName; |
||||
} else { |
||||
return; |
||||
} |
||||
} |
||||
textEditor.Save(currentFileName); |
||||
} |
||||
|
||||
void exitClick(object sender, EventArgs e) |
||||
{ |
||||
Application.Current.Shutdown(); |
||||
} |
||||
|
||||
void propertyGridComboBoxSelectionChanged(object sender, RoutedEventArgs e) |
||||
{ |
||||
if (propertyGrid == null) |
||||
return; |
||||
switch (propertyGridComboBox.SelectedIndex) { |
||||
case 0: |
||||
propertyGrid.SelectedObject = textEditor; |
||||
break; |
||||
case 1: |
||||
propertyGrid.SelectedObject = textEditor.TextArea; |
||||
break; |
||||
case 2: |
||||
propertyGrid.SelectedObject = textEditor.Options; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
CompletionWindow completionWindow; |
||||
|
||||
void textEditor_TextArea_TextEntered(object sender, TextCompositionEventArgs e) |
||||
{ |
||||
if (e.Text == ".") { |
||||
// open code completion after the user has pressed dot: |
||||
completionWindow = new CompletionWindow(textEditor.TextArea); |
||||
// provide AvalonEdit with the data: |
||||
IList<ICompletionData> data = completionWindow.CompletionList.CompletionData; |
||||
data.Add(new MyCompletionData("Item1")); |
||||
data.Add(new MyCompletionData("Item2")); |
||||
data.Add(new MyCompletionData("Item3")); |
||||
data.Add(new MyCompletionData("Another item")); |
||||
completionWindow.Show(); |
||||
completionWindow.Closed += delegate { |
||||
completionWindow = null; |
||||
}; |
||||
} |
||||
} |
||||
|
||||
void textEditor_TextArea_TextEntering(object sender, TextCompositionEventArgs e) |
||||
{ |
||||
if (e.Text.Length > 0 && completionWindow != null) { |
||||
if (!char.IsLetterOrDigit(e.Text[0])) { |
||||
// Whenever a non-letter is typed while the completion window is open, |
||||
// insert the currently selected element. |
||||
completionWindow.CompletionList.RequestInsertion(e); |
||||
} |
||||
} |
||||
// do not set e.Handled=true - we still want to insert the character that was typed |
||||
} |
||||
|
||||
#region Folding |
||||
FoldingManager foldingManager; |
||||
AbstractFoldingStrategy foldingStrategy; |
||||
|
||||
void HighlightingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) |
||||
{ |
||||
if (textEditor.SyntaxHighlighting == null) { |
||||
foldingStrategy = null; |
||||
} else { |
||||
switch (textEditor.SyntaxHighlighting.Name) { |
||||
case "XML": |
||||
foldingStrategy = new XmlFoldingStrategy(); |
||||
textEditor.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy(); |
||||
break; |
||||
case "C#": |
||||
case "C++": |
||||
case "PHP": |
||||
case "Java": |
||||
textEditor.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.CSharp.CSharpIndentationStrategy(textEditor.Options); |
||||
foldingStrategy = new BraceFoldingStrategy(); |
||||
break; |
||||
default: |
||||
textEditor.TextArea.IndentationStrategy = new ICSharpCode.AvalonEdit.Indentation.DefaultIndentationStrategy(); |
||||
foldingStrategy = null; |
||||
break; |
||||
} |
||||
} |
||||
if (foldingStrategy != null) { |
||||
if (foldingManager == null) |
||||
foldingManager = FoldingManager.Install(textEditor.TextArea); |
||||
foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document); |
||||
} else { |
||||
if (foldingManager != null) { |
||||
FoldingManager.Uninstall(foldingManager); |
||||
foldingManager = null; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void foldingUpdateTimer_Tick(object sender, EventArgs e) |
||||
{ |
||||
if (foldingStrategy != null) { |
||||
foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document); |
||||
} |
||||
} |
||||
#endregion |
||||
} |
||||
} |
@ -0,0 +1,88 @@
@@ -0,0 +1,88 @@
|
||||
<!-- |
||||
Copyright (c) 2009 Daniel Grunwald |
||||
|
||||
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. |
||||
--> |
||||
<Window x:Class="$rootnamespace$.AvalonEdit.Sample.Window1" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" |
||||
xmlns:forms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" |
||||
Title="AvalonEdit.Sample" Height="500" Width="700" |
||||
> |
||||
<DockPanel> |
||||
<Menu DockPanel.Dock="Top"> |
||||
<MenuItem Header="_File"> |
||||
<MenuItem Header="_Open..." Click="openFileClick"/> |
||||
<MenuItem Header="_Save" Click="saveFileClick"/> |
||||
<Separator/> |
||||
<MenuItem Header="E_xit" Click="exitClick"/> |
||||
</MenuItem> |
||||
<MenuItem Header="_Edit"> |
||||
<MenuItem Header="Cu_t" Command="Redo"/> |
||||
<MenuItem Header="_Copy" Command="Copy"/> |
||||
<MenuItem Header="_Paste" Command="Paste"/> |
||||
<MenuItem Header="_Delete" Command="Delete"/> |
||||
<Separator/> |
||||
<MenuItem Header="_Undo" Command="Undo"/> |
||||
<MenuItem Header="_Redo" Command="Redo"/> |
||||
</MenuItem> |
||||
<MenuItem Header="Fo_rmat"> |
||||
<MenuItem Header="_Word Wrap" IsCheckable="True" IsChecked="{Binding ElementName=textEditor,Path=WordWrap}"/> |
||||
<MenuItem Header="Show _Line Numbers" IsCheckable="True" IsChecked="{Binding ElementName=textEditor,Path=ShowLineNumbers}"/> |
||||
<MenuItem Header="Show _End of Line" IsCheckable="True" IsChecked="{Binding ElementName=textEditor,Path=Options.ShowEndOfLine}"/> |
||||
</MenuItem> |
||||
</Menu> |
||||
<ToolBar DockPanel.Dock="Top"> |
||||
<CheckBox IsChecked="{Binding ElementName=textEditor,Path=ShowLineNumbers}"> |
||||
<TextBlock Width="16" TextAlignment="Center">#</TextBlock> |
||||
</CheckBox> |
||||
<CheckBox IsChecked="{Binding ElementName=textEditor,Path=Options.ShowEndOfLine}"> |
||||
<TextBlock Width="16" TextAlignment="Center">¶</TextBlock> |
||||
</CheckBox> |
||||
<ComboBox Name="highlightingComboBox" |
||||
SelectedItem="{Binding SyntaxHighlighting, ElementName=textEditor}" |
||||
ItemsSource="{Binding Source={x:Static avalonEdit:HighlightingManager.Instance}, Path=HighlightingDefinitions}" |
||||
SelectionChanged="HighlightingComboBox_SelectionChanged"/> |
||||
</ToolBar> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="1*"/> |
||||
<ColumnDefinition Width="100"/> |
||||
</Grid.ColumnDefinitions> |
||||
<avalonEdit:TextEditor |
||||
Name="textEditor" |
||||
FontFamily="Consolas" |
||||
FontSize="10pt" |
||||
SyntaxHighlighting="C#" |
||||
>Welcome to AvalonEdit! |
||||
</avalonEdit:TextEditor> |
||||
<GridSplitter Grid.Column="1" Width="4" HorizontalAlignment="Left"/> |
||||
<DockPanel Grid.Column="1" Margin="4 0 0 0"> |
||||
<ComboBox Name="propertyGridComboBox" DockPanel.Dock="Top" |
||||
SelectedIndex="0" SelectionChanged="propertyGridComboBoxSelectionChanged"> |
||||
<ComboBoxItem>TextEditor</ComboBoxItem> |
||||
<ComboBoxItem>TextArea</ComboBoxItem> |
||||
<ComboBoxItem>Options</ComboBoxItem> |
||||
</ComboBox> |
||||
<WindowsFormsHost DockPanel.Dock="Right" Name="propertyGridHost"> |
||||
<forms:PropertyGrid x:Name="propertyGrid"/> |
||||
</WindowsFormsHost> |
||||
</DockPanel> |
||||
</Grid> |
||||
</DockPanel> |
||||
</Window> |
@ -0,0 +1,429 @@
@@ -0,0 +1,429 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
||||
<!------------------------------------------------------------> |
||||
<!-- INTRODUCTION |
||||
|
||||
The Code Project article submission template (HTML version) |
||||
|
||||
Using this template will help us post your article sooner. To use, just |
||||
follow the 3 easy steps below: |
||||
|
||||
1. Fill in the article description details |
||||
2. Add links to your images and downloads |
||||
3. Include the main article text |
||||
|
||||
That's all there is to it! All formatting will be done by our submission |
||||
scripts and style sheets. |
||||
|
||||
--> |
||||
<!------------------------------------------------------------> |
||||
<!-- IGNORE THIS SECTION --> |
||||
<html> |
||||
<head> |
||||
<title>AvalonEdit</title> |
||||
<Style> |
||||
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt } |
||||
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; } |
||||
H2 { font-size: 13pt; } |
||||
H3 { font-size: 12pt; } |
||||
H4 { font-size: 10pt; color: black; } |
||||
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono; WHITE-SPACE: pre; } |
||||
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; } |
||||
</style> |
||||
<link rel="stylesheet" type="text/css" href="http://www.codeproject.com/App_Themes/NetCommunity/CodeProject.css"> |
||||
</head> |
||||
<body bgcolor="#FFFFFF" color=#000000> |
||||
<div style="width:600px; margin-left: 24px;"> |
||||
<!------------------------------------------------------------> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
<!-- Fill in the details (CodeProject will reformat this section for you) --> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
<!-- Include download and sample image information. --> |
||||
|
||||
<ul class=download> |
||||
<li><a href="AvalonEdit/AvalonEdit_Binaries.zip">Download binaries - 206.5 KB</a></li> |
||||
<li><a href="AvalonEdit/AvalonEdit_Source.zip">Download source code - 391.3 KB</a></li> |
||||
<li><a href="AvalonEdit/AvalonEdit_CHM_Documentation.zip">Download .chm documentation file - 1.88 MB</a></li> |
||||
</ul> |
||||
<p>The latest version of AvalonEdit can be found as part of the <a href="http://www.icsharpcode.net/OpenSource/SD/">SharpDevelop</a> project. |
||||
For details on AvalonEdit, please see <a href="http://www.avalonedit.net/">www.avalonedit.net</a>.</p> |
||||
|
||||
<p><img src="AvalonEdit/screenshot.png" width="611" height="441" alt="Sample Image" /></p> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
|
||||
<!-- Add the article text. Please use simple formatting (<h2>, <p> etc) --> |
||||
|
||||
<h2>Introduction</h2> |
||||
|
||||
<p>ICSharpCode.AvalonEdit is the WPF-based text editor that I've written for SharpDevelop 4.0. It is meant as a replacement |
||||
for <a href="http://www.codeproject.com/KB/edit/TextEditorControl.aspx">ICSharpCode.TextEditor</a>, but should be: |
||||
<ul> |
||||
<li>Extensible</li> |
||||
<li>Easy to use</li> |
||||
<li>Better at handling large files</li> |
||||
</ul> |
||||
<p> |
||||
<b>Extensible</b> means that I wanted SharpDevelop AddIns to be able to add features to the text editor. |
||||
For example, an AddIn should be able to allow inserting images into comments – this way you could put |
||||
stuff like class diagrams right into the source code! |
||||
<p> |
||||
With, <b>Easy to use</b>, I'm referring to the programming API. It should just work. |
||||
For example, this means if you change the document text, |
||||
the editor should automatically redraw without having to call <code>Invalidate()</code>. |
||||
|
||||
And if you do something wrong, you should get a meaningful exception, not corrupted state and crash later at an unrelated location. |
||||
|
||||
<p> |
||||
<b>Better at handling large files</b> means that the editor should be able to handle large files (e.g. |
||||
the mscorlib XML documentation file, 7 MB, 74100 LOC), even when features like folding (code collapsing) are enabled. |
||||
|
||||
<h2>Using the Code</h2> |
||||
|
||||
<p>The main class of the editor is <code>ICSharpCode.AvalonEdit.TextEditor</code>. |
||||
You can use it just similar to a normal WPF <code>TextBox</code>: |
||||
<pre lang="xml"><avalonEdit:TextEditor |
||||
xmlns:avalonEdit="http://icsharpcode.net/sharpdevelop/avalonedit" |
||||
Name="textEditor" |
||||
FontFamily="Consolas" |
||||
FontSize="10pt"/></pre> |
||||
|
||||
<p>To enable syntax highlighting, use: |
||||
|
||||
<pre lang="cs">textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");</pre> |
||||
AvalonEdit has syntax highlighting definitions built in for: |
||||
ASP.NET, Boo, Coco/R grammars, C++, C#, HTML, Java, JavaScript, Patch files, PHP, TeX, VB, XML |
||||
|
||||
<p>If you need more of AvalonEdit than a simple text box with syntax highlighting, you will first have to learn more about the architecture of AvalonEdit. |
||||
|
||||
<!------------------------------------------------------------> |
||||
<h2>Architecture of AvalonEdit</h2> |
||||
<img src="AvalonEdit/dependencies.png" width="583" height="439" alt="Namespace Dependency Graph"/> |
||||
<p> |
||||
As you can see in this dependency graph, AvalonEdit consists of a few sub-namespaces that have cleanly separated jobs. |
||||
Most of the namespaces have a kind of 'main' class. |
||||
<ul> |
||||
<li>ICSharpCode.AvalonEdit.Utils: Various utility classes</li> |
||||
<li>ICSharpCode.AvalonEdit.Document: <code>TextDocument</code> — text model</li> |
||||
<li>ICSharpCode.AvalonEdit.Rendering: <code>TextView</code> — extensible view onto the document</li> |
||||
<li>ICSharpCode.AvalonEdit.Editing: <code>TextArea</code> — controls text editing (e.g. caret, selection, handles user input)</li> |
||||
<li>ICSharpCode.AvalonEdit.Folding: <code>FoldingManager</code> — enables code collapsing</li> |
||||
<li>ICSharpCode.AvalonEdit.Highlighting: <code>HighlightingManager</code> — highlighting engine</li> |
||||
<li>ICSharpCode.AvalonEdit.Highlighting.Xshd: <code>HighlightingLoader</code> — XML syntax highlighting definition support (.xshd files)</li> |
||||
<li>ICSharpCode.AvalonEdit.CodeCompletion: <code>CompletionWindow</code> — shows a drop-down list for code completion</li> |
||||
<li>ICSharpCode.AvalonEdit: <code>TextEditor</code> — the main control that brings it all together</li> |
||||
</ul> |
||||
|
||||
<p> |
||||
Here is the visual tree of the <code>TextEditor</code> control:<br> |
||||
<img src="AvalonEdit/snoop.png" width="272" height="351" alt="Visual Tree"/> |
||||
<p> |
||||
It's important to understand that AvalonEdit is a composite control with the three layers: <code>TextEditor</code> (main control), <code>TextArea</code> (editing), <code>TextView</code> (rendering). |
||||
While the main control provides some convenience methods for common tasks, for most advanced features you have to work directly with the inner controls. You can access them using <code>textEditor.TextArea</code> |
||||
or <code>textEditor.TextArea.TextView</code>. |
||||
|
||||
<!------------------------------------------------------------> |
||||
<h2>The Text Model: Document</h2> |
||||
|
||||
<p>The main class of the model is <code>ICSharpCode.AvalonEdit.Document.TextDocument</code>. |
||||
Basically, the document is a <code>StringBuilder</code> with events. |
||||
However, the <code>Document</code> namespace also contains several features that are useful to applications working with the text editor. |
||||
|
||||
<p>In the text editor, all three controls (<code>TextEditor</code>, <code>TextArea</code>, <code>TextView</code>) have a <code>Document</code> property pointing to the <code>TextDocument</code> instance. |
||||
You can change the <code>Document</code> property to bind the editor to another document. It is possible to bind two editor instances to the same document; you can use this feature to create a split view. |
||||
|
||||
<p><i>Simplified</i> definition of <code>TextDocument</code>: |
||||
<pre lang="cs">public sealed class TextDocument : ITextSource |
||||
{ |
||||
public event EventHandler<DocumentChangeEventArgs> Changing; |
||||
public event EventHandler<DocumentChangeEventArgs> Changed; |
||||
public event EventHandler TextChanged; |
||||
|
||||
public IList<DocumentLine> Lines { get; } |
||||
public DocumentLine GetLineByNumber(int number); |
||||
public DocumentLine GetLineByOffset(int offset); |
||||
public TextLocation GetLocation(int offset); |
||||
public int GetOffset(int line, int column); |
||||
|
||||
public char GetCharAt(int offset); |
||||
public string GetText(int offset, int length); |
||||
|
||||
public void Insert(int offset, string text); |
||||
public void Remove(int offset, int length); |
||||
public void Replace(int offset, int length, string text); |
||||
|
||||
public string Text { get; set; } |
||||
public int LineCount { get; } |
||||
public int TextLength { get; } |
||||
public UndoStack UndoStack { get; } |
||||
}</pre> |
||||
|
||||
In AvalonEdit, an index into the document is called an <b>offset</b>. |
||||
|
||||
<p>Offsets usually represent the position between two characters. |
||||
The first offset at the start of the document is 0; the offset after the first <code>char</code> in the document is 1. |
||||
The last valid offset is <code>document.TextLength</code>, representing the end of the document. |
||||
This is exactly the same as the 'index' parameter used by methods in the .NET <code>String</code> or <code>StringBuilder</code> classes. |
||||
<p> |
||||
Offsets are easy to use, but sometimes you need Line / Column pairs instead. |
||||
AvalonEdit defines a <code>struct</code> called <code>TextLocation</code> for those. |
||||
|
||||
<p>The document provides the methods <code>GetLocation</code> and <code>GetOffset</code> to convert between offsets and <code>TextLocation</code>s. |
||||
Those are convenience methods built on top of the <code>DocumentLine</code> class. |
||||
|
||||
<p>The <code>TextDocument.Lines</code> collection contains one <code>DocumentLine</code> instance for every line in the document. |
||||
This collection is read-only to user code and is automatically updated to reflect the current document content. |
||||
|
||||
<!------------------------------------------------------------> |
||||
<h2>Rendering: TextView</h2> |
||||
|
||||
In the whole 'Document' section, there was no mention of extensibility. |
||||
The text rendering infrastructure now has to compensate for that by being completely extensible. |
||||
|
||||
<p>The <code>ICSharpCode.AvalonEdit.Rendering.TextView</code> class is the heart of AvalonEdit. |
||||
It takes care of getting the document onto the screen. |
||||
|
||||
<p>To do this in an extensible way, the <code>TextView</code> uses its own kind of model: the <code>VisualLine</code>. |
||||
Visual lines are created only for the visible part of the document. |
||||
<p>The rendering process looks like this:<br> |
||||
<img src="AvalonEdit/renderingPipeline.png" width="443" height="570" alt="rendering pipeline"/><br> |
||||
The last step in the pipeline is the conversion to one or more <code>System.Windows.Media.TextFormatting.TextLine</code> instances. WPF then takes care of the actual text rendering. |
||||
<p> |
||||
The "element generators", "line transformers" and "background renderers" are the extension points; it is possible to add custom implementations of |
||||
them to the <code>TextView</code> to implement additional features in the editor. |
||||
<!-- |
||||
<p> |
||||
The extensibility features of the rendering namespace are discussed in detail in the article "AvalonEdit Rendering". (to be published soon) |
||||
--> |
||||
|
||||
<h2>Editing: TextArea</h2> |
||||
|
||||
The <code>TextArea</code> class is handling user input and executing the appropriate actions. |
||||
Both the caret and the selection are controlled by the <code>TextArea</code>. |
||||
<p> |
||||
You can customize the text area by modifying the <code>TextArea.DefaultInputHandler</code> by adding new or replacing existing |
||||
WPF input bindings in it. You can also set <code>TextArea.ActiveInputHandler</code> to something different than the default |
||||
to switch the text area into another mode. You could use this to implement an "incremental search" feature, or even a VI emulator. |
||||
<p> |
||||
The text area has the <code>LeftMargins</code> property – use it to add controls to the left of the text view that look like |
||||
they're inside the scroll viewer, but don't actually scroll. The <code>AbstractMargin</code> base class contains some useful code |
||||
to detect when the margin is attached/detaching from a text view; or when the active document changes. However, you're not forced to use it; |
||||
any <code>UIElement</code> can be used as margin. |
||||
|
||||
<h2>Folding</h2> |
||||
Folding (code collapsing) is implemented as an extension to the editor. |
||||
It could have been implemented in a separate assembly without having to modify the AvalonEdit code. |
||||
A <code>VisualLineElementGenerator</code> takes care of the collapsed sections in the text document; and a custom margin draws the plus and minus |
||||
buttons. |
||||
<p> |
||||
You could use the relevant classes separately; but, to make it a bit easier to use, the static <code>FoldingManager.Install</code> |
||||
method will create and register the necessary parts automatically. |
||||
<p> |
||||
All that's left for you is to regularly call <code>FoldingManager.UpdateFoldings</code> with the list of foldings you want to provide. |
||||
You could calculate that list yourself, or you could use a built-in folding strategy to do it for you. |
||||
<p> |
||||
Here is the full code required to enable folding: |
||||
<pre lang="cs">foldingManager = FoldingManager.Install(textEditor.TextArea); |
||||
foldingStrategy = new XmlFoldingStrategy(); |
||||
foldingStrategy.UpdateFoldings(foldingManager, textEditor.Document);</pre> |
||||
If you want the folding markers to update when the text is changed, you have to repeat the <code>foldingStrategy.UpdateFoldings</code> call regularly. |
||||
<p> |
||||
Currently, only the <code>XmlFoldingStrategy</code> is built into AvalonEdit. |
||||
The sample application to this article also contains the <code>BraceFoldingStrategy</code> that folds using { and }. |
||||
However, it is a very simple implementation and does not handle { and } inside strings or comments correctly. |
||||
|
||||
<h2>Syntax Highlighting</h2> |
||||
The highlighting engine in AvalonEdit is implemented in the class <code>DocumentHighlighter</code>. |
||||
Highlighting is the process of taking a <code>DocumentLine</code> and constructing a <code>HighlightedLine</code> instance for it |
||||
by assigning colors to different sections of the line. |
||||
<p> |
||||
The <code>HighlightingColorizer</code> class is the only link between highlighting and rendering. It uses a <code>DocumentHighlighter</code> |
||||
to implement a line transformer that applies the highlighting to the visual lines in the rendering process. |
||||
<p> |
||||
Except for this single call, syntax highlighting is independent from the rendering namespace. |
||||
To help with other potential uses of the highlighting engine, the <code>HighlightedLine</code> class has the method |
||||
<code>ToHtml</code> to produces syntax highlighted HTML source code. |
||||
<p> |
||||
The rules for the highlighting are defined using an "extensible syntax highlighting definition" (.xshd) file. |
||||
Here is a complete highlighting definition for a sub-set of C#: |
||||
<pre lang="xml"><SyntaxDefinition name="C#" |
||||
xmlns="http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"> |
||||
<Color name="Comment" foreground="Green" /> |
||||
<Color name="String" foreground="Blue" /> |
||||
|
||||
<!-- This is the main ruleset. --> |
||||
<RuleSet> |
||||
<Span color="Comment" begin="//" /> |
||||
<Span color="Comment" multiline="true" begin="/\*" end="\*/" /> |
||||
|
||||
<Span color="String"> |
||||
<Begin>"</Begin> |
||||
<End>"</End> |
||||
<RuleSet> |
||||
<!-- nested span for escape sequences --> |
||||
<Span begin="\\" end="." /> |
||||
</RuleSet> |
||||
</Span> |
||||
|
||||
<Keywords fontWeight="bold" foreground="Blue"> |
||||
<Word>if</Word> |
||||
<Word>else</Word> |
||||
<!-- ... --> |
||||
</Keywords> |
||||
|
||||
<!-- Digits --> |
||||
<Rule foreground="DarkBlue"> |
||||
\b0[xX][0-9a-fA-F]+ # hex number |
||||
| \b |
||||
( \d+(\.[0-9]+)? #number with optional floating point |
||||
| \.[0-9]+ #or just starting with floating point |
||||
) |
||||
([eE][+-]?[0-9]+)? # optional exponent |
||||
</Rule> |
||||
</RuleSet> |
||||
</SyntaxDefinition></pre> |
||||
The highlighting engine works with "spans" and "rules" that each have a color assigned to them. In the XSHD format, colors can be both |
||||
referenced (<code>color="Comment"</code>) or directly specified (<code>fontWeight="bold" foreground="Blue"</code>). |
||||
<p> |
||||
Spans consist of two regular expressions (begin+end), while rules are simply a single RegEx with a color. The <code><Keywords></code> element is just a nice |
||||
syntax to define a highlighting rule that matches a set of words; internally a single RegEx will be used for the whole keyword list. |
||||
<p> |
||||
The highlighting engine works by first analyzing the spans: whenever a begin RegEx matches some text, that span is pushed onto a stack. |
||||
Whenever the end RegEx of the current span matches some text, the span is popped from the stack. |
||||
<p> |
||||
Each span has a nested rule set associated with it, which is empty by default. |
||||
This is why keywords won't be highlighted inside comments: the span's empty ruleset is active there, so the keyword rule is not applied. |
||||
<p> |
||||
This feature is also used in the string span: the nested span will match when a backslash is encountered, and the character following the backslash |
||||
will be consumed by the end RegEx of the nested span (<code>.</code> matches any character). |
||||
This ensures that <code>\"</code> does not denote the end of the string span; but <code>\\"</code> still does. |
||||
<p> |
||||
What's great about the highlighting engine is that it highlights only on-demand, works incrementally, |
||||
and yet usually requires only a few KB of memory even for large code files. |
||||
|
||||
<p><i>On-demand</i> means that when a document is opened, only the lines initially visible will be highlighted. When the user scrolls down, highlighting will |
||||
continue from the point where it stopped the last time. |
||||
If the user scrolls quickly, so that the first visible line is far below the last highlighted line, then the highlighting engine still has to process all the |
||||
lines in between – there might be comment starts in them. However, it will only scan that region for changes in the span stack; highlighting rules will not |
||||
be tested. |
||||
<p>The stack of active spans is stored at the beginning of every line. If the user scrolls back up, the lines getting into view can be highlighted immediately |
||||
because the necessary context (the span stack) is still available. |
||||
<p><i>Incrementally</i> means that even if the document is changed, the stored span stacks will be reused as far as possible. If the user types <code>/*</code>, that would |
||||
theoretically cause the whole remainder of the file to become highlighted in the comment color. However, because the engine works on-demand, it will only update the |
||||
span stacks within the currently visible region and keep a notice 'the highlighting state is not consistent between line X and line X+1', where X is the last line |
||||
in the visible region. Now, if the user would scroll down, the highlighting state would be updated and the 'not consistent' notice would be moved down. |
||||
But usually, the user will continue typing and type <code>*/</code> only a few lines later. Now the highlighting state in the visible region will revert to the |
||||
normal 'only the main ruleset is on the stack of active spans'. When the user now scrolls down below the line with the 'not consistent' marker; |
||||
the engine will notice that the old stack and the new stack are identical; and will remove the 'not consistent' marker. This allows reusing the stored span stacks |
||||
cached from before the user typed <code>/*</code>. |
||||
|
||||
<p>While the stack of active spans might change frequently inside the lines, it rarely changes from the beginning of one line to the beginning of the next line. |
||||
With most languages, such changes happen only at the start and end of multiline comments. The highlighting engine exploits this property by storing |
||||
the list of span stacks in a special data structure (<code>ICSharpCode.AvalonEdit.Utils.CompressingTreeList</code>). |
||||
The memory usage of the highlighting engine is linear to the number of span stack changes; not to the total number of lines. |
||||
This allows the highlighting engine to store the span stacks for big code files using only a tiny amount of memory, |
||||
especially in languages like C# where sequences of <code>//</code> or <code>///</code> are more popular than <code>/* */</code> comments. |
||||
|
||||
<h2>Code Completion</h2> |
||||
<p>AvalonEdit comes with a code completion drop down window. |
||||
You only have to handle the text entering events to determine when you want to show the window; all the UI is already done for you. |
||||
<p> |
||||
Here's how you can use it: |
||||
<pre lang="cs"> // in the constructor: |
||||
textEditor.TextArea.TextEntering += textEditor_TextArea_TextEntering; |
||||
textEditor.TextArea.TextEntered += textEditor_TextArea_TextEntered; |
||||
} |
||||
|
||||
CompletionWindow completionWindow; |
||||
|
||||
void textEditor_TextArea_TextEntered(object sender, TextCompositionEventArgs e) |
||||
{ |
||||
if (e.Text == ".") { |
||||
// Open code completion after the user has pressed dot: |
||||
completionWindow = new CompletionWindow(textEditor.TextArea); |
||||
IList<ICompletionData> data = completionWindow.CompletionList.CompletionData; |
||||
data.Add(new MyCompletionData("Item1")); |
||||
data.Add(new MyCompletionData("Item2")); |
||||
data.Add(new MyCompletionData("Item3")); |
||||
completionWindow.Show(); |
||||
completionWindow.Closed += delegate { |
||||
completionWindow = null; |
||||
}; |
||||
} |
||||
} |
||||
|
||||
void textEditor_TextArea_TextEntering(object sender, TextCompositionEventArgs e) |
||||
{ |
||||
if (e.Text.Length > 0 && completionWindow != null) { |
||||
if (!char.IsLetterOrDigit(e.Text[0])) { |
||||
// Whenever a non-letter is typed while the completion window is open, |
||||
// insert the currently selected element. |
||||
completionWindow.CompletionList.RequestInsertion(e); |
||||
} |
||||
} |
||||
// Do not set e.Handled=true. |
||||
// We still want to insert the character that was typed. |
||||
}</pre> |
||||
This code will open the code completion window whenever '.' is pressed. |
||||
By default, the <code>CompletionWindow</code> only handles key presses like Tab and Enter to insert the currently selected item. To also make |
||||
it complete when keys like '.' or ';' are pressed, we attach another handler to the <code>TextEntering</code> event and tell the |
||||
completion window to insert the selected item. |
||||
<p> |
||||
The <code>CompletionWindow</code> will actually never have focus - instead, it hijacks the WPF keyboard input events |
||||
on the text area and passes them through its <code>ListBox</code>. |
||||
This allows selecting entries in the completion list using the keyboard and normal typing in the editor at the same time. |
||||
<p>For the sake of completeness, here is the implementation of the <code>MyCompletionData</code> class used in the code above: |
||||
<pre lang="cs">/// Implements AvalonEdit ICompletionData interface to provide the entries in the |
||||
/// completion drop down. |
||||
public class MyCompletionData : ICompletionData |
||||
{ |
||||
public MyCompletionData(string text) |
||||
{ |
||||
this.Text = text; |
||||
} |
||||
|
||||
public System.Windows.Media.ImageSource Image { |
||||
get { return null; } |
||||
} |
||||
|
||||
public string Text { get; private set; } |
||||
|
||||
// Use this property if you want to show a fancy UIElement in the list. |
||||
public object Content { |
||||
get { return this.Text; } |
||||
} |
||||
|
||||
public object Description { |
||||
get { return "Description for " + this.Text; } |
||||
} |
||||
|
||||
public void Complete(TextArea textArea, ISegment completionSegment, |
||||
EventArgs insertionRequestEventArgs) |
||||
{ |
||||
textArea.Document.Replace(completionSegment, this.Text); |
||||
} |
||||
}</pre> |
||||
Both the content and the description shown may be any content acceptable in WPF, including custom UIElements. |
||||
You may also implement custom logic in the <code>Complete</code> method if you want to do more than simply inserting the text. |
||||
The <code>insertionRequestEventArgs</code> can help decide which kind of insertion the user wants - depending on how the insertion |
||||
was triggered, it is an instance of <code>TextCompositionEventArgs</code>, <code>KeyEventArgs</code> or <code>MouseEventArgs</code>. |
||||
|
||||
<h2>History</h2> |
||||
|
||||
<ul> |
||||
<li>August 13, 2008: Work on AvalonEdit started</li> |
||||
<li>November 7, 2008: First version of AvalonEdit added to SharpDevelop 4.0 trunk</li> |
||||
<li>June 14, 2009: The SharpDevelop team switches to SharpDevelop 4 as their IDE for working on SharpDevelop; AvalonEdit starts to get used for real work</li> |
||||
<li>October 4, 2009: This article first published on The Code Project</li> |
||||
</ul> |
||||
|
||||
<p><b>Note: although my sample code is provided under the MIT license, ICSharpCode.AvalonEdit itself is provided under the terms of the GNU LGPL.</b> |
||||
|
||||
<!------------------------------- That's it! ---------------------------> |
||||
</div></body> |
||||
|
||||
</html> |
@ -0,0 +1,244 @@
@@ -0,0 +1,244 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
||||
<!------------------------------------------------------------> |
||||
<!-- INTRODUCTION |
||||
|
||||
The Code Project article submission template (HTML version) |
||||
|
||||
Using this template will help us post your article sooner. To use, just |
||||
follow the 3 easy steps below: |
||||
|
||||
1. Fill in the article description details |
||||
2. Add links to your images and downloads |
||||
3. Include the main article text |
||||
|
||||
That's all there is to it! All formatting will be done by our submission |
||||
scripts and style sheets. |
||||
|
||||
--> |
||||
<!------------------------------------------------------------> |
||||
<!-- IGNORE THIS SECTION --> |
||||
<html> |
||||
<head> |
||||
<title>Document</title> |
||||
<Style> |
||||
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt } |
||||
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; } |
||||
H2 { font-size: 13pt; } |
||||
H3 { font-size: 12pt; } |
||||
H4 { font-size: 10pt; color: black; } |
||||
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono; WHITE-SPACE: pre; } |
||||
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; } |
||||
</style> |
||||
<link rel="stylesheet" type="text/css" href="http://www.codeproject.com/App_Themes/NetCommunity/CodeProject.css"> |
||||
</head> |
||||
<body bgcolor="#FFFFFF" color=#000000> |
||||
<div style="width:600px; margin-left: 24px;"> |
||||
<!------------------------------------------------------------> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
<!-- Fill in the details (CodeProject will reformat this section for you) --> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
<!-- Include download and sample image information. --> |
||||
|
||||
For the sample application and source code download, please see the main article: |
||||
<a href="http://www.codeproject.com/KB/edit/AvalonEdit.aspx">Using AvalonEdit (WPF Text Editor)</a> |
||||
|
||||
<p><img src="Article.gif" alt="Sample Image - maximum width is 600 pixels" width=400 height=200></p> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
|
||||
<!-- Add the article text. Please use simple formatting (<h2>, <p> etc) --> |
||||
|
||||
<h2>Introduction</h2> |
||||
|
||||
|
||||
|
||||
<h2>Using the Code</h2> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
<h2>Document (The Text Model)</h2> |
||||
|
||||
<p>So, what is the model of a text editor that has support for complex features like syntax highlighting and folding?<br> |
||||
Would you expect to be able to access collapsed text using the document model, given that the text is folded away?<br> |
||||
Is the syntax highlighting part of the model? |
||||
|
||||
<p>In my quest for a good representation of the model, I decided on a radical strategy: |
||||
<b>if it's not a <code>char</code>, it's not in the model</b>! |
||||
|
||||
<p>The main class of the model is <code>ICSharpCode.AvalonEdit.Document.TextDocument</code>. |
||||
Basically, the document is a <code>StringBuilder</code> with events. |
||||
However, the <code>Document</code> namespace also contains several features that are useful to applications working with the text editor. |
||||
|
||||
<p>In the text editor, all three controls (<code>TextEditor</code>, <code>TextArea</code>, <code>TextView</code>) have a <code>Document</code> property pointing to the <code>TextDocument</code> instance. |
||||
You can change the <code>Document</code> property to bind the editor to another document; but please only do so on the outermost control (usually <code>TextEditor</code>), it will inform its child controls about that change. |
||||
Changing the document only on a child control would leave the outer controls confused. |
||||
<p> |
||||
It is possible to bind two editor instances to the same document; you can use this feature to create a split view. |
||||
|
||||
<p><i>Simplified</i> definition of <code>TextDocument</code>: |
||||
<pre lang="cs">public sealed class TextDocument : ITextSource |
||||
{ |
||||
public event EventHandler UpdateStarted; |
||||
public event EventHandler<DocumentChangeEventArgs> Changing; |
||||
public event EventHandler<DocumentChangeEventArgs> Changed; |
||||
public event EventHandler TextChanged; |
||||
public event EventHandler UpdateFinished; |
||||
|
||||
public TextAnchor CreateAnchor(int offset); |
||||
public ITextSource CreateSnapshot(); |
||||
|
||||
public IList<DocumentLine> Lines { get; } |
||||
public DocumentLine GetLineByNumber(int number); |
||||
public DocumentLine GetLineByOffset(int offset); |
||||
public TextLocation GetLocation(int offset); |
||||
public int GetOffset(int line, int column); |
||||
|
||||
public char GetCharAt(int offset); |
||||
public string GetText(int offset, int length); |
||||
|
||||
public void BeginUpdate(); |
||||
public bool IsInUpdate { get; } |
||||
public void EndUpdate(); |
||||
|
||||
public void Insert(int offset, string text); |
||||
public void Remove(int offset, int length); |
||||
public void Replace(int offset, int length, string text); |
||||
|
||||
public string Text { get; set; } |
||||
public int LineCount { get; } |
||||
public int TextLength { get; } |
||||
public UndoStack UndoStack { get; } |
||||
}</pre> |
||||
|
||||
<h3>Offsets</h3> |
||||
In AvalonEdit, an index into the document is called an <b>offset</b>. |
||||
|
||||
<p>Offsets usually represent the position between two characters. |
||||
The first offset at the start of the document is 0; the offset after the first <code>char</code> in the document is 1. |
||||
The last valid offset is <code>document.TextLength</code>, representing the end of the document. |
||||
|
||||
<p>This is exactly the same as the 'index' parameter used by methods in the .NET <code>String</code> or <code>StringBuilder</code> classes. |
||||
Offsets are used because they are dead simple. To all text between offset 10 and offset 30, |
||||
simply call <code>document.GetText(10, 20)</code> – just like <code>String.Substring</code>, AvalonEdit usually uses <code>Offset / Length</code> pairs to refer to text segments. |
||||
|
||||
<p>To easily pass such segments around, AvalonEdit defines the <code>ISegment</code> interface: |
||||
<pre lang="cs">public interface ISegment |
||||
{ |
||||
int Offset { get; } |
||||
int Length { get; } // must be non-negative |
||||
int EndOffset { get; } // must return Offset+Length |
||||
}</pre> |
||||
All <code>TextDocument</code> methods taking Offset/Length parameters also have an overload taking an <code>ISegment</code> instance – I have just removed those from the code listing above to make it easier to read. |
||||
|
||||
<h3>Lines</h3> |
||||
Offsets are easy to use, but sometimes you need Line / Column pairs instead. |
||||
AvalonEdit defines a <code>struct</code> called <code>TextLocation</code> for those. |
||||
|
||||
<p>The document provides the methods <code>GetLocation</code> and <code>GetOffset</code> to convert between offsets and <code>TextLocation</code>s. |
||||
Those are convenience methods built on top of the <code>DocumentLine</code> class. |
||||
|
||||
<p>The <code>TextDocument.Lines</code> collection contains one <code>DocumentLine</code> instance for every line in the document. |
||||
This collection is read-only to user code and is automatically updated to always<sup><small>*</small></sup> reflect the current document content. |
||||
|
||||
<p>Internally, the <code>DocumentLine</code> instances are arranged in a binary tree that allows for both efficient updates and lookup. |
||||
Converting between offset and line number is possible in O(lg N) time, and the data structure also updates all offsets in O(lg N) whenever text is inserted/removed. |
||||
|
||||
|
||||
<p><small>* tiny exception: it is possible to see the line collection in an inconsistent state inside <code>ILineTracker</code> callbacks. Don't use <code>ILineTracker</code> |
||||
unless you know what you are doing!</small> |
||||
|
||||
<h3>Change Events</h3> |
||||
|
||||
Here is the order in which events are raised during a document update: |
||||
|
||||
<p><b>BeginUpdate()</b> |
||||
<ul><li><code>UpdateStarted</code> event is raised</li></ul> |
||||
|
||||
<p><b>Insert() / Remove() / Replace()</b> |
||||
<ul> |
||||
<li><code>Changing</code> event is raised</li> |
||||
<li>The document is changed</li> |
||||
<li><code>TextAnchor.Deleted</code> events are raised if anchors were in the deleted text portion</li> |
||||
<li><code>Changed</code> event is raised</li> |
||||
</ul> |
||||
|
||||
<p><b>EndUpdate()</b> |
||||
<ul><li><code>TextChanged</code> event is raised</li> |
||||
<li><code>TextLengthChanged</code> event is raised</li> |
||||
<li><code>LineCountChanged</code> event is raised</li> |
||||
<li><code>UpdateFinished</code> event is raised</li></ul> |
||||
|
||||
<p>If the insert/remove/replace methods are called without a call to <code>BeginUpdate()</code>, they will call |
||||
<code>BeginUpdate()</code> and <code>EndUpdate()</code> to ensure no change happens outside of <code>UpdateStarted</code>/<code>UpdateFinished</code>. |
||||
|
||||
<p>There can be multiple document changes between the <code>BeginUpdate()</code> and <code>EndUpdate()</code> calls. |
||||
In this case, the events associated with <code>EndUpdate</code> will be raised only once after the whole document update is done. |
||||
|
||||
<p>The <code>UndoStack</code> listens to the <code>UpdateStarted</code> and <code>UpdateFinished</code> events to group |
||||
all changes into a single undo step. |
||||
|
||||
<h3>TextAnchor</h3> |
||||
If you are working with the text editor, you will likely run into the problem that you need to store an offset, but want it to adjust |
||||
automatically whenever text is inserted prior to that offset. |
||||
|
||||
<p>Sure, you could listen to the <code>TextDocument.Changed</code> event and call <code>GetNewOffset</code> on the <code>DocumentChangeEventArgs</code> to translate |
||||
the offset, but that gets tedious; especially when your object is short-lived and you have to deal with deregistering the event handler at the correct point of time.<br> |
||||
|
||||
<p>A much simpler solution is to use the <code>TextAnchor</code> class. Usage: |
||||
<pre lang="cs">TextAnchor anchor = document.CreateAnchor(offset); |
||||
ChangeMyDocument(); |
||||
int newOffset = anchor.Offset;</pre> |
||||
|
||||
<p>The document will automatically update all text anchors; and because it uses weak references to do so, the GC can simply collect the anchor object when you don't need it anymore. |
||||
|
||||
<p>Moreover, the document is able to efficiently update a large number of anchors without having to look at each anchor object individually. Updating the offsets of all anchors |
||||
usually only takes time logarithmic to the number of anchors. Retrieving the <code>TextAnchor.Offset</code> property also runs in O(lg N). |
||||
|
||||
<p>When a piece of text containing an anchor is removed; that anchor will be deleted. First, the <code>TextAnchor.IsDeleted</code> property is set to true on all deleted anchors, then the |
||||
<code>TextAnchor.Deleted</code> events are raised. You cannot retrieve the offset from an anchor that has been deleted. |
||||
|
||||
<p>This deletion behavior might be useful when using anchors for building a bookmark feature, but in other cases you want to still be able to use the anchor. For those cases, set <code>TextAnchor.SurviveDeletion = true</code>. |
||||
|
||||
<p>Note that anchor movement is ambiguous if text is inserted exactly at the anchor's location. Does the anchor stay before the inserted text, or does it move after it? |
||||
The property <code>TextAnchor.MovementType</code> will be used to determine which of these two options the anchor will choose. The default value is <code>AnchorMovementType.BeforeInsertion</code>. |
||||
|
||||
<p>If you want to track a segment, you can use the <code>AnchorSegment</code> class which implements <code>ISegment</code> using two text anchors. |
||||
|
||||
<h3>TextSegmentCollection</h3> |
||||
<p>Sometimes it is useful to store a list of segments and be able to efficiently find all segments overlapping with some other segment.<br> |
||||
Example: you might want to store a large number of compiler warnings and render squiggly underlines only for those that are in the visible region of the document. |
||||
|
||||
<p>The <code>TextSegmentCollection</code> serves this purpose. Connected to a document, it will automatically update the offsets of all <code>TextSegment</code> instances inside the collection; |
||||
but it also has the useful methods <code>FindOverlappingSegments</code> and <code>FindFirstSegmentWithStartAfter</code>. |
||||
The underlying data structure is a hybrid between the one used for text anchors and an <a href="http://en.wikipedia.org/wiki/Interval_tree#Augmented_tree">interval tree</a>, so it is able to do both jobs quite fast. |
||||
|
||||
<h3>Thread Safety</h3> |
||||
<p>The <code>TextDocument</code> class is not thread-safe. It expects to have a single owner thread and will throw an <code>InvalidOperationException</code> when accessed from another thread. |
||||
|
||||
<p>However, there is a single method that is thread-safe: <code>CreateSnapshot()</code><br> |
||||
It returns an immutable snapshot of the document, and may be safely called even when the owner thread is concurrently modifying the document. |
||||
This is very useful for features like a background parser that is running on its own thread. |
||||
The overload <code>CreateSnapshot(out ChangeTrackingCheckpoint)</code> also returns a <code>ChangeTrackingCheckpoint</code> for the document snapshot. |
||||
Once you have two checkpoints, you can call <code>GetChangesTo</code> to retrieve the complete list of document changes that happened between those versions of the document. |
||||
|
||||
|
||||
<h2>Points of Interest</h2> |
||||
|
||||
<p>Did you learn anything interesting/fun/annoying while writing the code? Did you |
||||
do anything particularly clever or wild or zany? |
||||
|
||||
<h2>History</h2> |
||||
|
||||
<p>Keep a running update of any changes or improvements you've made here. |
||||
|
||||
<p><b>Note: although my sample code is provided under the MIT license, ICSharpCode.AvalonEdit itself is provided under the terms of the GNU LGPL.</b> |
||||
|
||||
<!------------------------------- That's it! ---------------------------> |
||||
</div></body> |
||||
|
||||
</html> |
@ -0,0 +1,265 @@
@@ -0,0 +1,265 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
||||
<!------------------------------------------------------------> |
||||
<!-- INTRODUCTION |
||||
|
||||
The Code Project article submission template (HTML version) |
||||
|
||||
Using this template will help us post your article sooner. To use, just |
||||
follow the 3 easy steps below: |
||||
|
||||
1. Fill in the article description details |
||||
2. Add links to your images and downloads |
||||
3. Include the main article text |
||||
|
||||
That's all there is to it! All formatting will be done by our submission |
||||
scripts and style sheets. |
||||
|
||||
--> |
||||
<!------------------------------------------------------------> |
||||
<!-- IGNORE THIS SECTION --> |
||||
<html> |
||||
<head> |
||||
<title>Rendering</title> |
||||
<Style> |
||||
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt } |
||||
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; } |
||||
H2 { font-size: 13pt; } |
||||
H3 { font-size: 12pt; } |
||||
H4 { font-size: 10pt; color: black; } |
||||
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono; WHITE-SPACE: pre; } |
||||
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; } |
||||
</style> |
||||
<link rel="stylesheet" type="text/css" href="http://www.codeproject.com/App_Themes/NetCommunity/CodeProject.css"> |
||||
</head> |
||||
<body bgcolor="#FFFFFF" color=#000000> |
||||
<div style="width:600px; margin-left: 24px;"> |
||||
<!------------------------------------------------------------> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
<!-- Fill in the details (CodeProject will reformat this section for you) --> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
<!-- Include download and sample image information. --> |
||||
|
||||
For the sample application and source code download, please see the main article: |
||||
<a href="http://www.codeproject.com/KB/edit/AvalonEdit.aspx">Using AvalonEdit (WPF Text Editor)</a> |
||||
|
||||
<p><img src="Article.gif" alt="Sample Image - maximum width is 600 pixels" width=400 height=200></p> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
|
||||
<!-- Add the article text. Please use simple formatting (<h2>, <p> etc) --> |
||||
|
||||
<h2>Introduction</h2> |
||||
|
||||
<h2>Using the Code</h2> |
||||
|
||||
|
||||
<!------------------------------------------------------------> |
||||
<h2>Rendering</h2> |
||||
|
||||
Noticed how through the whole 'Document' section, there was no mention of extensibility? |
||||
The text rendering infrastructure now has to compensate for that by being completely extensible. |
||||
|
||||
<p>The <code>ICSharpCode.AvalonEdit.Rendering.TextView</code> class is the heart of AvalonEdit. |
||||
It takes care of getting the document onto the screen. |
||||
|
||||
<p>To do this in an extensible way, the <code>TextView</code> uses its own kind of model: the <code>VisualLine</code>. |
||||
Visual lines are created only for the visible part of the document. |
||||
<p>The rendering process looks like this:<br> |
||||
<img src="AvalonEdit/renderingPipeline.png" alt="rendering pipeline"><br> |
||||
The last step in the pipeline is the conversion to one or more <code>System.Windows.Media.TextFormatting.TextLine</code> instances. WPF then takes care of the actual text rendering. |
||||
|
||||
<h3>Lifetime of visual lines</h3> |
||||
When the <code>TextView</code> needs to construct visual lines (usually before rendering), it first |
||||
determines which <code>DocumentLine</code> is the top-most visible line in the currently viewed region. |
||||
From there, it starts to build visual lines and also immediately does the conversion to <code>TextLine</code> (word-wrapping). |
||||
The process stops once the viewed document region is filled. |
||||
<p> |
||||
The resulting visual lines (and <code>TextLine</code>s) will be cached and reused in future rendering passes. |
||||
When the user scrolls down, only the visual lines coming into view are created, the rest is reused. |
||||
<p> |
||||
The <code>TextView.Redraw</code> methods are used to remove visual lines from the cache. |
||||
AvalonEdit will redraw automatically on the affected lines when the document is changed; and will invalidate the whole cache |
||||
when any editor options are changed. You will only have to call <code>Redraw</code> manually if you write extensions to the visual line creation process |
||||
that maintain their own data source. For example, the <code>FoldingManager</code> invokes <code>Redraw</code> whenever text sections are expanded or collapsed. |
||||
<p> |
||||
Calling <code>Redraw</code> does not cause immediate recreation of the lines. |
||||
They are just removed from the cache so that the next rendering step will recreate them. |
||||
All redraw methods will enqueue a new rendering step, using the WPF Dispatcher with a low priority. |
||||
|
||||
<h3>Elements inside visual line</h3> |
||||
A visual line consists of a series of elements. These have both a <code>DocumentLength</code> measured in characters as well as a logical length called <code>VisualLength</code>. |
||||
For normal text elements, the two lengths are identical; but some elements like fold markers may have a huge document length, yet a logical length of 1. |
||||
On the other hand, some elements that are simply inserted by element generators may have a document length of 0, but still need a logical length of at least 1 to allow |
||||
addressing elements inside the visual line. |
||||
<p> |
||||
The <code>VisualColumn</code> is a position inside a visual line as measured by the logical length of elements. It is counted starting from 0 at the begin of the visual line.<br> |
||||
Also, inside visual lines, instead of normal offsets to the text document; relative offsets are used.<br> |
||||
<code>Absolute offset = relative offset + VisualLine.FirstDocumentLine.Offset</code><br> |
||||
This means that offsets inside the visual line do not have to be adjusted when text is inserted or removed in front of the visual line; we simply rely on the document |
||||
automatically updating <code>DocumentLine.Offset</code>. |
||||
<p> |
||||
The main job of a visual line element is to implement the <code>CreateTextRun</code> method. |
||||
This method should return a <code>System.Windows.Media.TextFormatting.TextRun</code> instance that can be rendered using the <code>TextLine</code> class. |
||||
<p> |
||||
Visual line elements can also handle mouse clicks and control how the caret should move. The mouse click handling might suffice as a light-weight alternative |
||||
to embedding inline <code>UIElement</code>s in the visual lines. |
||||
|
||||
<h3>Element Generators</h3> |
||||
|
||||
You can extend the text view by registering a custom class deriving from <code>VisualLineElementGenerator</code> in the <code>TextView.ElementGenerators</code> collection. |
||||
This allows you to add custom <code>VisualLineElements</code>. |
||||
Using the <code>InlineObjectElement</code> class, you can even put interactive WPF controls (anything derived from <code>UIElement</code>) into the text document. |
||||
<p> |
||||
For all document text not consumed by element generators, AvalonEdit will create <code>VisualLineText</code> elements. |
||||
<p> |
||||
Usually, the construction of the visual line will stop at the end of the <code>DocumentLine</code>. However, if some <code>VisualLineElementGenerator</code> |
||||
creates an element that's longer than the rest of the line, construction of the visual line may resume in another <code>DocumentLine</code>. |
||||
Currently, only the <code>FoldingElementGenerator</code> can cause one visual line to span multiple <code>DocumentLine</code>s. |
||||
<p> |
||||
<img src="AvalonEdit/folding.png" alt="Screenshot Folding and ImageElementGenerator"> |
||||
<p> |
||||
Here is the full source code for a class that implements embedding images into AvalonEdit: |
||||
<pre lang="cs">public class ImageElementGenerator : VisualLineElementGenerator |
||||
{ |
||||
readonly static Regex imageRegex = new Regex(@"<img src=""([\.\/\w\d]+)""/?>", |
||||
RegexOptions.IgnoreCase); |
||||
readonly string basePath; |
||||
|
||||
public ImageElementGenerator(string basePath) |
||||
{ |
||||
if (basePath == null) |
||||
throw new ArgumentNullException("basePath"); |
||||
this.basePath = basePath; |
||||
} |
||||
|
||||
Match FindMatch(int startOffset) |
||||
{ |
||||
// fetch the end offset of the VisualLine being generated |
||||
int endOffset = CurrentContext.VisualLine.LastDocumentLine.EndOffset; |
||||
TextDocument document = CurrentContext.Document; |
||||
string relevantText = document.GetText(startOffset, endOffset - startOffset); |
||||
return imageRegex.Match(relevantText); |
||||
} |
||||
|
||||
/// Gets the first offset >= startOffset where the generator wants to construct |
||||
/// an element. |
||||
/// Return -1 to signal no interest. |
||||
public override int GetFirstInterestedOffset(int startOffset) |
||||
{ |
||||
Match m = FindMatch(startOffset); |
||||
return m.Success ? (startOffset + m.Index) : -1; |
||||
} |
||||
|
||||
/// Constructs an element at the specified offset. |
||||
/// May return null if no element should be constructed. |
||||
public override VisualLineElement ConstructElement(int offset) |
||||
{ |
||||
Match m = FindMatch(offset); |
||||
// check whether there's a match exactly at offset |
||||
if (m.Success && m.Index == 0) { |
||||
BitmapImage bitmap = LoadBitmap(m.Groups[1].Value); |
||||
if (bitmap != null) { |
||||
Image image = new Image(); |
||||
image.Source = bitmap; |
||||
image.Width = bitmap.PixelWidth; |
||||
image.Height = bitmap.PixelHeight; |
||||
// Pass the length of the match to the 'documentLength' parameter |
||||
// of InlineObjectElement. |
||||
return new InlineObjectElement(m.Length, image); |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
BitmapImage LoadBitmap(string fileName) |
||||
{ |
||||
// TODO: add some kind of cache to avoid reloading the image whenever the |
||||
// VisualLine is reconstructed |
||||
try { |
||||
string fullFileName = Path.Combine(basePath, fileName); |
||||
if (File.Exists(fullFileName)) { |
||||
BitmapImage bitmap = new BitmapImage(new Uri(fullFileName)); |
||||
bitmap.Freeze(); |
||||
return bitmap; |
||||
} |
||||
} catch (ArgumentException) { |
||||
// invalid filename syntax |
||||
} catch (IOException) { |
||||
// other IO error |
||||
} |
||||
return null; |
||||
} |
||||
}</pre> |
||||
|
||||
<h3>Line Transformers</h3> |
||||
|
||||
Line transformers can modify the visual lines after they have been generated. The main usage of this is to colorize the text, |
||||
as done both by syntax highlighting and the selection. |
||||
<p> |
||||
The base classes <code>ColorizingTransformer</code> and <code>DocumentColorizingTransformer</code> help with this task |
||||
by providing helper methods for colorizing that split up visual line elements where necessary. The difference between |
||||
the two classes is that one works using visual columns whereas the other one uses offsets into the document. |
||||
<p> |
||||
Here is an example <code>DocumentColorizingTransformer</code> that highlights the word 'AvalonEdit' using bold font: |
||||
<pre lang="cs">public class ColorizeAvalonEdit : DocumentColorizingTransformer |
||||
{ |
||||
protected override void ColorizeLine(DocumentLine line) |
||||
{ |
||||
int lineStartOffset = line.Offset; |
||||
string text = CurrentContext.Document.GetText(line); |
||||
int start = 0; |
||||
int index; |
||||
while ((index = text.IndexOf("AvalonEdit", start)) >= 0) { |
||||
base.ChangeLinePart( |
||||
lineStartOffset + index, // startOffset |
||||
lineStartOffset + index + 10, // endOffset |
||||
(VisualLineElement element) => { |
||||
// This lambda gets called once for every VisualLineElement |
||||
// between the specified offsets. |
||||
Typeface tf = element.TextRunProperties.Typeface; |
||||
// Replace the typeface with a modified version of |
||||
// the same typeface |
||||
element.TextRunProperties.SetTypeface(new Typeface( |
||||
tf.FontFamily, |
||||
FontStyles.Italic, |
||||
FontWeights.Bold, |
||||
tf.Stretch |
||||
)); |
||||
}); |
||||
start = index + 1; // search for next occurrence |
||||
} } }</pre> |
||||
|
||||
<h3>Background renderers</h3> |
||||
|
||||
Background renderers are simple objects that allow you to draw anything in the text view. |
||||
They can be used to draw nice-looking backgrounds behind the text. |
||||
<p> |
||||
AvalonEdit contains the class <code>BackgroundGeometryBuilder</code> that helps with this task. |
||||
You can use the static <code>BackgroundGeometryBuilder.GetRectsForSegment</code> to fetch a list of rectangles that |
||||
contain text from the specified segment (you will get one rectangle per <code>TextLine</code>); |
||||
or you can use the instance methods to build a <code>PathGeometry</code> for the text's outline. |
||||
AvalonEdit also internally uses this geometry builder to create the selection with the rounded corners. |
||||
<p> |
||||
Inside SharpDevelop, the first option (getting list of rectangles) is used to render the squiggly red line that for compiler errors, |
||||
while the second option is used to produce nice-looking breakpoint markers. |
||||
|
||||
<h2>Points of Interest</h2> |
||||
|
||||
<p>Did you learn anything interesting/fun/annoying while writing the code? Did you |
||||
do anything particularly clever or wild or zany? |
||||
|
||||
<h2>History</h2> |
||||
|
||||
<p>Keep a running update of any changes or improvements you've made here. |
||||
|
||||
<p><b>Note: although my sample code is provided under the MIT license, ICSharpCode.AvalonEdit itself is provided under the terms of the GNU LGPL.</b> |
||||
|
||||
<!------------------------------- That's it! ---------------------------> |
||||
</div></body> |
||||
|
||||
</html> |
Binary file not shown.
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?> |
||||
<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
||||
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> |
||||
<id>AvalonEdit</id> |
||||
<version>4.0.0.7070</version> |
||||
<authors>Daniel Grunwald</authors> |
||||
<owners>SharpDevelop</owners> |
||||
<licenseUrl>http://www.opensource.org/licenses/lgpl-2.1.php</licenseUrl> |
||||
<projectUrl>http://www.avalonedit.net</projectUrl> |
||||
<iconUrl>http://community.sharpdevelop.net/blogs/mattward/SharpDevelop.png</iconUrl> |
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance> |
||||
<description>AvalonEdit is the WPF-based text editor used in SharpDevelop 4.0. |
||||
There are two builds of AvalonEdit included in this package. One that targets .NET 4.0 and |
||||
one that targets .NET 3.5.</description> |
||||
<summary>AvalonEdit is the WPF-based text editor used in SharpDevelop 4.0.</summary> |
||||
<language>en-US</language> |
||||
</metadata> |
||||
</package> |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Windows.Forms; |
||||
using ICSharpCode.TextEditor; |
||||
using ICSharpCode.TextEditor.Gui.CompletionWindow; |
||||
|
||||
namespace $rootnamespace$.TextEditorSample |
||||
{ |
||||
public class CompletionDataProvider : ICompletionDataProvider |
||||
{ |
||||
ImageList imageList = new ImageList(); |
||||
|
||||
List<DefaultCompletionData> completionData = new List<DefaultCompletionData>(); |
||||
|
||||
public CompletionDataProvider() |
||||
{ |
||||
completionData.Add(new DefaultCompletionData("Item1", 0)); |
||||
completionData.Add(new DefaultCompletionData("Item2", 0)); |
||||
completionData.Add(new DefaultCompletionData("Item3", 0)); |
||||
completionData.Add(new DefaultCompletionData("Another item", 0)); |
||||
} |
||||
|
||||
public ImageList ImageList { |
||||
get { return imageList; } |
||||
} |
||||
|
||||
public string PreSelection { |
||||
get { return null; } |
||||
} |
||||
|
||||
public int DefaultIndex { |
||||
get { return 0; } |
||||
} |
||||
|
||||
public CompletionDataProviderKeyResult ProcessKey(char key) |
||||
{ |
||||
if (char.IsLetterOrDigit(key)) { |
||||
return CompletionDataProviderKeyResult.NormalKey; |
||||
} |
||||
return CompletionDataProviderKeyResult.InsertionKey; |
||||
} |
||||
|
||||
public bool InsertAction(ICompletionData data, TextArea textArea, int insertionOffset, char key) |
||||
{ |
||||
textArea.Caret.Position = textArea.Document.OffsetToPosition(insertionOffset); |
||||
return data.InsertAction(textArea, key); |
||||
} |
||||
|
||||
public ICompletionData[] GenerateCompletionData(string fileName, TextArea textArea, char charTyped) |
||||
{ |
||||
return completionData.ToArray(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,288 @@
@@ -0,0 +1,288 @@
|
||||
|
||||
namespace $rootnamespace$.TextEditorSample |
||||
{ |
||||
partial class TextEditorForm |
||||
{ |
||||
/// <summary> |
||||
/// Designer variable used to keep track of non-visual components. |
||||
/// </summary> |
||||
private System.ComponentModel.IContainer components = null; |
||||
|
||||
/// <summary> |
||||
/// Disposes resources used by the form. |
||||
/// </summary> |
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> |
||||
protected override void Dispose(bool disposing) |
||||
{ |
||||
if (disposing) { |
||||
if (components != null) { |
||||
components.Dispose(); |
||||
} |
||||
} |
||||
base.Dispose(disposing); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// This method is required for Windows Forms designer support. |
||||
/// Do not change the method contents inside the source code editor. The Forms designer might |
||||
/// not be able to load this method if it was changed manually. |
||||
/// </summary> |
||||
private void InitializeComponent() |
||||
{ |
||||
this.mainMenuStrip = new System.Windows.Forms.MenuStrip(); |
||||
this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.openToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.saveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.fileExitSeparatorToolStripMenuItem = new System.Windows.Forms.ToolStripSeparator(); |
||||
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.editToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.cutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.copyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.pasteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.deleteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.undoSeparatorToolStripMenuItem = new System.Windows.Forms.ToolStripSeparator(); |
||||
this.undoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.redoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); |
||||
this.splitContainer = new System.Windows.Forms.SplitContainer(); |
||||
this.textEditorControl = new ICSharpCode.TextEditor.TextEditorControl(); |
||||
this.propertyGridComboBox = new System.Windows.Forms.ComboBox(); |
||||
this.propertyGrid = new System.Windows.Forms.PropertyGrid(); |
||||
this.toolStrip = new System.Windows.Forms.ToolStrip(); |
||||
this.highlightingToolStripComboBox = new System.Windows.Forms.ToolStripComboBox(); |
||||
this.mainMenuStrip.SuspendLayout(); |
||||
this.splitContainer.Panel1.SuspendLayout(); |
||||
this.splitContainer.Panel2.SuspendLayout(); |
||||
this.splitContainer.SuspendLayout(); |
||||
this.toolStrip.SuspendLayout(); |
||||
this.SuspendLayout(); |
||||
// |
||||
// mainMenuStrip |
||||
// |
||||
this.mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { |
||||
this.fileToolStripMenuItem, |
||||
this.editToolStripMenuItem}); |
||||
this.mainMenuStrip.Location = new System.Drawing.Point(0, 0); |
||||
this.mainMenuStrip.Name = "mainMenuStrip"; |
||||
this.mainMenuStrip.Size = new System.Drawing.Size(827, 24); |
||||
this.mainMenuStrip.TabIndex = 0; |
||||
this.mainMenuStrip.Text = "menuStrip1"; |
||||
// |
||||
// fileToolStripMenuItem |
||||
// |
||||
this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { |
||||
this.openToolStripMenuItem, |
||||
this.saveToolStripMenuItem, |
||||
this.fileExitSeparatorToolStripMenuItem, |
||||
this.exitToolStripMenuItem}); |
||||
this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; |
||||
this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); |
||||
this.fileToolStripMenuItem.Text = "&File"; |
||||
// |
||||
// openToolStripMenuItem |
||||
// |
||||
this.openToolStripMenuItem.Name = "openToolStripMenuItem"; |
||||
this.openToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); |
||||
this.openToolStripMenuItem.Size = new System.Drawing.Size(155, 22); |
||||
this.openToolStripMenuItem.Text = "&Open..."; |
||||
this.openToolStripMenuItem.Click += new System.EventHandler(this.OpenToolStripMenuItemClick); |
||||
// |
||||
// saveToolStripMenuItem |
||||
// |
||||
this.saveToolStripMenuItem.Name = "saveToolStripMenuItem"; |
||||
this.saveToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); |
||||
this.saveToolStripMenuItem.Size = new System.Drawing.Size(155, 22); |
||||
this.saveToolStripMenuItem.Text = "&Save"; |
||||
this.saveToolStripMenuItem.Click += new System.EventHandler(this.SaveToolStripMenuItemClick); |
||||
// |
||||
// fileExitSeparatorToolStripMenuItem |
||||
// |
||||
this.fileExitSeparatorToolStripMenuItem.Name = "fileExitSeparatorToolStripMenuItem"; |
||||
this.fileExitSeparatorToolStripMenuItem.Size = new System.Drawing.Size(152, 6); |
||||
// |
||||
// exitToolStripMenuItem |
||||
// |
||||
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem"; |
||||
this.exitToolStripMenuItem.Size = new System.Drawing.Size(155, 22); |
||||
this.exitToolStripMenuItem.Text = "E&xit"; |
||||
this.exitToolStripMenuItem.Click += new System.EventHandler(this.ExitToolStripMenuItemClick); |
||||
// |
||||
// editToolStripMenuItem |
||||
// |
||||
this.editToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { |
||||
this.cutToolStripMenuItem, |
||||
this.copyToolStripMenuItem, |
||||
this.pasteToolStripMenuItem, |
||||
this.deleteToolStripMenuItem, |
||||
this.undoSeparatorToolStripMenuItem, |
||||
this.undoToolStripMenuItem, |
||||
this.redoToolStripMenuItem}); |
||||
this.editToolStripMenuItem.Name = "editToolStripMenuItem"; |
||||
this.editToolStripMenuItem.Size = new System.Drawing.Size(39, 20); |
||||
this.editToolStripMenuItem.Text = "&Edit"; |
||||
// |
||||
// cutToolStripMenuItem |
||||
// |
||||
this.cutToolStripMenuItem.Name = "cutToolStripMenuItem"; |
||||
this.cutToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.X))); |
||||
this.cutToolStripMenuItem.Size = new System.Drawing.Size(144, 22); |
||||
this.cutToolStripMenuItem.Text = "Cu&t"; |
||||
this.cutToolStripMenuItem.Click += new System.EventHandler(this.CutToolStripMenuItemClick); |
||||
// |
||||
// copyToolStripMenuItem |
||||
// |
||||
this.copyToolStripMenuItem.Name = "copyToolStripMenuItem"; |
||||
this.copyToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.C))); |
||||
this.copyToolStripMenuItem.Size = new System.Drawing.Size(144, 22); |
||||
this.copyToolStripMenuItem.Text = "&Copy"; |
||||
this.copyToolStripMenuItem.Click += new System.EventHandler(this.CopyToolStripMenuItemClick); |
||||
// |
||||
// pasteToolStripMenuItem |
||||
// |
||||
this.pasteToolStripMenuItem.Name = "pasteToolStripMenuItem"; |
||||
this.pasteToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.V))); |
||||
this.pasteToolStripMenuItem.Size = new System.Drawing.Size(144, 22); |
||||
this.pasteToolStripMenuItem.Text = "&Paste"; |
||||
this.pasteToolStripMenuItem.Click += new System.EventHandler(this.PasteToolStripMenuItemClick); |
||||
// |
||||
// deleteToolStripMenuItem |
||||
// |
||||
this.deleteToolStripMenuItem.Name = "deleteToolStripMenuItem"; |
||||
this.deleteToolStripMenuItem.Size = new System.Drawing.Size(144, 22); |
||||
this.deleteToolStripMenuItem.Text = "&Delete"; |
||||
this.deleteToolStripMenuItem.Click += new System.EventHandler(this.DeleteToolStripMenuItemClick); |
||||
// |
||||
// undoSeparatorToolStripMenuItem |
||||
// |
||||
this.undoSeparatorToolStripMenuItem.Name = "undoSeparatorToolStripMenuItem"; |
||||
this.undoSeparatorToolStripMenuItem.Size = new System.Drawing.Size(141, 6); |
||||
// |
||||
// undoToolStripMenuItem |
||||
// |
||||
this.undoToolStripMenuItem.Name = "undoToolStripMenuItem"; |
||||
this.undoToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Z))); |
||||
this.undoToolStripMenuItem.Size = new System.Drawing.Size(144, 22); |
||||
this.undoToolStripMenuItem.Text = "&Undo"; |
||||
this.undoToolStripMenuItem.Click += new System.EventHandler(this.UndoToolStripMenuItemClick); |
||||
// |
||||
// redoToolStripMenuItem |
||||
// |
||||
this.redoToolStripMenuItem.Name = "redoToolStripMenuItem"; |
||||
this.redoToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Y))); |
||||
this.redoToolStripMenuItem.Size = new System.Drawing.Size(144, 22); |
||||
this.redoToolStripMenuItem.Text = "&Redo"; |
||||
this.redoToolStripMenuItem.Click += new System.EventHandler(this.RedoToolStripMenuItemClick); |
||||
// |
||||
// splitContainer |
||||
// |
||||
this.splitContainer.Dock = System.Windows.Forms.DockStyle.Fill; |
||||
this.splitContainer.Location = new System.Drawing.Point(0, 49); |
||||
this.splitContainer.Name = "splitContainer"; |
||||
// |
||||
// splitContainer.Panel1 |
||||
// |
||||
this.splitContainer.Panel1.Controls.Add(this.textEditorControl); |
||||
// |
||||
// splitContainer.Panel2 |
||||
// |
||||
this.splitContainer.Panel2.Controls.Add(this.propertyGridComboBox); |
||||
this.splitContainer.Panel2.Controls.Add(this.propertyGrid); |
||||
this.splitContainer.Size = new System.Drawing.Size(827, 370); |
||||
this.splitContainer.SplitterDistance = 500; |
||||
this.splitContainer.TabIndex = 4; |
||||
// |
||||
// textEditorControl |
||||
// |
||||
this.textEditorControl.Dock = System.Windows.Forms.DockStyle.Fill; |
||||
this.textEditorControl.IsReadOnly = false; |
||||
this.textEditorControl.Location = new System.Drawing.Point(0, 0); |
||||
this.textEditorControl.Name = "textEditorControl"; |
||||
this.textEditorControl.Size = new System.Drawing.Size(500, 370); |
||||
this.textEditorControl.TabIndex = 2; |
||||
this.textEditorControl.Text = "public class Sample\r\n{\r\n\tpublic Sample()\r\n\t{\r\n\t}\r\n}"; |
||||
// |
||||
// propertyGridComboBox |
||||
// |
||||
this.propertyGridComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) |
||||
| System.Windows.Forms.AnchorStyles.Right))); |
||||
this.propertyGridComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; |
||||
this.propertyGridComboBox.FormattingEnabled = true; |
||||
this.propertyGridComboBox.Items.AddRange(new object[] { |
||||
"Text Editor Properties", |
||||
"Text Editor Control"}); |
||||
this.propertyGridComboBox.Location = new System.Drawing.Point(3, 3); |
||||
this.propertyGridComboBox.Name = "propertyGridComboBox"; |
||||
this.propertyGridComboBox.Size = new System.Drawing.Size(317, 21); |
||||
this.propertyGridComboBox.TabIndex = 4; |
||||
this.propertyGridComboBox.SelectedIndexChanged += new System.EventHandler(this.PropertyGridComboBoxSelectedIndexChanged); |
||||
// |
||||
// propertyGrid |
||||
// |
||||
this.propertyGrid.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) |
||||
| System.Windows.Forms.AnchorStyles.Left) |
||||
| System.Windows.Forms.AnchorStyles.Right))); |
||||
this.propertyGrid.Location = new System.Drawing.Point(0, 24); |
||||
this.propertyGrid.Name = "propertyGrid"; |
||||
this.propertyGrid.Size = new System.Drawing.Size(323, 346); |
||||
this.propertyGrid.TabIndex = 3; |
||||
// |
||||
// toolStrip |
||||
// |
||||
this.toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { |
||||
this.highlightingToolStripComboBox}); |
||||
this.toolStrip.Location = new System.Drawing.Point(0, 24); |
||||
this.toolStrip.Name = "toolStrip"; |
||||
this.toolStrip.Size = new System.Drawing.Size(827, 25); |
||||
this.toolStrip.TabIndex = 3; |
||||
this.toolStrip.Text = "toolStrip"; |
||||
// |
||||
// highlightingToolStripComboBox |
||||
// |
||||
this.highlightingToolStripComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; |
||||
this.highlightingToolStripComboBox.Name = "highlightingToolStripComboBox"; |
||||
this.highlightingToolStripComboBox.Size = new System.Drawing.Size(121, 25); |
||||
this.highlightingToolStripComboBox.SelectedIndexChanged += new System.EventHandler(this.HighlightingToolStripComboBoxSelectedIndexChanged); |
||||
// |
||||
// TextEditorForm |
||||
// |
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); |
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; |
||||
this.ClientSize = new System.Drawing.Size(827, 419); |
||||
this.Controls.Add(this.splitContainer); |
||||
this.Controls.Add(this.toolStrip); |
||||
this.Controls.Add(this.mainMenuStrip); |
||||
this.MainMenuStrip = this.mainMenuStrip; |
||||
this.Name = "TextEditorForm"; |
||||
this.Text = "Text Editor Sample"; |
||||
this.mainMenuStrip.ResumeLayout(false); |
||||
this.mainMenuStrip.PerformLayout(); |
||||
this.splitContainer.Panel1.ResumeLayout(false); |
||||
this.splitContainer.Panel2.ResumeLayout(false); |
||||
this.splitContainer.ResumeLayout(false); |
||||
this.toolStrip.ResumeLayout(false); |
||||
this.toolStrip.PerformLayout(); |
||||
this.ResumeLayout(false); |
||||
this.PerformLayout(); |
||||
} |
||||
private System.Windows.Forms.ToolStripComboBox highlightingToolStripComboBox; |
||||
private System.Windows.Forms.ToolStrip toolStrip; |
||||
private System.Windows.Forms.ComboBox propertyGridComboBox; |
||||
private System.Windows.Forms.ToolStripMenuItem redoToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem undoToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripSeparator undoSeparatorToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem deleteToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem pasteToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem copyToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem cutToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem editToolStripMenuItem; |
||||
private System.Windows.Forms.SplitContainer splitContainer; |
||||
private System.Windows.Forms.PropertyGrid propertyGrid; |
||||
private ICSharpCode.TextEditor.TextEditorControl textEditorControl; |
||||
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripSeparator fileExitSeparatorToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem saveToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem openToolStripMenuItem; |
||||
private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem; |
||||
private System.Windows.Forms.MenuStrip mainMenuStrip; |
||||
|
||||
} |
||||
} |
@ -0,0 +1,152 @@
@@ -0,0 +1,152 @@
|
||||
|
||||
using System; |
||||
using System.Drawing; |
||||
using System.Windows.Forms; |
||||
using ICSharpCode.TextEditor; |
||||
using ICSharpCode.TextEditor.Document; |
||||
using ICSharpCode.TextEditor.Gui.CompletionWindow; |
||||
|
||||
namespace $rootnamespace$.TextEditorSample |
||||
{ |
||||
public partial class TextEditorForm : Form |
||||
{ |
||||
string currentFileName; |
||||
TextArea textArea; |
||||
CodeCompletionWindow completionWindow; |
||||
|
||||
public TextEditorForm() |
||||
{ |
||||
// |
||||
// The InitializeComponent() call is required for Windows Forms designer support. |
||||
// |
||||
InitializeComponent(); |
||||
Init(); |
||||
} |
||||
|
||||
void Init() |
||||
{ |
||||
propertyGridComboBox.SelectedIndex = 1; |
||||
textArea = textEditorControl.ActiveTextAreaControl.TextArea; |
||||
textArea.KeyEventHandler += ProcessKey; |
||||
|
||||
PopulateHighlightingComboBox(); |
||||
|
||||
highlightingToolStripComboBox.Text = "C#"; |
||||
} |
||||
|
||||
bool ProcessKey(char ch) |
||||
{ |
||||
if (ch == '.') { |
||||
ShowCompletionWindow(); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
void ShowCompletionWindow() |
||||
{ |
||||
CompletionDataProvider completionDataProvider = new CompletionDataProvider(); |
||||
completionWindow = CodeCompletionWindow.ShowCompletionWindow(this, textEditorControl, String.Empty, completionDataProvider, '.'); |
||||
if (completionWindow != null) { |
||||
completionWindow.Closed += CompletionWindowClosed; |
||||
} |
||||
} |
||||
|
||||
void CompletionWindowClosed(object source, EventArgs e) |
||||
{ |
||||
if (completionWindow != null) { |
||||
completionWindow.Closed -= CompletionWindowClosed; |
||||
completionWindow.Dispose(); |
||||
completionWindow = null; |
||||
} |
||||
} |
||||
|
||||
void PopulateHighlightingComboBox() |
||||
{ |
||||
foreach (string highlighting in HighlightingManager.Manager.HighlightingDefinitions.Keys) { |
||||
highlightingToolStripComboBox.Items.Add(highlighting); |
||||
} |
||||
highlightingToolStripComboBox.Sorted = true; |
||||
} |
||||
|
||||
void ExitToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
Close(); |
||||
} |
||||
|
||||
void PropertyGridComboBoxSelectedIndexChanged(object sender, EventArgs e) |
||||
{ |
||||
switch (propertyGridComboBox.SelectedIndex) { |
||||
case 0: |
||||
propertyGrid.SelectedObject = textEditorControl.TextEditorProperties; |
||||
break; |
||||
case 1: |
||||
propertyGrid.SelectedObject = textEditorControl; |
||||
break; |
||||
} |
||||
} |
||||
|
||||
void OpenToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
using (OpenFileDialog openFileDialog = new OpenFileDialog()) { |
||||
openFileDialog.CheckFileExists = true; |
||||
if (openFileDialog.ShowDialog() == DialogResult.OK) { |
||||
currentFileName = openFileDialog.FileName; |
||||
textEditorControl.LoadFile(currentFileName); |
||||
highlightingToolStripComboBox.Text = textEditorControl.Document.HighlightingStrategy.Name; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void SaveToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
if (currentFileName == null) { |
||||
using (SaveFileDialog saveFileDialog = new SaveFileDialog()) { |
||||
if (saveFileDialog.ShowDialog() == DialogResult.OK) { |
||||
currentFileName = saveFileDialog.FileName; |
||||
} else { |
||||
return; |
||||
} |
||||
} |
||||
} |
||||
textEditorControl.SaveFile(currentFileName); |
||||
} |
||||
|
||||
void CutToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
textArea.ClipboardHandler.Cut(sender, e); |
||||
} |
||||
|
||||
void UndoToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
textEditorControl.Undo(); |
||||
} |
||||
|
||||
void RedoToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
textEditorControl.Redo(); |
||||
} |
||||
|
||||
void CopyToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
textArea.AutoClearSelection = false; |
||||
textArea.ClipboardHandler.Copy(sender, e); |
||||
} |
||||
|
||||
void PasteToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
textArea.ClipboardHandler.Paste(sender, e); |
||||
} |
||||
|
||||
void DeleteToolStripMenuItemClick(object sender, EventArgs e) |
||||
{ |
||||
textArea.ClipboardHandler.Delete(sender, e); |
||||
} |
||||
|
||||
void HighlightingToolStripComboBoxSelectedIndexChanged(object sender, EventArgs e) |
||||
{ |
||||
string highlighter = highlightingToolStripComboBox.Text; |
||||
textEditorControl.SetHighlighting(highlighter); |
||||
textEditorControl.Refresh(); |
||||
} |
||||
} |
||||
} |
Binary file not shown.
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0"?> |
||||
<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
||||
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> |
||||
<id>ICSharpCode.TextEditor.Sample</id> |
||||
<version>3.2.1.6466</version> |
||||
<authors>SharpDevelop</authors> |
||||
<owners>SharpDevelop</owners> |
||||
<projectUrl>http://wiki.sharpdevelop.net/Using%20the%20texteditor.ashx</projectUrl> |
||||
<iconUrl>http://community.sharpdevelop.net/blogs/mattward/SharpDevelop.png</iconUrl> |
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance> |
||||
<description>Sample code for the Text editor used in SharpDevelop 3.</description> |
||||
<summary>Sample code for the Text editor used in SharpDevelop 3.</summary> |
||||
<language>en-US</language> |
||||
<dependencies> |
||||
<dependency id="ICSharpCode.TextEditor" version="3.2.1.6466" /> |
||||
</dependencies> |
||||
</metadata> |
||||
</package> |
Binary file not shown.
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0"?> |
||||
<package xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> |
||||
<metadata xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"> |
||||
<id>ICSharpCode.TextEditor</id> |
||||
<version>3.2.1.6466</version> |
||||
<authors>SharpDevelop</authors> |
||||
<owners>SharpDevelop</owners> |
||||
<licenseUrl>http://www.opensource.org/licenses/lgpl-2.1.php</licenseUrl> |
||||
<projectUrl>http://wiki.sharpdevelop.net/Using%20the%20texteditor.ashx</projectUrl> |
||||
<iconUrl>http://community.sharpdevelop.net/blogs/mattward/SharpDevelop.png</iconUrl> |
||||
<requireLicenseAcceptance>true</requireLicenseAcceptance> |
||||
<description>Text editor used in SharpDevelop 3.</description> |
||||
<summary>Text editor used in SharpDevelop 3.</summary> |
||||
<language>en-US</language> |
||||
</metadata> |
||||
</package> |
Binary file not shown.
Binary file not shown.
@ -0,0 +1,4 @@
@@ -0,0 +1,4 @@
|
||||
nuget.exe pack AvalonEdit\AvalonEdit.nuspec -b AvalonEdit -o AvalonEdit |
||||
nuget.exe pack AvalonEdit.Sample\AvalonEdit.Sample.nuspec -b AvalonEdit.Sample -o AvalonEdit.Sample |
||||
nuget.exe pack ICSharpCode.TextEditor\ICSharpCode.TextEditor.nuspec -b ICSharpCode.TextEditor -o ICSharpCode.TextEditor |
||||
nuget.exe pack ICSharpCode.TextEditor.Sample\ICSharpCode.TextEditor.Sample.nuspec -b ICSharpCode.TextEditor.Sample -o ICSharpCode.TextEditor.Sample |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System.Reflection; |
||||
|
||||
// Information about this assembly is defined by the following
|
||||
// attributes.
|
||||
//
|
||||
// change them to the information which is associated with the assembly
|
||||
// you compile.
|
||||
|
||||
[assembly: AssemblyTitle("PackageManagement")] |
||||
[assembly: AssemblyDescription("Package Management for SharpDevelop")] |
||||
[assembly: AssemblyConfiguration("")] |
||||
[assembly: AssemblyTrademark("")] |
||||
[assembly: AssemblyCulture("")] |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
<AddIn |
||||
name="Package Management" |
||||
author="Matt Ward" |
||||
copyright="prj:///doc/copyright.txt" |
||||
url="http://sharpdevelop.com" |
||||
description="NuGet Package Management" |
||||
addInManagerHidden="preinstalled"> |
||||
|
||||
<Manifest> |
||||
<Identity name="ICSharpCode.PackageManagement"/> |
||||
</Manifest> |
||||
|
||||
<Runtime> |
||||
<Import assembly=":ICSharpCode.SharpDevelop"/> |
||||
<Import assembly="PackageManagement.dll"/> |
||||
</Runtime> |
||||
|
||||
<!-- Projects window context menu - project selected --> |
||||
<Path path="/SharpDevelop/Pads/ProjectBrowser/ContextMenu/ProjectNode"> |
||||
<Condition name="WriteableProject" action="Disable"> |
||||
<MenuItem |
||||
id="AddPackageReference" |
||||
label="Add Package Reference" |
||||
insertafter="AddReference" |
||||
insertbefore="AddWebReference" |
||||
class = "ICSharpCode.PackageManagement.AddPackageReferenceCommand"/> |
||||
</Condition> |
||||
</Path> |
||||
|
||||
<!-- Projects window context menu - References selected --> |
||||
<Path name="/SharpDevelop/Pads/ProjectBrowser/ContextMenu/ReferenceFolderNode"> |
||||
<Condition name="WriteableProject" action="Disable"> |
||||
<MenuItem |
||||
id="AddPackageReference" |
||||
label="Add Package Reference" |
||||
insertafter="AddReference" |
||||
insertbefore="AddWebReference" |
||||
class="ICSharpCode.PackageManagement.AddPackageReferenceCommand"/> |
||||
</Condition> |
||||
</Path> |
||||
|
||||
<!-- Project main menu --> |
||||
<Path name="/SharpDevelop/Workbench/MainMenu/Project"> |
||||
<Condition name="WriteableProject" action="Disable"> |
||||
<MenuItem |
||||
id="AddPackageReference" |
||||
label="Add Package Reference" |
||||
insertafter="AddReference" |
||||
insertbefore="AddWebReference" |
||||
class="ICSharpCode.PackageManagement.AddPackageReferenceCommand"/> |
||||
</Condition> |
||||
</Path> |
||||
|
||||
<!-- Tools options --> |
||||
<Path name="/SharpDevelop/Dialogs/OptionsDialog/ToolsOptions"> |
||||
<OptionPanel |
||||
id="PackageManagementOptions" |
||||
label="Package Management" |
||||
class="ICSharpCode.PackageManagement.PackageManagementOptionsView" |
||||
/> |
||||
</Path> |
||||
</AddIn> |
@ -0,0 +1,184 @@
@@ -0,0 +1,184 @@
|
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build"> |
||||
<PropertyGroup> |
||||
<ProjectGuid>{AE4AB0FA-6087-4480-AF37-0FA1452B3DA1}</ProjectGuid> |
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform> |
||||
<OutputType>Library</OutputType> |
||||
<RootNamespace>ICSharpCode.PackageManagement</RootNamespace> |
||||
<AssemblyName>PackageManagement</AssemblyName> |
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> |
||||
<NoStdLib>False</NoStdLib> |
||||
<WarningLevel>4</WarningLevel> |
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> |
||||
<OutputPath>..\..\..\..\..\AddIns\Misc\PackageManagement\</OutputPath> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Platform)' == 'x86' "> |
||||
<PlatformTarget>x86</PlatformTarget> |
||||
<RegisterForComInterop>False</RegisterForComInterop> |
||||
<GenerateSerializationAssemblies>Auto</GenerateSerializationAssemblies> |
||||
<BaseAddress>4194304</BaseAddress> |
||||
<FileAlignment>4096</FileAlignment> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> |
||||
<DebugSymbols>true</DebugSymbols> |
||||
<DebugType>Full</DebugType> |
||||
<Optimize>False</Optimize> |
||||
<CheckForOverflowUnderflow>True</CheckForOverflowUnderflow> |
||||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
||||
</PropertyGroup> |
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> |
||||
<DebugSymbols>false</DebugSymbols> |
||||
<DebugType>None</DebugType> |
||||
<Optimize>True</Optimize> |
||||
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow> |
||||
<DefineConstants>TRACE</DefineConstants> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<Reference Include="NuGet.Core"> |
||||
<HintPath>..\RequiredLibraries\NuGet.Core.dll</HintPath> |
||||
</Reference> |
||||
<Reference Include="PresentationCore" /> |
||||
<Reference Include="PresentationFramework" /> |
||||
<Reference Include="System" /> |
||||
<Reference Include="System.Core"> |
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework> |
||||
</Reference> |
||||
<Reference Include="System.Xaml"> |
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework> |
||||
</Reference> |
||||
<Reference Include="System.Xml" /> |
||||
<Reference Include="WindowsBase" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Folder Include="Configuration" /> |
||||
<Folder Include="Resources" /> |
||||
<Folder Include="Src" /> |
||||
<Folder Include="Src\Design" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Compile Include="..\..\..\..\Main\GlobalAssemblyInfo.cs"> |
||||
<Link>Configuration\GlobalAssemblyInfo.cs</Link> |
||||
</Compile> |
||||
<Compile Include="Configuration\AssemblyInfo.cs" /> |
||||
<Compile Include="Src\AddPackageReferenceCommand.cs" /> |
||||
<Compile Include="Src\AddPackageReferenceView.xaml.cs"> |
||||
<DependentUpon>AddPackageReferenceView.xaml</DependentUpon> |
||||
<SubType>Code</SubType> |
||||
</Compile> |
||||
<Compile Include="Src\AddPackageReferenceViewModel.cs" /> |
||||
<Compile Include="Src\AvailablePackagesViewModel.cs" /> |
||||
<Compile Include="Src\BooleanToFontWeightConverter.cs" /> |
||||
<Compile Include="Src\DelegateCommand.cs" /> |
||||
<Compile Include="Src\Design\DesignTimeLicenseAcceptanceViewModel.cs" /> |
||||
<Compile Include="Src\Design\DesignTimePackageManagementOptionsViewModel.cs" /> |
||||
<Compile Include="Src\Design\DesignTimePackageManagementService.cs" /> |
||||
<Compile Include="Src\Design\DesignTimePackagesViewModel.cs" /> |
||||
<Compile Include="Src\Design\FakePackage.cs" /> |
||||
<Compile Include="Src\Design\FakePackageManagementService.cs" /> |
||||
<Compile Include="Src\Design\FakePackageRepository.cs" /> |
||||
<Compile Include="Src\Design\FakeProjectManager.cs" /> |
||||
<Compile Include="Src\Design\WpfDesigner.cs" /> |
||||
<Compile Include="Src\ILicenseAcceptanceService.cs" /> |
||||
<Compile Include="Src\InstalledPackagesViewModel.cs" /> |
||||
<Compile Include="Src\IPackageManagementFileService.cs" /> |
||||
<Compile Include="Src\IPackageManagementProjectService.cs" /> |
||||
<Compile Include="Src\IPackageManagementService.cs" /> |
||||
<Compile Include="Src\IPackageManagerFactory.cs" /> |
||||
<Compile Include="Src\IPackageViewModelFactory.cs" /> |
||||
<Compile Include="Src\ISharpDevelopPackageManager.cs" /> |
||||
<Compile Include="Src\ISharpDevelopPackageRepositoryFactory.cs" /> |
||||
<Compile Include="Src\ISharpDevelopProjectManager.cs" /> |
||||
<Compile Include="Src\ISharpDevelopProjectSystemFactory.cs" /> |
||||
<Compile Include="Src\LicenseAcceptanceService.cs" /> |
||||
<Compile Include="Src\LicenseAcceptanceView.xaml.cs"> |
||||
<DependentUpon>LicenseAcceptanceView.xaml</DependentUpon> |
||||
<SubType>Code</SubType> |
||||
</Compile> |
||||
<Compile Include="Src\LicenseAcceptanceViewModel.cs" /> |
||||
<Compile Include="Src\ListBoxBehaviour.cs" /> |
||||
<Compile Include="Src\OpenHyperlinkCommand.cs" /> |
||||
<Compile Include="Src\PackageManagementFileService.cs" /> |
||||
<Compile Include="Src\PackageManagementOptions.cs" /> |
||||
<Compile Include="Src\PackageManagementOptionsView.xaml.cs"> |
||||
<DependentUpon>PackageManagementOptionsView.xaml</DependentUpon> |
||||
<SubType>Code</SubType> |
||||
</Compile> |
||||
<Compile Include="Src\PackageManagementOptionsViewModel.cs" /> |
||||
<Compile Include="Src\PackageManagementProjectService.cs" /> |
||||
<Compile Include="Src\PackageManagementEnumerableExtensions.cs" /> |
||||
<Compile Include="Src\PackageManagementService.cs" /> |
||||
<Compile Include="Src\PackageRepositoryPaths.cs" /> |
||||
<Compile Include="Src\PackageSourceConverter.cs" /> |
||||
<Compile Include="Src\PackageSourceViewModel.cs" /> |
||||
<Compile Include="Src\PackagesView.xaml.cs"> |
||||
<DependentUpon>PackagesView.xaml</DependentUpon> |
||||
<SubType>Code</SubType> |
||||
</Compile> |
||||
<Compile Include="Src\PackagesViewModel.cs" /> |
||||
<Compile Include="Src\PackageUpdatesViewModel.cs" /> |
||||
<Compile Include="Src\PackageViewModel.cs" /> |
||||
<Compile Include="Src\PackageViewModelFactory.cs" /> |
||||
<Compile Include="Src\Page.cs" /> |
||||
<Compile Include="Src\PagedResultsView.xaml.cs"> |
||||
<DependentUpon>PagedResultsView.xaml</DependentUpon> |
||||
<SubType>Code</SubType> |
||||
</Compile> |
||||
<Compile Include="Src\Pages.cs" /> |
||||
<Compile Include="Src\ProjectTargetFramework.cs" /> |
||||
<Compile Include="Src\RegisteredPackageSource.cs" /> |
||||
<Compile Include="Src\RegisteredPackageSources.cs" /> |
||||
<Compile Include="Src\SelectedListBoxItemScrollingBehaviour.cs" /> |
||||
<Compile Include="Src\SharpDevelopPackageManager.cs" /> |
||||
<Compile Include="Src\SharpDevelopPackageManagerFactory.cs" /> |
||||
<Compile Include="Src\SharpDevelopPackageRepositoryFactory.cs" /> |
||||
<Compile Include="Src\SharpDevelopProjectManager.cs" /> |
||||
<Compile Include="Src\SharpDevelopProjectSystem.cs" /> |
||||
<Compile Include="Src\SharpDevelopProjectSystemFactory.cs" /> |
||||
<Compile Include="Src\StringToStringCollectionConverter.cs" /> |
||||
<Compile Include="Src\TextBoxBehaviour.cs" /> |
||||
<Compile Include="Src\ViewModelBase.cs" /> |
||||
<Compile Include="Src\ViewModelLocator.cs" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<Page Include="Src\AddPackageReferenceView.xaml" /> |
||||
<Page Include="Src\LicenseAcceptanceView.xaml" /> |
||||
<Page Include="Src\PackageManagementOptionsView.xaml" /> |
||||
<Page Include="Src\PackagesView.xaml" /> |
||||
<Page Include="Src\PagedResultsView.xaml" /> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<ProjectReference Include="..\..\..\..\Main\Base\Project\ICSharpCode.SharpDevelop.csproj"> |
||||
<Project>{2748AD25-9C63-4E12-877B-4DCE96FBED54}</Project> |
||||
<Name>ICSharpCode.SharpDevelop</Name> |
||||
<Private>False</Private> |
||||
</ProjectReference> |
||||
<ProjectReference Include="..\..\..\..\Main\Core\Project\ICSharpCode.Core.csproj"> |
||||
<Project>{35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}</Project> |
||||
<Name>ICSharpCode.Core</Name> |
||||
<Private>False</Private> |
||||
</ProjectReference> |
||||
<ProjectReference Include="..\..\..\..\Main\ICSharpCode.Core.Presentation\ICSharpCode.Core.Presentation.csproj"> |
||||
<Project>{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}</Project> |
||||
<Name>ICSharpCode.Core.Presentation</Name> |
||||
<Private>False</Private> |
||||
</ProjectReference> |
||||
</ItemGroup> |
||||
<ItemGroup> |
||||
<None Include="..\RequiredLibraries\LICENSE.txt"> |
||||
<Link>NuGet-LICENSE.txt</Link> |
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
||||
</None> |
||||
<None Include="PackageManagement.addin"> |
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory> |
||||
</None> |
||||
<Resource Include="Resources\packageicon.png" /> |
||||
<Resource Include="Resources\magnifier.png" /> |
||||
<Resource Include="Resources\resultset_next.png" /> |
||||
<Resource Include="Resources\resultset_previous.png" /> |
||||
<Resource Include="Resources\accept.png" /> |
||||
<None Include="Resources\license.txt" /> |
||||
</ItemGroup> |
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> |
||||
</Project> |
After Width: | Height: | Size: 781 B |
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
NuGet Package Icon: |
||||
License: Apache 2.0 |
||||
http://www.apache.org/licenses/LICENSE-2.0 |
||||
|
||||
Silk icons: |
||||
License: Creative Commons Attribution 2.5 License |
||||
http://www.famfamfam.com/lab/icons/silk/ |
After Width: | Height: | Size: 619 B |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 395 B |
After Width: | Height: | Size: 389 B |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Windows; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class AddPackageReferenceCommand : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
AddPackageReferenceView view = new AddPackageReferenceView(); |
||||
view.Owner = WorkbenchSingleton.MainWindow; |
||||
view.ShowDialog(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,53 @@
@@ -0,0 +1,53 @@
|
||||
<Window |
||||
x:Class="ICSharpCode.PackageManagement.AddPackageReferenceView" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:pm="clr-namespace:ICSharpCode.PackageManagement" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
Height="480" |
||||
Width="640" |
||||
MinHeight="380" |
||||
MinWidth="440" |
||||
Style="{x:Static core:GlobalStyles.DialogWindowStyle}" |
||||
Title="Add Package Reference" |
||||
WindowStartupLocation="CenterOwner"> |
||||
|
||||
<Window.Resources> |
||||
<Style TargetType="Button" BasedOn="{x:Static core:GlobalStyles.ButtonStyle}"/> |
||||
<pm:ViewModelLocator x:Key="ViewModelLocator"/> |
||||
</Window.Resources> |
||||
|
||||
<DockPanel> |
||||
<!-- Use DockPanel.DataContext instead of Window.DataContext otherwise Visual Studio does not show |
||||
design time data --> |
||||
<DockPanel.DataContext> |
||||
<Binding Source="{StaticResource ViewModelLocator}" Path="AddPackageReferenceViewModel"/> |
||||
</DockPanel.DataContext> |
||||
<StackPanel |
||||
DockPanel.Dock="Bottom" |
||||
Margin="4, 4" |
||||
HorizontalAlignment="Right"> |
||||
<Button |
||||
Content="{core:Localize Global.CloseButtonText}" |
||||
IsCancel="True"> |
||||
</Button> |
||||
</StackPanel> |
||||
<TabControl> |
||||
<TabItem Header="Installed"> |
||||
<pm:PackagesView |
||||
x:Name="installedPackagesView" |
||||
DataContext="{Binding Path=InstalledPackagesViewModel}"/> |
||||
</TabItem> |
||||
<TabItem Header="Available"> |
||||
<pm:PackagesView |
||||
x:Name="availablePackagesView" |
||||
DataContext="{Binding Path=AvailablePackagesViewModel}"/> |
||||
</TabItem> |
||||
<TabItem Header="Updates"> |
||||
<pm:PackagesView |
||||
x:Name="packageUpdatesView" |
||||
DataContext="{Binding Path=PackageUpdatesViewModel}"/> |
||||
</TabItem> |
||||
</TabControl> |
||||
</DockPanel> |
||||
</Window> |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Windows; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public partial class AddPackageReferenceView : Window |
||||
{ |
||||
public AddPackageReferenceView() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.ObjectModel; |
||||
using System.Linq; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class AddPackageReferenceViewModel : ViewModelBase<AddPackageReferenceViewModel> |
||||
{ |
||||
IPackageManagementService packageManagementService; |
||||
InstalledPackagesViewModel installedPackagesViewModel; |
||||
AvailablePackagesViewModel availablePackagesViewModel; |
||||
PackageUpdatesViewModel packageUpdatesViewModel; |
||||
|
||||
public AddPackageReferenceViewModel(IPackageManagementService packageManagementService) |
||||
{ |
||||
this.packageManagementService = packageManagementService; |
||||
installedPackagesViewModel = new InstalledPackagesViewModel(packageManagementService); |
||||
availablePackagesViewModel = new AvailablePackagesViewModel(packageManagementService); |
||||
packageUpdatesViewModel = new PackageUpdatesViewModel(packageManagementService); |
||||
|
||||
installedPackagesViewModel.ReadPackages(); |
||||
availablePackagesViewModel.ReadPackages(); |
||||
packageUpdatesViewModel.ReadPackages(); |
||||
} |
||||
|
||||
public InstalledPackagesViewModel InstalledPackagesViewModel { |
||||
get { return installedPackagesViewModel; } |
||||
} |
||||
|
||||
public AvailablePackagesViewModel AvailablePackagesViewModel { |
||||
get { return availablePackagesViewModel; } |
||||
} |
||||
|
||||
public PackageUpdatesViewModel PackageUpdatesViewModel { |
||||
get { return packageUpdatesViewModel; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class AvailablePackagesViewModel : PackagesViewModel |
||||
{ |
||||
public AvailablePackagesViewModel(IPackageManagementService packageManagementService) |
||||
: base(packageManagementService) |
||||
{ |
||||
IsSearchable = true; |
||||
} |
||||
|
||||
protected override IQueryable<IPackage> GetAllPackages() |
||||
{ |
||||
return PackageManagementService.ActivePackageRepository.GetPackages(); |
||||
} |
||||
|
||||
protected override IEnumerable<IPackage> GetFilteredPackagesBeforePagingResults(IQueryable<IPackage> allPackages) |
||||
{ |
||||
IEnumerable<IPackage> filteredPackages = base.GetFilteredPackagesBeforePagingResults(allPackages); |
||||
return GetDistinctPackagesById(filteredPackages); |
||||
} |
||||
|
||||
IEnumerable<IPackage> GetDistinctPackagesById(IEnumerable<IPackage> allPackages) |
||||
{ |
||||
return allPackages.DistinctLast<IPackage>(PackageEqualityComparer.Id); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Globalization; |
||||
using System.Windows; |
||||
using System.Windows.Data; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
[ValueConversion(typeof(Boolean), typeof(FontWeight))] |
||||
public class BooleanToFontWeightConverter : IValueConverter |
||||
{ |
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
if (value is Boolean) { |
||||
Boolean fontIsBold = (Boolean)value; |
||||
return ConvertToFontWeight(fontIsBold); |
||||
} |
||||
return DependencyProperty.UnsetValue; |
||||
} |
||||
|
||||
FontWeight ConvertToFontWeight(Boolean bold) |
||||
{ |
||||
if (bold) { |
||||
return FontWeights.Bold; |
||||
} |
||||
return FontWeights.Normal; |
||||
} |
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||
{ |
||||
if (value is FontWeight) { |
||||
FontWeight fontWeight = (FontWeight)value; |
||||
return ConvertToBoolean(fontWeight); |
||||
} |
||||
return DependencyProperty.UnsetValue; |
||||
} |
||||
|
||||
bool ConvertToBoolean(FontWeight fontWeight) |
||||
{ |
||||
return fontWeight == FontWeights.Bold; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Windows.Input; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class DelegateCommand : ICommand |
||||
{ |
||||
Action<object> execute; |
||||
Predicate<object> canExecute; |
||||
|
||||
public DelegateCommand(Action<object> execute, Predicate<object> canExecute) |
||||
{ |
||||
this.execute = execute; |
||||
this.canExecute = canExecute; |
||||
} |
||||
|
||||
public DelegateCommand(Action<object> execute) |
||||
: this(execute, null) |
||||
{ |
||||
} |
||||
|
||||
public event EventHandler CanExecuteChanged { |
||||
add { CommandManager.RequerySuggested += value; } |
||||
remove { CommandManager.RequerySuggested -= value; } |
||||
} |
||||
|
||||
public void Execute(object parameter) |
||||
{ |
||||
execute(parameter); |
||||
} |
||||
|
||||
public bool CanExecute(object parameter) |
||||
{ |
||||
if (canExecute != null) { |
||||
return canExecute(parameter); |
||||
} |
||||
return true; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public class DesignTimeLicenseAcceptanceViewModel : LicenseAcceptanceViewModel |
||||
{ |
||||
public DesignTimeLicenseAcceptanceViewModel() |
||||
: base(CreatePackages()) |
||||
{ |
||||
} |
||||
|
||||
static IEnumerable<IPackage> CreatePackages() |
||||
{ |
||||
var packageManagementService = new DesignTimePackageManagementService(); |
||||
return packageManagementService.FakeActivePackageRepository.FakePackages; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.PackageManagement; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public class DesignTimePackageManagementOptionsViewModel : PackageManagementOptionsViewModel |
||||
{ |
||||
public DesignTimePackageManagementOptionsViewModel() |
||||
: this(new PackageManagementOptions(new Properties())) |
||||
{ |
||||
} |
||||
|
||||
public DesignTimePackageManagementOptionsViewModel(PackageManagementOptions options) |
||||
: base(options) |
||||
{ |
||||
options.PackageSources.Add(new PackageSource("Source2", "http://sharpdevelop.codeplex.com")); |
||||
options.PackageSources.Add(new PackageSource("Source3", "http://sharpdevelop.codeplex.com")); |
||||
options.PackageSources.Add(new PackageSource("Source4", "http://sharpdevelop.codeplex.com")); |
||||
options.PackageSources.Add(new PackageSource("Source5", "http://sharpdevelop.codeplex.com")); |
||||
Load(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public class DesignTimePackageManagementService : FakePackageManagementService |
||||
{ |
||||
public DesignTimePackageManagementService() |
||||
{ |
||||
AddDesignTimePackages(); |
||||
} |
||||
|
||||
void AddDesignTimePackages() |
||||
{ |
||||
for (int i = 0; i < 5; ++i) { |
||||
FakePackage package = CreatePackage(i); |
||||
FakeActiveProjectManager.FakeLocalRepository.FakePackages.Add(package); |
||||
FakeActivePackageRepository.FakePackages.Add(package); |
||||
} |
||||
} |
||||
|
||||
FakePackage CreatePackage(int i) |
||||
{ |
||||
var package = new FakePackage(); |
||||
package.Id = "Package ID: " + i; |
||||
package.Description = "Package description."; |
||||
package.Summary = "Package summary. Package summary. Package summary. " + |
||||
"Package summary. Package summary. Package summary. Package summary."; |
||||
package.DownloadCount = i; |
||||
package.Rating = 4.5; |
||||
package.RatingsCount = 344; |
||||
package.RequireLicenseAcceptance = true; |
||||
package.LicenseUrl = new Uri("http://www.google.com/license"); |
||||
package.ProjectUrl = new Uri("http://www.codeplex.com"); |
||||
package.ReportAbuseUrl = new Uri("http://www.google.com"); |
||||
package.Version = Version.Parse("1.0.4.5"); |
||||
package.AddAuthor("A User"); |
||||
package.AddAuthor("B User"); |
||||
package.AddDependency("NuGet.Package." + i, Version.Parse("1.0.0.1"), Version.Parse("1.2.0.2")); |
||||
package.AddDependency("NuGet.Package." + i + 1, Version.Parse("1.2.0.2"), Version.Parse("2.2.0.0")); |
||||
return package; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.ObjectModel; |
||||
using System.Linq; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public class DesignTimePackagesViewModel : PackagesViewModel |
||||
{ |
||||
public DesignTimePackagesViewModel() |
||||
: base(new DesignTimePackageManagementService()) |
||||
{ |
||||
PageSize = 3; |
||||
AddPackageViewModels(); |
||||
} |
||||
|
||||
void AddPackageViewModels() |
||||
{ |
||||
IQueryable<IPackage> packages = PackageManagementService.ActivePackageRepository.GetPackages(); |
||||
PackageViewModels.AddRange(ConvertToPackageViewModels(packages)); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,112 @@
@@ -0,0 +1,112 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public class FakePackage : IPackage |
||||
{ |
||||
List<string> authors = new List<string>(); |
||||
List<string> owners = new List<string>(); |
||||
Stream stream = null; |
||||
List<IPackageFile> files = new List<IPackageFile>(); |
||||
List<IPackageAssemblyReference> assemblyReferences = |
||||
new List<IPackageAssemblyReference>(); |
||||
|
||||
public List<PackageDependency> DependenciesList = |
||||
new List<PackageDependency>(); |
||||
|
||||
public FakePackage() |
||||
: this(String.Empty) |
||||
{ |
||||
} |
||||
|
||||
public FakePackage(string id) |
||||
{ |
||||
this.Id = id; |
||||
this.Description = String.Empty; |
||||
this.Version = new Version(1, 0, 0, 0); |
||||
} |
||||
|
||||
public string Id { get; set; } |
||||
public Version Version { get; set; } |
||||
public string Title { get; set; } |
||||
public Uri IconUrl { get; set; } |
||||
public Uri LicenseUrl { get; set; } |
||||
public Uri ProjectUrl { get; set; } |
||||
public bool RequireLicenseAcceptance { get; set; } |
||||
public string Description { get; set; } |
||||
public string Summary { get; set; } |
||||
public string Language { get; set; } |
||||
public string Tags { get; set; } |
||||
public Uri ReportAbuseUrl { get; set; } |
||||
public int DownloadCount { get; set; } |
||||
public int RatingsCount { get; set; } |
||||
public double Rating { get; set; } |
||||
|
||||
public IEnumerable<IPackageAssemblyReference> AssemblyReferences { |
||||
get { return assemblyReferences; } |
||||
} |
||||
|
||||
public IEnumerable<string> Authors { |
||||
get { return authors; } |
||||
} |
||||
|
||||
public IEnumerable<string> Owners { |
||||
get { return owners; } |
||||
} |
||||
|
||||
public IEnumerable<PackageDependency> Dependencies { |
||||
get { return DependenciesList; } |
||||
} |
||||
|
||||
public IEnumerable<IPackageFile> GetFiles() |
||||
{ |
||||
return files; |
||||
} |
||||
|
||||
public Stream GetStream() |
||||
{ |
||||
return stream; |
||||
} |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return "Package.Id: " + Id; |
||||
} |
||||
|
||||
public override bool Equals(object obj) |
||||
{ |
||||
FakePackage rhs = obj as FakePackage; |
||||
return (Id == rhs.Id) && (Version == rhs.Version); |
||||
} |
||||
|
||||
public override int GetHashCode() |
||||
{ |
||||
return base.GetHashCode(); |
||||
} |
||||
|
||||
public void AddAuthor(string author) |
||||
{ |
||||
authors.Add(author); |
||||
} |
||||
|
||||
public void AddDependency(string id, Version minVersion, Version maxVersion) |
||||
{ |
||||
var versionSpec = new VersionSpec(); |
||||
versionSpec.MinVersion = minVersion; |
||||
versionSpec.MaxVersion = maxVersion; |
||||
var dependency = new PackageDependency(id, versionSpec); |
||||
DependenciesList.Add(dependency); |
||||
} |
||||
|
||||
public void AddDependency(string id) |
||||
{ |
||||
DependenciesList.Add(new PackageDependency(id)); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,86 @@
@@ -0,0 +1,86 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.PackageManagement; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public class FakePackageManagementService : IPackageManagementService |
||||
{ |
||||
public event EventHandler PackageInstalled; |
||||
|
||||
PackageManagementOptions options = new PackageManagementOptions(new Properties()); |
||||
|
||||
protected virtual void OnPackageInstalled() |
||||
{ |
||||
if (PackageInstalled != null) { |
||||
PackageInstalled(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
public event EventHandler PackageUninstalled; |
||||
|
||||
protected virtual void OnPackageUninstalled() |
||||
{ |
||||
if (PackageUninstalled != null) { |
||||
PackageUninstalled(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
public IPackageRepository RepositoryPassedToInstallPackage; |
||||
public IPackage PackagePassedToInstallPackage; |
||||
public bool IsInstallPackageCalled; |
||||
|
||||
public IPackageRepository RepositoryPassedToUninstallPackage; |
||||
public IPackage PackagePassedToUninstallPackage; |
||||
|
||||
public FakeProjectManager FakeActiveProjectManager = new FakeProjectManager(); |
||||
public FakePackageRepository FakeActivePackageRepository = new FakePackageRepository(); |
||||
|
||||
public FakePackageManagementService() |
||||
{ |
||||
ActiveProjectManager = FakeActiveProjectManager; |
||||
ActivePackageRepository = FakeActivePackageRepository; |
||||
FakeActiveProjectManager.FakeSourceRepository = FakeActivePackageRepository; |
||||
} |
||||
|
||||
public IPackageRepository ActivePackageRepository { get; set; } |
||||
public IProjectManager ActiveProjectManager { get; set; } |
||||
|
||||
public void InstallPackage(IPackageRepository repository, IPackage package) |
||||
{ |
||||
IsInstallPackageCalled = true; |
||||
RepositoryPassedToInstallPackage = repository; |
||||
PackagePassedToInstallPackage = package; |
||||
} |
||||
|
||||
public void UninstallPackage(IPackageRepository repository, IPackage package) |
||||
{ |
||||
RepositoryPassedToUninstallPackage = repository; |
||||
PackagePassedToUninstallPackage = package; |
||||
} |
||||
|
||||
public void FirePackageInstalled() |
||||
{ |
||||
OnPackageInstalled(); |
||||
} |
||||
|
||||
public void FirePackageUninstalled() |
||||
{ |
||||
OnPackageUninstalled(); |
||||
} |
||||
|
||||
public void AddPackageToProjectLocalRepository(FakePackage package) |
||||
{ |
||||
FakeActiveProjectManager.FakeLocalRepository.FakePackages.Add(package); |
||||
} |
||||
|
||||
public PackageManagementOptions Options { |
||||
get { return options; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public class FakePackageRepository : IPackageRepository |
||||
{ |
||||
public List<FakePackage> FakePackages = new List<FakePackage>(); |
||||
public bool IsRemovePackageCalled; |
||||
|
||||
public IQueryable<IPackage> GetPackages() |
||||
{ |
||||
return FakePackages.AsQueryable(); |
||||
} |
||||
|
||||
public void AddPackage(IPackage package) |
||||
{ |
||||
} |
||||
|
||||
public void RemovePackage(IPackage package) |
||||
{ |
||||
IsRemovePackageCalled = true; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public class FakeProjectManager : ISharpDevelopProjectManager |
||||
{ |
||||
public FakePackageRepository FakeLocalRepository = new FakePackageRepository(); |
||||
public FakePackageRepository FakeSourceRepository = new FakePackageRepository(); |
||||
|
||||
public bool IsInstalledReturnValue; |
||||
|
||||
public FakeProjectManager() |
||||
{ |
||||
LocalRepository = FakeLocalRepository; |
||||
SourceRepository = FakeSourceRepository; |
||||
} |
||||
|
||||
public event EventHandler<PackageOperationEventArgs> PackageReferenceAdded; |
||||
|
||||
protected virtual void OnPackageReferenceAdded(IPackage package) |
||||
{ |
||||
if (PackageReferenceAdded != null) { |
||||
PackageReferenceAdded(this, new PackageOperationEventArgs(package, String.Empty)); |
||||
} |
||||
} |
||||
|
||||
#pragma warning disable 67
|
||||
public event EventHandler<PackageOperationEventArgs> PackageReferenceAdding; |
||||
public event EventHandler<PackageOperationEventArgs> PackageReferenceRemoved; |
||||
public event EventHandler<PackageOperationEventArgs> PackageReferenceRemoving; |
||||
#pragma warning restore 67
|
||||
|
||||
public IPackageRepository LocalRepository { get; set; } |
||||
public ILogger Logger { get; set; } |
||||
public IProjectSystem Project { get; set; } |
||||
public IPackageRepository SourceRepository { get; set; } |
||||
public IPackagePathResolver PathResolver { get; set; } |
||||
|
||||
public void AddPackageReference(string packageId, Version version, bool ignoreDependencies) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public void RemovePackageReference(string packageId, bool forceRemove, bool removeDependencies) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public void UpdatePackageReference(string packageId, Version version, bool updateDependencies) |
||||
{ |
||||
throw new NotImplementedException(); |
||||
} |
||||
|
||||
public bool IsInstalled(IPackage package) |
||||
{ |
||||
return IsInstalledReturnValue; |
||||
} |
||||
|
||||
public void FirePackageReferenceAdded(IPackage package) |
||||
{ |
||||
OnPackageReferenceAdded(package); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.ComponentModel; |
||||
using System.Windows; |
||||
|
||||
namespace ICSharpCode.PackageManagement.Design |
||||
{ |
||||
public static class WpfDesigner |
||||
{ |
||||
public static bool IsInDesignMode() |
||||
{ |
||||
var isInDesignModeProperty = DesignerProperties.IsInDesignModeProperty; |
||||
return GetPropertyDefaultValueAsBool(isInDesignModeProperty); |
||||
} |
||||
|
||||
static bool GetPropertyDefaultValueAsBool(DependencyProperty property) |
||||
{ |
||||
var dependencyPropertyDescriptor = GetDependencyPropertyDescriptor(property); |
||||
return GetPropertyDefaultValueAsBool(dependencyPropertyDescriptor); |
||||
} |
||||
|
||||
static DependencyPropertyDescriptor GetDependencyPropertyDescriptor(DependencyProperty property) |
||||
{ |
||||
return DependencyPropertyDescriptor.FromProperty(property, typeof(FrameworkElement)); |
||||
} |
||||
|
||||
static bool GetPropertyDefaultValueAsBool(DependencyPropertyDescriptor dependencyPropertyDescriptor) |
||||
{ |
||||
return (bool)dependencyPropertyDescriptor.Metadata.DefaultValue; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface ILicenseAcceptanceService |
||||
{ |
||||
bool AcceptLicenses(IEnumerable<IPackage> packages); |
||||
} |
||||
} |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface IPackageManagementFileService |
||||
{ |
||||
void RemoveFile(string path); |
||||
void RemoveDirectory(string path); |
||||
} |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface IPackageManagementProjectService |
||||
{ |
||||
IProject CurrentProject { get; } |
||||
void RefreshProjectBrowser(); |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface IPackageManagementService |
||||
{ |
||||
event EventHandler PackageInstalled; |
||||
event EventHandler PackageUninstalled; |
||||
|
||||
IPackageRepository ActivePackageRepository { get; } |
||||
IProjectManager ActiveProjectManager { get; } |
||||
|
||||
void InstallPackage(IPackageRepository repository, IPackage package); |
||||
void UninstallPackage(IPackageRepository repository, IPackage package); |
||||
|
||||
PackageManagementOptions Options { get; } |
||||
} |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface IPackageManagerFactory |
||||
{ |
||||
ISharpDevelopPackageManager CreatePackageManager( |
||||
IPackageRepository packageRepository, |
||||
MSBuildBasedProject project); |
||||
} |
||||
} |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface IPackageViewModelFactory |
||||
{ |
||||
PackageViewModel CreatePackageViewModel(IPackage package); |
||||
} |
||||
} |
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface ISharpDevelopPackageManager : IPackageManager |
||||
{ |
||||
ISharpDevelopProjectManager ProjectManager { get; } |
||||
void InstallPackage(IPackage package); |
||||
void UninstallPackage(IPackage package); |
||||
} |
||||
} |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface ISharpDevelopPackageRepositoryFactory : IPackageRepositoryFactory |
||||
{ |
||||
ISharedPackageRepository CreateSharedRepository(string path); |
||||
} |
||||
} |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface ISharpDevelopProjectManager : IProjectManager |
||||
{ |
||||
IPackagePathResolver PathResolver { get; } |
||||
} |
||||
} |
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public interface ISharpDevelopProjectSystemFactory |
||||
{ |
||||
IProjectSystem CreateProjectSystem(MSBuildBasedProject project); |
||||
} |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Linq; |
||||
using System.Collections.Generic; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class InstalledPackagesViewModel : PackagesViewModel |
||||
{ |
||||
public InstalledPackagesViewModel(IPackageManagementService packageManagementService) |
||||
: base(packageManagementService) |
||||
{ |
||||
packageManagementService.PackageInstalled += PackageInstalled; |
||||
packageManagementService.PackageUninstalled += PackageUninstalled; |
||||
} |
||||
|
||||
void PackageInstalled(object sender, EventArgs e) |
||||
{ |
||||
ReadPackages(); |
||||
} |
||||
|
||||
void PackageUninstalled(object sender, EventArgs e) |
||||
{ |
||||
ReadPackages(); |
||||
} |
||||
|
||||
protected override IQueryable<IPackage> GetAllPackages() |
||||
{ |
||||
IPackageRepository repository = GetRepository(); |
||||
return repository.GetPackages(); |
||||
} |
||||
|
||||
IPackageRepository GetRepository() |
||||
{ |
||||
return ProjectManager.LocalRepository; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Windows; |
||||
|
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class LicenseAcceptanceService : ILicenseAcceptanceService |
||||
{ |
||||
Window owner; |
||||
|
||||
public Window Owner { |
||||
get { |
||||
if (owner == null) { |
||||
owner = WorkbenchSingleton.MainWindow; |
||||
} |
||||
return owner; |
||||
} |
||||
set { owner = value; } |
||||
} |
||||
|
||||
public bool AcceptLicenses(IEnumerable<IPackage> packages) |
||||
{ |
||||
LicenseAcceptanceView view = CreateLicenseAcceptanceView(packages); |
||||
return view.ShowDialog() ?? false; |
||||
} |
||||
|
||||
LicenseAcceptanceView CreateLicenseAcceptanceView(IEnumerable<IPackage> packages) |
||||
{ |
||||
var viewModel = new LicenseAcceptanceViewModel(packages); |
||||
return CreateLicenseAcceptanceView(viewModel); |
||||
} |
||||
|
||||
LicenseAcceptanceView CreateLicenseAcceptanceView(LicenseAcceptanceViewModel viewModel) |
||||
{ |
||||
var view = new LicenseAcceptanceView(); |
||||
view.DataContext = viewModel; |
||||
view.Owner = Owner; |
||||
return view; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,116 @@
@@ -0,0 +1,116 @@
|
||||
<Window |
||||
x:Class="ICSharpCode.PackageManagement.LicenseAcceptanceView" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
xmlns:pm="clr-namespace:ICSharpCode.PackageManagement" |
||||
xmlns:pmd="clr-namespace:ICSharpCode.PackageManagement.Design" |
||||
mc:Ignorable="d" |
||||
WindowStartupLocation="CenterOwner" |
||||
Style="{x:Static core:GlobalStyles.DialogWindowStyle}" |
||||
Title="License Agreements" |
||||
Height="300" |
||||
Width="480" |
||||
MinHeight="300" |
||||
MinWidth="300"> |
||||
|
||||
<Window.Resources> |
||||
<Style TargetType="Button" BasedOn="{x:Static core:GlobalStyles.ButtonStyle}"/> |
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/> |
||||
<pm:OpenHyperlinkCommand x:Key="OpenHyperlinkCommand"/> |
||||
|
||||
<DataTemplate x:Key="ListBoxItemTemplate"> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto"/> |
||||
<ColumnDefinition /> |
||||
</Grid.ColumnDefinitions> |
||||
<StackPanel Margin="4"> |
||||
<TextBlock |
||||
FontWeight="Bold" |
||||
Text="{Binding Id}"/> |
||||
<TextBlock> |
||||
<Hyperlink |
||||
Command="{StaticResource OpenHyperlinkCommand}" |
||||
CommandParameter="{Binding Path=LicenseUrl}"> |
||||
<TextBlock Text="View License Terms"/> |
||||
</Hyperlink> |
||||
</TextBlock> |
||||
</StackPanel> |
||||
<TextBlock |
||||
Grid.Column="1" |
||||
Margin="4" |
||||
TextTrimming="CharacterEllipsis" |
||||
TextWrapping="Wrap" |
||||
MaxHeight="40" |
||||
Text="{Binding Summary}"/> |
||||
</Grid> |
||||
</DataTemplate> |
||||
</Window.Resources> |
||||
|
||||
<Grid |
||||
d:DataContext="{d:DesignInstance pmd:DesignTimeLicenseAcceptanceViewModel, IsDesignTimeCreatable=True}"> |
||||
|
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="Auto"/> |
||||
<RowDefinition /> |
||||
<RowDefinition Height="Auto"/> |
||||
<RowDefinition Height="Auto"/> |
||||
</Grid.RowDefinitions> |
||||
|
||||
<StackPanel |
||||
Margin="4, 2"> |
||||
<TextBlock |
||||
Visibility="{Binding Path=HasMultiplePackages, Converter={StaticResource BoolToVisibility}}" |
||||
TextWrapping="Wrap" |
||||
Text="The following packages require a click-to-accept license:"/> |
||||
<TextBlock |
||||
Visibility="{Binding Path=HasOnePackage, Converter={StaticResource BoolToVisibility}}" |
||||
TextWrapping="Wrap" |
||||
Text="The following package requires a click-to-accept license:"/> |
||||
</StackPanel> |
||||
<Border |
||||
Grid.Row="1" |
||||
BorderThickness="1" |
||||
BorderBrush="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"> |
||||
<ScrollViewer |
||||
VerticalScrollBarVisibility="Auto" |
||||
HorizontalScrollBarVisibility="Disabled"> |
||||
<ItemsControl |
||||
Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" |
||||
ItemTemplate="{StaticResource ListBoxItemTemplate}" |
||||
ItemsSource="{Binding Path=Packages}"/> |
||||
</ScrollViewer> |
||||
</Border> |
||||
<StackPanel |
||||
Grid.Row="2" |
||||
Margin="4"> |
||||
<TextBlock |
||||
Visibility="{Binding Path=HasMultiplePackages, Converter={StaticResource BoolToVisibility}}" |
||||
TextWrapping="Wrap"> |
||||
By clicking "I Accept" you agree to the license terms for the packages listed above. |
||||
If you do not agree to the license terms click "I Decline". |
||||
</TextBlock> |
||||
<TextBlock |
||||
Visibility="{Binding Path=HasOnePackage, Converter={StaticResource BoolToVisibility}}" |
||||
TextWrapping="Wrap"> |
||||
By clicking "I Accept" you agree to the license terms for the package listed above. |
||||
If you do not agree to the license terms click "I Decline". |
||||
</TextBlock> |
||||
</StackPanel> |
||||
<StackPanel |
||||
Grid.Row="3" |
||||
Margin="4" |
||||
Orientation="Horizontal" |
||||
HorizontalAlignment="Right"> |
||||
<Button |
||||
Content="I _Decline" |
||||
IsCancel="True"/> |
||||
<Button |
||||
Content="I _Accept" |
||||
Click="AcceptButtonClick"/> |
||||
</StackPanel> |
||||
</Grid> |
||||
</Window> |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Windows; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public partial class LicenseAcceptanceView : Window |
||||
{ |
||||
public LicenseAcceptanceView() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
|
||||
void AcceptButtonClick(object sender, RoutedEventArgs e) |
||||
{ |
||||
DialogResult = true; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class LicenseAcceptanceViewModel : ViewModelBase<LicenseAcceptanceViewModel> |
||||
{ |
||||
IList<IPackage> packages; |
||||
|
||||
public LicenseAcceptanceViewModel(IEnumerable<IPackage> packages) |
||||
{ |
||||
this.packages = packages.ToList(); |
||||
} |
||||
|
||||
public IEnumerable<IPackage> Packages { |
||||
get { return packages; } |
||||
} |
||||
|
||||
public bool HasOnePackage { |
||||
get { return packages.Count == 1; } |
||||
} |
||||
|
||||
public bool HasMultiplePackages { |
||||
get { return packages.Count > 1; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public static class ListBoxBehaviour |
||||
{ |
||||
public static readonly DependencyProperty IsSelectedItemScrolledIntoViewProperty = |
||||
DependencyProperty.RegisterAttached( |
||||
"IsSelectedItemScrolledIntoView", |
||||
typeof(bool), |
||||
typeof(ListBoxBehaviour), |
||||
new UIPropertyMetadata(false, OnIsSelectedItemScrolledIntoViewChanged)); |
||||
|
||||
public static bool GetIsSelectedItemScrolledIntoView(ListBox listBox) |
||||
{ |
||||
return (bool)listBox.GetValue(IsSelectedItemScrolledIntoViewProperty); |
||||
} |
||||
|
||||
public static void SetIsSelectedItemScrolledIntoView(ListBox listBox, bool value) |
||||
{ |
||||
listBox.SetValue(IsSelectedItemScrolledIntoViewProperty, value); |
||||
} |
||||
|
||||
static void OnIsSelectedItemScrolledIntoViewChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) |
||||
{ |
||||
var scrollingBehaviour = new SelectedListBoxItemScrollingBehaviour(dependencyObject, e); |
||||
scrollingBehaviour.Update(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Windows.Input; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class OpenHyperlinkCommand : ICommand |
||||
{ |
||||
public event EventHandler CanExecuteChanged; |
||||
|
||||
protected virtual void OnCanExecuteChanged() |
||||
{ |
||||
if (CanExecuteChanged != null) { |
||||
CanExecuteChanged(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
public bool CanExecute(object parameter) |
||||
{ |
||||
return true; |
||||
} |
||||
|
||||
public void Execute(object parameter) |
||||
{ |
||||
Uri uri = parameter as Uri; |
||||
if (uri != null) { |
||||
StartProcess(uri.AbsoluteUri); |
||||
} else { |
||||
StartProcess(parameter as string); |
||||
} |
||||
} |
||||
|
||||
protected virtual void StartProcess(string fileName) |
||||
{ |
||||
Process.Start(fileName); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public static class PackageManagementEnumerableExtensions |
||||
{ |
||||
public static IEnumerable<TSource> DistinctLast<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer) |
||||
{ |
||||
TSource previousItem = default(TSource); |
||||
|
||||
foreach (TSource currentItem in source) { |
||||
if (previousItem != null) { |
||||
if (!comparer.Equals(previousItem, currentItem)) { |
||||
yield return previousItem; |
||||
} |
||||
} |
||||
previousItem = currentItem; |
||||
} |
||||
|
||||
if (previousItem != null) { |
||||
yield return previousItem; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageManagementFileService : IPackageManagementFileService |
||||
{ |
||||
public void RemoveFile(string path) |
||||
{ |
||||
FileService.RemoveFile(path, false); |
||||
} |
||||
|
||||
public void RemoveDirectory(string path) |
||||
{ |
||||
FileService.RemoveFile(path, true); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.Specialized; |
||||
|
||||
using ICSharpCode.Core; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageManagementOptions |
||||
{ |
||||
Properties properties; |
||||
const string PackageSourcesPropertyName = "PackageSources"; |
||||
const string PackageDirectoryPropertyName = "PackagesDirectory"; |
||||
RegisteredPackageSources packageSources; |
||||
|
||||
public PackageManagementOptions(Properties properties) |
||||
{ |
||||
this.properties = properties; |
||||
} |
||||
|
||||
public PackageManagementOptions() |
||||
: this(PropertyService.Get("PackageManagementSettings", new Properties())) |
||||
{ |
||||
} |
||||
|
||||
public RegisteredPackageSources PackageSources { |
||||
get { |
||||
if (packageSources == null) { |
||||
packageSources = new RegisteredPackageSources(GetSavedPackageSources()); |
||||
packageSources.CollectionChanged += PackageSourcesChanged; |
||||
} |
||||
return packageSources; |
||||
} |
||||
} |
||||
|
||||
IEnumerable<PackageSource> GetSavedPackageSources() |
||||
{ |
||||
return PackageSourceConverter.ConvertFromRegisteredPackageSources(SavedRegisteredPackageSources); |
||||
} |
||||
|
||||
void PackageSourcesChanged(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
UpdateSavedPackageSources(); |
||||
} |
||||
|
||||
void UpdateSavedPackageSources() |
||||
{ |
||||
SavedRegisteredPackageSources = |
||||
PackageSourceConverter.ConvertToRegisteredPackageSourcesList(packageSources); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Use RegisteredPackageSource since PackageSource cannot be serialized.
|
||||
/// </summary>
|
||||
IList<RegisteredPackageSource> SavedRegisteredPackageSources { |
||||
get { |
||||
List<RegisteredPackageSource> defaultSources = new List<RegisteredPackageSource>(); |
||||
return properties.Get<List<RegisteredPackageSource>>(PackageSourcesPropertyName, defaultSources); |
||||
} |
||||
set { properties.Set(PackageSourcesPropertyName, value); } |
||||
} |
||||
|
||||
public string PackagesDirectory { |
||||
get { return properties.Get(PackageDirectoryPropertyName, "packages"); } |
||||
set { properties.Set(PackageDirectoryPropertyName, value); } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,134 @@
@@ -0,0 +1,134 @@
|
||||
<gui:OptionPanel |
||||
x:Class="ICSharpCode.PackageManagement.PackageManagementOptionsView" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:gui="clr-namespace:ICSharpCode.SharpDevelop.Gui;assembly=ICSharpCode.SharpDevelop" |
||||
xmlns:pm="clr-namespace:ICSharpCode.PackageManagement" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
Height="300"> |
||||
|
||||
<Grid x:Name="MainGrid"> |
||||
<Grid.Resources> |
||||
<pm:ViewModelLocator x:Key="ViewModelLocator"/> |
||||
|
||||
<Style |
||||
x:Key="ListBoxItemStyle" |
||||
TargetType="{x:Type ListBoxItem}"> |
||||
|
||||
<Style.Resources> |
||||
<SolidColorBrush |
||||
x:Key="{x:Static SystemColors.ControlBrushKey}" |
||||
Color="{DynamicResource {x:Static SystemColors.HighlightColorKey}}" /> |
||||
</Style.Resources> |
||||
|
||||
<Setter |
||||
Property="Background" |
||||
Value="LightGray"/> |
||||
|
||||
<Style.Triggers> |
||||
<Trigger |
||||
Property="ItemsControl.AlternationIndex" |
||||
Value="0"> |
||||
<Setter |
||||
Property="Background" |
||||
Value="White"/> |
||||
</Trigger> |
||||
</Style.Triggers> |
||||
</Style> |
||||
|
||||
<DataTemplate x:Key="PackageSourceListBoxTemplate"> |
||||
<StackPanel |
||||
x:Name="PackageSourceStackPanel" |
||||
Margin="4"> |
||||
<TextBlock Text="{Binding Path=Name}"/> |
||||
<TextBlock> |
||||
<Hyperlink> |
||||
<TextBlock Text="{Binding Path=SourceUrl}"/> |
||||
</Hyperlink> |
||||
</TextBlock> |
||||
</StackPanel> |
||||
</DataTemplate> |
||||
</Grid.Resources> |
||||
|
||||
<Grid.DataContext> |
||||
<Binding Source="{StaticResource ViewModelLocator}" Path="PackageManagementOptionsViewModel"/> |
||||
</Grid.DataContext> |
||||
|
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition Width="Auto"/> |
||||
</Grid.ColumnDefinitions> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition /> |
||||
<RowDefinition Height="Auto"/> |
||||
</Grid.RowDefinitions> |
||||
<ListBox |
||||
Grid.Row="0" |
||||
HorizontalContentAlignment="Stretch" |
||||
AlternationCount="2" |
||||
pm:ListBoxBehaviour.IsSelectedItemScrolledIntoView="True" |
||||
ItemContainerStyle="{StaticResource ListBoxItemStyle}" |
||||
ItemTemplate="{StaticResource PackageSourceListBoxTemplate}" |
||||
ItemsSource="{Binding Path=PackageSourceViewModels}" |
||||
SelectedItem="{Binding Path=SelectedPackageSourceViewModel}"/> |
||||
<Grid |
||||
Grid.Row="1" |
||||
Margin="4"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto"/> |
||||
<ColumnDefinition /> |
||||
</Grid.ColumnDefinitions> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition /> |
||||
<RowDefinition /> |
||||
</Grid.RowDefinitions> |
||||
<TextBlock |
||||
Grid.Row="0" |
||||
Grid.Column="0" |
||||
Margin="4" |
||||
Text="Name:"/> |
||||
<TextBox |
||||
Grid.Row="0" |
||||
Grid.Column="1" |
||||
Text="{Binding Path=NewPackageSourceName, UpdateSourceTrigger=PropertyChanged}" |
||||
Margin="4, 2"/> |
||||
<TextBlock |
||||
Grid.Row="1" |
||||
Grid.Column="0" |
||||
Margin="4" |
||||
Text="Source:"/> |
||||
<TextBox |
||||
Grid.Row="1" |
||||
Grid.Column="1" |
||||
Text="{Binding Path=NewPackageSourceUrl, UpdateSourceTrigger=PropertyChanged}" |
||||
Margin="4,2"/> |
||||
</Grid> |
||||
<StackPanel |
||||
Grid.Column="1" |
||||
Grid.Row="0"> |
||||
<Button |
||||
Content="Move Up" |
||||
Command="{Binding Path=MovePackageSourceUpCommand}" |
||||
Margin="4, 2" |
||||
Padding="7, 0"/> |
||||
<Button |
||||
Content="Move Down" |
||||
Command="{Binding Path=MovePackageSourceDownCommand}" |
||||
Margin="4, 2" |
||||
Padding="7, 0"/> |
||||
<Button |
||||
Content="Remove" |
||||
Command="{Binding Path=RemovePackageSourceCommand}" |
||||
Margin="4, 2" |
||||
Padding="7, 0"/> |
||||
</StackPanel> |
||||
<StackPanel |
||||
Grid.Column="1" |
||||
Grid.Row="1"> |
||||
<Button |
||||
Content="Add" |
||||
Command="{Binding Path=AddPackageSourceCommand}" |
||||
Margin="4, 2" |
||||
Padding="7, 0"/> |
||||
</StackPanel> |
||||
</Grid> |
||||
</gui:OptionPanel> |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public partial class PackageManagementOptionsView : OptionPanel |
||||
{ |
||||
const string ViewModelResourceName = "PackageManagementOptionsViewModel"; |
||||
PackageManagementOptionsViewModel viewModel; |
||||
|
||||
public PackageManagementOptionsView() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
|
||||
PackageManagementOptionsViewModel ViewModel { |
||||
get { |
||||
if (viewModel == null) { |
||||
viewModel = MainGrid.DataContext as PackageManagementOptionsViewModel; |
||||
} |
||||
return viewModel; |
||||
} |
||||
} |
||||
|
||||
public override void LoadOptions() |
||||
{ |
||||
ViewModel.Load(); |
||||
} |
||||
|
||||
public override bool SaveOptions() |
||||
{ |
||||
ViewModel.Save(); |
||||
return true; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,213 @@
@@ -0,0 +1,213 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.ObjectModel; |
||||
using System.Linq; |
||||
using System.Windows.Input; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageManagementOptionsViewModel : ViewModelBase<PackageManagementOptionsViewModel> |
||||
{ |
||||
ObservableCollection<PackageSourceViewModel> packageSourceViewModels = |
||||
new ObservableCollection<PackageSourceViewModel>(); |
||||
PackageManagementOptions options; |
||||
|
||||
DelegateCommand addPackageSourceCommmand; |
||||
DelegateCommand removePackageSourceCommand; |
||||
DelegateCommand movePackageSourceUpCommand; |
||||
DelegateCommand movePackageSourceDownCommand; |
||||
|
||||
RegisteredPackageSource newPackageSource = new RegisteredPackageSource(); |
||||
PackageSourceViewModel selectedPackageSourceViewModel; |
||||
|
||||
public PackageManagementOptionsViewModel(PackageManagementOptions options) |
||||
{ |
||||
this.options = options; |
||||
CreateCommands(); |
||||
} |
||||
|
||||
void CreateCommands() |
||||
{ |
||||
addPackageSourceCommmand = |
||||
new DelegateCommand(param => AddPackageSource(), |
||||
param => CanAddPackageSource); |
||||
|
||||
removePackageSourceCommand = |
||||
new DelegateCommand(param => RemovePackageSource(), |
||||
param => CanRemovePackageSource); |
||||
|
||||
movePackageSourceUpCommand = |
||||
new DelegateCommand(param => MovePackageSourceUp(), |
||||
param => CanMovePackageSourceUp); |
||||
|
||||
movePackageSourceDownCommand = |
||||
new DelegateCommand(param => MovePackageSourceDown(), |
||||
param => CanMovePackageSourceDown); |
||||
} |
||||
|
||||
public ICommand AddPackageSourceCommand { |
||||
get { return addPackageSourceCommmand; } |
||||
} |
||||
|
||||
public ICommand RemovePackageSourceCommand { |
||||
get { return removePackageSourceCommand; } |
||||
} |
||||
|
||||
public ICommand MovePackageSourceUpCommand { |
||||
get { return movePackageSourceUpCommand; } |
||||
} |
||||
|
||||
public ICommand MovePackageSourceDownCommand { |
||||
get { return movePackageSourceDownCommand; } |
||||
} |
||||
|
||||
public ObservableCollection<PackageSourceViewModel> PackageSourceViewModels { |
||||
get { return packageSourceViewModels; } |
||||
} |
||||
|
||||
public void Load() |
||||
{ |
||||
foreach (PackageSource packageSource in options.PackageSources) { |
||||
AddPackageSourceToViewModel(packageSource); |
||||
} |
||||
} |
||||
|
||||
void AddPackageSourceToViewModel(PackageSource packageSource) |
||||
{ |
||||
var packageSourceViewModel = new PackageSourceViewModel(packageSource); |
||||
packageSourceViewModels.Add(packageSourceViewModel); |
||||
} |
||||
|
||||
public void Save() |
||||
{ |
||||
options.PackageSources.Clear(); |
||||
foreach (PackageSourceViewModel packageSourceViewModel in packageSourceViewModels) { |
||||
PackageSource source = packageSourceViewModel.GetPackageSource(); |
||||
options.PackageSources.Add(source); |
||||
} |
||||
} |
||||
|
||||
public string NewPackageSourceName { |
||||
get { return newPackageSource.Name; } |
||||
set { newPackageSource.Name = value; } |
||||
} |
||||
|
||||
public string NewPackageSourceUrl { |
||||
get { return newPackageSource.Source; } |
||||
set { newPackageSource.Source = value; } |
||||
} |
||||
|
||||
public PackageSourceViewModel SelectedPackageSourceViewModel { |
||||
get { return selectedPackageSourceViewModel; } |
||||
set { |
||||
selectedPackageSourceViewModel = value; |
||||
OnPropertyChanged(viewModel => viewModel.SelectedPackageSourceViewModel); |
||||
OnPropertyChanged(viewModel => viewModel.CanAddPackageSource); |
||||
} |
||||
} |
||||
|
||||
public void AddPackageSource() |
||||
{ |
||||
AddNewPackageSourceToViewModel(); |
||||
SelectLastPackageSourceViewModel(); |
||||
} |
||||
|
||||
void AddNewPackageSourceToViewModel() |
||||
{ |
||||
var packageSource = newPackageSource.ToPackageSource(); |
||||
AddPackageSourceToViewModel(packageSource); |
||||
} |
||||
|
||||
void SelectLastPackageSourceViewModel() |
||||
{ |
||||
SelectedPackageSourceViewModel = GetLastPackageSourceViewModel(); |
||||
} |
||||
|
||||
public bool CanAddPackageSource { |
||||
get { |
||||
return NewPackageSourceHasUrl && NewPackageSourceHasName; |
||||
} |
||||
} |
||||
|
||||
bool NewPackageSourceHasUrl { |
||||
get { |
||||
return !String.IsNullOrEmpty(NewPackageSourceUrl); |
||||
} |
||||
} |
||||
|
||||
bool NewPackageSourceHasName { |
||||
get { |
||||
return !String.IsNullOrEmpty(NewPackageSourceName); |
||||
} |
||||
} |
||||
|
||||
public void RemovePackageSource() |
||||
{ |
||||
RemoveSelectedPackageSourceViewModel(); |
||||
} |
||||
|
||||
public bool CanRemovePackageSource { |
||||
get { return selectedPackageSourceViewModel != null; } |
||||
} |
||||
|
||||
void RemoveSelectedPackageSourceViewModel() |
||||
{ |
||||
packageSourceViewModels.Remove(selectedPackageSourceViewModel); |
||||
} |
||||
|
||||
public void MovePackageSourceUp() |
||||
{ |
||||
int selectedPackageSourceIndex = GetSelectedPackageSourceViewModelIndex(); |
||||
int destinationPackageSourceIndex = selectedPackageSourceIndex--; |
||||
packageSourceViewModels.Move(selectedPackageSourceIndex, destinationPackageSourceIndex); |
||||
} |
||||
|
||||
int GetSelectedPackageSourceViewModelIndex() |
||||
{ |
||||
return packageSourceViewModels.IndexOf(selectedPackageSourceViewModel); |
||||
} |
||||
|
||||
public bool CanMovePackageSourceUp { |
||||
get { |
||||
return HasAtLeastTwoPackageSources() && !IsFirstPackageSourceSelected(); |
||||
} |
||||
} |
||||
|
||||
bool IsFirstPackageSourceSelected() |
||||
{ |
||||
return selectedPackageSourceViewModel == packageSourceViewModels[0]; |
||||
} |
||||
|
||||
public void MovePackageSourceDown() |
||||
{ |
||||
int selectedPackageSourceIndex = GetSelectedPackageSourceViewModelIndex(); |
||||
int destinationPackageSourceIndex = selectedPackageSourceIndex++; |
||||
packageSourceViewModels.Move(selectedPackageSourceIndex, destinationPackageSourceIndex); |
||||
} |
||||
|
||||
public bool CanMovePackageSourceDown { |
||||
get { |
||||
return HasAtLeastTwoPackageSources() && !IsLastPackageSourceSelected(); |
||||
} |
||||
} |
||||
|
||||
bool HasAtLeastTwoPackageSources() |
||||
{ |
||||
return packageSourceViewModels.Count >= 2; |
||||
} |
||||
|
||||
bool IsLastPackageSourceSelected() |
||||
{ |
||||
PackageSourceViewModel lastViewModel = GetLastPackageSourceViewModel(); |
||||
return lastViewModel == selectedPackageSourceViewModel; |
||||
} |
||||
|
||||
PackageSourceViewModel GetLastPackageSourceViewModel() |
||||
{ |
||||
return packageSourceViewModels.Last(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using ICSharpCode.SharpDevelop.Project.Commands; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageManagementProjectService : IPackageManagementProjectService |
||||
{ |
||||
public IProject CurrentProject { |
||||
get { return ProjectService.CurrentProject; } |
||||
} |
||||
|
||||
public void RefreshProjectBrowser() |
||||
{ |
||||
var refreshCommand = new RefreshProjectBrowser(); |
||||
refreshCommand.Run(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,108 @@
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageManagementService : IPackageManagementService |
||||
{ |
||||
PackageManagementOptions options; |
||||
ISharpDevelopPackageRepositoryFactory packageRepositoryFactory; |
||||
IPackageManagerFactory packageManagerFactory; |
||||
IPackageManagementProjectService projectService; |
||||
IPackageRepository activePackageRepository; |
||||
|
||||
public PackageManagementService(PackageManagementOptions options, |
||||
ISharpDevelopPackageRepositoryFactory packageRepositoryFactory, |
||||
IPackageManagerFactory packageManagerFactory, |
||||
IPackageManagementProjectService projectService) |
||||
{ |
||||
this.options = options; |
||||
this.packageRepositoryFactory = packageRepositoryFactory; |
||||
this.packageManagerFactory = packageManagerFactory; |
||||
this.projectService = projectService; |
||||
} |
||||
|
||||
public PackageManagementService() |
||||
: this(new PackageManagementOptions(), |
||||
new SharpDevelopPackageRepositoryFactory(), |
||||
new SharpDevelopPackageManagerFactory(), |
||||
new PackageManagementProjectService()) |
||||
{ |
||||
} |
||||
|
||||
public PackageManagementOptions Options { |
||||
get { return options; } |
||||
} |
||||
|
||||
public event EventHandler PackageInstalled; |
||||
|
||||
protected virtual void OnPackageInstalled() |
||||
{ |
||||
if (PackageInstalled != null) { |
||||
PackageInstalled(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
public event EventHandler PackageUninstalled; |
||||
|
||||
protected virtual void OnPackageUninstalled() |
||||
{ |
||||
if (PackageUninstalled != null) { |
||||
PackageUninstalled(this, new EventArgs()); |
||||
} |
||||
} |
||||
|
||||
public IPackageRepository ActivePackageRepository { |
||||
get { return GetActivePackageRepository(); } |
||||
} |
||||
|
||||
IPackageRepository GetActivePackageRepository() |
||||
{ |
||||
if (activePackageRepository == null) { |
||||
PackageSource packageSource = options.PackageSources[0]; |
||||
activePackageRepository = packageRepositoryFactory.CreateRepository(packageSource); |
||||
} |
||||
return activePackageRepository; |
||||
} |
||||
|
||||
public IProjectManager ActiveProjectManager { |
||||
get { return GetActiveProjectManager(); } |
||||
} |
||||
|
||||
IProjectManager GetActiveProjectManager() |
||||
{ |
||||
IPackageRepository repository = ActivePackageRepository; |
||||
ISharpDevelopPackageManager packageManager = CreatePackageManager(repository); |
||||
return packageManager.ProjectManager; |
||||
} |
||||
|
||||
public void InstallPackage(IPackageRepository packageRepository, IPackage package) |
||||
{ |
||||
ISharpDevelopPackageManager packageManager = CreatePackageManager(packageRepository); |
||||
packageManager.InstallPackage(package); |
||||
projectService.RefreshProjectBrowser(); |
||||
OnPackageInstalled(); |
||||
} |
||||
|
||||
ISharpDevelopPackageManager CreatePackageManager(IPackageRepository packageRepository) |
||||
{ |
||||
MSBuildBasedProject project = projectService.CurrentProject as MSBuildBasedProject; |
||||
return packageManagerFactory.CreatePackageManager(packageRepository, project); |
||||
} |
||||
|
||||
public void UninstallPackage(IPackageRepository repository, IPackage package) |
||||
{ |
||||
ISharpDevelopPackageManager packageManager = CreatePackageManager(repository); |
||||
packageManager.UninstallPackage(package); |
||||
projectService.RefreshProjectBrowser(); |
||||
OnPackageUninstalled(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.IO; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageRepositoryPaths |
||||
{ |
||||
string packagesRelativeDirectory; |
||||
string solutionPackagesPath; |
||||
IProject project; |
||||
|
||||
public PackageRepositoryPaths(IProject project) |
||||
: this(project, new PackageManagementOptions()) |
||||
{ |
||||
} |
||||
|
||||
public PackageRepositoryPaths(IProject project, PackageManagementOptions options) |
||||
{ |
||||
packagesRelativeDirectory = options.PackagesDirectory; |
||||
this.project = project; |
||||
GetPaths(); |
||||
} |
||||
|
||||
void GetPaths() |
||||
{ |
||||
GetSolutionPackagesPath(); |
||||
} |
||||
|
||||
void GetSolutionPackagesPath() |
||||
{ |
||||
solutionPackagesPath = Path.Combine(project.ParentSolution.Directory, packagesRelativeDirectory); |
||||
} |
||||
|
||||
public string SolutionPackagesPath { |
||||
get { return solutionPackagesPath; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public static class PackageSourceConverter |
||||
{ |
||||
public static IEnumerable<PackageSource> ConvertFromRegisteredPackageSources(IEnumerable<RegisteredPackageSource> registeredPackageSources) |
||||
{ |
||||
foreach (RegisteredPackageSource registeredPackageSource in registeredPackageSources) { |
||||
yield return registeredPackageSource.ToPackageSource(); |
||||
} |
||||
} |
||||
|
||||
public static IEnumerable<RegisteredPackageSource> ConvertToRegisteredPackageSources(IEnumerable<PackageSource> packageSources) |
||||
{ |
||||
foreach (PackageSource packageSource in packageSources) { |
||||
yield return new RegisteredPackageSource(packageSource); |
||||
} |
||||
} |
||||
|
||||
public static IList<RegisteredPackageSource> ConvertToRegisteredPackageSourcesList(IEnumerable<PackageSource> packageSources) |
||||
{ |
||||
IEnumerable<RegisteredPackageSource> convertedPackageSources = ConvertToRegisteredPackageSources(packageSources); |
||||
return new List<RegisteredPackageSource>(convertedPackageSources); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageSourceViewModel : ViewModelBase<PackageSourceViewModel> |
||||
{ |
||||
RegisteredPackageSource packageSource; |
||||
|
||||
public PackageSourceViewModel(PackageSource packageSource) |
||||
{ |
||||
this.packageSource = new RegisteredPackageSource(packageSource); |
||||
} |
||||
|
||||
public PackageSource GetPackageSource() |
||||
{ |
||||
return packageSource.ToPackageSource(); |
||||
} |
||||
|
||||
public string Name { |
||||
get { return packageSource.Name; } |
||||
set { packageSource.Name = value; } |
||||
} |
||||
|
||||
public string SourceUrl { |
||||
get { return packageSource.Source; } |
||||
set { packageSource.Source = value; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
|
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageUpdatesViewModel : PackagesViewModel |
||||
{ |
||||
List<IPackage> packages = new List<IPackage>(); |
||||
IPackageManagementService packageManagementService; |
||||
|
||||
public PackageUpdatesViewModel(IPackageManagementService packageManagementService) |
||||
: base(packageManagementService) |
||||
{ |
||||
this.packageManagementService = packageManagementService; |
||||
} |
||||
|
||||
protected override IQueryable<IPackage> GetAllPackages() |
||||
{ |
||||
IQueryable<IPackage> localPackages = GetLocalRepositoryPackages(); |
||||
return GetUpdatedPackages(localPackages); |
||||
} |
||||
|
||||
IQueryable<IPackage> GetLocalRepositoryPackages() |
||||
{ |
||||
IProjectManager projectManager = packageManagementService.ActiveProjectManager; |
||||
IPackageRepository localRepository = projectManager.LocalRepository; |
||||
return localRepository.GetPackages(); |
||||
} |
||||
|
||||
IQueryable<IPackage> GetUpdatedPackages(IQueryable<IPackage> localPackages) |
||||
{ |
||||
IPackageRepository sourceRepository = packageManagementService.ActivePackageRepository; |
||||
return sourceRepository.GetUpdates(localPackages).AsQueryable(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,203 @@
@@ -0,0 +1,203 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Windows.Input; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageViewModel : ViewModelBase<PackageViewModel> |
||||
{ |
||||
DelegateCommand addPackageCommand; |
||||
DelegateCommand removePackageCommand; |
||||
|
||||
IPackageManagementService packageManagementService; |
||||
ILicenseAcceptanceService licenseAcceptanceService; |
||||
IPackage package; |
||||
IPackageRepository packageRepository; |
||||
bool? hasDependencies; |
||||
|
||||
public PackageViewModel( |
||||
IPackage package, |
||||
IPackageManagementService packageManagementService, |
||||
ILicenseAcceptanceService licenseAcceptanceService) |
||||
{ |
||||
this.package = package; |
||||
this.packageRepository = packageManagementService.ActivePackageRepository; |
||||
this.packageManagementService = packageManagementService; |
||||
this.licenseAcceptanceService = licenseAcceptanceService; |
||||
|
||||
CreateCommands(); |
||||
} |
||||
|
||||
void CreateCommands() |
||||
{ |
||||
addPackageCommand = new DelegateCommand(param => AddPackage()); |
||||
removePackageCommand = new DelegateCommand(param => RemovePackage()); |
||||
} |
||||
|
||||
public IPackageRepository Repository { |
||||
get { return packageRepository; } |
||||
} |
||||
|
||||
public ICommand AddPackageCommand { |
||||
get { return addPackageCommand; } |
||||
} |
||||
|
||||
public ICommand RemovePackageCommand { |
||||
get { return removePackageCommand; } |
||||
} |
||||
|
||||
public IPackage GetPackage() |
||||
{ |
||||
return package; |
||||
} |
||||
|
||||
public bool HasLicenseUrl { |
||||
get { return LicenseUrl != null; } |
||||
} |
||||
|
||||
public Uri LicenseUrl { |
||||
get { return package.LicenseUrl; } |
||||
} |
||||
|
||||
public bool HasProjectUrl { |
||||
get { return ProjectUrl != null; } |
||||
} |
||||
|
||||
public Uri ProjectUrl { |
||||
get { return package.ProjectUrl; } |
||||
} |
||||
|
||||
public bool HasReportAbuseUrl { |
||||
get { return ReportAbuseUrl != null; } |
||||
} |
||||
|
||||
public Uri ReportAbuseUrl { |
||||
get { return package.ReportAbuseUrl; } |
||||
} |
||||
|
||||
public bool IsAdded { |
||||
get { return IsPackageInstalled(); } |
||||
} |
||||
|
||||
bool IsPackageInstalled() |
||||
{ |
||||
return IsPackageInstalled(package); |
||||
} |
||||
|
||||
bool IsPackageInstalled(IPackage package) |
||||
{ |
||||
return packageManagementService.ActiveProjectManager.IsInstalled(package); |
||||
} |
||||
|
||||
public IEnumerable<PackageDependency> Dependencies { |
||||
get { return package.Dependencies; } |
||||
} |
||||
|
||||
public bool HasDependencies { |
||||
get { |
||||
if (!hasDependencies.HasValue) { |
||||
IEnumerator<PackageDependency> enumerator = Dependencies.GetEnumerator(); |
||||
hasDependencies = enumerator.MoveNext(); |
||||
} |
||||
return hasDependencies.Value; |
||||
} |
||||
} |
||||
|
||||
public bool HasNoDependencies { |
||||
get { return !HasDependencies; } |
||||
} |
||||
|
||||
public IEnumerable<string> Authors { |
||||
get { return package.Authors; } |
||||
} |
||||
|
||||
public bool HasDownloadCount { |
||||
get { |
||||
return package.DownloadCount >= 0; |
||||
} |
||||
} |
||||
|
||||
public string Id { |
||||
get { return package.Id; } |
||||
} |
||||
|
||||
public Uri IconUrl { |
||||
get { return package.IconUrl; } |
||||
} |
||||
|
||||
public string Summary { |
||||
get { return package.Summary; } |
||||
} |
||||
|
||||
public Version Version { |
||||
get { return package.Version; } |
||||
} |
||||
|
||||
public int DownloadCount { |
||||
get { return package.DownloadCount; } |
||||
} |
||||
|
||||
public double Rating { |
||||
get { return package.Rating; } |
||||
} |
||||
|
||||
public string Description { |
||||
get { return package.Description; } |
||||
} |
||||
|
||||
public void AddPackage() |
||||
{ |
||||
if (CanInstallPackage()) { |
||||
InstallPackage(); |
||||
} |
||||
} |
||||
|
||||
bool CanInstallPackage() |
||||
{ |
||||
IEnumerable<IPackage> packages = GetPackagesRequiringLicenseAcceptance(); |
||||
if (packages.Any()) { |
||||
return licenseAcceptanceService.AcceptLicenses(packages); |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
IEnumerable<IPackage> GetPackagesRequiringLicenseAcceptance() |
||||
{ |
||||
IList<IPackage> packagesToBeInstalled = GetPackagesToBeInstalled(); |
||||
return GetPackagesRequiringLicenseAcceptance(packagesToBeInstalled); |
||||
} |
||||
|
||||
IEnumerable<IPackage> GetPackagesRequiringLicenseAcceptance(IList<IPackage> packagesToBeInstalled) |
||||
{ |
||||
return packagesToBeInstalled.Where(package => PackageRequiresLicenseAcceptance(package)); |
||||
} |
||||
|
||||
IList<IPackage> GetPackagesToBeInstalled() |
||||
{ |
||||
var resolver = new DependencyResolver(packageRepository); |
||||
return resolver.GetDependencies(package).ToList(); |
||||
} |
||||
|
||||
bool PackageRequiresLicenseAcceptance(IPackage package) |
||||
{ |
||||
return package.RequireLicenseAcceptance && !IsPackageInstalled(package); |
||||
} |
||||
|
||||
void InstallPackage() |
||||
{ |
||||
packageManagementService.InstallPackage(packageRepository, package); |
||||
OnPropertyChanged(model => model.IsAdded); |
||||
} |
||||
|
||||
public void RemovePackage() |
||||
{ |
||||
packageManagementService.UninstallPackage(packageRepository, package); |
||||
OnPropertyChanged(model => model.IsAdded); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class PackageViewModelFactory : IPackageViewModelFactory |
||||
{ |
||||
IPackageManagementService packageManagementService; |
||||
ILicenseAcceptanceService licenseAcceptanceService; |
||||
|
||||
public PackageViewModelFactory(IPackageManagementService packageManagementService) |
||||
: this(packageManagementService, null) |
||||
{ |
||||
} |
||||
|
||||
public PackageViewModelFactory( |
||||
IPackageManagementService packageManagementService, |
||||
ILicenseAcceptanceService licenseAcceptanceService) |
||||
{ |
||||
this.packageManagementService = packageManagementService; |
||||
this.licenseAcceptanceService = licenseAcceptanceService; |
||||
} |
||||
|
||||
public PackageViewModel CreatePackageViewModel(IPackage package) |
||||
{ |
||||
return new PackageViewModel( |
||||
package, |
||||
packageManagementService, |
||||
licenseAcceptanceService); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,278 @@
@@ -0,0 +1,278 @@
|
||||
<UserControl |
||||
x:Class="ICSharpCode.PackageManagement.PackagesView" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
xmlns:pm="clr-namespace:ICSharpCode.PackageManagement" |
||||
xmlns:pmd="clr-namespace:ICSharpCode.PackageManagement.Design" |
||||
mc:Ignorable="d" |
||||
d:DesignHeight="250" |
||||
d:DesignWidth="500"> |
||||
|
||||
<UserControl.Resources> |
||||
<Style TargetType="Button" BasedOn="{x:Static core:GlobalStyles.ButtonStyle}"/> |
||||
<pm:OpenHyperlinkCommand x:Key="OpenHyperlinkCommand"/> |
||||
<BitmapImage x:Key="DefaultPackageIcon" |
||||
UriSource="pack://application:,,,/PackageManagement;component/Resources/packageicon.png"/> |
||||
<BitmapImage x:Key="PackageAddedIcon" |
||||
UriSource="pack://application:,,,/PackageManagement;component/Resources/accept.png"/> |
||||
<BitmapImage x:Key="SearchIcon" |
||||
UriSource="pack://application:,,,/PackageManagement;component/Resources/magnifier.png"/> |
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/> |
||||
|
||||
<DataTemplate x:Key="PackagesListBoxTemplate"> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="60"/> |
||||
<ColumnDefinition Width="*"/> |
||||
<ColumnDefinition Width="Auto"/> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="60"/> |
||||
</Grid.RowDefinitions> |
||||
|
||||
<Image |
||||
Grid.Column="0" |
||||
Height="32" |
||||
Source="{Binding Path=IconUrl, TargetNullValue={StaticResource DefaultPackageIcon}}"/> |
||||
<StackPanel |
||||
Grid.Column="1" |
||||
Margin="4, 0"> |
||||
<TextBlock |
||||
Text="{Binding Path=Id}" |
||||
FontWeight="Bold"/> |
||||
<TextBlock |
||||
Text="{Binding Path=Summary}" |
||||
TextWrapping="Wrap" |
||||
TextTrimming="CharacterEllipsis" |
||||
MaxHeight="40"/> |
||||
</StackPanel> |
||||
<Image |
||||
Grid.Column="2" |
||||
VerticalAlignment="Top" |
||||
HorizontalAlignment="Right" |
||||
Height="16" |
||||
Width="16" |
||||
Source="{StaticResource PackageAddedIcon}" |
||||
Visibility="{Binding Path=IsAdded, Converter={StaticResource BoolToVisibility}}"/> |
||||
<Button |
||||
x:Name="addPackageButton" |
||||
Grid.Column="2" |
||||
Content="Add" |
||||
IsDefault="True" |
||||
Visibility="Collapsed" |
||||
Command="{Binding Path=AddPackageCommand}" |
||||
VerticalAlignment="Top"/> |
||||
<Button |
||||
x:Name="removePackageButton" |
||||
Grid.Column="2" |
||||
Content="Remove" |
||||
IsDefault="True" |
||||
Visibility="Collapsed" |
||||
Command="{Binding Path=RemovePackageCommand}" |
||||
VerticalAlignment="Bottom"/> |
||||
</Grid> |
||||
|
||||
<DataTemplate.Triggers> |
||||
<MultiDataTrigger> |
||||
<MultiDataTrigger.Conditions> |
||||
<Condition |
||||
Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" |
||||
Value="True"/> |
||||
<Condition |
||||
Binding="{Binding Path=IsAdded}" |
||||
Value="False"/> |
||||
</MultiDataTrigger.Conditions> |
||||
<Setter |
||||
TargetName="addPackageButton" |
||||
Property="Visibility" |
||||
Value="Visible"/> |
||||
</MultiDataTrigger> |
||||
<MultiDataTrigger> |
||||
<MultiDataTrigger.Conditions> |
||||
<Condition |
||||
Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" |
||||
Value="True"/> |
||||
<Condition |
||||
Binding="{Binding Path=IsAdded}" |
||||
Value="True"/> |
||||
</MultiDataTrigger.Conditions> |
||||
<Setter |
||||
TargetName="removePackageButton" |
||||
Property="Visibility" |
||||
Value="Visible"/> |
||||
</MultiDataTrigger> |
||||
</DataTemplate.Triggers> |
||||
</DataTemplate> |
||||
|
||||
<DataTemplate x:Key="PackageTemplate"> |
||||
<ScrollViewer |
||||
VerticalScrollBarVisibility="Auto"> |
||||
<StackPanel Margin="8, 4"> |
||||
<StackPanel |
||||
Orientation="Horizontal" |
||||
Margin="0, 4"> |
||||
<TextBlock |
||||
Text="Created by:" |
||||
FontWeight="Bold"/> |
||||
<ItemsControl |
||||
Margin="4, 0" |
||||
ItemsSource="{Binding Path=Authors}"/> |
||||
</StackPanel> |
||||
<StackPanel |
||||
Orientation="Horizontal" |
||||
Margin="0, 4"> |
||||
<TextBlock |
||||
Text="Version:" |
||||
FontWeight="Bold" |
||||
Margin="0, 0, 4, 0"/> |
||||
<TextBlock Text="{Binding Path=Version}"/> |
||||
</StackPanel> |
||||
<StackPanel |
||||
Orientation="Horizontal" |
||||
Visibility="{Binding Path=HasDownloadCount, Converter={StaticResource BoolToVisibility}}" |
||||
Margin="0, 4"> |
||||
<TextBlock |
||||
Margin="0, 0, 4, 0" |
||||
Text="Downloads:" |
||||
FontWeight="Bold"/> |
||||
<TextBlock Text="{Binding Path=DownloadCount}"/> |
||||
</StackPanel> |
||||
<StackPanel |
||||
Visibility="Collapsed" |
||||
Orientation="Horizontal" |
||||
Margin="0, 4"> |
||||
<TextBlock |
||||
Margin="0, 0, 4, 0" |
||||
Text="Rating:" |
||||
FontWeight="Bold"/> |
||||
<TextBlock Text="{Binding Path=Rating}"/> |
||||
</StackPanel> |
||||
<TextBlock |
||||
Visibility="{Binding Path=HasLicenseUrl, Converter={StaticResource BoolToVisibility}}"> |
||||
<Hyperlink |
||||
Command="{StaticResource OpenHyperlinkCommand}" |
||||
CommandParameter="{Binding Path=LicenseUrl}"> |
||||
<TextBlock Text="View License Terms"/> |
||||
</Hyperlink> |
||||
</TextBlock> |
||||
<TextBlock |
||||
Visibility="{Binding Path=HasProjectUrl, Converter={StaticResource BoolToVisibility}}"> |
||||
<Hyperlink |
||||
Command="{StaticResource OpenHyperlinkCommand}" |
||||
CommandParameter="{Binding Path=ProjectUrl}"> |
||||
<TextBlock Text="More Information"/> |
||||
</Hyperlink> |
||||
</TextBlock> |
||||
<TextBlock |
||||
Visibility="{Binding Path=HasReportAbuseUrl, Converter={StaticResource BoolToVisibility}}"> |
||||
<Hyperlink |
||||
Command="{StaticResource OpenHyperlinkCommand}" |
||||
CommandParameter="{Binding Path=ReportAbuseUrl}"> |
||||
<TextBlock Text="Report Abuse"/> |
||||
</Hyperlink> |
||||
</TextBlock> |
||||
<TextBlock |
||||
Margin="0, 4" |
||||
TextWrapping="Wrap" |
||||
Text="{Binding Path=Description}"/> |
||||
<StackPanel Margin="0, 4"> |
||||
<StackPanel Orientation="Horizontal"> |
||||
<TextBlock |
||||
Text="Dependencies:" |
||||
Margin="0, 0, 4, 0" |
||||
FontWeight="Bold"/> |
||||
<TextBlock |
||||
Text="None" |
||||
Visibility="{Binding Path=HasNoDependencies, Converter={StaticResource BoolToVisibility}}"/> |
||||
</StackPanel> |
||||
<ItemsControl |
||||
Margin="4, 4" |
||||
ItemsSource="{Binding Path=Dependencies}"/> |
||||
</StackPanel> |
||||
</StackPanel> |
||||
</ScrollViewer> |
||||
|
||||
<DataTemplate.Triggers> |
||||
<DataTrigger |
||||
Binding="{Binding}" |
||||
Value="{x:Null}"> |
||||
<Setter |
||||
Property="StackPanel.Visibility" |
||||
Value="Hidden"/> |
||||
</DataTrigger> |
||||
</DataTemplate.Triggers> |
||||
</DataTemplate> |
||||
</UserControl.Resources> |
||||
|
||||
<Grid d:DataContext="{d:DesignInstance pmd:DesignTimePackagesViewModel, IsDesignTimeCreatable=True}"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition MinWidth="100"/> |
||||
<ColumnDefinition Width="Auto"/> |
||||
<ColumnDefinition MinWidth="100"/> |
||||
</Grid.ColumnDefinitions> |
||||
|
||||
<Grid Grid.Column="0"> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition /> |
||||
<RowDefinition Height="Auto"/> |
||||
</Grid.RowDefinitions> |
||||
<ListBox |
||||
x:Name="allPackagesListBox" |
||||
Grid.Row="0" |
||||
SelectedIndex="0" |
||||
ItemTemplate="{StaticResource PackagesListBoxTemplate}" |
||||
ItemsSource="{Binding Path=PackageViewModels}" |
||||
HorizontalContentAlignment="Stretch" |
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"/> |
||||
<pm:PagedResultsView |
||||
x:Name="pagedResultsView" |
||||
Grid.Row="1" |
||||
HorizontalAlignment="Center" |
||||
Visibility="{Binding Path=IsPaged, Converter={StaticResource BoolToVisibility}}" |
||||
DataContext="{Binding}"/> |
||||
</Grid> |
||||
<GridSplitter |
||||
Grid.Column="1" |
||||
Width="5" |
||||
HorizontalAlignment="Stretch" |
||||
VerticalAlignment="Stretch"/> |
||||
<Grid |
||||
Grid.Column="2"> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="Auto"/> |
||||
<RowDefinition /> |
||||
</Grid.RowDefinitions> |
||||
<Grid |
||||
Visibility="{Binding Path=IsSearchable, Converter={StaticResource BoolToVisibility}}"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition /> |
||||
<ColumnDefinition Width="Auto"/> |
||||
</Grid.ColumnDefinitions> |
||||
<TextBox |
||||
Grid.Column="0" |
||||
pm:TextBoxBehaviour.EnterKeyCommand="{Binding Path=SearchCommand}" |
||||
Text="{Binding Path=SearchTerms, UpdateSourceTrigger=PropertyChanged}"/> |
||||
<TextBlock |
||||
Grid.Column="1" |
||||
Margin="4"> |
||||
<Hyperlink |
||||
TextDecorations="{x:Null}" |
||||
Command="{Binding Path=SearchCommand}"> |
||||
<Image |
||||
Source="{StaticResource SearchIcon}" |
||||
Height="16" |
||||
Width="16"/> |
||||
</Hyperlink> |
||||
</TextBlock> |
||||
</Grid> |
||||
<ContentControl |
||||
Grid.Row="1" |
||||
ContentTemplate="{StaticResource PackageTemplate}" |
||||
Content="{Binding ElementName=allPackagesListBox, Path=SelectedItem}"/> |
||||
</Grid> |
||||
</Grid> |
||||
</UserControl> |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Windows.Controls; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public partial class PackagesView : UserControl |
||||
{ |
||||
public PackagesView() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,253 @@
@@ -0,0 +1,253 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using System.Collections.Specialized; |
||||
using System.Linq; |
||||
using System.Windows.Input; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public abstract class PackagesViewModel : ViewModelBase<PackagesViewModel> |
||||
{ |
||||
DelegateCommand showNextPageCommand; |
||||
DelegateCommand showPreviousPageCommand; |
||||
DelegateCommand showPageCommand; |
||||
DelegateCommand searchCommand; |
||||
|
||||
ObservableCollection<PackageViewModel> packageViewModels = |
||||
new ObservableCollection<PackageViewModel>(); |
||||
Pages pages = new Pages(); |
||||
|
||||
IPackageManagementService packageManagementService; |
||||
IPackageViewModelFactory packageViewModelFactory; |
||||
IProjectManager projectManager; |
||||
IEnumerable<IPackage> allPackages; |
||||
string searchTerms; |
||||
|
||||
public PackagesViewModel(IPackageManagementService packageManagementService) |
||||
: this(packageManagementService, new LicenseAcceptanceService()) |
||||
{ |
||||
} |
||||
|
||||
public PackagesViewModel( |
||||
IPackageManagementService packageManagementService, |
||||
ILicenseAcceptanceService licenseAcceptanceService) |
||||
: this( |
||||
packageManagementService, |
||||
new PackageViewModelFactory(packageManagementService, licenseAcceptanceService)) |
||||
{ |
||||
} |
||||
|
||||
public PackagesViewModel( |
||||
IPackageManagementService packageManagementService, |
||||
IPackageViewModelFactory packageViewModelFactory) |
||||
{ |
||||
this.packageManagementService = packageManagementService; |
||||
this.packageViewModelFactory = packageViewModelFactory; |
||||
this.projectManager = packageManagementService.ActiveProjectManager; |
||||
|
||||
CreateCommands(); |
||||
} |
||||
|
||||
void CreateCommands() |
||||
{ |
||||
showNextPageCommand = new DelegateCommand(param => ShowNextPage()); |
||||
showPreviousPageCommand = new DelegateCommand(param => ShowPreviousPage()); |
||||
showPageCommand = new DelegateCommand(param => ExecuteShowPageCommand(param)); |
||||
searchCommand = new DelegateCommand(param => Search()); |
||||
} |
||||
|
||||
public ICommand ShowNextPageCommand { |
||||
get { return showNextPageCommand; } |
||||
} |
||||
|
||||
public ICommand ShowPreviousPageCommand { |
||||
get { return showPreviousPageCommand; } |
||||
} |
||||
|
||||
public ICommand ShowPageCommand { |
||||
get { return showPageCommand; } |
||||
} |
||||
|
||||
public ICommand SearchCommand { |
||||
get { return searchCommand; } |
||||
} |
||||
|
||||
public ObservableCollection<PackageViewModel> PackageViewModels { |
||||
get { return packageViewModels; } |
||||
set { packageViewModels = value; } |
||||
} |
||||
|
||||
public IPackageManagementService PackageManagementService { |
||||
get { return packageManagementService; } |
||||
} |
||||
|
||||
public IProjectManager ProjectManager { |
||||
get { return projectManager; } |
||||
} |
||||
|
||||
public void ReadPackages() |
||||
{ |
||||
allPackages = null; |
||||
pages.CollectionChanged -= PagesChanged; |
||||
UpdatePackageViewModels(); |
||||
pages.CollectionChanged += PagesChanged; |
||||
} |
||||
|
||||
void PagesChanged(object sender, NotifyCollectionChangedEventArgs e) |
||||
{ |
||||
UpdatePackageViewModels(); |
||||
base.OnPropertyChanged(null); |
||||
} |
||||
|
||||
void UpdatePackageViewModels() |
||||
{ |
||||
IEnumerable<IPackage> packages = GetPackagesForSelectedPage(); |
||||
pages.TotalItemsOnSelectedPage = packages.Count(); |
||||
UpdatePackageViewModels(packages); |
||||
} |
||||
|
||||
IEnumerable<IPackage> GetPackagesForSelectedPage() |
||||
{ |
||||
IEnumerable<IPackage> filteredPackages = GetFilteredPackagesBeforePagingResults(); |
||||
return GetPackagesForSelectedPage(filteredPackages); |
||||
} |
||||
|
||||
IEnumerable<IPackage> GetPackagesForSelectedPage(IEnumerable<IPackage> allPackages) |
||||
{ |
||||
int packagesToSkip = pages.ItemsBeforeFirstPage; |
||||
return allPackages |
||||
.Skip(packagesToSkip) |
||||
.Take(pages.PageSize); |
||||
} |
||||
|
||||
IEnumerable<IPackage> GetFilteredPackagesBeforePagingResults() |
||||
{ |
||||
if (allPackages == null) { |
||||
IQueryable<IPackage> packages = GetAllPackages(); |
||||
pages.TotalItems = packages.Count(); |
||||
allPackages = GetFilteredPackagesBeforePagingResults(packages); |
||||
} |
||||
return allPackages; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Returns all the packages.
|
||||
/// </summary>
|
||||
protected virtual IQueryable<IPackage> GetAllPackages() |
||||
{ |
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Allows filtering of the packages before paging the results. Call base class method
|
||||
/// to run default filtering.
|
||||
/// </summary>
|
||||
protected virtual IEnumerable<IPackage> GetFilteredPackagesBeforePagingResults(IQueryable<IPackage> allPackages) |
||||
{ |
||||
allPackages = allPackages.Find(searchTerms); |
||||
IEnumerable<IPackage> bufferedPackages = GetBufferedPackages(allPackages); |
||||
return bufferedPackages; |
||||
} |
||||
|
||||
IEnumerable<IPackage> GetBufferedPackages(IQueryable<IPackage> allPackages) |
||||
{ |
||||
return allPackages.AsBufferedEnumerable(30); |
||||
} |
||||
|
||||
void UpdatePackageViewModels(IEnumerable<IPackage> packages) |
||||
{ |
||||
IEnumerable<PackageViewModel> currentViewModels = ConvertToPackageViewModels(packages); |
||||
UpdatePackageViewModels(currentViewModels); |
||||
} |
||||
|
||||
void UpdatePackageViewModels(IEnumerable<PackageViewModel> newPackageViewModels) |
||||
{ |
||||
PackageViewModels.Clear(); |
||||
PackageViewModels.AddRange(newPackageViewModels); |
||||
} |
||||
|
||||
public IEnumerable<PackageViewModel> ConvertToPackageViewModels(IEnumerable<IPackage> packages) |
||||
{ |
||||
foreach (IPackage package in packages) { |
||||
yield return CreatePackageViewModel(package); |
||||
} |
||||
} |
||||
|
||||
PackageViewModel CreatePackageViewModel(IPackage package) |
||||
{ |
||||
return packageViewModelFactory.CreatePackageViewModel(package); |
||||
} |
||||
|
||||
public int SelectedPageNumber { |
||||
get { return pages.SelectedPageNumber; } |
||||
set { pages.SelectedPageNumber = value; } |
||||
} |
||||
|
||||
public int PageSize { |
||||
get { return pages.PageSize; } |
||||
set { pages.PageSize = value; } |
||||
} |
||||
|
||||
public bool IsPaged { |
||||
get { return pages.IsPaged; } |
||||
} |
||||
|
||||
public ObservableCollection<Page> Pages { |
||||
get { return pages; } |
||||
} |
||||
|
||||
public bool HasPreviousPage { |
||||
get { return pages.HasPreviousPage; } |
||||
} |
||||
|
||||
public bool HasNextPage { |
||||
get { return pages.HasNextPage; } |
||||
} |
||||
|
||||
public int MaximumSelectablePages { |
||||
get { return pages.MaximumSelectablePages; } |
||||
set { pages.MaximumSelectablePages = value; } |
||||
} |
||||
|
||||
public void ShowNextPage() |
||||
{ |
||||
SelectedPageNumber += 1; |
||||
} |
||||
|
||||
public void ShowPreviousPage() |
||||
{ |
||||
SelectedPageNumber -= 1; |
||||
} |
||||
|
||||
void ExecuteShowPageCommand(object param) |
||||
{ |
||||
int pageNumber = (int)param; |
||||
ShowPage(pageNumber); |
||||
} |
||||
|
||||
public void ShowPage(int pageNumber) |
||||
{ |
||||
SelectedPageNumber = pageNumber; |
||||
} |
||||
|
||||
public bool IsSearchable { |
||||
get; set; |
||||
} |
||||
|
||||
public string SearchTerms { |
||||
get { return searchTerms; } |
||||
set { searchTerms = value; } |
||||
} |
||||
|
||||
public void Search() |
||||
{ |
||||
SelectedPageNumber = 1; |
||||
ReadPackages(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class Page |
||||
{ |
||||
public int Number { get; set; } |
||||
public bool IsSelected { get; set; } |
||||
|
||||
public override string ToString() |
||||
{ |
||||
return String.Format("[Page] Number={0}, IsSelected={1}", Number, IsSelected); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
<UserControl |
||||
x:Class="ICSharpCode.PackageManagement.PagedResultsView" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
xmlns:pm="clr-namespace:ICSharpCode.PackageManagement" |
||||
xmlns:pmd="clr-namespace:ICSharpCode.PackageManagement.Design" |
||||
mc:Ignorable="d"> |
||||
|
||||
<UserControl.Resources> |
||||
<BitmapImage x:Key="PreviousPageIcon" |
||||
UriSource="pack://application:,,,/PackageManagement;component/Resources/resultset_previous.png"/> |
||||
<BitmapImage x:Key="NextPageIcon" |
||||
UriSource="pack://application:,,,/PackageManagement;component/Resources/resultset_next.png"/> |
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibility"/> |
||||
<pm:BooleanToFontWeightConverter x:Key="BoolToFontWeight"/> |
||||
|
||||
<DataTemplate x:Key="PagedListTemplate"> |
||||
<Button |
||||
Background="Transparent" |
||||
BorderBrush="Transparent" |
||||
Padding="4,0,4,0" |
||||
MinWidth="0" |
||||
Content="{Binding Path=Number}" |
||||
Command="{Binding Path=DataContext.ShowPageCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" |
||||
CommandParameter="{Binding Path=Number}" |
||||
FontWeight="{Binding Path=IsSelected, Converter={StaticResource BoolToFontWeight}}"/> |
||||
</DataTemplate> |
||||
</UserControl.Resources> |
||||
|
||||
<StackPanel |
||||
d:DataContext="{d:DesignInstance pmd:DesignTimePackagesViewModel, IsDesignTimeCreatable=True}" |
||||
Orientation="Horizontal"> |
||||
<Button |
||||
Visibility="{Binding Path=HasPreviousPage, Converter={StaticResource BoolToVisibility}}" |
||||
Command="{Binding Path=ShowPreviousPageCommand}" |
||||
Background="Transparent" |
||||
BorderBrush="Transparent" |
||||
MinWidth="0" |
||||
Padding="0,2" |
||||
VerticalAlignment="Top"> |
||||
<Image Source="{StaticResource PreviousPageIcon}" |
||||
Height="16" |
||||
Width="16"/> |
||||
</Button> |
||||
<ListBox |
||||
VerticalAlignment="Top" |
||||
HorizontalAlignment="Center" |
||||
BorderBrush="Transparent" |
||||
ItemTemplate="{StaticResource PagedListTemplate}" |
||||
ItemsSource="{Binding Path=Pages}"> |
||||
<ListBox.ItemsPanel> |
||||
<ItemsPanelTemplate> |
||||
<StackPanel Orientation="Horizontal"/> |
||||
</ItemsPanelTemplate> |
||||
</ListBox.ItemsPanel> |
||||
</ListBox> |
||||
<Button |
||||
Visibility="{Binding Path=HasNextPage, Converter={StaticResource BoolToVisibility}}" |
||||
Command="{Binding Path=ShowNextPageCommand}" |
||||
Background="Transparent" |
||||
BorderBrush="Transparent" |
||||
MinWidth="0" |
||||
Padding="0,2" |
||||
VerticalAlignment="Top"> |
||||
<Image |
||||
Source="{StaticResource NextPageIcon}" |
||||
Height="16" |
||||
Width="16"/> |
||||
</Button> |
||||
</StackPanel> |
||||
</UserControl> |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Windows.Controls; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public partial class PagedResultsView : UserControl |
||||
{ |
||||
public PagedResultsView() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,155 @@
@@ -0,0 +1,155 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.ObjectModel; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class Pages : ObservableCollection<Page> |
||||
{ |
||||
public const int DefaultPageSize = 10; |
||||
public const int DefaultMaximumSelectablePages = 5; |
||||
|
||||
int pageSize = DefaultPageSize; |
||||
int selectedPageNumber = 1; |
||||
int maximumSelectablePages = DefaultMaximumSelectablePages; |
||||
int totalItems = 0; |
||||
int itemsOnSelectedPage = 0; |
||||
|
||||
public int TotalItems { |
||||
get { return totalItems; } |
||||
set { |
||||
if (totalItems != value) { |
||||
totalItems = value; |
||||
UpdatePages(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public int SelectedPageNumber { |
||||
get { return selectedPageNumber; } |
||||
set { |
||||
if (selectedPageNumber != value) { |
||||
selectedPageNumber = value; |
||||
UpdatePages(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public int MaximumSelectablePages { |
||||
get { return maximumSelectablePages; } |
||||
set { |
||||
if (maximumSelectablePages != value) { |
||||
maximumSelectablePages = value; |
||||
UpdatePages(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public int ItemsBeforeFirstPage { |
||||
get { |
||||
return (selectedPageNumber - 1) * pageSize; |
||||
} |
||||
} |
||||
|
||||
public bool IsPaged { |
||||
get { return totalItems > pageSize; } |
||||
} |
||||
|
||||
public bool HasPreviousPage { |
||||
get { return IsPaged && !IsFirstPageSelected; } |
||||
} |
||||
|
||||
bool IsFirstPageSelected { |
||||
get { return selectedPageNumber == 1; } |
||||
} |
||||
|
||||
public bool HasNextPage { |
||||
get { return IsPaged && !IsLastPageSelected; } |
||||
} |
||||
|
||||
bool IsLastPageSelected { |
||||
get { return selectedPageNumber == TotalPages; } |
||||
} |
||||
|
||||
public int TotalPages { |
||||
get { return (totalItems + pageSize - 1) / pageSize; } |
||||
} |
||||
|
||||
public int PageSize { |
||||
get { return pageSize; } |
||||
set { |
||||
if (pageSize != value) { |
||||
pageSize = value; |
||||
UpdatePages(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void UpdatePages() |
||||
{ |
||||
Clear(); |
||||
|
||||
int startPage = GetStartPage(); |
||||
for (int pageNumber = startPage; pageNumber <= TotalPages; ++pageNumber) { |
||||
if (Count >= maximumSelectablePages) { |
||||
break; |
||||
} |
||||
Page page = CreatePage(pageNumber); |
||||
Add(page); |
||||
} |
||||
} |
||||
|
||||
int GetStartPage() |
||||
{ |
||||
// Less pages than can be selected?
|
||||
int totalPages = TotalPages; |
||||
if (totalPages <= maximumSelectablePages) { |
||||
return 1; |
||||
} |
||||
|
||||
// First choice for start page.
|
||||
int startPage = selectedPageNumber - (maximumSelectablePages / 2); |
||||
if (startPage <= 0) { |
||||
return 1; |
||||
} |
||||
|
||||
// Do we have enough pages?
|
||||
int totalPagesBasedOnStartPage = totalPages - startPage + 1; |
||||
if (totalPagesBasedOnStartPage >= maximumSelectablePages) { |
||||
return startPage; |
||||
} |
||||
|
||||
// Ensure we have enough pages.
|
||||
startPage -= maximumSelectablePages - totalPagesBasedOnStartPage; |
||||
if (startPage > 0) { |
||||
return startPage; |
||||
} |
||||
return 1; |
||||
} |
||||
|
||||
Page CreatePage(int pageNumber) |
||||
{ |
||||
var page = new Page(); |
||||
page.Number = pageNumber; |
||||
page.IsSelected = IsSelectedPage(pageNumber); |
||||
return page; |
||||
} |
||||
|
||||
bool IsSelectedPage(int pageNumber) |
||||
{ |
||||
return pageNumber == selectedPageNumber; |
||||
} |
||||
|
||||
public int TotalItemsOnSelectedPage { |
||||
get { return itemsOnSelectedPage; } |
||||
set { |
||||
itemsOnSelectedPage = value; |
||||
if (itemsOnSelectedPage < pageSize) { |
||||
TotalItems = (selectedPageNumber - 1) * pageSize + itemsOnSelectedPage; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,64 @@
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Runtime.Versioning; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class ProjectTargetFramework |
||||
{ |
||||
MSBuildBasedProject project; |
||||
FrameworkName targetFramework; |
||||
|
||||
public ProjectTargetFramework(MSBuildBasedProject project) |
||||
{ |
||||
this.project = project; |
||||
GetTargetFramework(); |
||||
} |
||||
|
||||
void GetTargetFramework() |
||||
{ |
||||
string identifier = GetTargetFrameworkIdentifier(); |
||||
string version = GetTargetFrameworkVersion(); |
||||
string profile = GetTargetFrameworkProfile(); |
||||
|
||||
GetTargetFramework(identifier, version, profile); |
||||
} |
||||
|
||||
void GetTargetFramework(string identifier, string version, string profile) |
||||
{ |
||||
string name = String.Format("{0}, Version={1}, Profile={2}", identifier, version, profile); |
||||
targetFramework = new FrameworkName(name); |
||||
} |
||||
|
||||
string GetTargetFrameworkIdentifier() |
||||
{ |
||||
return GetEvaluatedPropertyOrDefault("TargetFrameworkIdentifier", ".NETFramework"); |
||||
} |
||||
|
||||
string GetTargetFrameworkVersion() |
||||
{ |
||||
return project.GetEvaluatedProperty("TargetFrameworkVersion"); |
||||
} |
||||
|
||||
string GetTargetFrameworkProfile() |
||||
{ |
||||
return GetEvaluatedPropertyOrDefault("TargetFrameworkProfile", "Full"); |
||||
} |
||||
|
||||
string GetEvaluatedPropertyOrDefault(string propertyName, string defaultPropertyValue) |
||||
{ |
||||
string propertyValue = project.GetEvaluatedProperty(propertyName); |
||||
if (String.IsNullOrEmpty(propertyValue)) { |
||||
return defaultPropertyValue; |
||||
} |
||||
return propertyValue; |
||||
} |
||||
|
||||
public FrameworkName TargetFrameworkName { |
||||
get { return targetFramework; } |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class RegisteredPackageSource |
||||
{ |
||||
public string Source { get; set; } |
||||
public string Name { get; set; } |
||||
|
||||
public RegisteredPackageSource() |
||||
{ |
||||
} |
||||
|
||||
public RegisteredPackageSource(string name, string source) |
||||
{ |
||||
this.Name = name; |
||||
this.Source = source; |
||||
} |
||||
|
||||
public RegisteredPackageSource(PackageSource packageSource) |
||||
{ |
||||
Source = packageSource.Source; |
||||
Name = packageSource.Name; |
||||
} |
||||
|
||||
public PackageSource ToPackageSource() |
||||
{ |
||||
return new PackageSource(Source, Name); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,56 @@
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using System.Collections.Specialized; |
||||
using ICSharpCode.Core; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class RegisteredPackageSources : ObservableCollection<PackageSource> |
||||
{ |
||||
public static readonly string DefaultPackageSourceUrl = "http://go.microsoft.com/fwlink/?LinkID=206669"; |
||||
public static readonly string DefaultPackageSourceName = "NuGet Official Package Source"; |
||||
|
||||
public static readonly PackageSource DefaultPackageSource = |
||||
new PackageSource(DefaultPackageSourceUrl, DefaultPackageSourceName); |
||||
|
||||
public RegisteredPackageSources(IEnumerable<PackageSource> packageSources) |
||||
{ |
||||
AddPackageSources(packageSources); |
||||
AddDefaultPackageSourceIfNoRegisteredPackageSources(); |
||||
} |
||||
|
||||
void AddPackageSources(IEnumerable<PackageSource> packageSources) |
||||
{ |
||||
foreach (PackageSource source in packageSources) { |
||||
Add(source); |
||||
} |
||||
} |
||||
|
||||
void AddDefaultPackageSourceIfNoRegisteredPackageSources() |
||||
{ |
||||
if (HasNoRegisteredPackageSources) { |
||||
Add(DefaultPackageSource); |
||||
} |
||||
} |
||||
|
||||
bool HasNoRegisteredPackageSources { |
||||
get { return Count == 0; } |
||||
} |
||||
|
||||
// protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
// {
|
||||
// options.UpdateSavedPackageSources();
|
||||
// base.OnCollectionChanged(e);
|
||||
// }
|
||||
//
|
||||
// void UpdateSavedPackageSources()
|
||||
// {
|
||||
// options.SavedRegisteredPackageSources = PackageSourceConverter.ConvertToRegisteredPackageSourcesList(this);
|
||||
// }
|
||||
} |
||||
} |
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using System.Collections; |
||||
using System.Windows; |
||||
using System.Windows.Controls; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class SelectedListBoxItemScrollingBehaviour |
||||
{ |
||||
ListBox listBox; |
||||
DependencyPropertyChangedEventArgs propertyChangedEventArgs; |
||||
|
||||
public SelectedListBoxItemScrollingBehaviour(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) |
||||
{ |
||||
this.listBox = dependencyObject as ListBox; |
||||
this.propertyChangedEventArgs = e; |
||||
} |
||||
|
||||
public void Update() |
||||
{ |
||||
if (ShouldUpdateSelectionChangedHandlerRegistration()) { |
||||
UpdateSelectionChangedHandlerRegistration(); |
||||
} |
||||
} |
||||
|
||||
bool ShouldUpdateSelectionChangedHandlerRegistration() |
||||
{ |
||||
return DependencyObjectIsListBox() && NewPropertyValueIsBoolean(); |
||||
} |
||||
|
||||
bool DependencyObjectIsListBox() |
||||
{ |
||||
return (listBox != null); |
||||
} |
||||
|
||||
bool NewPropertyValueIsBoolean() |
||||
{ |
||||
return (propertyChangedEventArgs.NewValue is bool); |
||||
} |
||||
|
||||
void UpdateSelectionChangedHandlerRegistration() |
||||
{ |
||||
if ((bool)propertyChangedEventArgs.NewValue) { |
||||
RegisterSelectionChangedHandler(listBox); |
||||
} else { |
||||
UnregisterSelectionChangedHandler(listBox); |
||||
} |
||||
} |
||||
|
||||
protected virtual void RegisterSelectionChangedHandler(ListBox listBox) |
||||
{ |
||||
listBox.SelectionChanged += OnListBoxSelectionChanged; |
||||
} |
||||
|
||||
protected virtual void UnregisterSelectionChangedHandler(ListBox listBox) |
||||
{ |
||||
listBox.SelectionChanged -= OnListBoxSelectionChanged; |
||||
} |
||||
|
||||
static void OnListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) |
||||
{ |
||||
OnListBoxSelectionChanged(sender, e.OriginalSource, e.AddedItems, ScrollListBoxItemIntoView); |
||||
} |
||||
|
||||
static void ScrollListBoxItemIntoView(ListBox listBox, object item) |
||||
{ |
||||
listBox.ScrollIntoView(item); |
||||
} |
||||
|
||||
protected static void OnListBoxSelectionChanged(object sender, |
||||
object originalSource, |
||||
IList addedItems, |
||||
Action<ListBox, object> executeScrollListBoxItemIntoView) |
||||
{ |
||||
if (!Object.ReferenceEquals(sender, originalSource)) { |
||||
return; |
||||
} |
||||
|
||||
ListBox listBox = originalSource as ListBox; |
||||
if (listBox != null) { |
||||
if (addedItems.Count > 0) { |
||||
executeScrollListBoxItemIntoView(listBox, addedItems[0]); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class SharpDevelopPackageManager : PackageManager, ISharpDevelopPackageManager |
||||
{ |
||||
IProjectSystem projectSystem; |
||||
|
||||
public SharpDevelopPackageManager(IPackageRepository sourceRepository, |
||||
MSBuildBasedProject project, |
||||
ISharedPackageRepository localRepository, |
||||
PackageRepositoryPaths repositoryPaths) |
||||
: this(sourceRepository, new SharpDevelopProjectSystem(project), localRepository, repositoryPaths) |
||||
{ |
||||
} |
||||
|
||||
public SharpDevelopPackageManager(IPackageRepository sourceRepository, |
||||
IProjectSystem projectSystem, |
||||
ISharedPackageRepository localRepository, |
||||
PackageRepositoryPaths repositoryPaths) |
||||
: this(sourceRepository, |
||||
projectSystem, |
||||
localRepository, |
||||
repositoryPaths, |
||||
repositoryPaths.SolutionPackagesPath) |
||||
{ |
||||
} |
||||
|
||||
SharpDevelopPackageManager(IPackageRepository sourceRepository, |
||||
IProjectSystem projectSystem, |
||||
ISharedPackageRepository localRepository, |
||||
PackageRepositoryPaths repositoryPaths, |
||||
string solutionPackagesPath) |
||||
: base(sourceRepository, |
||||
new DefaultPackagePathResolver(solutionPackagesPath), |
||||
new PhysicalFileSystem(solutionPackagesPath), |
||||
localRepository) |
||||
{ |
||||
this.projectSystem = projectSystem; |
||||
CreateProjectManager(); |
||||
} |
||||
|
||||
// <summary>
|
||||
/// project manager should be created with:
|
||||
/// local repo = PackageReferenceRepository(projectSystem, sharedRepo)
|
||||
/// packageRefRepo should have its RegisterIfNecessary() method called before creating the project manager.
|
||||
/// source repo = sharedRepository
|
||||
/// </summary>
|
||||
void CreateProjectManager() |
||||
{ |
||||
var sharedRepository = LocalRepository as ISharedPackageRepository; |
||||
var packageRefRepository = new PackageReferenceRepository(projectSystem, sharedRepository); |
||||
packageRefRepository.RegisterIfNecessary(); |
||||
|
||||
ProjectManager = new SharpDevelopProjectManager(LocalRepository, PathResolver, projectSystem, packageRefRepository); |
||||
} |
||||
|
||||
public ISharpDevelopProjectManager ProjectManager { get; set; } |
||||
|
||||
public void InstallPackage(IPackage package) |
||||
{ |
||||
bool ignoreDependencies = false; |
||||
InstallPackage(package, ignoreDependencies); |
||||
} |
||||
|
||||
public override void InstallPackage(IPackage package, bool ignoreDependencies) |
||||
{ |
||||
base.InstallPackage(package, ignoreDependencies); |
||||
ProjectManager.AddPackageReference(package.Id, package.Version, ignoreDependencies); |
||||
} |
||||
|
||||
public override void UninstallPackage(IPackage package, bool forceRemove, bool removeDependencies) |
||||
{ |
||||
ProjectManager.RemovePackageReference(package.Id, forceRemove, removeDependencies); |
||||
base.UninstallPackage(package, forceRemove, removeDependencies); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using ICSharpCode.SharpDevelop.Project; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class SharpDevelopPackageManagerFactory : IPackageManagerFactory |
||||
{ |
||||
PackageManagementOptions options; |
||||
ISharpDevelopPackageRepositoryFactory packageRepositoryFactory; |
||||
ISharpDevelopProjectSystemFactory projectSystemFactory; |
||||
|
||||
public SharpDevelopPackageManagerFactory() |
||||
: this(new SharpDevelopPackageRepositoryFactory(), |
||||
new SharpDevelopProjectSystemFactory(), |
||||
new PackageManagementOptions()) |
||||
{ |
||||
} |
||||
|
||||
public SharpDevelopPackageManagerFactory(ISharpDevelopPackageRepositoryFactory packageRepositoryFactory, |
||||
ISharpDevelopProjectSystemFactory projectSystemFactory, |
||||
PackageManagementOptions options) |
||||
{ |
||||
this.packageRepositoryFactory = packageRepositoryFactory; |
||||
this.projectSystemFactory = projectSystemFactory; |
||||
this.options = options; |
||||
} |
||||
|
||||
public ISharpDevelopPackageManager CreatePackageManager(IPackageRepository packageRepository, MSBuildBasedProject project) |
||||
{ |
||||
PackageRepositoryPaths repositoryPaths = new PackageRepositoryPaths(project, options); |
||||
IProjectSystem projectSystem = CreateProjectSystem(project); |
||||
ISharedPackageRepository sharedRepository = CreateSharedRepository(repositoryPaths.SolutionPackagesPath); |
||||
return new SharpDevelopPackageManager(packageRepository, projectSystem, sharedRepository, repositoryPaths); |
||||
} |
||||
|
||||
IProjectSystem CreateProjectSystem(MSBuildBasedProject project) |
||||
{ |
||||
return projectSystemFactory.CreateProjectSystem(project); |
||||
} |
||||
|
||||
ISharedPackageRepository CreateSharedRepository(string path) |
||||
{ |
||||
return packageRepositoryFactory.CreateSharedRepository(path); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class SharpDevelopPackageRepositoryFactory : PackageRepositoryFactory, ISharpDevelopPackageRepositoryFactory |
||||
{ |
||||
public ISharedPackageRepository CreateSharedRepository(string path) |
||||
{ |
||||
return new SharedPackageRepository(path); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
|
||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||
|
||||
using System; |
||||
using NuGet; |
||||
|
||||
namespace ICSharpCode.PackageManagement |
||||
{ |
||||
public class SharpDevelopProjectManager : ProjectManager, ISharpDevelopProjectManager |
||||
{ |
||||
public SharpDevelopProjectManager(IPackageRepository sourceRepository, |
||||
IPackagePathResolver pathResolver, |
||||
IProjectSystem project, |
||||
IPackageRepository localRepository) |
||||
: base(sourceRepository, pathResolver, project, localRepository) |
||||
{ |
||||
} |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue