Action selection dialog refactoring

This commit is contained in:
Josef Nemec 2022-05-11 11:40:57 +02:00
parent e6367eb61d
commit d94a2555c9
21 changed files with 131 additions and 204 deletions

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Playnite.DesktopApp.ViewModels;
using Playnite.DesktopApp.Windows;
using Playnite.SDK.Models;
using Playnite.SDK.Plugins;
namespace Playnite.DesktopApp
{
public class DesktopActionSelector : IActionSelector
{
public object SelectPlayAction(List<PlayController> controllers, List<GameAction> actions)
{
return new ActionSelectionViewModel(new ActionSelectionWindowFactory()).SelectPlayAction(controllers, actions);
}
public InstallController SelectInstallAction(List<InstallController> pluginActions)
{
return new ActionSelectionViewModel(new ActionSelectionWindowFactory()).SelectInstallAction(pluginActions);
}
public UninstallController SelectUninstallAction(List<UninstallController> pluginActions)
{
return new ActionSelectionViewModel(new ActionSelectionWindowFactory()).SelectUninstallAction(pluginActions);
}
}
}

View File

@ -71,7 +71,6 @@ namespace Playnite.DesktopApp
ExtensionCrashHandlerWindowFactory.SetWindowType<ExtensionCrashHandlerWindow>();
UpdateWindowFactory.SetWindowType<UpdateWindow>();
LicenseAgreementWindowFactory.SetWindowType<LicenseAgreementWindow>();
ActionSelectionWindowFactory.SetWindowType<ActionSelectionWindow>();
Dialogs = new DesktopDialogs();
Playnite.Dialogs.SetHandler(Dialogs);
if (!ConfigureApplication())
@ -138,7 +137,8 @@ namespace Playnite.DesktopApp
AppSettings,
Dialogs,
Extensions,
this);
this,
new DesktopActionSelector());
Game.DatabaseReference = Database;
ImageSourceManager.SetDatabase(Database);
MainModel = new DesktopAppViewModel(

View File

@ -23,13 +23,15 @@ namespace Playnite.DesktopApp
PlayniteSettings appSettings,
IDialogsFactory dialogs,
ExtensionFactory extensions,
PlayniteApplication app) : base(
PlayniteApplication app,
IActionSelector actionSelector) : base(
database,
controllerFactory,
appSettings,
dialogs,
extensions,
app)
app,
actionSelector)
{
}

View File

@ -262,12 +262,14 @@
<Compile Include="Controls\Views\TopPanel.cs" />
<Compile Include="Controls\SliderEx.cs" />
<Compile Include="Controls\GridViewPanel.cs" />
<Compile Include="DesktopActionSelector.cs" />
<Compile Include="DesktopApplication.cs" />
<Compile Include="DesktopCollectionView.cs" />
<Compile Include="DesktopDialogs.cs" />
<Compile Include="DesktopGamesEditor.cs" />
<Compile Include="Markups.cs" />
<Compile Include="ViewModels\AboutViewModel.cs" />
<Compile Include="ViewModels\ActionSelectionViewModel.cs" />
<Compile Include="ViewModels\AddonsViewModel.cs" />
<Compile Include="ViewModels\AddonsViewModel_Installed.cs" />
<Compile Include="ViewModels\AddonsViewModel_Online.cs" />

View File

@ -10,7 +10,7 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
namespace Playnite.ViewModels
namespace Playnite.DesktopApp.ViewModels
{
public class ActionSelectionViewModel : ObservableObject
{
@ -46,7 +46,7 @@ namespace Playnite.ViewModels
});
}
public ActionSelectionViewModel(ActionSelectionWindowFactory window)
public ActionSelectionViewModel(IWindowFactory window)
{
this.window = window;
}

View File

@ -3,6 +3,14 @@ using Playnite.Windows;
namespace Playnite.DesktopApp.Windows
{
public class ActionSelectionWindowFactory : WindowFactory
{
public override WindowBase CreateNewWindowInstance()
{
return new ActionSelectionWindow();
}
}
/// <summary>
/// Interaction logic for AboutWindow.xaml
/// </summary>

View File

@ -39,7 +39,6 @@
<ResourceDictionary Source="Themes/Fullscreen/Default/DerivedStyles/ButtonTopMenu.xaml" />
<!--Views-->
<ResourceDictionary Source="Themes/Fullscreen/Default/Views/ActionSelection.xaml" />
<ResourceDictionary Source="Themes/Fullscreen/Default/Views/FiltersAdditional.xaml" />
<ResourceDictionary Source="Themes/Fullscreen/Default/Views/FiltersView.xaml" />
<ResourceDictionary Source="Themes/Fullscreen/Default/Views/GameDetails.xaml" />

View File

@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Playnite.FullscreenApp.ViewModels;
using Playnite.FullscreenApp.Windows;
using Playnite.SDK;
using Playnite.SDK.Models;
using Playnite.SDK.Plugins;
namespace Playnite.FullscreenApp
{
public class FullscreenActionSelector : IActionSelector
{
public object SelectPlayAction(List<PlayController> controllers, List<GameAction> actions)
{
var allActions = new List<NamedObject<object>>();
if (controllers.HasItems())
{
allActions.AddRange(controllers.Select(a => new NamedObject<object>(a, a.Name)));
}
if (actions.HasItems())
{
allActions.AddRange(actions.Select(a => new NamedObject<object>(a, a.Name)));
}
return new SingleItemSelectionViewModel<object>(
new SingleItemSelectionWindowFactory(),
ResourceProvider.GetString(LOC.SelectActionTitle)).
SelectItem(allActions);
}
public InstallController SelectInstallAction(List<InstallController> pluginActions)
{
return new SingleItemSelectionViewModel<InstallController>(
new SingleItemSelectionWindowFactory(),
ResourceProvider.GetString(LOC.SelectActionTitle)).
SelectItem(pluginActions.Select(a => new NamedObject<InstallController>(a, a.Name)).ToList());
}
public UninstallController SelectUninstallAction(List<UninstallController> pluginActions)
{
return new SingleItemSelectionViewModel<UninstallController>(
new SingleItemSelectionWindowFactory(),
ResourceProvider.GetString(LOC.SelectActionTitle)).
SelectItem(pluginActions.Select(a => new NamedObject<UninstallController>(a, a.Name)).ToList());
}
}
}

View File

@ -63,7 +63,6 @@ namespace Playnite.FullscreenApp
ExtensionCrashHandlerWindowFactory.SetWindowType<ExtensionCrashWindow>();
LicenseAgreementWindowFactory.SetWindowType<LicenseAgreementWindow>();
UpdateWindowFactory.SetWindowType<UpdateWindow>();
ActionSelectionWindowFactory.SetWindowType<ActionSelectionWindow>();
Dialogs = new FullscreenDialogs();
Playnite.Dialogs.SetHandler(Dialogs);
if (!AppSettings.FirstTimeWizardComplete)
@ -107,7 +106,8 @@ namespace Playnite.FullscreenApp
AppSettings,
Dialogs,
Extensions,
this);
this,
new FullscreenActionSelector());
Game.DatabaseReference = Database;
ImageSourceManager.SetDatabase(Database);
MainModel = new FullscreenAppViewModel(

View File

@ -166,6 +166,7 @@
<Compile Include="Controls\Views\GameDetails.cs" />
<Compile Include="Controls\Views\GameStatus.cs" />
<Compile Include="Controls\Views\Main.cs" />
<Compile Include="FullscreenActionSelector.cs" />
<Compile Include="FullscreenCollectionView.cs" />
<Compile Include="FullscreenDialogs.cs" />
<Compile Include="Markup\Markups.cs" />
@ -184,9 +185,6 @@
<Compile Include="Windows\SingleItemSelectionWindow.xaml.cs">
<DependentUpon>SingleItemSelectionWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\ActionSelectionWindow.xaml.cs">
<DependentUpon>ActionSelectionWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Windows\LicenseAgreementWindow.xaml.cs">
<DependentUpon>LicenseAgreementWindow.xaml</DependentUpon>
</Compile>
@ -415,11 +413,6 @@
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Themes\Fullscreen\Default\Views\ActionSelection.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Themes\Fullscreen\Default\Views\GameMenu.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@ -464,10 +457,6 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Windows\ActionSelectionWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Windows\LicenseAgreementWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>

View File

@ -1,22 +0,0 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="ActionSelectionButton" BasedOn="{StaticResource {x:Type ButtonEx}}" TargetType="ButtonEx">
<Setter Property="Margin" Value="5" />
</Style>
<Style x:Key="ActionSelectionBorder" TargetType="Border">
<Setter Property="CornerRadius" Value="3" />
<Setter Property="Width" Value="400" />
<Setter Property="Background" Value="{DynamicResource OverlayMenuBackgroundBrush}" />
</Style>
<Style x:Key="ActionSelectionHeaderText" BasedOn="{StaticResource TextBlockBaseStyle}" TargetType="TextBlock" >
<Setter Property="VerticalAlignment" Value="Bottom" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="Padding" Value="15,15,15,15" />
<Setter Property="Background" Value="#AA000000" />
</Style>
</ResourceDictionary>

View File

@ -177,16 +177,12 @@ namespace Playnite.FullscreenApp.ViewModels
public void AssignCompletionStatus()
{
Close();
var items = new List<CompletionStatus>()
var items = new List<NamedObject<CompletionStatus>>()
{
new CompletionStatus
{
Id = Guid.Empty,
Name = ResourceProvider.GetString(LOC.None)
}
new NamedObject<CompletionStatus>(new CompletionStatus { Id = Guid.Empty }, ResourceProvider.GetString(LOC.None))
};
items.AddRange(mainModel.Database.CompletionStatuses.OrderByDescending(a => a.Name));
items.AddRange(mainModel.Database.CompletionStatuses.OrderByDescending(a => a.Name).Select(a => new NamedObject<CompletionStatus>(a, a.Name)));
var item = new SingleItemSelectionViewModel<CompletionStatus>(new SingleItemSelectionWindowFactory(), ResourceProvider.GetString(LOC.SetCompletionStatus)).SelectItem(items);
if (item != null)
{

View File

@ -13,7 +13,7 @@ namespace Playnite.FullscreenApp.ViewModels
private static readonly ILogger logger = LogManager.GetLogger();
private IWindowFactory window;
public List<TItem> Items { get; set; }
public List<NamedObject<TItem>> Items { get; set; }
public TItem SelectedItem { get; private set; }
public string HeaderText { get; set; }
@ -31,7 +31,7 @@ namespace Playnite.FullscreenApp.ViewModels
});
}
public TItem SelectItem(List<TItem> items)
public TItem SelectItem(List<NamedObject<TItem>> items)
{
Items = items;
if (window.CreateAndOpenDialog(this) == true)

View File

@ -1,74 +0,0 @@
<c:WindowBase x:Class="Playnite.FullscreenApp.Windows.ActionSelectionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Playnite.FullscreenApp.Windows"
xmlns:c="clr-namespace:Playnite.Controls;assembly=Playnite"
xmlns:pbeh="clr-namespace:Playnite.Behaviors;assembly=Playnite"
xmlns:pcon="clr-namespace:Playnite.Converters;assembly=Playnite"
xmlns:html="clr-namespace:TheArtOfDev.HtmlRenderer.WPF;assembly=HtmlRenderer.WPF"
xmlns:pctrls="clr-namespace:Playnite.FullscreenApp.Controls"
xmlns:pin="clr-namespace:Playnite.Input;assembly=Playnite"
mc:Ignorable="d"
Style="{StaticResource ChildWindowStyle}"
ShowMinimizeButton="False" ShowMaximizeButton="False" ShowCloseButton="False"
ShowInTaskbar="False" WindowStyle="None"
ResizeMode="NoResize" WindowStartupLocation="CenterOwner"
d:DesignWidth="1920" d:DesignHeight="1080"
Name="WindowActionSelectionWindow">
<c:WindowBase.InputBindings>
<pin:XInputBinding Button="{Binding Path=(pin:XInputGesture.CancellationBinding)}" Command="{Binding CancelCommand}" />
<KeyBinding Key="Esc" Command="{Binding CancelCommand}" />
</c:WindowBase.InputBindings>
<Viewbox>
<Grid Height="1080" Width="1920" Name="GridMain">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="3*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Style="{DynamicResource ActionSelectionBorder}"
MinWidth="400" Width="Auto"
Grid.Column="1" Grid.Row="1"
HorizontalAlignment="Center" VerticalAlignment="Center">
<DockPanel>
<TextBlock Text="{DynamicResource LOCSelectActionTitle}"
Style="{DynamicResource ActionSelectionHeaderText}"
DockPanel.Dock="Top"/>
<pctrls:ItemsControlEx x:Name="PART_ItemsHost" Focusable="False"
KeyboardNavigation.DirectionalNavigation="Once"
pbeh:FocusBahaviors.FocusBinding="True"
ItemsSource="{Binding Actions}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<pctrls:ButtonEx Content="{Binding Item.Name}"
Command="{Binding DataContext.PlaySpecificCommand, ElementName=WindowActionSelectionWindow}"
CommandParameter="{Binding Item}"
Style="{DynamicResource ActionSelectionButton}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer Focusable="False"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
CanContentScroll="True">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</pctrls:ItemsControlEx>
</DockPanel>
</Border>
</Grid>
</Viewbox>
</c:WindowBase>

View File

@ -1,30 +0,0 @@
using Playnite.Controls;
using Playnite.Windows;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Playnite.FullscreenApp.Windows
{
/// <summary>
/// Interaction logic for UpdateWindow.xaml
/// </summary>
public partial class ActionSelectionWindow : WindowBase
{
public ActionSelectionWindow() : base()
{
InitializeComponent();
WindowTools.ConfigureChildWindow(this);
}
}
}

View File

@ -48,9 +48,9 @@
ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<pctrls:ButtonEx Content="{Binding}"
<pctrls:ButtonEx Content="{Binding Name}"
Command="{Binding DataContext.SelectItemCommand, ElementName=WindowSingleItemSelectionWindow}"
CommandParameter="{Binding}"
CommandParameter="{Binding Value}"
Style="{DynamicResource ItemSelectionButton}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>

View File

@ -42,6 +42,13 @@ namespace Playnite
None
}
public interface IActionSelector
{
object SelectPlayAction(List<PlayController> controllers, List<GameAction> actions);
InstallController SelectInstallAction(List<InstallController> pluginActions);
UninstallController SelectUninstallAction(List<UninstallController> pluginActions);
}
public class ClientShutdownJob
{
public Guid PluginId { get; set; }
@ -58,8 +65,10 @@ namespace Playnite
private readonly ConcurrentDictionary<Guid, ClientShutdownJob> shutdownJobs = new ConcurrentDictionary<Guid, ClientShutdownJob>();
private readonly ConcurrentDictionary<Guid, DateTime> gameStartups = new ConcurrentDictionary<Guid, DateTime>();
private readonly ConcurrentDictionary<Guid, IPowerShellRuntime> scriptRuntimes = new ConcurrentDictionary<Guid, IPowerShellRuntime>();
private readonly IActionSelector actionSelector;
public PlayniteApplication Application;
public ExtensionFactory Extensions { get; private set; }
public GameDatabase Database { get; private set; }
public IDialogsFactory Dialogs { get; private set; }
@ -91,13 +100,15 @@ namespace Playnite
PlayniteSettings appSettings,
IDialogsFactory dialogs,
ExtensionFactory extensions,
PlayniteApplication app)
PlayniteApplication app,
IActionSelector actionSelector)
{
this.Dialogs = dialogs;
this.Database = database;
this.AppSettings = appSettings;
this.Extensions = extensions;
this.Application = app;
this.actionSelector = actionSelector;
controllers = controllerFactory;
controllers.Installed += Controllers_Installed;
controllers.Uninstalled += Controllers_Uninstalled;
@ -173,7 +184,7 @@ namespace Playnite
object playAction = null;
if ((gameActions.Item1.Count + gameActions.Item2.Count) > 1)
{
playAction = SelectPlayAction(gameActions.Item1, gameActions.Item2);
playAction = actionSelector.SelectPlayAction(gameActions.Item1, gameActions.Item2);
}
else
{
@ -738,7 +749,7 @@ namespace Playnite
if (installControllers.Count > 1)
{
controller = SelectInstallAction(installControllers);
controller = actionSelector.SelectInstallAction(installControllers);
}
else
{
@ -792,7 +803,7 @@ namespace Playnite
if (uninstallControllers.Count > 1)
{
controller = SelectUninstallAction(uninstallControllers);
controller = actionSelector.SelectUninstallAction(uninstallControllers);
}
else
{
@ -1324,11 +1335,6 @@ namespace Playnite
return new Tuple<List<PlayController>, List<GameAction>>(controllers, actions);
}
public object SelectPlayAction(List<PlayController> controllers, List<GameAction> actions)
{
return new ActionSelectionViewModel(new Windows.ActionSelectionWindowFactory()).SelectPlayAction(controllers, actions);
}
public List<InstallController> GetInstallActions(Game game)
{
var allActions = new List<InstallController>();
@ -1351,11 +1357,6 @@ namespace Playnite
return allActions;
}
public InstallController SelectInstallAction(List<InstallController> actions)
{
return new ActionSelectionViewModel(new Windows.ActionSelectionWindowFactory()).SelectInstallAction(actions);
}
public List<UninstallController> GetUninstallActions(Game game)
{
var allActions = new List<UninstallController>();
@ -1377,10 +1378,5 @@ namespace Playnite
return allActions;
}
public UninstallController SelectUninstallAction(List<UninstallController> actions)
{
return new ActionSelectionViewModel(new Windows.ActionSelectionWindowFactory()).SelectUninstallAction(actions);
}
}
}

View File

@ -471,7 +471,6 @@
<Compile Include="ObservableTime.cs" />
<Compile Include="UrlConstants.cs" />
<Compile Include="ViewModels\AddonsViewModelBase_Online.cs" />
<Compile Include="ViewModels\ActionSelectionViewModel.cs" />
<Compile Include="ViewModels\CrashHandlerViewModel.cs" />
<Compile Include="ViewModels\MainViewModelBase.cs" />
<Compile Include="ViewModels\ProgressViewViewModel.cs" />
@ -484,7 +483,6 @@
<Compile Include="WebView\WebViewBase.cs" />
<Compile Include="WebView\WebViewFactory.cs" />
<Compile Include="WindowsNotifyIconManager.cs" />
<Compile Include="Windows\GameStartSelectionWindowFactory.cs" />
<Compile Include="Windows\LicenseAgreementWindowFactory.cs" />
<Compile Include="Windows\ExtensionCrashHandlerWindowFactory.cs" />
<Compile Include="Windows\CrashHandlerWindowFactory.cs" />

View File

@ -1,24 +0,0 @@
using Playnite.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Playnite.Windows
{
public class ActionSelectionWindowFactory : WindowFactory
{
public static Type WindowType { get; private set; }
public static void SetWindowType<TType>() where TType : WindowBase
{
WindowType = typeof(TType);
}
public override WindowBase CreateNewWindowInstance()
{
return WindowType.CrateInstance<WindowBase>();
}
}
}

View File

@ -225,6 +225,12 @@ namespace Playnite.SDK.Plugins
args.Source = this;
execContext.Send((a) => Stopped?.Invoke(this, args), null);
}
/// <inheritdoc/>
public override string ToString()
{
return Name ?? base.ToString();
}
}
/// <summary>

View File

@ -34,7 +34,7 @@ namespace Playnite.Tests
InstallDirectory = tempDir.TempPath
};
var editor = new GamesEditor(null, new GameControllerFactory(null), new PlayniteSettings(), null, null, new TestPlayniteApplication());
var editor = new GamesEditor(null, new GameControllerFactory(null), new PlayniteSettings(), null, null, new TestPlayniteApplication(), null);
editor.ExecuteScriptAction(runtime, script, game, true, false, GameScriptType.None);
var testPath = Path.Combine(tempDir.TempPath, executeScriptActionTestFileName);
var content = File.ReadAllText(testPath);