Browse Source

- Add Context menu with general set of operations.

- 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-cef0b8235c61
pull/1/head
Kumar Devvrat 16 years ago
parent
commit
901b1ce927
  1. 81
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/CutCopyPaste.cs
  2. 45
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/Pads.cs
  3. 40
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/Remove.cs
  4. 65
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/UndoRedo.cs
  5. 23
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/ViewXaml.cs
  6. 5
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs
  7. 6
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj
  8. 59
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.addin
  9. 46
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignCommand.cs
  10. 42
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.xaml.cs
  11. 219
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/FocusNavigator.cs
  12. 52
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DesignerKeyBindings.cs
  13. 4
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj
  14. 11
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs
  15. 167
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlEditOperations.cs
  16. 4
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj
  17. 31
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs
  18. 27
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlStaticTools.cs
  19. 34
      src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs

81
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/CutCopyPaste.cs

@ -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;
}
}
}

45
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/Pads.cs

@ -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();
}
}
}

40
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/Remove.cs

@ -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;
}
}
}

65
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/UndoRedo.cs

@ -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;
}
}
}

23
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/Commands/ViewXaml.cs

@ -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);
}
}
}

5
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/WpfViewContent.cs

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// </file>
using System;
using System.Windows;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -26,6 +27,8 @@ using ICSharpCode.WpfDesign.Designer.Services; @@ -26,6 +27,8 @@ using ICSharpCode.WpfDesign.Designer.Services;
using ICSharpCode.WpfDesign.Designer.Xaml;
using ICSharpCode.WpfDesign.PropertyGrid;
using ICSharpCode.Core.Presentation;
namespace ICSharpCode.WpfDesign.AddIn
{
/// <summary>
@ -87,6 +90,8 @@ namespace ICSharpCode.WpfDesign.AddIn @@ -87,6 +90,8 @@ namespace ICSharpCode.WpfDesign.AddIn
designer.LoadDesigner(r, settings);
designer.ContextMenuOpening += (sender, e) => MenuService.ShowContextMenu(e.OriginalSource as UIElement, designer, "/Addins/WpfDesign/Designer/ContextMenu");
UpdateTasks();
if (outline != null && designer.DesignContext != null && designer.DesignContext.RootItem != null) {

6
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj

@ -60,6 +60,11 @@ @@ -60,6 +60,11 @@
</Compile>
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\AbstractEventHandlerService.cs" />
<Compile Include="Src\Commands\CutCopyPaste.cs" />
<Compile Include="Src\Commands\Pads.cs" />
<Compile Include="Src\Commands\Remove.cs" />
<Compile Include="Src\Commands\UndoRedo.cs" />
<Compile Include="Src\Commands\ViewXaml.cs" />
<Compile Include="Src\CSharpEventHandlerService.cs" />
<Compile Include="Src\FileUriContext.cs" />
<Compile Include="Src\IdeChooseClassService.cs" />
@ -146,5 +151,6 @@ @@ -146,5 +151,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Src\ImageSourceEditor" />
<Folder Include="Src\Commands" />
</ItemGroup>
</Project>

59
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.addin

@ -1,30 +1,28 @@ @@ -1,30 +1,28 @@
<AddIn name = "WPF Designer AddIn"
author = "Daniel Grunwald"
copyright = "prj:///doc/copyright.txt"
description = "WPF Designer"
addInManagerHidden="preinstalled">
<AddIn name="WPF Designer AddIn" author="Daniel Grunwald" copyright="prj:///doc/copyright.txt" description="WPF Designer" addInManagerHidden="preinstalled">
<Manifest>
<Identity name="ICSharpCode.WpfDesigner"/>
<Dependency addin = "ICSharpCode.FormsDesigner" requirePreload = "true"/>
<Identity name="ICSharpCode.WpfDesigner" />
<Dependency addin="ICSharpCode.FormsDesigner" requirePreload="true" />
</Manifest>
<Runtime>
<Import assembly = "ICSharpCode.WpfDesign.AddIn.dll"/>
<Import assembly="ICSharpCode.WpfDesign.AddIn.dll">
<ConditionEvaluator name="IsCutCopyEnabled" class="ICSharpCode.WpfDesign.AddIn.Commands.IsCutCopyEnabled" />
<ConditionEvaluator name="IsPasteEnabled" class="ICSharpCode.WpfDesign.AddIn.Commands.IsPasteEnabled" />
<ConditionEvaluator name="IsRemoveEnabled" class="ICSharpCode.WpfDesign.AddIn.Commands.IsRemoveEnabled" />
<ConditionEvaluator name="IsUndoEnabled" class="ICSharpCode.WpfDesign.AddIn.Commands.IsUndoEnabled" />
<ConditionEvaluator name="IsRedoEnabled" class="ICSharpCode.WpfDesign.AddIn.Commands.IsRedoEnabled" />
<ConditionEvaluator name="IsToolsOpen" class="ICSharpCode.WpfDesign.AddIn.Commands.IsToolsOpen" />
<ConditionEvaluator name="IsPropertiesOpen" class="ICSharpCode.WpfDesign.AddIn.Commands.IsPropertiesOpen" />
<ConditionEvaluator name="IsOutlineOpen" class="ICSharpCode.WpfDesign.AddIn.Commands.IsOutlineOpen" />
</Import>
</Runtime>
<Path name = "/SharpDevelop/Workbench/DisplayBindings">
<Path name="/SharpDevelop/Workbench/DisplayBindings">
<!--<DisplayBinding id = "WPFDesigner"
class = "ICSharpCode.WpfDesign.AddIn.WpfPrimaryDisplayBinding"
insertbefore = "Text"
fileNamePattern = "\.xaml$"
title = "WPF designer"/>-->
<DisplayBinding id = "WPFDesigner"
type = "Secondary"
class = "ICSharpCode.WpfDesign.AddIn.WpfSecondaryDisplayBinding"
fileNamePattern = "\.xaml$"/>
<DisplayBinding id="WPFDesigner" type="Secondary" class="ICSharpCode.WpfDesign.AddIn.WpfSecondaryDisplayBinding" fileNamePattern="\.xaml$" />
</Path>
<!--
<Path name = "/SharpDevelop/Workbench/Pads">
<Pad id = "OutlineViewPad"
@ -35,4 +33,29 @@ @@ -35,4 +33,29 @@
class = "ICSharpCode.WpfDesign.AddIn.OutlineViewPad"/>
</Path>
-->
</AddIn>
<Path name="/Addins/WpfDesign/Designer/ContextMenu">
<MenuItem label="${res:ICSharpCode.WPFDesigner.ContextMenu.ViewXAML}" id="viewXaml" icon="Icons.16x16.XMLFileIcon" class="ICSharpCode.WpfDesign.AddIn.Commands.ViewXaml" />
<MenuItem label="seperator1" type="Separator" />
<Condition name="IsCutCopyEnabled" action="Disable">
<MenuItem id="cut" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Cut}" icon="Icons.16x16.CutIcon" shortcut="Control|X" class="ICSharpCode.WpfDesign.AddIn.Commands.Cut" />
<MenuItem id="copy" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Copy}" icon="Icons.16x16.CopyIcon" shortcut="Control|C" class="ICSharpCode.WpfDesign.AddIn.Commands.Copy" />
</Condition>
<Condition name="IsPasteEnabled" action="Disable">
<MenuItem id="paste" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Paste}" icon="Icons.16x16.PasteIcon" shortcut="Control|V" class="ICSharpCode.WpfDesign.AddIn.Commands.Paste" />
</Condition>
<Condition name="IsRemoveEnabled" action="Disable">
<MenuItem id="remove" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Remove}" icon="Icons.16x16.DeleteIcon" shortcut="Del" class="ICSharpCode.WpfDesign.AddIn.Commands.Remove" />
</Condition>
<MenuItem label="seperator2" type="Separator" />
<Condition name="IsUndoEnabled" action="Disable">
<MenuItem id="undo" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Undo}" icon="Icons.16x16.UndoIcon" shortcut="Control|Z" class="ICSharpCode.WpfDesign.AddIn.Commands.Undo" />
</Condition>
<Condition name="IsRedoEnabled" action="Disable">
<MenuItem id="redo" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Redo}" icon="Icons.16x16.RedoIcon" shortcut="Control|R" class="ICSharpCode.WpfDesign.AddIn.Commands.Redo" />
</Condition>
<MenuItem label="seperator3" type="Separator" />
<MenuItem id="tools" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Tools}" icon="PadIcons.Toolbar" shortcut="Control|Alt|X" class="ICSharpCode.WpfDesign.AddIn.Commands.Tools" />
<MenuItem id="properties" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Properties}" icon="Icons.16x16.PropertiesIcon" shortcut="F4" class="ICSharpCode.WpfDesign.AddIn.Commands.Properties" />
<MenuItem id="outline" label="${res:ICSharpCode.WPFDesigner.ContextMenu.Outline}" icon="PadIcons.Toolbar" class="ICSharpCode.WpfDesign.AddIn.Commands.Outline" />
</Path>
</AddIn>

46
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignCommand.cs

@ -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; }
}
}
}

42
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/DesignSurface.xaml.cs

@ -33,6 +33,7 @@ namespace ICSharpCode.WpfDesign.Designer @@ -33,6 +33,7 @@ namespace ICSharpCode.WpfDesign.Designer
/// </summary>
public partial class DesignSurface
{
private FocusNavigator _focusNav;
static DesignSurface()
{
//TODO: this is for converters (see PropertyGrid)
@ -45,8 +46,8 @@ namespace ICSharpCode.WpfDesign.Designer @@ -45,8 +46,8 @@ namespace ICSharpCode.WpfDesign.Designer
this.AddCommandHandler(ApplicationCommands.Undo, Undo, CanUndo);
this.AddCommandHandler(ApplicationCommands.Redo, Redo, CanRedo);
this.AddCommandHandler(ApplicationCommands.Copy, Copy, HasSelection);
this.AddCommandHandler(ApplicationCommands.Cut, Cut, HasSelection);
this.AddCommandHandler(ApplicationCommands.Copy, Copy, CanCopyOrCut);
this.AddCommandHandler(ApplicationCommands.Cut, Cut, CanCopyOrCut);
this.AddCommandHandler(ApplicationCommands.Delete, Delete, CanDelete);
this.AddCommandHandler(ApplicationCommands.Paste, Paste, CanPaste);
this.AddCommandHandler(ApplicationCommands.SelectAll, SelectAll, CanSelectAll);
@ -114,6 +115,10 @@ namespace ICSharpCode.WpfDesign.Designer @@ -114,6 +115,10 @@ namespace ICSharpCode.WpfDesign.Designer
context.Services.Selection.SelectionChanged += delegate {
CommandManager.InvalidateRequerySuggested();
};
context.Services.AddService(typeof(IKeyBindingService), new DesignerKeyBindings(this));
_focusNav=new FocusNavigator(this);
_focusNav.Start();
}
/// <summary>
@ -121,12 +126,14 @@ namespace ICSharpCode.WpfDesign.Designer @@ -121,12 +126,14 @@ namespace ICSharpCode.WpfDesign.Designer
/// </summary>
public void UnloadDesigner()
{
if(_focusNav!=null)
_focusNav.End();
if (_designContext != null) {
foreach (object o in _designContext.Services.AllServices) {
IDisposable d = o as IDisposable;
if (d != null) d.Dispose();
}
}
}
_designContext = null;
_designPanel.Context = null;
_sceneContainer.Child = null;
@ -165,17 +172,32 @@ namespace ICSharpCode.WpfDesign.Designer @@ -165,17 +172,32 @@ namespace ICSharpCode.WpfDesign.Designer
_designContext.Services.Selection.SetSelectedComponents(GetLiveElements(action.AffectedElements));
}
public bool HasSelection()
public bool CanCopyOrCut()
{
return false;
ISelectionService selectionService = GetService<ISelectionService>();
if (selectionService.SelectedItems.Count == 0)
return false;
if (selectionService.SelectedItems.Count == 1 && selectionService.PrimarySelection == DesignContext.RootItem)
return false;
return true;
}
public void Copy()
{
XamlDesignContext xamlContext = _designContext as XamlDesignContext;
ISelectionService selection = _designContext.Services.Selection;
if(xamlContext != null && selection != null){
xamlContext.XamlEditAction.Copy(selection.SelectedItems);
}
}
public void Cut()
{
XamlDesignContext xamlContext = _designContext as XamlDesignContext;
ISelectionService selection = _designContext.Services.Selection;
if(xamlContext != null && selection != null){
xamlContext.XamlEditAction.Cut(selection.SelectedItems);
}
}
public bool CanDelete()
@ -195,11 +217,21 @@ namespace ICSharpCode.WpfDesign.Designer @@ -195,11 +217,21 @@ namespace ICSharpCode.WpfDesign.Designer
public bool CanPaste()
{
ISelectionService selection = _designContext.Services.Selection;
if(selection.SelectedItems.Count!=0){
string xaml = Clipboard.GetText(TextDataFormat.Xaml);
if(xaml != "" && xaml != " ")
return true;
}
return false;
}
public void Paste()
{
XamlDesignContext xamlContext = _designContext as XamlDesignContext;
if(xamlContext != null){
xamlContext.XamlEditAction.Paste();
}
}
public bool CanSelectAll()

219
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/FocusNavigator.cs

@ -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);
}
}
}
}
}

52
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Services/DesignerKeyBindings.cs

@ -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; }
}
}
}

4
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/WpfDesign.Designer.csproj

@ -104,6 +104,7 @@ @@ -104,6 +104,7 @@
<Compile Include="Controls\WindowClone.cs" />
<Compile Include="Controls\ZoomControl.cs" />
<Compile Include="Converters.cs" />
<Compile Include="DesignCommand.cs" />
<Compile Include="DesignPanel.cs" />
<Compile Include="DesignSurface.xaml.cs">
<DependentUpon>DesignSurface.xaml</DependentUpon>
@ -127,6 +128,7 @@ @@ -127,6 +128,7 @@
<SubType>Code</SubType>
</Compile>
<Compile Include="Extensions\PanelMove.cs" />
<Compile Include="FocusNavigator.cs" />
<Compile Include="ModelTools.cs" />
<Compile Include="Extensions\PanelInstanceFactory.cs" />
<Compile Include="Extensions\PanelSelectionHandler.cs" />
@ -195,6 +197,7 @@ @@ -195,6 +197,7 @@
<Compile Include="Services\ChooseClassServiceBase.cs" />
<Compile Include="Services\ClickOrDragMouseGesture.cs" />
<Compile Include="Services\CreateComponentTool.cs" />
<Compile Include="Services\DesignerKeyBindings.cs" />
<Compile Include="Services\DragMoveMouseGesture.cs" />
<Compile Include="Services\ErrorService.cs" />
<Compile Include="Services\MouseGestureBase.cs" />
@ -210,6 +213,7 @@ @@ -210,6 +213,7 @@
<Compile Include="Services\WpfTopLevelWindowService.cs" />
<Compile Include="Services\XamlErrorService.cs" />
<Compile Include="SharedInstances.cs" />
<Compile Include="Xaml\XamlEditOperations.cs" />
<Compile Include="Xaml\XamlLoadSettings.cs" />
<Compile Include="Xaml\XamlModelCollectionElementsCollection.cs" />
<Compile Include="Xaml\XamlComponentService.cs" />

11
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlDesignContext.cs

@ -25,9 +25,15 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -25,9 +25,15 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
public sealed class XamlDesignContext : DesignContext
{
readonly XamlDocument _doc;
readonly XamlDesignItem _rootItem;
readonly XamlDesignItem _rootItem;
internal readonly XamlComponentService _componentService;
readonly XamlEditOperations _xamlEditOperations;
internal XamlEditOperations XamlEditAction {
get { return _xamlEditOperations; }
}
internal XamlDocument Document {
get { return _doc; }
}
@ -85,7 +91,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml @@ -85,7 +91,10 @@ namespace ICSharpCode.WpfDesign.Designer.Xaml
parserSettings.ServiceProvider = this.Services;
_doc = XamlParser.Parse(xamlReader, parserSettings);
_rootItem = _componentService.RegisterXamlComponentRecursive(_doc.RootElement);
_xamlEditOperations=new XamlEditOperations(this,parserSettings);
}
/// <summary>
/// Saves the XAML DOM into the XML writer.

167
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/Xaml/XamlEditOperations.cs

@ -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();
}
}
}

4
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/WpfDesign.XamlDom.csproj

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<ProjectGuid>{88DA149F-21B2-48AB-82C4-28FB6BDFD783}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -81,6 +82,7 @@ @@ -81,6 +82,7 @@
<Compile Include="XamlProperty.cs" />
<Compile Include="XamlPropertyInfo.cs" />
<Compile Include="XamlPropertyValue.cs" />
<Compile Include="XamlStaticTools.cs" />
<Compile Include="XamlTextValue.cs" />
<Compile Include="XamlTypeFinder.cs" />
<Compile Include="XamlTypeResolverProvider.cs" />

31
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlParser.cs

@ -577,5 +577,36 @@ namespace ICSharpCode.WpfDesign.XamlDom @@ -577,5 +577,36 @@ namespace ICSharpCode.WpfDesign.XamlDom
return converter.ConvertFromInvariantString(
scope.OwnerDocument.GetTypeDescriptorContext(scope), valueText);
}
/// <summary>
/// Method use to parse a piece of Xaml.
/// </summary>
/// <param name="root">The Root XamlObject of the current document.</param>
/// <param name="xaml">The Xaml being parsed.</param>
/// <param name="settings">Parser settings used by <see cref="XamlParser"/>.</param>
/// <returns>Returns the XamlObject of the parsed <paramref name="xaml"/>.</returns>
public static XamlObject ParseSnippet(XamlObject root, string xaml, XamlParserSettings settings)
{
XmlTextReader reader = new XmlTextReader(new StringReader(xaml));
var element = root.OwnerDocument.XmlDocument.ReadNode(reader);
if (element != null) {
XmlAttribute xmlnsAttribute=null;
foreach (XmlAttribute attrib in element.Attributes) {
if (attrib.Name == "xmlns")
xmlnsAttribute = attrib;
}
if(xmlnsAttribute!=null)
element.Attributes.Remove(xmlnsAttribute);
XamlParser parser = new XamlParser();
parser.settings = settings;
parser.document = root.OwnerDocument;
var xamlObject = parser.ParseObject(element as XmlElement);
if (xamlObject != null)
return xamlObject;
}
return null;
}
}
}

27
src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlStaticTools.cs

@ -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;
}
}
}

34
src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/Services.cs

@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
// </file>
using System;
using System.Windows.Input;
using System.Collections.Generic;
using System.Windows;
@ -217,4 +218,37 @@ namespace ICSharpCode.WpfDesign @@ -217,4 +218,37 @@ namespace ICSharpCode.WpfDesign
ITopLevelWindow GetTopLevelWindow(UIElement element);
}
#endregion
#region IKeyBindingService
/// <summary>
/// Service that handles all the key bindings in the designer.
/// </summary>
public interface IKeyBindingService
{
/// <summary>
/// Gets the object to which the bindings are being applied
/// </summary>
object Owner { get; }
/// <summary>
/// Register <paramref name="binding"/> with <see cref="Owner"/>.
/// </summary>
/// <param name="binding">The binding to be applied.</param>
void RegisterBinding(KeyBinding binding);
/// <summary>
/// De-register <paramref name="binding"/> with <see cref="Owner"/>.
/// </summary>
/// <param name="binding">The binding to be applied.</param>
void DeregisterBinding(KeyBinding binding);
/// <summary>
/// Gets binding for the corresponding gesture otherwise returns null.
/// </summary>
/// <param name="gesture">The keyboard gesture requested.</param>
KeyBinding GetBinding(KeyGesture gesture);
}
#endregion
}

Loading…
Cancel
Save