--- /dev/null
+//----------------------------------------------------------------
+// <copyright company="Microsoft Corporation">
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// </copyright>
+//----------------------------------------------------------------
+
+namespace System.Activities.Presentation
+{
+ using System.Globalization;
+ using System.Runtime;
+ using System.Runtime.Versioning;
+ using Microsoft.Activities.Presentation;
+
+ internal enum WorkflowDesignerHostId
+ {
+ Rehost,
+ Dev10,
+ Dev11
+ }
+
+ /// <summary>
+ /// Stores configuration information of designer
+ /// </summary>
+ public sealed class DesignerConfigurationService
+ {
+ private static FrameworkName defaultTargetFrameworkName = FrameworkNameConstants.NetFramework40;
+
+ private bool annotationEnabled;
+ private bool autoConnectEnabled;
+ private bool autoSplitEnabled;
+ private bool autoSurroundWithSequenceEnabled;
+ private bool backgroundValidationEnabled;
+ private bool isAnnotationEnabledSetByUser;
+ private bool isAutoConnectEnabledSetByUser;
+ private bool isAutoSplitEnabledSetByUser;
+ private bool isAutoSurroundWithSequenceEnabledSetByUser;
+ private bool isBackgroundValidationEnabledSetByUser;
+ private bool isLoadingFromUntrustedSourceEnabledSetByUser;
+ private bool isMultipleItemsDragDropEnabledSetByUser;
+ private bool isMultipleItemsContextMenuEnabledSetByUser;
+ private bool isPanModeEnabledSetByUser;
+ private bool isRubberBandSelectionEnabledSetByUser;
+ private bool loadingFromUntrustedSourceEnabled;
+ private bool multipleItemsDragDropEnabled;
+ private bool multipleItemsContextMenuEnabled;
+ private bool namespaceConversionEnabled;
+ private bool panModeEnabled;
+ private bool rubberBandSelectionEnabled;
+ private FrameworkName targetFrameworkName;
+ private WorkflowDesignerHostId workflowDesignerHostId;
+
+ /// <summary>
+ /// Default constructor
+ /// </summary>
+ internal DesignerConfigurationService()
+ {
+ this.namespaceConversionEnabled = true;
+ this.loadingFromUntrustedSourceEnabled = true;
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether annotation feature is enabled.
+ /// Can only be set before WorkflowDesigner.Load()
+ /// Can only be enabled when target framework is 4.5 or higher
+ /// </summary>
+ public bool AnnotationEnabled
+ {
+ get
+ {
+ return this.annotationEnabled;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.isAnnotationEnabledSetByUser = true;
+ this.annotationEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether auto connect feature is enabled.
+ /// </summary>
+ public bool AutoConnectEnabled
+ {
+ get
+ {
+ return this.autoConnectEnabled;
+ }
+
+ set
+ {
+ this.isAutoConnectEnabledSetByUser = true;
+ this.autoConnectEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether auto split feature is enabled.
+ /// </summary>
+ public bool AutoSplitEnabled
+ {
+ get
+ {
+ return this.autoSplitEnabled;
+ }
+
+ set
+ {
+ this.isAutoSplitEnabledSetByUser = true;
+ this.autoSplitEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether auto surround with sequence is enabled.
+ /// </summary>
+ public bool AutoSurroundWithSequenceEnabled
+ {
+ get
+ {
+ return this.autoSurroundWithSequenceEnabled;
+ }
+
+ set
+ {
+ this.isAutoSurroundWithSequenceEnabledSetByUser = true;
+ this.autoSurroundWithSequenceEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether background validation is enabled.
+ /// </summary>
+ public bool BackgroundValidationEnabled
+ {
+ get
+ {
+ return this.backgroundValidationEnabled;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.isBackgroundValidationEnabledSetByUser = true;
+ this.backgroundValidationEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether allow loading from untrusted source is enabled.
+ /// If false, loading from untrusted source will cause a SecurityException thrown out when WorkflowDesigner.Load(string fileName).
+ /// Can only be set before WorkflowDesigner.Load()
+ /// </summary>
+ public bool LoadingFromUntrustedSourceEnabled
+ {
+ get
+ {
+ return this.loadingFromUntrustedSourceEnabled;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.isLoadingFromUntrustedSourceEnabledSetByUser = true;
+ this.loadingFromUntrustedSourceEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether Context Menu can be displayed when selecting multiple items.
+ /// Can only be set before WorkflowDesigner.Load()
+ /// </summary>
+ public bool MultipleItemsContextMenuEnabled
+ {
+ get
+ {
+ return this.multipleItemsContextMenuEnabled;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.isMultipleItemsContextMenuEnabledSetByUser = true;
+ this.multipleItemsContextMenuEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether dragging multiple items is enabled.
+ /// Can only be set before WorkflowDesigner.Load()
+ /// </summary>
+ public bool MultipleItemsDragDropEnabled
+ {
+ get
+ {
+ return this.multipleItemsDragDropEnabled;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.isMultipleItemsDragDropEnabledSetByUser = true;
+ this.multipleItemsDragDropEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether namespace conversion is enabled.
+ /// Can only be set before WorkflowDesigner.Load()
+ /// </summary>
+ public bool NamespaceConversionEnabled
+ {
+ get
+ {
+ return this.namespaceConversionEnabled;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.namespaceConversionEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether pan mode is enabled.
+ /// Can only be set before WorkflowDesigner.Load()
+ /// </summary>
+ public bool PanModeEnabled
+ {
+ get
+ {
+ return this.panModeEnabled;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.isPanModeEnabledSetByUser = true;
+ this.panModeEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether rubberband selection is enabled.
+ /// Can only be set before WorkflowDesigner.Load()
+ /// </summary>
+ public bool RubberBandSelectionEnabled
+ {
+ get
+ {
+ return this.rubberBandSelectionEnabled;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.isRubberBandSelectionEnabledSetByUser = true;
+ this.rubberBandSelectionEnabled = value;
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets a value indicating the target framework.
+ /// Can only be set before WorkflowDesigner.Load()
+ /// The framework identifier only supports '.NET Framework' and '.NETFramework'.
+ /// The framework profile only supports string.Empty or 'Client'.
+ /// </summary>
+ public FrameworkName TargetFrameworkName
+ {
+ get
+ {
+ if (this.targetFrameworkName == null)
+ {
+ this.targetFrameworkName = defaultTargetFrameworkName;
+ }
+
+ return this.targetFrameworkName;
+ }
+
+ set
+ {
+ if (value == null)
+ {
+ throw FxTrace.Exception.ArgumentNull("TargetFrameworkName");
+ }
+
+ if (value.Identifier != FrameworkNameConstants.NetFramework
+ && value.Identifier != FrameworkNameConstants.NetFrameworkWithSpace)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.NotSupportedFrameworkIdentifier, value.Identifier)));
+ }
+
+ if (!value.IsProfileSupported())
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.NotSupportedFrameworkProfile, value.Profile)));
+ }
+
+ if (value.IsLessThan40())
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, SR.NotSupportedFrameworkVersion, value.Version.ToString())));
+ }
+
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.targetFrameworkName = value;
+ }
+ }
+
+ internal static FrameworkName DefaultTargetFrameworkName
+ {
+ get
+ {
+ return defaultTargetFrameworkName;
+ }
+ }
+
+ internal WorkflowDesignerHostId WorkflowDesignerHostId
+ {
+ get
+ {
+ return this.workflowDesignerHostId;
+ }
+
+ set
+ {
+ if (this.IsWorkflowLoaded)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CouldNotSetPropertyAfterLoad));
+ }
+
+ this.workflowDesignerHostId = value;
+ }
+ }
+
+ internal bool IsWorkflowLoaded { get; set; }
+
+ /// <summary>
+ /// Apply default preference based on TargetFramework and hoster.
+ /// If some flags were already set by user, don't set it to default.
+ /// </summary>
+ internal void ApplyDefaultPreference()
+ {
+ Fx.Assert(!this.IsWorkflowLoaded, "Cannot be invoked after WorkflowDesigner.Load");
+
+ if (this.TargetFrameworkName.Is45OrHigher())
+ {
+ // Dev11 + 4.5 and Rehost + 4.5, open all features.
+ // Dev10 + 4.5, invalid case.
+ this.SetAnnotationIfNotSetByUser(true);
+ this.SetAutoConnectIfNotSetByUser(true);
+ this.SetAutoSplitIfNotSetByUser(true);
+ this.SetAutoSurroundWithSequenceIfNotSetByUser(true);
+ this.SetBackgroundValidationIfNotSetByUser(true);
+ this.SetMultipleItemsContextMenuIfNotSetByUser(true);
+ this.SetMultipleItemsDragDropIfNotSetByUser(true);
+ this.SetPanModeIfNotSetByUser(true);
+ this.SetRubberBandSelectionIfNotSetByUser(true);
+ }
+ else
+ {
+ switch (this.workflowDesignerHostId)
+ {
+ case WorkflowDesignerHostId.Rehost:
+ case WorkflowDesignerHostId.Dev10:
+ this.SetAnnotationIfNotSetByUser(false);
+ this.SetAutoConnectIfNotSetByUser(false);
+ this.SetAutoSplitIfNotSetByUser(false);
+ this.SetAutoSurroundWithSequenceIfNotSetByUser(false);
+ this.SetBackgroundValidationIfNotSetByUser(false);
+ this.SetMultipleItemsContextMenuIfNotSetByUser(false);
+ this.SetMultipleItemsDragDropIfNotSetByUser(false);
+ this.SetPanModeIfNotSetByUser(false);
+ this.SetRubberBandSelectionIfNotSetByUser(false);
+ break;
+ case WorkflowDesignerHostId.Dev11:
+ this.SetAnnotationIfNotSetByUser(false);
+ this.SetAutoConnectIfNotSetByUser(true);
+ this.SetAutoSplitIfNotSetByUser(true);
+ this.SetAutoSurroundWithSequenceIfNotSetByUser(true);
+ this.SetBackgroundValidationIfNotSetByUser(true);
+ this.SetMultipleItemsContextMenuIfNotSetByUser(true);
+ this.SetMultipleItemsDragDropIfNotSetByUser(true);
+ this.SetPanModeIfNotSetByUser(true);
+ this.SetRubberBandSelectionIfNotSetByUser(true);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /// <summary>
+ /// The method should be invoked at WorkflowDesigner.Load(string fileName)
+ /// </summary>
+ internal void SetDefaultOfLoadingFromUntrustedSourceEnabled()
+ {
+ Fx.Assert(!this.IsWorkflowLoaded, "Cannot be invoked after WorkflowDesigner.Load");
+
+ // Only Rehost need to apply this flag's default value.
+ // Dev11 will opt-off this feature and handle this by itself.
+ if (this.WorkflowDesignerHostId == Presentation.WorkflowDesignerHostId.Rehost)
+ {
+ if (this.TargetFrameworkName.Is45OrHigher())
+ {
+ this.SetLoadingFromUntrustedSourceEnabledIfNotSetByUser(false);
+ }
+ }
+ }
+
+ internal void Validate()
+ {
+ if (this.TargetFrameworkName.IsLessThan45())
+ {
+ if (this.annotationEnabled)
+ {
+ throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CantEnableAnnotationBefore45));
+ }
+ }
+ }
+
+ private void SetAnnotationIfNotSetByUser(bool annotationEnable)
+ {
+ if (!this.isAnnotationEnabledSetByUser)
+ {
+ this.annotationEnabled = annotationEnable;
+ }
+ }
+
+ private void SetAutoConnectIfNotSetByUser(bool autoConnectEnabled)
+ {
+ if (!this.isAutoConnectEnabledSetByUser)
+ {
+ this.autoConnectEnabled = autoConnectEnabled;
+ }
+ }
+
+ private void SetAutoSplitIfNotSetByUser(bool autoSplitEnabled)
+ {
+ if (!this.isAutoSplitEnabledSetByUser)
+ {
+ this.autoSplitEnabled = autoSplitEnabled;
+ }
+ }
+
+ private void SetAutoSurroundWithSequenceIfNotSetByUser(bool autoSurroundWithSequenceEnabled)
+ {
+ if (!this.isAutoSurroundWithSequenceEnabledSetByUser)
+ {
+ this.autoSurroundWithSequenceEnabled = autoSurroundWithSequenceEnabled;
+ }
+ }
+
+ private void SetBackgroundValidationIfNotSetByUser(bool backgroundValidationEnabled)
+ {
+ if (!this.isBackgroundValidationEnabledSetByUser)
+ {
+ this.backgroundValidationEnabled = backgroundValidationEnabled;
+ }
+ }
+
+ private void SetMultipleItemsContextMenuIfNotSetByUser(bool multipleItemsContextMenuEnabled)
+ {
+ if (!this.isMultipleItemsContextMenuEnabledSetByUser)
+ {
+ this.multipleItemsContextMenuEnabled = multipleItemsContextMenuEnabled;
+ }
+ }
+
+ private void SetMultipleItemsDragDropIfNotSetByUser(bool multipleItemsDragDropEnabled)
+ {
+ if (!this.isMultipleItemsDragDropEnabledSetByUser)
+ {
+ this.multipleItemsDragDropEnabled = multipleItemsDragDropEnabled;
+ }
+ }
+
+ private void SetPanModeIfNotSetByUser(bool panModeEnabled)
+ {
+ if (!this.isPanModeEnabledSetByUser)
+ {
+ this.panModeEnabled = panModeEnabled;
+ }
+ }
+
+ private void SetRubberBandSelectionIfNotSetByUser(bool rubberBandSelectionEnabled)
+ {
+ if (!this.isRubberBandSelectionEnabledSetByUser)
+ {
+ this.rubberBandSelectionEnabled = rubberBandSelectionEnabled;
+ }
+ }
+
+ private void SetLoadingFromUntrustedSourceEnabledIfNotSetByUser(bool loadingFromUntrustedSourceEnabled)
+ {
+ if (!this.isLoadingFromUntrustedSourceEnabledSetByUser)
+ {
+ this.loadingFromUntrustedSourceEnabled = loadingFromUntrustedSourceEnabled;
+ }
+ }
+ }
+}