From 9c207314d071852637eb30692e987fcc7786e514 Mon Sep 17 00:00:00 2001 From: Johannes Schneider Date: Mon, 26 Oct 2020 15:01:23 +0100 Subject: [PATCH] * implement PlayerSwapping --- .../PlayerGoldDifferenceView.xaml | 14 +- .../PlayerGoldDifferenceView.xaml.cs | 126 ++++++++++++++- .../GoldDifferenceWindowController.cs | 4 +- GoldDiff/View/GoldDifferenceWindow.xaml | 16 +- GoldDiff/View/GoldDifferenceWindow.xaml.cs | 12 ++ .../Model/GoldDifferenceWindowViewModel.cs | 151 ++++++++++++------ .../DefaultPlayerGoldDifferenceStyle.xaml | 6 +- 7 files changed, 264 insertions(+), 65 deletions(-) diff --git a/GoldDiff/View/ControlElement/PlayerGoldDifferenceView.xaml b/GoldDiff/View/ControlElement/PlayerGoldDifferenceView.xaml index 488a889..d54ed48 100644 --- a/GoldDiff/View/ControlElement/PlayerGoldDifferenceView.xaml +++ b/GoldDiff/View/ControlElement/PlayerGoldDifferenceView.xaml @@ -44,8 +44,13 @@ + Source="{Binding Path=Champion.SmallTileImage}" + MouseLeftButtonDown="ChampionTileBlueSide_OnMouseLeftButtonDown" + DragEnter="ChampionTileBlueSide_OnDragOver" + DragOver="ChampionTileBlueSide_OnDragOver" + Drop="ChampionTileBlueSide_OnDrop" /> @@ -122,8 +127,13 @@ + Source="{Binding Path=Champion.SmallTileImage}" + MouseLeftButtonDown="ChampionTileRedSide_OnMouseLeftButtonDown" + DragEnter="ChampionTileRedSide_OnDragOver" + DragOver="ChampionTileRedSide_OnDragOver" + Drop="ChampionTileRedSide_OnDrop" /> diff --git a/GoldDiff/View/ControlElement/PlayerGoldDifferenceView.xaml.cs b/GoldDiff/View/ControlElement/PlayerGoldDifferenceView.xaml.cs index 63437f4..fa5569e 100644 --- a/GoldDiff/View/ControlElement/PlayerGoldDifferenceView.xaml.cs +++ b/GoldDiff/View/ControlElement/PlayerGoldDifferenceView.xaml.cs @@ -1,6 +1,8 @@ -using System.Reflection; +using System; +using System.Reflection; using System.Windows; using System.Windows.Controls; +using System.Windows.Input; using GoldDiff.LeagueOfLegends.Game; using GoldDiff.Shared.LeagueOfLegends; @@ -8,12 +10,38 @@ namespace GoldDiff.View.ControlElement { public partial class PlayerGoldDifferenceView : UserControl { + private class DragDropData + { + public LoLTeamType Team; + public LoLPositionType Position; + } + + public class SwapPlayersEventArguments + { + public LoLTeamType Team { get; } + + public LoLPositionType PositionA { get; } + + public LoLPositionType PositionB { get; } + + public SwapPlayersEventArguments(LoLTeamType team, LoLPositionType positionA, LoLPositionType positionB) + { + Team = team; + PositionA = positionA; + PositionB = positionB; + } + } + + public event EventHandler? SwapPlayers; + public static readonly DependencyProperty PositionProperty = DependencyProperty.Register(nameof(Position), typeof(LoLPositionType), MethodBase.GetCurrentMethod().DeclaringType); public static readonly DependencyProperty PlayerBlueSideProperty = DependencyProperty.Register(nameof(PlayerBlueSide), typeof(LoLPlayer), MethodBase.GetCurrentMethod().DeclaringType); public static readonly DependencyProperty PlayerRedSideProperty = DependencyProperty.Register(nameof(PlayerRedSide), typeof(LoLPlayer), MethodBase.GetCurrentMethod().DeclaringType); + public static readonly DependencyProperty CanSwapPlayersProperty = DependencyProperty.Register(nameof(CanSwapPlayers), typeof(bool), MethodBase.GetCurrentMethod().DeclaringType); + public LoLPositionType Position { get => (LoLPositionType) GetValue(PositionProperty); @@ -32,9 +60,105 @@ public LoLPlayer? PlayerRedSide set => SetValue(PlayerRedSideProperty, value); } + public bool CanSwapPlayers + { + get => (bool) GetValue(CanSwapPlayersProperty); + set => SetValue(CanSwapPlayersProperty, value); + } + public PlayerGoldDifferenceView() { InitializeComponent(); } + + private void ChampionTileBlueSide_OnMouseLeftButtonDown(object sender, MouseEventArgs e) + { + StartDragging(PlayerBlueSide, e); + } + + private void ChampionTileRedSide_OnMouseLeftButtonDown(object sender, MouseEventArgs e) + { + StartDragging(PlayerRedSide, e); + } + + private void StartDragging(LoLPlayer? player, MouseEventArgs e) + { + if (!CanSwapPlayers) + { + return; + } + + if (player == null) + { + return; + } + + if (e.LeftButton != MouseButtonState.Pressed) + { + return; + } + + DragDrop.DoDragDrop(this, new DataObject(typeof(DragDropData), new DragDropData{Team = player.Team, Position = Position}), DragDropEffects.Move); + } + + private void ChampionTileBlueSide_OnDragOver(object sender, DragEventArgs e) + { + HandleDragOver(LoLTeamType.BlueSide, e); + } + + private void ChampionTileRedSide_OnDragOver(object sender, DragEventArgs e) + { + HandleDragOver(LoLTeamType.RedSide, e); + } + + private void HandleDragOver(LoLTeamType acceptedTeam, DragEventArgs e) + { + e.Effects = AcceptDrop(acceptedTeam, e, out _) ? DragDropEffects.Move : DragDropEffects.None; + e.Handled = true; + } + + private void ChampionTileBlueSide_OnDrop(object sender, DragEventArgs e) + { + HandleDrop(LoLTeamType.BlueSide, e); + } + + private void ChampionTileRedSide_OnDrop(object sender, DragEventArgs e) + { + HandleDrop(LoLTeamType.RedSide, e); + } + + private void HandleDrop(LoLTeamType acceptedTeam, DragEventArgs e) + { + if (!AcceptDrop(acceptedTeam, e, out var dragDropData)) + { + return; + } + + if (dragDropData.Position == Position) + { + return; + } + + SwapPlayers?.Invoke(this, new SwapPlayersEventArguments(dragDropData.Team, dragDropData.Position, Position)); + } + + private bool AcceptDrop(LoLTeamType acceptedTeam, DragEventArgs e, out DragDropData dragDropData) + { + dragDropData = null!; + + if (!e.Data.GetDataPresent(typeof(DragDropData))) + { + return false; + } + + dragDropData = (e.Data.GetData(typeof(DragDropData)) as DragDropData)!; + + // ReSharper disable once ConditionIsAlwaysTrueOrFalse + if (ReferenceEquals(dragDropData, null) || dragDropData.Team != acceptedTeam) + { + return false; + } + return true; + } } } \ No newline at end of file diff --git a/GoldDiff/View/Controller/GoldDifferenceWindowController.cs b/GoldDiff/View/Controller/GoldDifferenceWindowController.cs index 9db2e27..aab616e 100644 --- a/GoldDiff/View/Controller/GoldDifferenceWindowController.cs +++ b/GoldDiff/View/Controller/GoldDifferenceWindowController.cs @@ -40,7 +40,7 @@ public GoldDifferenceWindowController(GoldDifferenceWindowViewModel? model, LoLG private void ModelOnPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (PlayerPropertyNames.Contains(e.PropertyName)) + if (string.IsNullOrEmpty(e.PropertyName) || PlayerPropertyNames.Contains(e.PropertyName)) { UpdateActivePlayerBackground(); } @@ -207,7 +207,5 @@ private Dictionary OrderPlayers(LoLTeam team, LoLCli return result; } - - } } \ No newline at end of file diff --git a/GoldDiff/View/GoldDifferenceWindow.xaml b/GoldDiff/View/GoldDifferenceWindow.xaml index 27ea7b5..7959184 100644 --- a/GoldDiff/View/GoldDifferenceWindow.xaml +++ b/GoldDiff/View/GoldDifferenceWindow.xaml @@ -14,7 +14,6 @@ x:Name="This" Style="{DynamicResource {x:Static view:GoldDiffSharedResourceKeys.DefaultWindowStyle}}" - Title="{x:Static properties:GoldDifferenceWindowResources.Title}" MinWidth="500" MinHeight="350" Height="400" @@ -53,7 +52,8 @@ + PlayerRedSide="{Binding TopPlayerRedSide, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" + SwapPlayers="PlayerGoldDifferenceView_OnSwapPlayers" /> + PlayerRedSide="{Binding JunglePlayerRedSide, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" + SwapPlayers="PlayerGoldDifferenceView_OnSwapPlayers" /> @@ -76,7 +77,8 @@ + PlayerRedSide="{Binding MiddlePlayerRedSide, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" + SwapPlayers="PlayerGoldDifferenceView_OnSwapPlayers" /> @@ -88,7 +90,8 @@ + PlayerRedSide="{Binding BottomPlayerRedSide, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" + SwapPlayers="PlayerGoldDifferenceView_OnSwapPlayers" /> @@ -100,7 +103,8 @@ + PlayerRedSide="{Binding SupportPlayerRedSide, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" + SwapPlayers="PlayerGoldDifferenceView_OnSwapPlayers" /> diff --git a/GoldDiff/View/GoldDifferenceWindow.xaml.cs b/GoldDiff/View/GoldDifferenceWindow.xaml.cs index 8556b92..847544d 100644 --- a/GoldDiff/View/GoldDifferenceWindow.xaml.cs +++ b/GoldDiff/View/GoldDifferenceWindow.xaml.cs @@ -3,6 +3,8 @@ using System.Windows; using System.Windows.Media; using GoldDiff.LeagueOfLegends.Game; +using GoldDiff.Shared.LeagueOfLegends; +using GoldDiff.View.ControlElement; using GoldDiff.View.Controller; using GoldDiff.View.Model; @@ -40,5 +42,15 @@ public GoldDifferenceWindow(LoLGame? game) PrivateModel = Model; } + + private void PlayerGoldDifferenceView_OnSwapPlayers(object sender, PlayerGoldDifferenceView.SwapPlayersEventArguments e) + { + if (e.PositionA == e.PositionB) + { + return; + } + + Model.SwapPlayers(e.Team, e.PositionA, e.PositionB); + } } } \ No newline at end of file diff --git a/GoldDiff/View/Model/GoldDifferenceWindowViewModel.cs b/GoldDiff/View/Model/GoldDifferenceWindowViewModel.cs index 0f69bf2..f7566ba 100644 --- a/GoldDiff/View/Model/GoldDifferenceWindowViewModel.cs +++ b/GoldDiff/View/Model/GoldDifferenceWindowViewModel.cs @@ -1,95 +1,141 @@ -using System.Windows.Media; +using System.Collections.Generic; +using System.Windows.Media; using GoldDiff.LeagueOfLegends.Game; +using GoldDiff.Shared.LeagueOfLegends; using GoldDiff.Shared.View.Model; namespace GoldDiff.View.Model { public class GoldDifferenceWindowViewModel : ViewModel { + private Dictionary> Players { get; } = new Dictionary> + { + { + LoLTeamType.BlueSide, new Dictionary + { + {LoLPositionType.Top, null}, + {LoLPositionType.Jungle, null}, + {LoLPositionType.Middle, null}, + {LoLPositionType.Bottom, null}, + {LoLPositionType.Support, null}, + } + }, + { + LoLTeamType.RedSide, new Dictionary + { + {LoLPositionType.Top, null}, + {LoLPositionType.Jungle, null}, + {LoLPositionType.Middle, null}, + {LoLPositionType.Bottom, null}, + {LoLPositionType.Support, null}, + } + }, + }; + #region Blue Side - - private LoLPlayer? _topPlayerBlueSide; - + public LoLPlayer? TopPlayerBlueSide { - get => _topPlayerBlueSide; - set => MutateVerbose(ref _topPlayerBlueSide, value); + get => Players[LoLTeamType.BlueSide][LoLPositionType.Top]; + set + { + Players[LoLTeamType.BlueSide][LoLPositionType.Top] = value; + OnPropertyChanged(); + } } - - private LoLPlayer? _middlePlayerBlueSide; - + public LoLPlayer? MiddlePlayerBlueSide { - get => _middlePlayerBlueSide; - set => MutateVerboseIfNotNull(ref _middlePlayerBlueSide, value); + get => Players[LoLTeamType.BlueSide][LoLPositionType.Middle]; + set + { + Players[LoLTeamType.BlueSide][LoLPositionType.Middle] = value; + OnPropertyChanged(); + } } - - private LoLPlayer? _bottomPlayerBlueSide; - + public LoLPlayer? BottomPlayerBlueSide { - get => _bottomPlayerBlueSide; - set => MutateVerboseIfNotNull(ref _bottomPlayerBlueSide, value); + get => Players[LoLTeamType.BlueSide][LoLPositionType.Bottom]; + set + { + Players[LoLTeamType.BlueSide][LoLPositionType.Bottom] = value; + OnPropertyChanged(); + } } - - private LoLPlayer? _junglePlayerBlueSide; - + public LoLPlayer? JunglePlayerBlueSide { - get => _junglePlayerBlueSide; - set => MutateVerboseIfNotNull(ref _junglePlayerBlueSide, value); + get => Players[LoLTeamType.BlueSide][LoLPositionType.Jungle]; + set + { + Players[LoLTeamType.BlueSide][LoLPositionType.Jungle] = value; + OnPropertyChanged(); + } } - - private LoLPlayer? _supportPlayerBlueSide; - + public LoLPlayer? SupportPlayerBlueSide { - get => _supportPlayerBlueSide; - set => MutateVerboseIfNotNull(ref _supportPlayerBlueSide, value); + get => Players[LoLTeamType.BlueSide][LoLPositionType.Support]; + set + { + Players[LoLTeamType.BlueSide][LoLPositionType.Support] = value; + OnPropertyChanged(); + } } #endregion #region Red Side - private LoLPlayer? _topPlayerRedSide; - public LoLPlayer? TopPlayerRedSide { - get => _topPlayerRedSide; - set => MutateVerbose(ref _topPlayerRedSide, value); + get => Players[LoLTeamType.RedSide][LoLPositionType.Top]; + set + { + Players[LoLTeamType.RedSide][LoLPositionType.Top] = value; + OnPropertyChanged(); + } } - - private LoLPlayer? _middlePlayerRedSide; - + public LoLPlayer? MiddlePlayerRedSide { - get => _middlePlayerRedSide; - set => MutateVerboseIfNotNull(ref _middlePlayerRedSide, value); + get => Players[LoLTeamType.RedSide][LoLPositionType.Middle]; + set + { + Players[LoLTeamType.RedSide][LoLPositionType.Middle] = value; + OnPropertyChanged(); + } } - - private LoLPlayer? _bottomPlayerRedSide; - + public LoLPlayer? BottomPlayerRedSide { - get => _bottomPlayerRedSide; - set => MutateVerboseIfNotNull(ref _bottomPlayerRedSide, value); + get => Players[LoLTeamType.RedSide][LoLPositionType.Bottom]; + set + { + Players[LoLTeamType.RedSide][LoLPositionType.Bottom] = value; + OnPropertyChanged(); + } } - - private LoLPlayer? _junglePlayerRedSide; - + public LoLPlayer? JunglePlayerRedSide { - get => _junglePlayerRedSide; - set => MutateVerboseIfNotNull(ref _junglePlayerRedSide, value); + get => Players[LoLTeamType.RedSide][LoLPositionType.Jungle]; + set + { + Players[LoLTeamType.RedSide][LoLPositionType.Jungle] = value; + OnPropertyChanged(); + } } - - private LoLPlayer? _supportPlayerRedSide; - + public LoLPlayer? SupportPlayerRedSide { - get => _supportPlayerRedSide; - set => MutateVerboseIfNotNull(ref _supportPlayerRedSide, value); + get => Players[LoLTeamType.RedSide][LoLPositionType.Support]; + set + { + Players[LoLTeamType.RedSide][LoLPositionType.Support] = value; + OnPropertyChanged(); + } } #endregion @@ -158,5 +204,10 @@ public Brush? SupportPlayerBackground set => MutateVerbose(ref _supportPlayerBackground, value); } + public void SwapPlayers(LoLTeamType team, LoLPositionType positionA, LoLPositionType positionB) + { + (Players[team][positionA], Players[team][positionB]) = (Players[team][positionB], Players[team][positionA]); + OnPropertyChanged(string.Empty); + } } } \ No newline at end of file diff --git a/GoldDiff/View/Style/DefaultPlayerGoldDifferenceStyle.xaml b/GoldDiff/View/Style/DefaultPlayerGoldDifferenceStyle.xaml index 2b30a72..29548a0 100644 --- a/GoldDiff/View/Style/DefaultPlayerGoldDifferenceStyle.xaml +++ b/GoldDiff/View/Style/DefaultPlayerGoldDifferenceStyle.xaml @@ -1,9 +1,9 @@  - + - + \ No newline at end of file