Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / Tools / System.Activities.Presentation / System / Activities / Presentation / View / DesignerView.xaml.cs / 1407647 / DesignerView.xaml.cs
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------
namespace System.Activities.Presentation.View
{
using System.Activities.Presentation.View;
using System.Activities.Presentation.Model;
using System.Activities.Presentation.Services;
using System.Activities.Presentation.Xaml;
using System.Activities.Presentation.Hosting;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Packaging;
using System.Printing;
using System.Reflection;
using System.Runtime;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Windows.Xps;
using System.Windows.Xps.Packaging;
using System.Linq;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Activities.Presentation.Validation;
using System.Diagnostics;
using System.Activities.Presentation.Internal.PropertyEditing;
using System.ServiceModel.Activities;
//
// Interaction logic for DesignerView.xaml
//
[Fx.Tag.XamlVisible(false)]
public partial class DesignerView : UserControl
{
public static readonly DependencyProperty RootDesignerProperty =
DependencyProperty.Register("RootDesigner", typeof(UIElement), typeof(DesignerView), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(DesignerView.OnRootDesignerChanged)));
public static readonly DependencyProperty IsReadOnlyProperty =
DependencyProperty.Register("IsReadOnly", typeof(bool), typeof(DesignerView), new UIPropertyMetadata(OnIsReadOnlyChanged));
static readonly DependencyPropertyKey ActivitySchemaPropertyKey =
DependencyProperty.RegisterReadOnly("ActivitySchema", typeof(ModelItem), typeof(DesignerView), new UIPropertyMetadata(OnActivitySchemaChanged));
public static readonly DependencyProperty ActivitySchemaProperty = ActivitySchemaPropertyKey.DependencyProperty;
static readonly DependencyPropertyKey FocusedViewElementPropertyKey =
DependencyProperty.RegisterReadOnly("FocusedViewElement", typeof(WorkflowViewElement), typeof(DesignerView), new UIPropertyMetadata(null));
public static readonly DependencyProperty FocusedViewElementProperty = FocusedViewElementPropertyKey.DependencyProperty;
internal static DependencyProperty ShouldExpandAllProperty = DependencyProperty.Register("ShouldExpandAll", typeof(bool), typeof(DesignerView), new PropertyMetadata(false, new PropertyChangedCallback(OnExpandAllCollapseAllChanged)));
internal static DependencyProperty ShouldCollapseAllProperty = DependencyProperty.Register("ShouldCollapseAll", typeof(bool), typeof(DesignerView), new PropertyMetadata(false, new PropertyChangedCallback(OnExpandAllCollapseAllChanged)));
const double scrollDeltaDivider = 100.0;
GridLength bottomPaneHeight;
EditingContext context;
DragDropHelper.ViewElementDragShadow viewElementDragShadow;
ZoomToTicksConverter zoomToTicksConverter;
ShellBarItemVisibility shellBarItemVisibility = ShellBarItemVisibility.Variables | ShellBarItemVisibility.Arguments | ShellBarItemVisibility.Imports;
Dictionary selectionMap = new Dictionary();
Point dpiScale = new Point(1.0, 1.0);
private bool isInErrorState = false;
const string breadCrumbRootKey = "BreadCrumbRoot";
const string selectionKey = "Selection";
internal WorkflowViewElement lastClickedDesigner;
private DesignerView()
{
}
internal DesignerView(EditingContext context)
{
this.context = context;
InitializeComponent();
this.InitializeMenuActions();
foreach (UIElement element in this.designerExtensionSurface.Children)
{
element.IsEnabled = false;
}
this.buttonArguments1.Visibility = Visibility.Hidden;
this.buttonArguments1.IsChecked = false;
Grid.SetColumn(importsStatusBarItem, 3);
this.zoomToTicksConverter = new ZoomToTicksConverter(this, this.zoomSlider, this.zoomPicker);
this.zoomSlider.ValueChanged += new RoutedPropertyChangedEventHandler(OnZoomSliderValueChanged);
HideBottomPane();
this.variables1.VariableCollectionChanged += this.OnVariablesCollectionChanged;
this.arguments1.ArgumentCollectionChanged += this.OnArgumentsCollectionChanged;
Dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(OnDispatcherUnhandledException);
this.ShouldIgnoreDataGridAutoCommit = false;
}
void OnReadOnlyStateChanged(ReadOnlyState state)
{
this.IsReadOnly = state.IsReadOnly;
}
void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
if (!e.Handled)
{
if (!isInErrorState)
{
isInErrorState = true;
//try to prun the visual tree and collapse all the workflow view elements that are too deep
//this is due to the limitation of WPF has a visual tree depth limit.
if (e.Exception is InvalidOperationException)
{
ICollection deepElements = VisualTreeUtils.PrunVisualTree(this.RootDesigner);
foreach (WorkflowViewElement viewElement in deepElements)
{
viewElement.ForceCollapse();
}
}
Exception ex = e.Exception.InnerException ?? e.Exception;
ErrorReporting.ShowErrorMessage(ex);
isInErrorState = false;
}
e.Handled = true;
}
}
public bool IsMultipleSelectionMode
{
get;
private set;
}
void OnDesignerViewLoaded(object sender, RoutedEventArgs e)
{
ViewStateService viewStateService = this.Context.Services.GetService();
ModelTreeManager modelTreeManager = this.context.Services.GetService();
//Initialize ShouldExpandAll if it exists in ViewState.
object expandAllState = viewStateService.RetrieveViewState(modelTreeManager.Root, DesignerView.ShouldExpandAllProperty.Name);
if (expandAllState != null)
{
this.ShouldExpandAll = (bool)expandAllState;
}
if (!this.ShouldExpandAll)
{
object collapseAllState = viewStateService.RetrieveViewState(modelTreeManager.Root, DesignerView.ShouldCollapseAllProperty.Name);
if (collapseAllState != null)
{
this.ShouldCollapseAll = (bool)collapseAllState;
}
}
}
static void OnExpandAllCollapseAllChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
((DesignerView)o).OnExpandAllCollapseAllChanged(e);
}
void OnExpandAllCollapseAllChanged(DependencyPropertyChangedEventArgs e)
{
ViewStateService viewStateService = this.Context.Services.GetService();
ModelTreeManager modelTreeManager = this.context.Services.GetService();
{
viewStateService.StoreViewState(modelTreeManager.Root, e.Property.Name, e.NewValue);
}
}
protected override void OnInitialized(EventArgs e)
{
this.AddHandler(UIElement.GotKeyboardFocusEvent, new KeyboardFocusChangedEventHandler(this.OnWorkflowElementGotKeyboardFocus), true);
this.AddHandler(UIElement.MouseLeftButtonDownEvent, new MouseButtonEventHandler(this.OnDesignerSurfaceMouseLeftButtonDown), true);
base.OnInitialized(e);
this.Foreground = new SolidColorBrush(SystemColors.ControlTextColor);
this.Loaded += this.OnDesignerViewLoaded;
this.IsKeyboardFocusWithinChanged += this.OnDesignerKeyboardFocusWithinChanged;
this.MenuItemStyle = (Style)this.FindResource("menuItemStyle");
Fx.Assert(this.MenuItemStyle != null, "menuItemStyle resource not found");
this.MenuSeparatorStyle = (Style)this.FindResource("separatorStyle");
Fx.Assert(this.MenuSeparatorStyle != null, "separatorStyle resource not found");
ReadOnlyState state = this.Context.Items.GetValue();
this.IsReadOnly = state.IsReadOnly;
this.Context.Items.Subscribe(OnReadOnlyStateChanged);
}
public ModelItem ActivitySchema
{
get { return (ModelItem)GetValue(ActivitySchemaProperty); }
private set { SetValue(ActivitySchemaPropertyKey, value); }
}
public EditingContext Context
{
get { return this.context; }
}
public UIElement RootDesigner
{
get { return (UIElement)GetValue(RootDesignerProperty); }
set { SetValue(RootDesignerProperty, value); }
}
public bool ShouldExpandAll
{
get { return (bool)GetValue(ShouldExpandAllProperty); }
set { SetValue(ShouldExpandAllProperty, value); }
}
public bool ShouldCollapseAll
{
get { return (bool)GetValue(ShouldCollapseAllProperty); }
set { SetValue(ShouldCollapseAllProperty, value); }
}
public bool IsReadOnly
{
get { return (bool)GetValue(IsReadOnlyProperty); }
set { SetValue(IsReadOnlyProperty, value); }
}
public WorkflowViewElement FocusedViewElement
{
get { return (WorkflowViewElement)GetValue(FocusedViewElementProperty); }
private set { SetValue(FocusedViewElementPropertyKey, value); }
}
internal double ZoomFactor
{
get
{
return this.zoomToTicksConverter.ZoomFactor;
}
}
internal ScrollViewer ScrollViewer
{
get
{
return this.scrollViewer;
}
}
internal UIElement ScrollableContent
{
get
{
return this.scrollableContent;
}
}
internal bool ShouldIgnoreDataGridAutoCommit
{
get;
set;
}
public ShellBarItemVisibility WorkflowShellBarItemVisibility
{
get { return this.shellBarItemVisibility; }
set { this.ApplyShellBarItemVisibility(value); }
}
public void MakeRootDesigner(ModelItem modelItem)
{
bool checkIfCanBeMadeRoot = true;
if (modelItem == modelItem.Root)
{
checkIfCanBeMadeRoot = false;
}
MakeRootDesigner(modelItem, /* setAsSelection = */ true, checkIfCanBeMadeRoot);
}
internal void MakeRootDesigner(ModelItem modelItem, bool setAsSelection)
{
MakeRootDesigner(modelItem, setAsSelection, true);
}
internal void ForceMakeRootDesigner(ModelItem modelItem)
{
MakeRootDesigner(modelItem, /* setAsSelection = */ true, false);
}
static bool IsSwitchCase(ModelItem modelItem)
{
if(IsModelItemKeyValuePair(modelItem.ItemType))
{
if (modelItem.Parent != null && //modelItem.Parent - ItemsCollection
modelItem.Parent.Parent != null && //modelItem.Parent.Parent - Cases
modelItem.Parent.Parent.Parent != null && //modelItem.Parent.Parent.Parent - Switch
modelItem.Parent.Parent.Parent.ItemType.IsGenericType &&
modelItem.Parent.Parent.Parent.ItemType.GetGenericTypeDefinition() == typeof(System.Activities.Statements.Switch<>))
{
return true;
}
}
return false;
}
static bool IsModelItemKeyValuePair(Type type)
{
return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ModelItemKeyValuePair<,>);
}
void SelectAll()
{
WorkflowViewElement root = this.RootDesigner as WorkflowViewElement;
ModelItem rootModelItem = null;
if (root != null)
{
rootModelItem = root.ModelItem;
}
if (rootModelItem != null)
{
ModelTreeManager modelTreeManager = this.Context.Services.GetService();
IEnumerable items = modelTreeManager.Find(rootModelItem, delegate(Type type)
{
WorkflowViewService viewService = this.Context.Services.GetService() as WorkflowViewService;
return (typeof(WorkflowViewElement).IsAssignableFrom(viewService.GetDesignerType(type)));
}, true);
IEnumerable itemsToSelect = items
// ModelItemKeyValuePair is associated with CaseDesigner.
// So ModelItemKeyValuePair will be returned even if they are not really Cases.
// Those ModelItemKeyValuePairs need to be excluded.
.Where(item => !IsModelItemKeyValuePair(item.ItemType) || IsSwitchCase(item))
.Except(new ModelItem[] {rootModelItem});
Selection selection = new Selection(itemsToSelect);
this.Context.Items.SetValue(selection);
}
}
internal void BeginDragShadowTracking(DragDropHelper.ViewElementDragShadow dragShadow)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(this.scrollableContent);
if (null != layer)
{
layer.Add(dragShadow);
this.viewElementDragShadow = dragShadow;
//get parent window handle
HwndSource relativeSource = (HwndSource)PresentationSource.FromVisual(this.scrollViewer);
this.viewElementDragShadow.LayerHWND = relativeSource.Handle;
//get relative position of scrollable designer area to its containing window
GeneralTransform transform = this.scrollViewer.TransformToAncestor(relativeSource.RootVisual);
Point offset = transform.Transform(new Point());
//get current dpi settings
var matrix = relativeSource.CompositionTarget.TransformFromDevice;
//store scaling information for calculation of screen position
this.dpiScale = new Point(matrix.M11, matrix.M22);
//update view element's shadow with that offset
this.viewElementDragShadow.UpdateOffset(offset.X, offset.Y);
//register for window messages notification
this.Context.Services.GetService().RegisterWindowMessageHandler(new WindowMessage(OnMessage));
}
}
internal void EndDragShadowTracking(DragDropHelper.ViewElementDragShadow dragShadow)
{
AdornerLayer layer = AdornerLayer.GetAdornerLayer(this.scrollableContent);
if (null != layer)
{
//unregister from window message notification
this.Context.Services.GetService().UnregisterWindowMessageHandler(new WindowMessage(OnMessage));
layer.Remove(dragShadow);
this.viewElementDragShadow = null;
}
}
static void UpdateAncestorFlag(ModelItem oldRoot, ModelItem newRoot)
{
// Walk up the tree and update the flags from the new root. If we hit the old root in the process, we are done.
// Otherwise, continue to update the flags from the old root until we hit the new root.
if (oldRoot == newRoot)
{
return;
}
bool hitOldRoot = false;
if (newRoot != null)
{
WorkflowViewElement viewElement = newRoot.View as WorkflowViewElement;
if (viewElement != null)
{
viewElement.IsAncestorOfRootDesigner = false;
}
ModelItem parent = newRoot.Parent;
while (parent != null)
{
WorkflowViewElement view = parent.View as WorkflowViewElement;
if (view != null)
{
view.IsAncestorOfRootDesigner = true;
}
if (parent == oldRoot)
{
hitOldRoot = true;
}
parent = parent.Parent;
}
}
if (oldRoot != null && !hitOldRoot)
{
ModelItem parent = oldRoot.Parent;
while (parent != null && parent != newRoot)
{
WorkflowViewElement view = parent.View as WorkflowViewElement;
if (view != null)
{
view.IsAncestorOfRootDesigner = false;
}
parent = parent.Parent;
}
}
}
internal void MakeRootDesigner(ModelItem modelItem, bool setAsSelection, bool checkIfCanBeMadeRoot)
{
ModelItem currentRootModelItem = (this.RootDesigner != null) ? ((WorkflowViewElement)this.RootDesigner).ModelItem : null;
if (modelItem == currentRootModelItem)
{
return;
}
if (typeof(ActivityBuilder).IsAssignableFrom(modelItem.ItemType))
{
this.ActivitySchema = modelItem;
}
WorkflowViewService viewService = this.Context.Services.GetService() as WorkflowViewService;
//try get designer for given model item
Type designerType = viewService.GetDesignerType(modelItem.ItemType);
//if one doesn't exist - check its parent tree, perhaps there will be one
while (null == designerType && null != modelItem.Parent)
{
modelItem = modelItem.Parent;
designerType = viewService.GetDesignerType(modelItem.ItemType);
}
if (viewService.ShouldAppearOnBreadCrumb(modelItem, checkIfCanBeMadeRoot))
{
UpdateAncestorFlag(currentRootModelItem, modelItem);
Dictionary newSelectionMap = new Dictionary();
ModelItem newRootModelItem = modelItem;
ObservableCollection