Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
<PackageVersion Include="Debounce.Core" Version="1.0.0" />
<PackageVersion Include="DockPanelSuite" Version="3.1.1" />
<PackageVersion Include="DockPanelSuite.ThemeVS2015" Version="3.1.1" />
<PackageVersion Include="Extended.Wpf.Toolkit" Version="5.0.0" />
<PackageVersion Include="Fody" Version="6.6.4" />
<PackageVersion Include="FTD2XX.Net" Version="1.2.1" />
<PackageVersion Include="gong-wpf-dragdrop" Version="4.0.0" />
<PackageVersion Include="HtmlRenderer.WPF" Version="1.5.2" />
<PackageVersion Include="LiteDB" Version="4.1.4" />
<PackageVersion Include="LoadAssembliesOnStartup.Fody" Version="4.6.0" />
<PackageVersion Include="MessagePack" Version="2.5.192" />
Expand Down

This file was deleted.

211 changes: 166 additions & 45 deletions src/Vixen.Application/SetupDisplay/ViewModels/PropNodeTreeViewModel.cs
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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -126,6 +133,27 @@ public ObservableCollection<PropNodeViewModel> PropNodes

#endregion

#region Temporary properties to get Change Prop to work
Copy link
Contributor

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?

// 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
Copy link
Contributor

Choose a reason for hiding this comment

The 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()
Copy link
Contributor

Choose a reason for hiding this comment

The 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>
Expand Down Expand Up @@ -162,6 +190,7 @@ private void SelectedItemsCollectionChanged(object? sender, System.Collections.S
MoveToGroupCommand.RaiseCanExecuteChanged();
CreateNodeCommand.RaiseCanExecuteChanged();
CreatePropCommand.RaiseCanExecuteChanged();
ChangePropCommand.RaiseCanExecuteChanged();
}

#endregion
Expand Down Expand Up @@ -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;
}
}
}
Expand All @@ -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 })
{
Expand All @@ -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;
Expand Down Expand Up @@ -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();
Copy link
Contributor

Choose a reason for hiding this comment

The 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));

Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down
Loading