-
Notifications
You must be signed in to change notification settings - Fork 30
VIX-3697 New Arch Prop #738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/VIX-3693
Are you sure you want to change the base?
Changes from 13 commits
796d3b6
bf0da4e
e33f3ca
ac27e19
6b01550
ed8e0b9
d605d99
9934ab9
2225876
9ebb3ac
8d2bef6
ce7c3cb
fd7661a
5b51019
4c385e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,4 @@ | ||
| using Catel.Collections; | ||
| using Catel.Data; | ||
| using Catel.Data; | ||
| using Catel.IoC; | ||
| using Catel.MVVM; | ||
| using Catel.Services; | ||
|
|
@@ -9,11 +8,11 @@ | |
| using Orc.Wizard; | ||
| using System.Collections.ObjectModel; | ||
| using System.ComponentModel; | ||
| using Vixen.Extensions; | ||
| using Vixen.Sys; | ||
| using Vixen.Sys.Managers; | ||
| using Vixen.Sys.Props; | ||
| using VixenApplication.SetupDisplay.Wizards.Factory; | ||
| using VixenApplication.SetupDisplay.Wizards.Pages; | ||
| using VixenApplication.SetupDisplay.Wizards.PropFactories; | ||
| using VixenApplication.SetupDisplay.Wizards.Wizard; | ||
| using VixenModules.Editor.PropWizard; | ||
|
|
@@ -27,6 +26,9 @@ public class PropNodeTreeViewModel : ViewModelBase, IDropTarget, IDragSource | |
| private static NLog.Logger Logging = NLog.LogManager.GetCurrentClassLogger(); | ||
| public event EventHandler ModelsChanged; | ||
|
|
||
| public ObservableCollection<PropTypeMenuItem> AvailableProps { get; } | ||
| = new ObservableCollection<PropTypeMenuItem>(); | ||
|
|
||
| public PropNodeTreeViewModel() | ||
| { | ||
| PropManager = VixenSystem.Props; | ||
|
|
@@ -42,6 +44,11 @@ public PropNodeTreeViewModel() | |
| PropManager.PropCollectionChanged += PropManager_PropCollectionChanged; | ||
| SelectedItems = new(); | ||
| SelectedItems.CollectionChanged += SelectedItemsCollectionChanged; | ||
|
|
||
| foreach (PropType menuItem in Enum.GetValues(typeof(PropType))) | ||
| { | ||
| AvailableProps.Add(new PropTypeMenuItem { Id = menuItem, DisplayName = menuItem.GetEnumDescription() }); | ||
| } | ||
| } | ||
|
|
||
| private void PropManager_PropCollectionChanged(object? sender, EventArgs e) | ||
|
|
@@ -126,6 +133,27 @@ public ObservableCollection<PropNodeViewModel> PropNodes | |
|
|
||
| #endregion | ||
|
|
||
| #region Temporary properties to get Change Prop to work | ||
| // Temporary properties to get Change Prop to work | ||
| public bool IsTopNode | ||
| { | ||
| get => GetValue<bool>(IsTopNodeProperty); | ||
| set => SetValue(IsTopNodeProperty, value); | ||
| } | ||
| public static readonly IPropertyData IsTopNodeProperty = RegisterProperty<bool>(nameof(IsTopNode), true); | ||
|
|
||
| public bool IsSubNode | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If IsTopNode and IsSubNode are inverses of each other used for visibility there are several methods of handling that in the XAML with InverseBooleanToVisibilityConverter. Only change if this appeals to you. |
||
| { | ||
| get => GetValue<bool>(IsSubNodeProperty); | ||
| set => SetValue(IsSubNodeProperty, value); | ||
| } | ||
| public static readonly IPropertyData IsSubNodeProperty = RegisterProperty<bool>(nameof(IsSubNode), false); | ||
| #endregion | ||
|
|
||
| private void OnIsTopNodeChanged() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method appears not be used. |
||
| { | ||
| RaisePropertyChanged(nameof(IsSubNode)); | ||
| } | ||
| #region SelectedItems property | ||
|
|
||
| /// <summary> | ||
|
|
@@ -162,6 +190,7 @@ private void SelectedItemsCollectionChanged(object? sender, System.Collections.S | |
| MoveToGroupCommand.RaiseCanExecuteChanged(); | ||
| CreateNodeCommand.RaiseCanExecuteChanged(); | ||
| CreatePropCommand.RaiseCanExecuteChanged(); | ||
| ChangePropCommand.RaiseCanExecuteChanged(); | ||
| } | ||
|
|
||
| #endregion | ||
|
|
@@ -540,65 +569,62 @@ private bool CanCreateNode() | |
|
|
||
| #region CreateProp command | ||
|
|
||
| private TaskCommand<string> _createPropCommand; | ||
| private TaskCommand<PropType> _createPropCommand; | ||
|
|
||
| /// <summary> | ||
| /// Gets the CreateProp command. | ||
| /// </summary> | ||
| public TaskCommand<string> CreatePropCommand | ||
| public TaskCommand<PropType> CreatePropCommand | ||
| { | ||
| get { return _createPropCommand ??= new(CreateProp, CanCreateProp); } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Method to invoke when the CreatePropNode command is executed. | ||
| /// </summary> | ||
| private async Task CreateProp(string? propType) | ||
| private async Task CreateProp(PropType result) | ||
| { | ||
| if(Enum.TryParse(propType, out PropType result)) | ||
| { | ||
| IPropGroup propGroup = await GeneratePropNodes(result); | ||
| IPropGroup propGroup = await GeneratePropNodes(result); | ||
|
|
||
| if (propGroup != null) | ||
| if (propGroup != null) | ||
| { | ||
| // Determine the parent of the group or props | ||
| PropNode pNodeParent; | ||
| if (SelectedItem != null) | ||
| { | ||
| // Determine the parent of the group or props | ||
| PropNode pNodeParent; | ||
| if (SelectedItem != null) | ||
| { | ||
| pNodeParent = SelectedItem.PropNode; | ||
| } | ||
| else | ||
| { | ||
| pNodeParent = PropManager.RootNode; | ||
| } | ||
| pNodeParent = SelectedItem.PropNode; | ||
| } | ||
| else | ||
| { | ||
| pNodeParent = PropManager.RootNode; | ||
| } | ||
|
|
||
| // If the props are to be grouped then... | ||
| PropNode groupNode; | ||
| if (propGroup.CreateGroup) | ||
| { | ||
| // Create the group prop node | ||
| groupNode = new(propGroup.GroupName); | ||
| // If the props are to be grouped then... | ||
| PropNode groupNode; | ||
| if (propGroup.CreateGroup) | ||
| { | ||
| // Create the group prop node | ||
| groupNode = new(propGroup.GroupName); | ||
|
|
||
| // Add the group node to the tree | ||
| PropManager.AddPropNode(groupNode, pNodeParent); | ||
| // Add the group node to the tree | ||
| PropManager.AddPropNode(groupNode, pNodeParent); | ||
|
|
||
| // Make the group node the parent | ||
| pNodeParent = groupNode; | ||
| } | ||
| // Make the group node the parent | ||
| pNodeParent = groupNode; | ||
| } | ||
|
|
||
| // Loop over the props | ||
| foreach (IProp prop in propGroup.Props) | ||
| // Loop over the props | ||
| foreach (IProp prop in propGroup.Props) | ||
| { | ||
| if (prop != null) | ||
| { | ||
| if (prop != null) | ||
| // Add the prop to the tree | ||
| PropManager.AddProp(prop, pNodeParent); | ||
|
|
||
| //Ensure parent is expanded | ||
| if (SelectedItem != null) | ||
| { | ||
| // Add the prop to the tree | ||
| PropManager.AddProp(prop, pNodeParent); | ||
|
|
||
| //Ensure parent is expanded | ||
| if (SelectedItem != null) | ||
| { | ||
| SelectedItem.IsExpanded = true; | ||
| } | ||
| SelectedItem.IsExpanded = true; | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -609,7 +635,7 @@ private async Task CreateProp(string? propType) | |
| /// Method to check whether the CreatePropNode command can be executed. | ||
| /// </summary> | ||
| /// <returns><c>true</c> if the command can be executed; otherwise <c>false</c></returns> | ||
| private bool CanCreateProp(string? propType) | ||
| private bool CanCreateProp(PropType propType) | ||
| { | ||
| if (SelectedItems.Count == 1 && SelectedItem is { IsGroupNode: true }) | ||
| { | ||
|
|
@@ -621,6 +647,30 @@ private bool CanCreateProp(string? propType) | |
|
|
||
| #endregion | ||
|
|
||
| #region ChangeProp command | ||
| private TaskCommand<PropType> _changePropCommand; | ||
| public TaskCommand<PropType> ChangePropCommand | ||
| { | ||
| get { return _changePropCommand ??= new(ChangeProp, CanChangeProp); } | ||
| } | ||
|
|
||
| private async Task ChangeProp(PropType result) | ||
| { | ||
| IPropGroup propGroup = await EditPropNode(SelectedItems[0].PropNode.Prop); | ||
| RaisePropertyChanged(nameof(SelectedItem)); | ||
| } | ||
|
|
||
| private bool CanChangeProp(PropType propType) | ||
| { | ||
| if (SelectedItems.Count == 1 && SelectedItem is { IsGroupNode: true }) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
| #endregion | ||
|
|
||
| #region Cut command | ||
|
|
||
| private Command _cutCommand; | ||
|
|
@@ -991,6 +1041,12 @@ private async Task<IPropGroup> GeneratePropNodes(PropType propType) | |
| // Get the Catel type factory | ||
| ITypeFactory typeFactory = this.GetTypeFactory(); | ||
|
|
||
| // Create a Prop Factory for the specific prop type | ||
| IPropFactory newPropFactory = PropFactory.CreateInstance(propType); | ||
|
|
||
| // Create a default Prop | ||
| (IProp newProp, IPropGroup propGroup) = newPropFactory.CreateBaseProp(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is where I noticed that supporting groups got broken. The previous design was that the prop(s) were not created until the user had gone through Wizard to know how many props to create. Seems like to me we may need to hide the Group page when editing the prop after initial creation. We also probably need to look into allowing the user to just hit finish rather than forcing them to go through all the pages. I think Nick was asking for this feature as well. |
||
|
|
||
| // Retrieve the color scheme service | ||
| IBaseColorSchemeService baseColorService = (IBaseColorSchemeService)dependencyResolver.Resolve(typeof(IBaseColorSchemeService)); | ||
|
|
||
|
|
@@ -1018,15 +1074,17 @@ private async Task<IPropGroup> GeneratePropNodes(PropType propType) | |
| // Configure the wizard with a navigation controller | ||
| propWizard.Wizard.NavigationControllerWrapper = typeFactory.CreateInstanceWithParametersAndAutoCompletion<PropWizardNavigationController>(propWizard.Wizard); | ||
|
|
||
| newPropFactory.LoadWizard(newProp, propWizard.Wizard); | ||
|
|
||
| var ws = dependencyResolver.Resolve<IWizardService>(); | ||
| if (ws != null && propWizard.Wizard != null) | ||
| { | ||
| bool? result = (await ws.ShowWizardAsync(propWizard.Wizard)).DialogResult; | ||
| // Determine if the wizard was cancelled | ||
| if (result.HasValue && result.Value) | ||
| { | ||
| // Have the prop factory create the props from the wizard data | ||
| IPropGroup propGroup = propWizard.Factory.GetProps(propWizard.Wizard); | ||
| // Have the prop factory update the default prop from the wizard data | ||
| newPropFactory.UpdateProp(newProp, propWizard.Wizard); | ||
|
|
||
| // User did not cancel | ||
| return propGroup; | ||
|
|
@@ -1036,6 +1094,69 @@ private async Task<IPropGroup> GeneratePropNodes(PropType propType) | |
| return null; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Display the Prop Wizard to edit an existing Prop | ||
| /// </summary> | ||
| /// <param name="existingProp">Specifies the prop to edit</param> | ||
| /// <returns>The <see cref="IPropGroup"/> that contains the updated Prop</returns> | ||
| private async Task<IPropGroup> EditPropNode(IProp existingProp) | ||
| { | ||
| var dependencyResolver = this.GetDependencyResolver(); | ||
|
|
||
| // Get the Catel type factory | ||
| ITypeFactory typeFactory = this.GetTypeFactory(); | ||
|
|
||
| // Configure current prop for editing | ||
| IPropFactory newPropFactory = PropFactory.CreateInstance(existingProp.PropType); | ||
| IPropGroup propGroup = newPropFactory.EditExistingProp(existingProp); | ||
|
|
||
| // Retrieve the color scheme service | ||
| IBaseColorSchemeService baseColorService = (IBaseColorSchemeService)dependencyResolver.Resolve(typeof(IBaseColorSchemeService)); | ||
|
|
||
| // Select the dark color scheme | ||
| baseColorService.SetBaseColorScheme("Dark"); | ||
|
|
||
| // Use the type factory to create the prop wizard | ||
| (IPropWizard Wizard, IPropFactory Factory) propWizard = PropWizardFactory.CreateInstance(existingProp.PropType, typeFactory); | ||
|
|
||
|
|
||
| // Configure the wizard window to show up in the Windows task bar | ||
| propWizard.Wizard.ShowInTaskbarWrapper = true; | ||
|
|
||
| // Enable the help button | ||
| propWizard.Wizard.ShowHelpWrapper = true; | ||
|
|
||
| // Configure the wizard to allow the user to jump between already visited pages | ||
| propWizard.Wizard.AllowQuickNavigationWrapper = true; | ||
|
|
||
| // Allow Catel to help determine when it is safe to transition to the next wizard page | ||
| propWizard.Wizard.HandleNavigationStatesWrapper = true; | ||
|
|
||
| // Configure the wizard to NOT cache views | ||
| propWizard.Wizard.CacheViewsWrapper = false; | ||
|
|
||
| // Configure the wizard with a navigation controller | ||
| propWizard.Wizard.NavigationControllerWrapper = typeFactory.CreateInstanceWithParametersAndAutoCompletion<PropWizardNavigationController>(propWizard.Wizard); | ||
|
|
||
| newPropFactory.LoadWizard(existingProp, propWizard.Wizard); | ||
|
|
||
| var ws = dependencyResolver.Resolve<IWizardService>(); | ||
| if (ws != null && propWizard.Wizard != null) | ||
| { | ||
| bool? result = (await ws.ShowWizardAsync(propWizard.Wizard)).DialogResult; | ||
| // Determine if the wizard was cancelled | ||
| if (result.HasValue && result.Value) | ||
| { | ||
| // Have the prop factory update the prop from the wizard data | ||
| newPropFactory.UpdateProp(existingProp, propWizard.Wizard); | ||
|
|
||
| // User did not cancel | ||
| return propGroup; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
| #endregion | ||
|
|
||
| #region Event Handling | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a strange region name. What is meant by Temporary?