9 changed files with 765 additions and 6 deletions
@ -0,0 +1,161 @@ |
|||||||
|
// 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.Threading; |
||||||
|
using System.Windows; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Threading; |
||||||
|
|
||||||
|
using ICSharpCode.AvalonEdit.Snippets; |
||||||
|
using ICSharpCode.Core.Presentation; |
||||||
|
using ICSharpCode.NRefactory.CSharp; |
||||||
|
using ICSharpCode.NRefactory.Editor; |
||||||
|
using ICSharpCode.NRefactory.TypeSystem; |
||||||
|
using ICSharpCode.SharpDevelop.Parser; |
||||||
|
using CSharpBinding.Refactoring; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
using ICSharpCode.SharpDevelop.Editor; |
||||||
|
|
||||||
|
namespace CSharpBinding.Refactoring |
||||||
|
{ |
||||||
|
public abstract class AbstractInlineRefactorDialog : GroupBox, IOptionBindingContainer, IActiveElement |
||||||
|
{ |
||||||
|
protected ITextAnchor anchor; |
||||||
|
protected ITextAnchor insertionEndAnchor; |
||||||
|
protected ITextEditor editor; |
||||||
|
|
||||||
|
protected SDRefactoringContext refactoringContext; |
||||||
|
protected InsertionContext insertionContext; |
||||||
|
|
||||||
|
public IInlineUIElement Element { get; set; } |
||||||
|
|
||||||
|
protected AbstractInlineRefactorDialog(InsertionContext context, ITextEditor editor, ITextAnchor anchor) |
||||||
|
{ |
||||||
|
if (context == null) |
||||||
|
throw new ArgumentNullException("context"); |
||||||
|
|
||||||
|
this.anchor = insertionEndAnchor = anchor; |
||||||
|
this.editor = editor; |
||||||
|
this.insertionContext = context; |
||||||
|
this.refactoringContext = SDRefactoringContext.Create(editor, CancellationToken.None); |
||||||
|
|
||||||
|
this.Background = SystemColors.ControlBrush; |
||||||
|
} |
||||||
|
|
||||||
|
protected virtual void FocusFirstElement() |
||||||
|
{ |
||||||
|
Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(delegate { this.MoveFocus(new TraversalRequest(FocusNavigationDirection.First)); })); |
||||||
|
} |
||||||
|
|
||||||
|
protected abstract string GenerateCode(IUnresolvedTypeDefinition currentClass); |
||||||
|
|
||||||
|
protected virtual void OKButtonClick(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
ParseInformation parseInfo = SD.ParserService.GetCachedParseInformation(editor.FileName); |
||||||
|
|
||||||
|
if (optionBindings != null) { |
||||||
|
foreach (OptionBinding binding in optionBindings) |
||||||
|
binding.Save(); |
||||||
|
} |
||||||
|
|
||||||
|
if (parseInfo != null) { |
||||||
|
IUnresolvedTypeDefinition current = parseInfo.UnresolvedFile.GetInnermostTypeDefinition(anchor.Line, anchor.Column); |
||||||
|
|
||||||
|
using (editor.Document.OpenUndoGroup()) { |
||||||
|
// GenerateCode could modify the document.
|
||||||
|
// So read anchor.Offset after code generation.
|
||||||
|
GenerateCode(current); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Deactivate(); |
||||||
|
} |
||||||
|
|
||||||
|
protected virtual void CancelButtonClick(object sender, RoutedEventArgs e) |
||||||
|
{ |
||||||
|
Deactivate(); |
||||||
|
} |
||||||
|
|
||||||
|
List<OptionBinding> optionBindings; |
||||||
|
|
||||||
|
public void AddBinding(OptionBinding binding) |
||||||
|
{ |
||||||
|
if (optionBindings == null) |
||||||
|
optionBindings = new List<OptionBinding>(); |
||||||
|
|
||||||
|
optionBindings.Add(binding); |
||||||
|
} |
||||||
|
|
||||||
|
protected AstType ConvertType(IType type) |
||||||
|
{ |
||||||
|
return refactoringContext.CreateShortType(type); |
||||||
|
} |
||||||
|
|
||||||
|
bool IActiveElement.IsEditable { |
||||||
|
get { return false; } |
||||||
|
} |
||||||
|
|
||||||
|
ISegment IActiveElement.Segment { |
||||||
|
get { return null; } |
||||||
|
} |
||||||
|
|
||||||
|
void IActiveElement.OnInsertionCompleted() |
||||||
|
{ |
||||||
|
OnInsertionCompleted(); |
||||||
|
} |
||||||
|
|
||||||
|
protected virtual void OnInsertionCompleted() |
||||||
|
{ |
||||||
|
FocusFirstElement(); |
||||||
|
} |
||||||
|
|
||||||
|
void IActiveElement.Deactivate(SnippetEventArgs e) |
||||||
|
{ |
||||||
|
if (e.Reason == DeactivateReason.Deleted) { |
||||||
|
Deactivate(); |
||||||
|
return; |
||||||
|
} |
||||||
|
|
||||||
|
if (e.Reason == DeactivateReason.ReturnPressed) |
||||||
|
OKButtonClick(null, null); |
||||||
|
|
||||||
|
if (e.Reason == DeactivateReason.EscapePressed) |
||||||
|
CancelButtonClick(null, null); |
||||||
|
|
||||||
|
Deactivate(); |
||||||
|
} |
||||||
|
|
||||||
|
bool deactivated; |
||||||
|
|
||||||
|
void Deactivate() |
||||||
|
{ |
||||||
|
if (Element == null) |
||||||
|
throw new InvalidOperationException("no IInlineUIElement set!"); |
||||||
|
if (deactivated) |
||||||
|
return; |
||||||
|
|
||||||
|
deactivated = true; |
||||||
|
Element.Remove(); |
||||||
|
|
||||||
|
insertionContext.Deactivate(null); |
||||||
|
} |
||||||
|
|
||||||
|
protected Key? GetAccessKeyFromButton(ContentControl control) |
||||||
|
{ |
||||||
|
if (control == null) |
||||||
|
return null; |
||||||
|
string text = control.Content as string; |
||||||
|
if (text == null) |
||||||
|
return null; |
||||||
|
int index = text.IndexOf('_'); |
||||||
|
if (index < 0 || index > text.Length - 2) |
||||||
|
return null; |
||||||
|
char ch = text[index + 1]; |
||||||
|
// works only for letter keys!
|
||||||
|
return (Key)new KeyConverter().ConvertFrom(ch.ToString()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -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.Linq; |
||||||
|
using System.Windows.Documents; |
||||||
|
|
||||||
|
using ICSharpCode.AvalonEdit.Snippets; |
||||||
|
|
||||||
|
namespace CSharpBinding.Refactoring |
||||||
|
{ |
||||||
|
class InlineRefactorSnippetElement : SnippetElement |
||||||
|
{ |
||||||
|
Func<InsertionContext, AbstractInlineRefactorDialog> createDialog; |
||||||
|
string previewText; |
||||||
|
|
||||||
|
public InlineRefactorSnippetElement(Func<InsertionContext, AbstractInlineRefactorDialog> createDialog, string previewText) |
||||||
|
{ |
||||||
|
this.createDialog = createDialog; |
||||||
|
this.previewText = previewText; |
||||||
|
} |
||||||
|
|
||||||
|
public override void Insert(InsertionContext context) |
||||||
|
{ |
||||||
|
AbstractInlineRefactorDialog dialog = createDialog(context); |
||||||
|
if (dialog != null) |
||||||
|
context.RegisterActiveElement(this, dialog); |
||||||
|
} |
||||||
|
|
||||||
|
public override Inline ToTextRun() |
||||||
|
{ |
||||||
|
return new Italic() { Inlines = { previewText } }; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
<ref:AbstractInlineRefactorDialog x:Class="CSharpBinding.Refactoring.InsertCtorDialog" |
||||||
|
Header="{sd:Localize AddIns.SharpRefactoring.InsertCtor}" |
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||||
|
xmlns:ref="clr-namespace:CSharpBinding.Refactoring" |
||||||
|
xmlns:sd="http://icsharpcode.net/sharpdevelop/core" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> |
||||||
|
<ref:AbstractInlineRefactorDialog.Resources> |
||||||
|
<ref:IntToBoolConverter x:Key="intToBoolConverter" /> |
||||||
|
<Style TargetType="Button" BasedOn="{x:Static sd:GlobalStyles.ButtonStyle}"/> |
||||||
|
</ref:AbstractInlineRefactorDialog.Resources> |
||||||
|
<Grid Cursor="Arrow" KeyboardNavigation.TabNavigation="Cycle"> |
||||||
|
<Grid.RowDefinitions> |
||||||
|
<RowDefinition Height="Auto" /> |
||||||
|
<RowDefinition Height="*" /> |
||||||
|
<RowDefinition Height="Auto" /> |
||||||
|
</Grid.RowDefinitions> |
||||||
|
<TextBlock Margin="3" |
||||||
|
Text="{sd:Localize AddIns.SharpRefactoring.InsertCtor.Description}" |
||||||
|
TextWrapping="Wrap" /> |
||||||
|
<ListView x:Name="varList" Grid.Row="1" |
||||||
|
SelectionMode="Multiple" KeyboardNavigation.TabNavigation="Cycle" |
||||||
|
ItemContainerStyle="{x:Static sd:GlobalStyles.ListViewItemFocusHighlightStyle}" MaxHeight="300"> |
||||||
|
<ListView.View> |
||||||
|
<GridView> |
||||||
|
<GridViewColumn Header="{sd:Localize AddIns.SharpRefactoring.InsertCtor.VariableLabel}"> |
||||||
|
<GridViewColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<CheckBox Content="{Binding Text}" IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsSelected}" /> |
||||||
|
</DataTemplate> |
||||||
|
</GridViewColumn.CellTemplate> |
||||||
|
</GridViewColumn> |
||||||
|
<GridViewColumn Header="{sd:Localize AddIns.SharpRefactoring.InsertCtor.AddCheckForNullLabel}"> |
||||||
|
<GridViewColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<CheckBox IsChecked="{Binding AddCheckForNull, Mode=TwoWay}" IsEnabled="{Binding IsNullable}" /> |
||||||
|
</DataTemplate> |
||||||
|
</GridViewColumn.CellTemplate> |
||||||
|
</GridViewColumn> |
||||||
|
<GridViewColumn Header="{sd:Localize AddIns.SharpRefactoring.InsertCtor.AddRangeCheckLabel}"> |
||||||
|
<GridViewColumn.CellTemplate> |
||||||
|
<DataTemplate> |
||||||
|
<CheckBox IsChecked="{Binding AddRangeCheck, Mode=TwoWay}" IsEnabled="{Binding HasRange}" /> |
||||||
|
</DataTemplate> |
||||||
|
</GridViewColumn.CellTemplate> |
||||||
|
</GridViewColumn> |
||||||
|
</GridView> |
||||||
|
</ListView.View> |
||||||
|
</ListView> |
||||||
|
<DockPanel Grid.Row="2" LastChildFill="False"> |
||||||
|
<Button DockPanel.Dock="Left" Content="{sd:Localize Global.OKButtonText}" Margin="3" Click="OKButtonClick" /> |
||||||
|
<Button DockPanel.Dock="Left" Content="{sd:Localize Global.CancelButtonText}" Margin="3" Click="CancelButtonClick" /> |
||||||
|
<Button x:Name="moveDown" DockPanel.Dock="Right" Content="{sd:Localize Global.MoveDown}" Margin="3" IsEnabled="{Binding SelectedIndex, ElementName=varList, Converter={StaticResource intToBoolConverter}}" Click="DownClick" /> |
||||||
|
<Button x:Name="moveUp" DockPanel.Dock="Right" Content="{sd:Localize Global.MoveUp}" Margin="3" IsEnabled="{Binding SelectedIndex, ElementName=varList, Converter={StaticResource intToBoolConverter}}" Click="UpClick" /> |
||||||
|
<ToggleButton x:Name="selectAll" DockPanel.Dock="Right" Content="{sd:Localize Global.SelectAllButtonText}" Margin="3" IsChecked="{Binding AllSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ref:InsertCtorDialog}}, Mode=OneWay}" Checked="SelectAllChecked" Unchecked="SelectAllUnchecked" /> |
||||||
|
</DockPanel> |
||||||
|
</Grid> |
||||||
|
</ref:AbstractInlineRefactorDialog> |
@ -0,0 +1,273 @@ |
|||||||
|
// 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.Globalization; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Text; |
||||||
|
using System.Windows.Controls; |
||||||
|
using System.Windows.Data; |
||||||
|
using System.Windows.Input; |
||||||
|
using System.Windows.Threading; |
||||||
|
|
||||||
|
using ICSharpCode.AvalonEdit.Snippets; |
||||||
|
using ICSharpCode.NRefactory.CSharp; |
||||||
|
using ICSharpCode.NRefactory.CSharp.Refactoring; |
||||||
|
using ICSharpCode.NRefactory.CSharp.Resolver; |
||||||
|
using ICSharpCode.NRefactory.Editor; |
||||||
|
using ICSharpCode.NRefactory.TypeSystem; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
using ICSharpCode.SharpDevelop.Editor; |
||||||
|
|
||||||
|
namespace CSharpBinding.Refactoring |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Interaction logic for InsertCtorDialog.xaml
|
||||||
|
/// </summary>
|
||||||
|
public partial class InsertCtorDialog : AbstractInlineRefactorDialog |
||||||
|
{ |
||||||
|
IList<PropertyOrFieldWrapper> parameterList; |
||||||
|
|
||||||
|
public InsertCtorDialog(InsertionContext context, ITextEditor editor, ITextAnchor anchor, IUnresolvedTypeDefinition current, IList<PropertyOrFieldWrapper> possibleParameters) |
||||||
|
: base(context, editor, anchor) |
||||||
|
{ |
||||||
|
InitializeComponent(); |
||||||
|
|
||||||
|
this.varList.ItemsSource = parameterList = possibleParameters; |
||||||
|
|
||||||
|
if (!parameterList.Any()) |
||||||
|
Visibility = System.Windows.Visibility.Collapsed; |
||||||
|
} |
||||||
|
|
||||||
|
protected override string GenerateCode(IUnresolvedTypeDefinition currentClass) |
||||||
|
{ |
||||||
|
List<PropertyOrFieldWrapper> filtered = this.varList.SelectedItems.OfType<PropertyOrFieldWrapper>() |
||||||
|
.OrderBy(p => p.Index) |
||||||
|
.ToList(); |
||||||
|
|
||||||
|
var insertedConstructor = refactoringContext.GetNode<ConstructorDeclaration>(); |
||||||
|
if (insertedConstructor == null) |
||||||
|
{ |
||||||
|
// We are not inside of a constructor declaration
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
using (Script script = refactoringContext.StartScript()) { |
||||||
|
BlockStatement originalCtorBody = insertedConstructor.Body; |
||||||
|
|
||||||
|
foreach (PropertyOrFieldWrapper w in filtered) { |
||||||
|
if (w.AddCheckForNull) { |
||||||
|
// true = reference, null = generic or unknown
|
||||||
|
if (w.Type.IsReferenceType != false) |
||||||
|
script.AddTo(originalCtorBody, |
||||||
|
new IfElseStatement( |
||||||
|
new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.Equality, new PrimitiveExpression(null)), |
||||||
|
new ThrowStatement(new ObjectCreateExpression(new SimpleType("ArgumentNullException"), new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"') })) |
||||||
|
) |
||||||
|
); |
||||||
|
else |
||||||
|
script.AddTo(originalCtorBody, |
||||||
|
new IfElseStatement( |
||||||
|
new UnaryOperatorExpression(UnaryOperatorType.Not, new MemberReferenceExpression(new IdentifierExpression(w.MemberName), "HasValue")), |
||||||
|
new ThrowStatement(new ObjectCreateExpression(new SimpleType("ArgumentNullException"), new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"') })) |
||||||
|
) |
||||||
|
); |
||||||
|
} |
||||||
|
if (w.AddRangeCheck) { |
||||||
|
script.AddTo(originalCtorBody, |
||||||
|
new IfElseStatement( |
||||||
|
new BinaryOperatorExpression( |
||||||
|
new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.LessThan, new IdentifierExpression("lower")), |
||||||
|
BinaryOperatorType.ConditionalOr, |
||||||
|
new BinaryOperatorExpression(new IdentifierExpression(w.ParameterName), BinaryOperatorType.GreaterThan, new IdentifierExpression("upper")) |
||||||
|
), |
||||||
|
new ThrowStatement( |
||||||
|
new ObjectCreateExpression( |
||||||
|
new SimpleType("ArgumentOutOfRangeException"), |
||||||
|
new List<Expression>() { new PrimitiveExpression(w.ParameterName, '"' + w.ParameterName + '"'), new IdentifierExpression(w.ParameterName), new BinaryOperatorExpression(new PrimitiveExpression("Value must be between "), BinaryOperatorType.Add, new BinaryOperatorExpression(new IdentifierExpression("lower"), BinaryOperatorType.Add, new BinaryOperatorExpression(new PrimitiveExpression(" and "), BinaryOperatorType.Add, new IdentifierExpression("upper")))) } |
||||||
|
) |
||||||
|
) |
||||||
|
) |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
foreach (PropertyOrFieldWrapper w in filtered) { |
||||||
|
script.AddTo(originalCtorBody, |
||||||
|
new ExpressionStatement(new AssignmentExpression(new MemberReferenceExpression(new ThisReferenceExpression(), w.MemberName), AssignmentOperatorType.Assign, new IdentifierExpression(w.ParameterName))) |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
AnchorElement parameterListElement = insertionContext.ActiveElements |
||||||
|
.OfType<AnchorElement>() |
||||||
|
.FirstOrDefault(item => item.Name.Equals("parameterList", StringComparison.OrdinalIgnoreCase)); |
||||||
|
|
||||||
|
if (parameterListElement != null) { |
||||||
|
StringBuilder pList = new StringBuilder(); |
||||||
|
|
||||||
|
var parameters = filtered |
||||||
|
.Select(p => new ParameterDeclaration(refactoringContext.CreateShortType(p.Type), p.ParameterName)) |
||||||
|
.ToList(); |
||||||
|
|
||||||
|
using (StringWriter textWriter = new StringWriter(pList)) { |
||||||
|
// Output parameter list as string
|
||||||
|
var formattingOptions = FormattingOptionsFactory.CreateMono(); |
||||||
|
CSharpOutputVisitor outputVisitor = new CSharpOutputVisitor(textWriter, formattingOptions); |
||||||
|
for (int i = 0; i < parameters.Count; i++) { |
||||||
|
if (i > 0) |
||||||
|
textWriter.Write(","); |
||||||
|
outputVisitor.VisitParameterDeclaration(parameters[i]); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
parameterListElement.Text = pList.ToString(); |
||||||
|
} |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
void UpClick(object sender, System.Windows.RoutedEventArgs e) |
||||||
|
{ |
||||||
|
int selection = varList.SelectedIndex; |
||||||
|
|
||||||
|
if (selection <= 0) |
||||||
|
return; |
||||||
|
|
||||||
|
var curItem = parameterList.First(p => p.Index == selection); |
||||||
|
var exchangeItem = parameterList.First(p => p.Index == selection - 1); |
||||||
|
|
||||||
|
curItem.Index = selection - 1; |
||||||
|
exchangeItem.Index = selection; |
||||||
|
|
||||||
|
varList.ItemsSource = parameterList.OrderBy(p => p.Index); |
||||||
|
varList.SelectedIndex = selection - 1; |
||||||
|
} |
||||||
|
|
||||||
|
void DownClick(object sender, System.Windows.RoutedEventArgs e) |
||||||
|
{ |
||||||
|
int selection = varList.SelectedIndex; |
||||||
|
|
||||||
|
if (selection < 0 || selection >= parameterList.Count - 1) |
||||||
|
return; |
||||||
|
|
||||||
|
var curItem = parameterList.First(p => p.Index == selection); |
||||||
|
var exchangeItem = parameterList.First(p => p.Index == selection + 1); |
||||||
|
|
||||||
|
curItem.Index = selection + 1; |
||||||
|
exchangeItem.Index = selection; |
||||||
|
|
||||||
|
varList.ItemsSource = parameterList.OrderBy(p => p.Index); |
||||||
|
varList.SelectedIndex = selection + 1; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnKeyDown(KeyEventArgs e) |
||||||
|
{ |
||||||
|
Key? downAccessKey = GetAccessKeyFromButton(moveDown); |
||||||
|
Key? upAccessKey = GetAccessKeyFromButton(moveUp); |
||||||
|
Key? allAccessKey = GetAccessKeyFromButton(selectAll); |
||||||
|
|
||||||
|
if ((e.KeyboardDevice.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt && allAccessKey == e.SystemKey) { |
||||||
|
if (AllSelected) |
||||||
|
varList.UnselectAll(); |
||||||
|
else |
||||||
|
varList.SelectAll(); |
||||||
|
e.Handled = true; |
||||||
|
} |
||||||
|
if ((e.KeyboardDevice.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt && upAccessKey == e.SystemKey) { |
||||||
|
UpClick(this, null); |
||||||
|
e.Handled = true; |
||||||
|
} |
||||||
|
if ((e.KeyboardDevice.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt && downAccessKey == e.SystemKey) { |
||||||
|
DownClick(this, null); |
||||||
|
e.Handled = true; |
||||||
|
} |
||||||
|
|
||||||
|
base.OnKeyDown(e); |
||||||
|
} |
||||||
|
|
||||||
|
protected override void FocusFirstElement() |
||||||
|
{ |
||||||
|
Dispatcher.BeginInvoke((Action)TryFocusAndSelectItem, DispatcherPriority.Background); |
||||||
|
} |
||||||
|
|
||||||
|
void TryFocusAndSelectItem() |
||||||
|
{ |
||||||
|
if (!parameterList.Any()) |
||||||
|
return; |
||||||
|
|
||||||
|
object ctorParamWrapper = varList.Items.GetItemAt(0); |
||||||
|
if (ctorParamWrapper != null) { |
||||||
|
ListBoxItem item = (ListBoxItem)varList.ItemContainerGenerator.ContainerFromItem(ctorParamWrapper); |
||||||
|
item.Focus(); |
||||||
|
|
||||||
|
varList.ScrollIntoView(item); |
||||||
|
varList.SelectedItem = item; |
||||||
|
Keyboard.Focus(item); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OnInsertionCompleted() |
||||||
|
{ |
||||||
|
base.OnInsertionCompleted(); |
||||||
|
|
||||||
|
Dispatcher.BeginInvoke( |
||||||
|
DispatcherPriority.Background, |
||||||
|
(Action)( |
||||||
|
() => { |
||||||
|
if (!parameterList.Any()) |
||||||
|
insertionContext.Deactivate(null); |
||||||
|
else { |
||||||
|
insertionEndAnchor = editor.Document.CreateAnchor(anchor.Offset); |
||||||
|
insertionEndAnchor.MovementType = AnchorMovementType.AfterInsertion; |
||||||
|
} |
||||||
|
} |
||||||
|
) |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
void SelectAllChecked(object sender, System.Windows.RoutedEventArgs e) |
||||||
|
{ |
||||||
|
this.varList.SelectAll(); |
||||||
|
} |
||||||
|
|
||||||
|
void SelectAllUnchecked(object sender, System.Windows.RoutedEventArgs e) |
||||||
|
{ |
||||||
|
this.varList.UnselectAll(); |
||||||
|
} |
||||||
|
|
||||||
|
bool AllSelected { |
||||||
|
get { return varList.SelectedItems.Count == varList.Items.Count; } |
||||||
|
} |
||||||
|
|
||||||
|
protected override void CancelButtonClick(object sender, System.Windows.RoutedEventArgs e) |
||||||
|
{ |
||||||
|
base.CancelButtonClick(sender, e); |
||||||
|
|
||||||
|
editor.Caret.Offset = anchor.Offset; |
||||||
|
} |
||||||
|
|
||||||
|
protected override void OKButtonClick(object sender, System.Windows.RoutedEventArgs e) |
||||||
|
{ |
||||||
|
base.OKButtonClick(sender, e); |
||||||
|
|
||||||
|
editor.Caret.Offset = insertionEndAnchor.Offset; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[ValueConversion(typeof(int), typeof(bool))] |
||||||
|
public class IntToBoolConverter : IValueConverter |
||||||
|
{ |
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) |
||||||
|
{ |
||||||
|
return ((int)value) != -1; |
||||||
|
} |
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) |
||||||
|
{ |
||||||
|
return ((bool)value) ? 0 : -1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
// 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.Threading; |
||||||
|
|
||||||
|
using ICSharpCode.AvalonEdit.Snippets; |
||||||
|
using ICSharpCode.NRefactory; |
||||||
|
using ICSharpCode.NRefactory.Editor; |
||||||
|
using ICSharpCode.NRefactory.TypeSystem; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
using ICSharpCode.SharpDevelop.Parser; |
||||||
|
using CSharpBinding.Refactoring; |
||||||
|
using ICSharpCode.SharpDevelop.Editor; |
||||||
|
|
||||||
|
namespace CSharpBinding.Refactoring |
||||||
|
{ |
||||||
|
public class InsertCtorSnippetRefactoring : ISnippetElementProvider |
||||||
|
{ |
||||||
|
public SnippetElement GetElement(SnippetInfo snippetInfo) |
||||||
|
{ |
||||||
|
if ("refactoring:ctor".Equals(snippetInfo.Tag, StringComparison.OrdinalIgnoreCase)) |
||||||
|
return new InlineRefactorSnippetElement(CreateDialog, "{" + snippetInfo.Tag + "}"); |
||||||
|
|
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
InsertCtorDialog CreateDialog(InsertionContext context) |
||||||
|
{ |
||||||
|
ITextEditor textEditor = context.TextArea.GetService(typeof(ITextEditor)) as ITextEditor; |
||||||
|
|
||||||
|
if (textEditor == null) |
||||||
|
return null; |
||||||
|
|
||||||
|
IEditorUIService uiService = textEditor.GetService(typeof(IEditorUIService)) as IEditorUIService; |
||||||
|
|
||||||
|
if (uiService == null) |
||||||
|
return null; |
||||||
|
|
||||||
|
ParseInformation parseInfo = SD.ParserService.GetCachedParseInformation(textEditor.FileName); |
||||||
|
|
||||||
|
if (parseInfo == null) |
||||||
|
return null; |
||||||
|
|
||||||
|
// cannot use insertion position at this point, because it might not be
|
||||||
|
// valid, because we are still generating the elements.
|
||||||
|
// DOM is not updated
|
||||||
|
TextLocation loc = context.Document.GetLocation(context.StartPosition); |
||||||
|
|
||||||
|
IUnresolvedTypeDefinition current = parseInfo.UnresolvedFile.GetInnermostTypeDefinition(loc); |
||||||
|
if (current == null) |
||||||
|
return null; |
||||||
|
|
||||||
|
var refactoringContext = SDRefactoringContext.Create(textEditor, CancellationToken.None); |
||||||
|
var resolvedCurrent = current.Resolve(refactoringContext.Resolver.TypeResolveContext); |
||||||
|
|
||||||
|
List<PropertyOrFieldWrapper> parameters = CreateCtorParams(current, resolvedCurrent).ToList(); |
||||||
|
|
||||||
|
if (!parameters.Any()) |
||||||
|
return null; |
||||||
|
|
||||||
|
ITextAnchor anchor = textEditor.Document.CreateAnchor(context.InsertionPosition); |
||||||
|
anchor.MovementType = AnchorMovementType.BeforeInsertion; |
||||||
|
|
||||||
|
InsertCtorDialog dialog = new InsertCtorDialog(context, textEditor, anchor, current, parameters); |
||||||
|
|
||||||
|
dialog.Element = uiService.CreateInlineUIElement(anchor, dialog); |
||||||
|
|
||||||
|
return dialog; |
||||||
|
} |
||||||
|
|
||||||
|
IEnumerable<PropertyOrFieldWrapper> CreateCtorParams(IUnresolvedTypeDefinition sourceType, IType resolvedSourceType) |
||||||
|
{ |
||||||
|
int i = 0; |
||||||
|
|
||||||
|
foreach (var f in resolvedSourceType.GetFields().Where(field => !field.IsConst |
||||||
|
&& field.IsStatic == sourceType.IsStatic |
||||||
|
&& field.ReturnType != null)) { |
||||||
|
yield return new PropertyOrFieldWrapper(f) { Index = i }; |
||||||
|
i++; |
||||||
|
} |
||||||
|
|
||||||
|
foreach (var p in resolvedSourceType.GetProperties().Where(prop => prop.CanSet && !prop.IsIndexer |
||||||
|
&& prop.IsStatic == sourceType.IsStatic |
||||||
|
&& prop.ReturnType != null)) { |
||||||
|
yield return new PropertyOrFieldWrapper(p) { Index = i }; |
||||||
|
i++; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,121 @@ |
|||||||
|
// 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.Linq; |
||||||
|
|
||||||
|
using ICSharpCode.NRefactory.TypeSystem; |
||||||
|
using ICSharpCode.SharpDevelop; |
||||||
|
|
||||||
|
namespace CSharpBinding.Refactoring |
||||||
|
{ |
||||||
|
public class PropertyOrFieldWrapper : INotifyPropertyChanged |
||||||
|
{ |
||||||
|
/// <summary>
|
||||||
|
/// Underlying member. Always IField or IProperty.
|
||||||
|
/// </summary>
|
||||||
|
public readonly IMember Member; |
||||||
|
private readonly string text; |
||||||
|
|
||||||
|
public PropertyOrFieldWrapper(IMember member) |
||||||
|
{ |
||||||
|
if (member == null) |
||||||
|
throw new ArgumentNullException("member"); |
||||||
|
if (!(member is IField || member is IProperty)) |
||||||
|
throw new ArgumentException("member must be IField or IProperty"); |
||||||
|
|
||||||
|
this.Member = member; |
||||||
|
IAmbience ambience = AmbienceService.GetCurrentAmbience(); |
||||||
|
ambience.ConversionFlags |= |
||||||
|
ConversionFlags.ShowReturnType |
||||||
|
| ConversionFlags.ShowModifiers |
||||||
|
| ConversionFlags.ShowAccessibility; |
||||||
|
this.text = ambience.ConvertEntity(member); |
||||||
|
} |
||||||
|
|
||||||
|
public string MemberName { |
||||||
|
get { return Member.Name; } |
||||||
|
} |
||||||
|
|
||||||
|
string parameterName; |
||||||
|
public string ParameterName { |
||||||
|
get { |
||||||
|
if (parameterName == null) |
||||||
|
parameterName = ToParameterName(this.MemberName); |
||||||
|
return parameterName; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public IType Type { |
||||||
|
get { return Member.ReturnType; } |
||||||
|
} |
||||||
|
|
||||||
|
public string Text { |
||||||
|
get { return text; } |
||||||
|
} |
||||||
|
|
||||||
|
public int Index { get; set; } |
||||||
|
|
||||||
|
public bool IsNullable { |
||||||
|
get { |
||||||
|
// true = reference, null = generic or unknown
|
||||||
|
return Member.ReturnType.IsReferenceType != false |
||||||
|
|| (Member.ReturnType.FullName == "System.Nullable"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public bool HasRange { |
||||||
|
get { |
||||||
|
return IsTypeWithRange(Member.ReturnType) || |
||||||
|
(Member.ReturnType.FullName == "System.Nullable") |
||||||
|
&& IsTypeWithRange(Member.ReturnType.TypeArguments.First()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool addCheckForNull; |
||||||
|
public bool AddCheckForNull { |
||||||
|
get { return addCheckForNull; } |
||||||
|
set { |
||||||
|
addCheckForNull = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool addRangeCheck; |
||||||
|
public bool AddRangeCheck { |
||||||
|
get { return addRangeCheck; } |
||||||
|
set { |
||||||
|
addRangeCheck = value; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool IsTypeWithRange(IType type) |
||||||
|
{ |
||||||
|
string crtType = type.FullName; |
||||||
|
return crtType == "System.Int32" || |
||||||
|
crtType == "System.Int16" || |
||||||
|
crtType == "System.Int64" || |
||||||
|
crtType == "System.Single" || |
||||||
|
crtType == "System.Double" || |
||||||
|
crtType == "System.UInt16" || |
||||||
|
crtType == "System.UInt32" || |
||||||
|
crtType == "System.UInt64"; |
||||||
|
} |
||||||
|
|
||||||
|
static string ToParameterName(string memberName) |
||||||
|
{ |
||||||
|
if (string.IsNullOrEmpty(memberName)) |
||||||
|
return memberName; |
||||||
|
return char.ToLower(memberName[0]) + memberName.Substring(1); |
||||||
|
} |
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged; |
||||||
|
|
||||||
|
protected virtual void OnPropertyChanged(string property) |
||||||
|
{ |
||||||
|
if (PropertyChanged != null) { |
||||||
|
PropertyChanged(this, new PropertyChangedEventArgs(property)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue