Browse Source
- Add short-cut extensibility in the designer. - Add Focus navigation(actually the primary selection navigation) up-the-element-tree and down-the-element tree though Tab and Shift+Tab respectively. - Add edit operations for the designer - Cut,Copy and Paste by copying Xaml of the element to clipboard and loading it, works with more than one instances of SharpDevelop too. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/wpfdesigner@6066 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61pull/1/head
19 changed files with 936 additions and 25 deletions
@ -0,0 +1,81 @@
@@ -0,0 +1,81 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.WpfDesign.Designer; |
||||
|
||||
namespace ICSharpCode.WpfDesign.AddIn.Commands |
||||
{ |
||||
/// <summary>
|
||||
/// Invokes Cut command on the Design surface.
|
||||
/// </summary>
|
||||
class Cut : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
var surface = Owner as DesignSurface; |
||||
if(surface!=null) |
||||
surface.Cut(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Invokes Copy command on the Design surface.
|
||||
/// </summary>
|
||||
class Copy : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
var surface = Owner as DesignSurface; |
||||
if (surface != null) |
||||
surface.Copy(); |
||||
|
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Invokes Paste operation on the Design surface.
|
||||
/// </summary>
|
||||
class Paste : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
var surface = Owner as DesignSurface; |
||||
if (surface != null) |
||||
surface.Paste(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Provides implementation of <see cref="IConditionEvaluator"/> for <see cref="Cut"/> and <see cref="Copy"/>.
|
||||
/// </summary>
|
||||
class IsCutCopyEnabled : IConditionEvaluator |
||||
{ |
||||
public bool IsValid(object owner, Condition condition) |
||||
{ |
||||
var surface = owner as DesignSurface; |
||||
if(surface!=null) { |
||||
return surface.CanCopyOrCut(); |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Provides implementation of <see cref="IConditionEvaluator"/> for <see cref="Paste"/>.
|
||||
/// </summary>
|
||||
class IsPasteEnabled : IConditionEvaluator |
||||
{ |
||||
public bool IsValid(object owner, Condition condition) |
||||
{ |
||||
var surface = owner as DesignSurface; |
||||
if (surface != null) |
||||
return surface.CanPaste(); |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.WpfDesign.AddIn.Commands |
||||
{ |
||||
/// <summary>
|
||||
/// Opens up the Tools Pad.
|
||||
/// </summary>
|
||||
class Tools : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
WorkbenchSingleton.Workbench.GetPad(typeof(ToolsPad)).BringPadToFront(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Opens up the Propeties Pad.
|
||||
/// </summary>
|
||||
class Properties : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
WorkbenchSingleton.Workbench.GetPad(typeof(PropertyPad)).BringPadToFront(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Opens up the Outline Pad.
|
||||
/// </summary>
|
||||
class Outline : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
WorkbenchSingleton.Workbench.GetPad(typeof(OutlinePad)).BringPadToFront(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
|
||||
using ICSharpCode.WpfDesign.Designer; |
||||
|
||||
namespace ICSharpCode.WpfDesign.AddIn.Commands |
||||
{ |
||||
/// <summary>
|
||||
/// Removes selected element from the designer.
|
||||
/// </summary>
|
||||
class Remove : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
var surface = Owner as DesignSurface; |
||||
if (surface != null) |
||||
surface.Delete(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Provides implementation of <see cref="IConditionEvaluator"/> for <see cref="Remove"/>.
|
||||
/// </summary>
|
||||
class IsRemoveEnabled : IConditionEvaluator |
||||
{ |
||||
public bool IsValid(object owner, Condition condition) |
||||
{ |
||||
var surface = owner as DesignSurface; |
||||
if (surface != null) |
||||
return surface.CanDelete(); |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,65 @@
@@ -0,0 +1,65 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.WpfDesign.Designer; |
||||
namespace ICSharpCode.WpfDesign.AddIn.Commands |
||||
{ |
||||
/// <summary>
|
||||
/// Invokes the Undo command if available on the Design Surface.
|
||||
/// </summary>
|
||||
class Undo : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
var surface = Owner as DesignSurface; |
||||
if (surface != null) |
||||
surface.Undo(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Invokes the Redo command if available on the Design surface.
|
||||
/// </summary>
|
||||
class Redo : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
var surface = Owner as DesignSurface; |
||||
if (surface != null) |
||||
surface.Redo(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Provides implementation of <see cref="IConditionEvaluator"/> for <see cref="Undo"/>.
|
||||
/// </summary>
|
||||
class IsUndoEnabled : IConditionEvaluator |
||||
{ |
||||
public bool IsValid(object owner, Condition condition) |
||||
{ |
||||
var surface = owner as DesignSurface; |
||||
if (surface != null) |
||||
return surface.CanUndo(); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Provides implementation of <see cref="IConditionEvaluator"/> for <see cref="Redo"/>.
|
||||
/// </summary>
|
||||
class IsRedoEnabled : IConditionEvaluator |
||||
{ |
||||
public bool IsValid(object owner, Condition condition) |
||||
{ |
||||
var surface = owner as DesignSurface; |
||||
if (surface != null) |
||||
return surface.CanRedo(); |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Gui; |
||||
|
||||
namespace ICSharpCode.WpfDesign.AddIn.Commands |
||||
{ |
||||
/// <summary>
|
||||
/// Switches to the XAML source code tab.
|
||||
/// </summary>
|
||||
public class ViewXaml : AbstractMenuCommand |
||||
{ |
||||
public override void Run() |
||||
{ |
||||
WorkbenchSingleton.Workbench.ActiveWorkbenchWindow.SwitchView(0); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
using System.Windows.Input; |
||||
using System.Diagnostics; |
||||
|
||||
namespace ICSharpCode.WpfDesign.Designer |
||||
{ |
||||
/// <summary>
|
||||
/// Custom implementation of ICommand based on the RelayCommand model by Josh Smith for the designer.
|
||||
/// </summary>
|
||||
public class DesignCommand : ICommand |
||||
{ |
||||
private readonly Action<object> _action; |
||||
private readonly Func<object, bool> _canExecute; |
||||
|
||||
public DesignCommand(Action<object> action,Func<object,bool> canExecute) |
||||
{ |
||||
Debug.Assert(action != null); |
||||
this._action = action; |
||||
this._canExecute = canExecute; |
||||
} |
||||
|
||||
public void Execute(object parameter) |
||||
{ |
||||
_action(parameter); |
||||
} |
||||
|
||||
public bool CanExecute(object parameter) |
||||
{ |
||||
if (_canExecute != null) |
||||
return _canExecute(parameter); |
||||
return true; |
||||
} |
||||
|
||||
public event EventHandler CanExecuteChanged |
||||
{ |
||||
add { CommandManager.RequerySuggested += value; } |
||||
remove { CommandManager.RequerySuggested -= value; } |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,219 @@
@@ -0,0 +1,219 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
using System.Linq; |
||||
using System.Windows.Input; |
||||
|
||||
namespace ICSharpCode.WpfDesign.Designer |
||||
{ |
||||
/// <summary>
|
||||
/// Manages the Focus/Primary Selection using TAB for down-the-tree navigation and Shift+TAB for up-the-tree navigation.
|
||||
/// </summary>
|
||||
class FocusNavigator |
||||
{ |
||||
/* The Focus navigator do not involves the concept of Logical Focus or KeyBoard Focus |
||||
* since nothing is getting focoused on the designer except for the DesignPanel. It just changes |
||||
* the primary selection between the hierarchy of elements present on the designer. */ |
||||
|
||||
private readonly DesignSurface _surface; |
||||
private KeyBinding _tabBinding; |
||||
private KeyBinding _shiftTabBinding; |
||||
|
||||
public FocusNavigator(DesignSurface surface) |
||||
{ |
||||
this._surface=surface; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Starts the navigator on the Design surface and add bindings.
|
||||
/// </summary>
|
||||
public void Start() |
||||
{ |
||||
DesignCommand tabFocus = new DesignCommand(parameter => this.MoveFocusForward(_surface), parameter => CanMoveFocusForward(_surface)); |
||||
DesignCommand shiftTabFocus = new DesignCommand(parameter => this.MoveFocusBack(_surface), parameter => this.CanMoveFocusBack(_surface)); |
||||
_tabBinding = new KeyBinding(tabFocus, new KeyGesture(Key.Tab)); |
||||
_shiftTabBinding = new KeyBinding(shiftTabFocus, new KeyGesture(Key.Tab, ModifierKeys.Shift)); |
||||
IKeyBindingService kbs = _surface.DesignContext.Services.GetService(typeof(IKeyBindingService)) as IKeyBindingService; |
||||
if (kbs != null) |
||||
{ |
||||
kbs.RegisterBinding(_tabBinding); |
||||
kbs.RegisterBinding(_shiftTabBinding); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// De-register the bindings from the Design Surface
|
||||
/// </summary>
|
||||
public void End() |
||||
{ |
||||
IKeyBindingService kbs = _surface.DesignContext.Services.GetService(typeof(IKeyBindingService)) as IKeyBindingService; |
||||
if (kbs != null) |
||||
{ |
||||
kbs.DeregisterBinding(_tabBinding); |
||||
kbs.DeregisterBinding(_shiftTabBinding); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Moves the Foucus down the tree.
|
||||
/// </summary>
|
||||
void MoveFocusForward(object surface) |
||||
{ |
||||
var designSurface = surface as DesignSurface; |
||||
if (designSurface != null) { |
||||
var context = designSurface.DesignContext; |
||||
ISelectionService selection=context.Services.Selection; |
||||
DesignItem item = selection.PrimarySelection; |
||||
selection.SetSelectedComponents(selection.SelectedItems, SelectionTypes.Remove); |
||||
if (item != GetLastElement()) |
||||
{ |
||||
if (item.ContentProperty != null) |
||||
{ |
||||
if (item.ContentProperty.IsCollection) |
||||
{ |
||||
if (item.ContentProperty.CollectionElements.Count != 0) |
||||
{ |
||||
if (ModelTools.CanSelectComponent(item.ContentProperty.CollectionElements.First())) |
||||
selection.SetSelectedComponents(new DesignItem[] { item.ContentProperty.CollectionElements.First() }, SelectionTypes.Primary); |
||||
else |
||||
SelectNextInPeers(item); |
||||
} |
||||
else |
||||
SelectNextInPeers(item); |
||||
} |
||||
else if (item.ContentProperty.Value != null) { |
||||
if (ModelTools.CanSelectComponent(item.ContentProperty.Value)) |
||||
selection.SetSelectedComponents(new DesignItem[] { item.ContentProperty.Value }, SelectionTypes.Primary); |
||||
else |
||||
SelectNextInPeers(item); |
||||
} |
||||
else { |
||||
SelectNextInPeers(item); |
||||
} |
||||
} |
||||
else { |
||||
SelectNextInPeers(item); |
||||
} |
||||
} |
||||
else { //if the element was last element move focus to the root element to keep a focus cycle.
|
||||
selection.SetSelectedComponents(new DesignItem[] {context.RootItem}, SelectionTypes.Primary); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Checks if focus navigation should be for down-the-tree be done.
|
||||
/// </summary>
|
||||
/// <param name="surface">Design Surface</param>
|
||||
bool CanMoveFocusForward(object surface) |
||||
{ |
||||
var designSurface = surface as DesignSurface; |
||||
if (designSurface != null) |
||||
if (Keyboard.FocusedElement == designSurface._designPanel) |
||||
return true; |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Moves focus up-the-tree.
|
||||
/// </summary>
|
||||
void MoveFocusBack(object surface) |
||||
{ |
||||
var designSurface = surface as DesignSurface; |
||||
if (designSurface != null) { |
||||
var context = designSurface.DesignContext; |
||||
ISelectionService selection = context.Services.Selection; |
||||
DesignItem item = selection.PrimarySelection; |
||||
if (item != context.RootItem) |
||||
{ |
||||
if (item.Parent != null && item.Parent.ContentProperty.IsCollection) |
||||
{ |
||||
int index = item.Parent.ContentProperty.CollectionElements.IndexOf(item); |
||||
if (index != 0) |
||||
{ |
||||
if (ModelTools.CanSelectComponent(item.Parent.ContentProperty.CollectionElements.ElementAt(index - 1))) |
||||
selection.SetSelectedComponents(new DesignItem[] { item.Parent.ContentProperty.CollectionElements.ElementAt(index - 1) }, SelectionTypes.Primary); |
||||
} |
||||
else |
||||
{ |
||||
if (ModelTools.CanSelectComponent(item.Parent)) |
||||
selection.SetSelectedComponents(new DesignItem[] { item.Parent }, SelectionTypes.Primary); |
||||
} |
||||
|
||||
} |
||||
else |
||||
{ |
||||
if (ModelTools.CanSelectComponent(item.Parent)) |
||||
selection.SetSelectedComponents(new DesignItem[] { item.Parent }, SelectionTypes.Primary); |
||||
} |
||||
} |
||||
else {// if the element was root item move focus again to the last element.
|
||||
selection.SetSelectedComponents(new DesignItem[] { GetLastElement() }, SelectionTypes.Primary); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Checks if focus navigation for the up-the-tree should be done.
|
||||
/// </summary>
|
||||
/// <param name="surface">Design Surface</param>
|
||||
bool CanMoveFocusBack(object surface) |
||||
{ |
||||
var designSurface = surface as DesignSurface; |
||||
if (designSurface != null) |
||||
if (Keyboard.FocusedElement == designSurface._designPanel) |
||||
return true; |
||||
return false; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the last element in the element hierarchy.
|
||||
/// </summary>
|
||||
DesignItem GetLastElement() |
||||
{ |
||||
DesignItem item = _surface.DesignContext.RootItem; |
||||
while (item != null && item.ContentProperty != null) |
||||
{ |
||||
if (item.ContentProperty.IsCollection) |
||||
{ |
||||
if (item.ContentProperty.CollectionElements.Count != 0) { |
||||
if (ModelTools.CanSelectComponent(item.ContentProperty.CollectionElements.Last())) |
||||
item = item.ContentProperty.CollectionElements.Last(); |
||||
else |
||||
break; |
||||
} |
||||
else |
||||
break; |
||||
} |
||||
else { |
||||
if (item.ContentProperty.Value != null) |
||||
item = item.ContentProperty.Value; |
||||
else |
||||
break; |
||||
} |
||||
} |
||||
return item; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Select the next element in the element collection if <paramref name="item"/> parent's had it's content property as collection.
|
||||
/// </summary>
|
||||
void SelectNextInPeers(DesignItem item) |
||||
{ |
||||
ISelectionService selection = _surface.DesignContext.Services.Selection; |
||||
if (item.Parent != null && item.Parent.ContentProperty != null) |
||||
{ |
||||
if (item.Parent.ContentProperty.IsCollection) |
||||
{ |
||||
int index = item.Parent.ContentProperty.CollectionElements.IndexOf(item); |
||||
if (index != item.Parent.ContentProperty.CollectionElements.Count) |
||||
selection.SetSelectedComponents(new DesignItem[] { item.Parent.ContentProperty.CollectionElements.ElementAt(index + 1) }, SelectionTypes.Primary); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System.Collections.ObjectModel; |
||||
using System.Diagnostics; |
||||
using System.Linq; |
||||
using System.Windows.Input; |
||||
|
||||
namespace ICSharpCode.WpfDesign.Designer.Services |
||||
{ |
||||
class DesignerKeyBindings : IKeyBindingService |
||||
{ |
||||
private readonly DesignSurface _surface; |
||||
private Collection<KeyBinding> _bindings; |
||||
|
||||
public DesignerKeyBindings(DesignSurface surface) |
||||
{ |
||||
Debug.Assert(surface != null); |
||||
this._surface = surface; |
||||
_bindings = new Collection<KeyBinding>(); |
||||
} |
||||
|
||||
public void RegisterBinding(KeyBinding binding) |
||||
{ |
||||
if(binding!=null) { |
||||
_surface.InputBindings.Add(binding); |
||||
_bindings.Add(binding); |
||||
} |
||||
} |
||||
|
||||
public void DeregisterBinding(KeyBinding binding) |
||||
{ |
||||
if(_bindings.Contains(binding)) { |
||||
_surface.InputBindings.Remove(binding); |
||||
_bindings.Remove(binding); |
||||
} |
||||
} |
||||
|
||||
public KeyBinding GetBinding(KeyGesture gesture) |
||||
{ |
||||
return _bindings.FirstOrDefault(binding => binding.Key == gesture.Key && binding.Modifiers == gesture.Modifiers); |
||||
} |
||||
|
||||
public object Owner{ |
||||
get { return _surface; } |
||||
} |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,167 @@
@@ -0,0 +1,167 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Collections.ObjectModel; |
||||
using System.Linq; |
||||
using System.Windows; |
||||
|
||||
using ICSharpCode.WpfDesign.XamlDom; |
||||
|
||||
namespace ICSharpCode.WpfDesign.Designer.Xaml |
||||
{ |
||||
/// <summary>
|
||||
/// Deals with operations on controls which also require access to internal XML properties of the XAML Document.
|
||||
/// </summary>
|
||||
public class XamlEditOperations |
||||
{ |
||||
readonly XamlDesignContext _context; |
||||
readonly XamlParserSettings _settings; |
||||
|
||||
/// <summary>
|
||||
/// Delimet character to seperate different piece of Xaml's
|
||||
/// </summary>
|
||||
readonly char _delimeter = Convert.ToChar(0x7F); |
||||
|
||||
public XamlEditOperations(XamlDesignContext context, XamlParserSettings settings) |
||||
{ |
||||
this._context = context; |
||||
this._settings = settings; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Copy <paramref name="designItems"/> from the designer to clipboard.
|
||||
/// </summary>
|
||||
public void Cut(ICollection<DesignItem> designItems) |
||||
{ |
||||
Clipboard.Clear(); |
||||
string cutXaml = ""; |
||||
var changeGroup = _context.OpenGroup("Cut " + designItems.Count + " elements", designItems); |
||||
foreach (var item in designItems) |
||||
{ |
||||
if (item != null && item != _context.RootItem) |
||||
{ |
||||
XamlDesignItem xamlItem = item as XamlDesignItem; |
||||
if (xamlItem != null) { |
||||
cutXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject); |
||||
cutXaml += _delimeter; |
||||
} |
||||
} |
||||
} |
||||
ModelTools.DeleteComponents(designItems); |
||||
Clipboard.SetText(cutXaml, TextDataFormat.Xaml); |
||||
changeGroup.Commit(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Copy <paramref name="designItems"/> from the designer to clipboard.
|
||||
/// </summary>
|
||||
public void Copy(ICollection<DesignItem> designItems) |
||||
{ |
||||
Clipboard.Clear(); |
||||
string copiedXaml = ""; |
||||
var changeGroup = _context.OpenGroup("Copy " + designItems.Count + " elements", designItems); |
||||
foreach (var item in designItems) |
||||
{ |
||||
if (item != null) |
||||
{ |
||||
XamlDesignItem xamlItem = item as XamlDesignItem; |
||||
if (xamlItem != null) { |
||||
copiedXaml += XamlStaticTools.GetXaml(xamlItem.XamlObject); |
||||
copiedXaml += _delimeter; |
||||
} |
||||
} |
||||
} |
||||
Clipboard.SetText(copiedXaml, TextDataFormat.Xaml); |
||||
changeGroup.Commit(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Paste items from clipboard into the designer.
|
||||
/// </summary>
|
||||
public void Paste() |
||||
{ |
||||
bool pasted = false; |
||||
string combinedXaml = Clipboard.GetText(TextDataFormat.Xaml); |
||||
IEnumerable<string> xamls = combinedXaml.Split(_delimeter); |
||||
xamls = xamls.Where(xaml => xaml != ""); |
||||
|
||||
DesignItem parent = _context.Services.Selection.PrimarySelection; |
||||
DesignItem child = _context.Services.Selection.PrimarySelection; |
||||
|
||||
XamlDesignItem rootItem = _context.RootItem as XamlDesignItem; |
||||
var pastedItems = new Collection<DesignItem>(); |
||||
foreach(var xaml in xamls) { |
||||
var obj = XamlParser.ParseSnippet(rootItem.XamlObject, xaml, _settings); |
||||
if(obj!=null) { |
||||
DesignItem item = _context._componentService.RegisterXamlComponentRecursive(obj); |
||||
if (item != null) |
||||
pastedItems.Add(item); |
||||
} |
||||
} |
||||
|
||||
if (pastedItems.Count != 0) { |
||||
var changeGroup = _context.OpenGroup("Paste " + pastedItems.Count + " elements", pastedItems); |
||||
while (parent != null && pasted == false) { |
||||
if (parent.ContentProperty != null) { |
||||
if (parent.ContentProperty.IsCollection) { |
||||
if (CollectionSupport.CanCollectionAdd(parent.ContentProperty.ReturnType, pastedItems.Select(item => item.Component))) { |
||||
AddInParent(parent, pastedItems); |
||||
pasted = true; |
||||
} |
||||
} else if (pastedItems.Count == 1 && parent.ContentProperty.Value == null && parent.ContentProperty.ValueOnInstance == null) { |
||||
AddInParent(parent, pastedItems); |
||||
pasted = true; |
||||
} else { |
||||
parent = parent.Parent; |
||||
} |
||||
} else { |
||||
parent = parent.Parent; |
||||
} |
||||
} |
||||
|
||||
while (pasted == false) { |
||||
if (child.ContentProperty != null) { |
||||
if (child.ContentProperty.IsCollection) { |
||||
foreach (var col in child.ContentProperty.CollectionElements) { |
||||
if (col.ContentProperty != null && col.ContentProperty.IsCollection) { |
||||
if (CollectionSupport.CanCollectionAdd(col.ContentProperty.ReturnType, pastedItems.Select(item => item.Component))) { |
||||
pasted = true; |
||||
} |
||||
} |
||||
} |
||||
break; |
||||
} else if (child.ContentProperty.Value != null) { |
||||
child = child.ContentProperty.Value; |
||||
} else if (pastedItems.Count == 1) { |
||||
child.ContentProperty.SetValue(pastedItems.First().Component); |
||||
pasted = true; |
||||
break; |
||||
} else |
||||
break; |
||||
} else |
||||
break; |
||||
} |
||||
changeGroup.Commit(); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Adds Items under a parent given that the content property is collection and can add types of <paramref name="pastedItems"/>
|
||||
/// </summary>
|
||||
/// <param name="parent">The Parent element</param>
|
||||
/// <param name="pastedItems">The list of elements to be added</param>
|
||||
void AddInParent(DesignItem parent,IList<DesignItem> pastedItems) |
||||
{ |
||||
IEnumerable<Rect> rects = pastedItems.Select(i => new Rect(new Point(0, 0), new Point((double)i.Properties["Width"].ValueOnInstance, (double)i.Properties["Height"].ValueOnInstance))); |
||||
var operation = PlacementOperation.TryStartInsertNewComponents(parent, pastedItems, rects.ToList(), PlacementType.AddItem); |
||||
ISelectionService selection = _context.Services.Selection; |
||||
selection.SetSelectedComponents(pastedItems); |
||||
operation.Commit(); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Kumar Devvrat"/>
|
||||
// <version>$Revision: $</version>
|
||||
// </file>
|
||||
using System; |
||||
|
||||
namespace ICSharpCode.WpfDesign.XamlDom |
||||
{ |
||||
/// <summary>
|
||||
/// Static methods to help with designer operations which require access to internal Xaml elements.
|
||||
/// </summary>
|
||||
public static class XamlStaticTools |
||||
{ |
||||
/// <summary>
|
||||
/// Gets the Xaml string of the <paramref name="xamlObject"/>
|
||||
/// </summary>
|
||||
/// <param name="xamlObject">The object whose Xaml is requested.</param>
|
||||
public static string GetXaml(XamlObject xamlObject) |
||||
{ |
||||
if (xamlObject != null) |
||||
return xamlObject.XmlElement.OuterXml; |
||||
return null; |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue