using DominionBase; using DominionBase.Enums; using DominionBase.Players; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace Dominion.NET_WPF.Controls.GameLog { /// /// Interaction logic for ucPlayerTurn.xaml /// public partial class ucPlayerTurn : LogSection { private int _currentInset; public DominionBase.Visual.VisualPlayer Player { get; private set; } public override bool IsExpanded { get { return expTurn.IsExpanded; } set { expTurn.IsExpanded = value; } } public ucPlayerTurn() { InitializeComponent(); SpContainer = spArea; } public override void TearDown() { base.TearDown(); Player = null; } protected override void Dispose(bool disposing) { // Check to see if Dispose has already been called. if (!Disposed) { // If disposing equals true, dispose all managed // and unmanaged resources. if (disposing) { // Dispose managed resources. } // Call the appropriate methods to clean up // unmanaged resources here. // If disposing is false, // only the following code is executed. //spContainer.Children.Clear(); Player = null; // Note disposing has been done. Disposed = true; } } public override void Push() { _currentInset++; } public override void Pop() { _currentInset = Math.Max(0, _currentInset - 1); } public override void End() { } private string DepthPrefix { get { var sb = new StringBuilder(); for (var c = 0; c < _currentInset; c++) sb.Append("... "); return sb.ToString(); } } public override void New(IPlayer player, List playerBrushes, IDisplayable grantedBy) { Player = new DominionBase.Visual.VisualPlayer(player); _currentInset = 0; if (!Equals(playerBrushes[0], Brushes.Transparent)) { Background = playerBrushes[1]; BorderBrush = playerBrushes[2]; } Utilities.Log(LogFile, $"{player} starting turn{(grantedBy == null ? "" : $" from {grantedBy.Name}")}"); var dp = new DockPanel(); var tbPlayerName = new TextBlock { Text = player.Name, FontWeight = FontWeights.Bold }; DockPanel.SetDock(tbPlayerName, Dock.Left); dp.Children.Add(tbPlayerName); tbPlayerName = new TextBlock { Text = " starting turn" }; DockPanel.SetDock(tbPlayerName, Dock.Left); dp.Children.Add(tbPlayerName); if (grantedBy != null) { var tbGrantedBy = new TextBlock { Text = " granted by " }; DockPanel.SetDock(tbGrantedBy, Dock.Left); dp.Children.Add(tbGrantedBy); var icon = CardIconUtilities.CreateCardIcon(grantedBy); DockPanel.SetDock(icon, Dock.Left); dp.Children.Add(icon); var tbBlank = new TextBlock(); DockPanel.SetDock(tbBlank, Dock.Left); dp.Children.Add(tbBlank); } expTurn.Header = dp; } public override void Log(DominionBase.Visual.VisualPlayer player, List playerBrushes, params object[] items) { var sbFullLine = new StringBuilder(); var tvi = new TreeViewItem { Margin = new Thickness(0), Padding = new Thickness(0) }; var dpContainer = new DockPanel { LastChildFill = true }; var tb = new TextBlock { Text = "\u2022" }; DockPanel.SetDock(tb, Dock.Left); dpContainer.Children.Add(tb); var container = new WrapPanel { Orientation = System.Windows.Controls.Orientation.Horizontal }; DockPanel.SetDock(container, Dock.Left); dpContainer.Children.Add(container); sbFullLine.Append(DepthPrefix); foreach (var item in items) { if (item is string s) { foreach (var elem in Utilities.RenderText(s, NET_WPF.RenderSize.Tiny, true)) { if (elem is TextBlock block) block.VerticalAlignment = VerticalAlignment.Center; container.Children.Add(elem); } sbFullLine.Append(item); } else if (item is Currency iCurr) { foreach (var elem in Utilities.RenderText(iCurr.ToStringInline(), NET_WPF.RenderSize.Tiny, true)) { if (elem is TextBlock block) block.VerticalAlignment = VerticalAlignment.Center; container.Children.Add(elem); } sbFullLine.Append(Utilities.RenderText(iCurr.ToStringInline())); } else if (item is DominionBase.Currencies.CurrencyBase iCurrBase) { foreach (var elem in Utilities.RenderText(iCurrBase.ToString(), NET_WPF.RenderSize.Tiny, true)) { if (elem is TextBlock block) block.VerticalAlignment = VerticalAlignment.Center; container.Children.Add(elem); } sbFullLine.Append(Utilities.RenderText(iCurrBase.ToString())); } else { if (item is Player itemPlayer) { var lineVisualPlayer = new DominionBase.Visual.VisualPlayer(itemPlayer); var tbLine = new TextBlock { Text = lineVisualPlayer.Name, VerticalAlignment = VerticalAlignment.Center }; if (lineVisualPlayer.PlayerUniqueId != Player.PlayerUniqueId) tbLine.FontWeight = FontWeights.Bold; container.Children.Add(tbLine); sbFullLine.Append(lineVisualPlayer.Name); } else if (item is DominionBase.Visual.VisualPlayer iVisual) { var tbLine = new TextBlock { Text = iVisual.Name, VerticalAlignment = VerticalAlignment.Center }; if (iVisual.PlayerUniqueId != Player.PlayerUniqueId) tbLine.FontWeight = FontWeights.Bold; container.Children.Add(tbLine); sbFullLine.Append(iVisual.Name); } else if (item is IDisplayable iDisp) { var icon = CardIconUtilities.CreateCardIcon(iDisp); icon.VerticalAlignment = VerticalAlignment.Center; container.Children.Add(icon); sbFullLine.Append(iDisp.Name); } else if (item is IEnumerable iEDisp) { foreach (var userControl in CardIconUtilities.CreateCardIcons(iEDisp)) { var icon = (ucCardIcon)userControl; icon.VerticalAlignment = VerticalAlignment.Center; container.Children.Add(icon); if (icon.Count == 1) sbFullLine.Append(icon.Card.Name); else sbFullLine.AppendFormat("{0}x {1}", icon.Count, icon.Card.Name); var tbLine = new TextBlock { Text = ", ", VerticalAlignment = VerticalAlignment.Center }; container.Children.Add(tbLine); sbFullLine.Append(", "); } if (iEDisp.Any()) { container.Children.RemoveAt(container.Children.Count - 1); sbFullLine = sbFullLine.Remove(sbFullLine.Length - 2, 2); } } else if (item is IEnumerable iEToken) { var count = iEToken.Count(); var displayString = iEToken.First().LongDisplayString; if (count != 1) displayString = $"{count}x {displayString}"; var tbLine = new TextBlock { Text = displayString, VerticalAlignment = VerticalAlignment.Center }; container.Children.Add(tbLine); sbFullLine.Append(displayString); } else if (item is Token iToken) { var displayString = iToken.LongDisplayString; IList elements = Utilities.RenderText(displayString, NET_WPF.RenderSize.Medium, true); foreach (var element in elements) container.Children.Add(element); sbFullLine.Append(Utilities.RenderText(displayString)); } else if (item is Enum iEnum) { var displayString = EnumUtility.GetEnumDescription(iEnum); var tbLine = new TextBlock { Text = displayString, VerticalAlignment = VerticalAlignment.Center }; container.Children.Add(tbLine); sbFullLine.Append(displayString); } } } if (tvi.Background != null && container.Children.Count > 0) { if (container.Children.Count == 1) { if (container.Children[0] is TextBlock block) block.Padding = new Thickness(2, 1, 2, 1); else if (container.Children[0] is ucCardIcon cardIcon) cardIcon.Padding = new Thickness(2, 1, 2, 1); } else { if (container.Children[0] is TextBlock block) block.Padding = new Thickness(2, 1, 0, 1); else if (container.Children[0] is ucCardIcon cardIcon) cardIcon.Padding = new Thickness(2, 1, 0, 1); if (container.Children[container.Children.Count - 1] is TextBlock childBlock) childBlock.Padding = new Thickness(0, 1, 2, 1); else if (container.Children[container.Children.Count - 1] is ucCardIcon cardIcon) cardIcon.Padding = new Thickness(0, 1, 2, 1); } } // Need something to fill the remaining gap container.Children.Add(new Grid { VerticalAlignment = VerticalAlignment.Stretch }); Utilities.Log(LogFile, sbFullLine.ToString()); var level = _currentInset; var lItems = tvArea.Items; TreeViewItem tviParent = null; while (level > 0) { if (lItems[lItems.Count - 1] is TreeViewItem item) tviParent = item; else if (lItems[lItems.Count - 1] is TreeView tv) tviParent = (TreeViewItem)tv.Items[tv.Items.Count - 1]; if (tviParent != null) { tviParent.IsExpanded = true; lItems = tviParent.Items; } level--; } if (player.PlayerUniqueId == Player.PlayerUniqueId) { lItems.Add(tvi); tvi.Header = dpContainer; tvi.HorizontalAlignment = HorizontalAlignment.Stretch; } else { if (lItems.Count == 0 || !(lItems[lItems.Count - 1] is TreeView) || (lItems[lItems.Count - 1] is TreeView tv && !Equals(tv.Background, playerBrushes[0]))) { // This is pretty mess at the moment -- this is to detect nested Player stuff // (e.g. discarding Market Square when trashing a card and then revealing Watchtower to put the gained Gold on top of your deck) if (tviParent != null && (tviParent.Parent is TreeView tvp && Equals(tvp.Background, playerBrushes[0]) || (tviParent.Parent as TreeViewItem)?.Parent is TreeView tvpp && Equals(tvpp.Background, playerBrushes[0]))) lItems.Add(tvi); else { var tvNewPlayer = new TreeView { Background = playerBrushes[0], Margin = new Thickness(-19, 0, 0, 0) }; tvNewPlayer.Items.Add(tvi); lItems.Add(tvNewPlayer); } } else if (lItems[lItems.Count - 1] is TreeView tv2) { tv2.Items.Add(tvi); } else lItems.Add(tvi); tvi.Header = dpContainer; tvi.HorizontalAlignment = HorizontalAlignment.Stretch; } container.BringIntoView(); } private void tvArea_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { if (!(sender is TreeView treeView) || e.Handled) return; e.Handled = true; var mwea = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta) { RoutedEvent = MouseWheelEvent, Source = sender }; (treeView.Parent as UIElement)?.RaiseEvent(mwea); } } }