using Dominion.NET_WPF.Caching; using Dominion.NET_WPF.Enums; using Dominion.NET_WPF.Models; using DominionBase; using DominionBase.Cards; using DominionBase.Piles; using DominionBase.Players; using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using Visibility = System.Windows.Visibility; namespace Dominion.NET_WPF.Controls { /// /// Interaction logic for ucChooser.xaml /// public partial class ucChooser : UserControl { #region Dependency Properties public static readonly RoutedEvent ChooserOkClickEvent = EventManager.RegisterRoutedEvent( "ChooserOkClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ucChooser)); public static readonly DependencyProperty ChoiceProperty = DependencyProperty.Register("Choice", typeof(Choice), typeof(ucChooser), new UIPropertyMetadata(null)); public static readonly DependencyProperty CanPreselectProperty = DependencyProperty.Register("CanPreselect", typeof(bool), typeof(ucChooser), new UIPropertyMetadata(null)); #endregion public ucChooser() { InitializeComponent(); ((INotifyCollectionChanged)lbReorder.Items).CollectionChanged += LbReorder_CollectionChanged; } #region Properties public event RoutedEventHandler ChooserOkClick { add { AddHandler(ChooserOkClickEvent, value); } remove { RemoveHandler(ChooserOkClickEvent, value); } } private Guid _LastChoiceId = Guid.Empty; private ChoiceResult _LastChoiceResult; private readonly List _usedHotkeys = new List(); public AutoYieldCollection AutoYields { get; } = new AutoYieldCollection(); private List Yields = new List { "Always for {0}", "Never for {0}", "Always for {0} this turn", "No more for {0} this turn", "Always this turn", "No more this turn", "Always", "Never" }; public string Target { get; set; } public IPlayer Player { get; set; } public ChoiceResult ChoiceResult { get; private set; } public Choice Choice { get { return GetValue(ChoiceProperty) as Choice; } set { SetValue(ChoiceProperty, value); CanPreselect = value == null || (value.EventArgs == null && value.ChoiceType != ChoiceType.Supplies) || value.Options == null || value.Options.Any(o => o.IsRequired) ; } } public bool? CanPreselect { get { return GetValue(CanPreselectProperty) as bool?; } set { SetValue(CanPreselectProperty, value); } } public List SupplyControls { get; set; } = new List(); public bool IsReady { set { ChoiceResult = null; if (!value) { Player = null; Choice = null; ChoiceResult = null; SupplyControls.Clear(); } if (value && Choice != null) { tbText.Text = string.Empty; wrapPanel1.Visibility = Visibility.Visible; wrapPanel1.Children.Clear(); bReorder.Visibility = bCardPool.Visibility = lbCardPool.Visibility = Visibility.Collapsed; lbReorder.DataContext = null; bHidden.Visibility = Visibility.Collapsed; lbHidden.DataContext = null; wpButtons.Visibility = bButtonDiv.Visibility = Visibility.Visible; bNone.Visibility = Visibility.Visible; bAll.Visibility = Visibility.Collapsed; bOK.IsEnabled = false; if (Choice.EventArgs is AttackedEventArgs args) tbText.Text = string.Format("{1} played {2}{0}", Environment.NewLine, args.Attacker, args.AttackCard); foreach (var sc in SupplyControls) sc.Clickability = SupplyVisibility.Plain; tbText.Text += $"{Player}, {Utilities.RenderText(Choice.Text)}"; switch (Choice.ChoiceType) { case ChoiceType.Options: ChoiceResult = new ChoiceResult(new List()); _usedHotkeys.Clear(); foreach (var option in Choice.Options) { var optionPreText = string.Empty; var optionShortcut = string.Empty; var optionText = option.Text; var shortcutIndex = FindShortcutIndex(option.Text); if (shortcutIndex >= 0) { optionPreText = option.Text.Substring(0, shortcutIndex); optionShortcut = $"_{option.Text.Substring(shortcutIndex, 1)}"; optionText = option.Text.Substring(shortcutIndex + 1); } wrapPanel1.Children.Add(CreateButton(option, Choice.EventArgs, option.IsRequired, buttonTexts: new string[] { optionPreText, optionShortcut, optionText })); } if (Choice.Maximum > 1 && Choice.Maximum >= wrapPanel1.Children.Count) bAll.Visibility = Visibility.Visible; break; case ChoiceType.Cards: ChoiceResult = new ChoiceResult(new CardCollection()); if (!Choice.IsOrdered) { foreach (var card in Choice.Cards) { if (card is DominionBase.Cards.Universal.Blank) { var bDivider = new Border { BorderBrush = Brushes.BlueViolet, BorderThickness = new Thickness(2), Margin = new Thickness(4) }; wrapPanel1.Children.Add(bDivider); } else { wrapPanel1.Children.Add(CreateCardButton(card)); } } if (Choice.Maximum > 1 && Choice.Maximum >= wrapPanel1.Children.OfType().Count()) bAll.Visibility = Visibility.Visible; } else { wrapPanel1.Visibility = Visibility.Collapsed; ViewModel.CardListViewModel clvmHidden; switch (Choice.Visibility) { case DominionBase.Piles.Visibility.All: bReorder.Visibility = Visibility.Visible; if (Choice.Cards.Count() == Choice.Minimum) { var clvm = new ViewModel.CardListViewModel(); clvm.ShowCards(Choice.Cards, Choice.Visibility); lbReorder.DataContext = clvm; } else { bCardPool.Visibility = lbCardPool.Visibility = Visibility.Visible; var clvmReorder = new ViewModel.CardListViewModel(); clvmReorder.ShowCards(new CardCollection(), Choice.Visibility); lbReorder.DataContext = clvmReorder; var clvmPool = new ViewModel.CardListViewModel { PreserveSourceOrdering = true }; clvmPool.ShowCards(Choice.Cards, Choice.Visibility); lbCardPool.DataContext = clvmPool; } if (lbReorder.Items.Count >= Choice.Minimum && lbReorder.Items.Count <= Choice.Maximum) bOK.IsEnabled = true; else bOK.IsEnabled = false; break; case DominionBase.Piles.Visibility.Top: bHidden.Visibility = Visibility.Visible; clvmHidden = new ViewModel.CardListViewModel(); clvmHidden.ShowCards(Choice.Cards, Choice.Visibility); lbHidden.DataContext = clvmHidden; if (lbHidden.Items.Count >= Choice.Minimum && lbHidden.Items.Count <= Choice.Maximum) bOK.IsEnabled = true; else bOK.IsEnabled = false; break; case DominionBase.Piles.Visibility.None: bHidden.Visibility = Visibility.Visible; var showCards = Choice.Cards; if (WMain.Settings?.ChooserAutomaticallyMoveStashToTop == true && Choice.Text == ResourcesHelper.Get("RearrangeShuffledCards") && Choice.Cards.Any(c => c is DominionBase.Cards.Promotional.Stash || c is DominionBase.Cards.Promotional2ndEdition.Stash )) { showCards = new CardCollection(Choice.Cards.OrderByDescending(card => card is DominionBase.Cards.Promotional.Stash || card is DominionBase.Cards.Promotional2ndEdition.Stash)); } clvmHidden = new ViewModel.CardListViewModel(); clvmHidden.ShowCards(showCards, Choice.Visibility); lbHidden.DataContext = clvmHidden; if (lbHidden.Items.Count >= Choice.Minimum && lbHidden.Items.Count <= Choice.Maximum) bOK.IsEnabled = true; else bOK.IsEnabled = false; break; } // "All" & "None" aren't valid for this case, either cbAutoClick.Visibility = bButtonDiv.Visibility = Visibility.Collapsed; bAll.Visibility = bNone.Visibility = Visibility.Collapsed; } break; case ChoiceType.Supplies: var tbSupplyNotification = new TextBlock { Text = "<-- Select a Supply pile to the left", FontSize = 14 }; wrapPanel1.Children.Add(tbSupplyNotification); foreach (var sc in SupplyControls) { if (Choice.Supplies.Values.Contains(sc.Supply)) { if (Choice.Source.Type == DominionBase.Cards.Seaside.TypeClass.Embargo || Choice.Source.Type == DominionBase.Cards.Seaside2ndEdition.TypeClass.Embargo //|| Choice.Source.Type == DominionBase.Cards.Seaside2019Errata.TypeClass.Embargo || Choice.Source.Type == DominionBase.Cards.DarkAges.TypeClass.BandOfMisfits || Choice.Source.Type == DominionBase.Cards.DarkAges2ndEdition.TypeClass.BandOfMisfits //|| Choice.Source.Type == DominionBase.Cards.DarkAges2019Errata.TypeClass.BandOfMisfits || Choice.Source.Type == DominionBase.Cards.Adventures.TypeClass.Ferry //|| _Choice.Source.Type == DominionBase.Cards.Adventures.TypeClass.Inheritance || Choice.Source.Type == DominionBase.Cards.Adventures.TypeClass.LostArts || Choice.Source.Type == DominionBase.Cards.Adventures.TypeClass.Pathfinding || Choice.Source.Type == DominionBase.Cards.Adventures.TypeClass.Plan || Choice.Source.Type == DominionBase.Cards.Adventures.TypeClass.Seaway || Choice.Source.Type == DominionBase.Cards.Adventures.TypeClass.Teacher || Choice.Source.Type == DominionBase.Cards.Adventures.TypeClass.Training || Choice.Source.Type == DominionBase.Cards.Adventures2ndEdition.TypeClass.Ferry //|| _Choice.Source.Type == DominionBase.Cards.Adventures2ndEdition.TypeClass.Inheritance || Choice.Source.Type == DominionBase.Cards.Adventures2ndEdition.TypeClass.LostArts || Choice.Source.Type == DominionBase.Cards.Adventures2ndEdition.TypeClass.Pathfinding || Choice.Source.Type == DominionBase.Cards.Adventures2ndEdition.TypeClass.Plan || Choice.Source.Type == DominionBase.Cards.Adventures2ndEdition.TypeClass.Seaway || Choice.Source.Type == DominionBase.Cards.Adventures2ndEdition.TypeClass.Training || Choice.Source.Type == DominionBase.Cards.Empires.TypeClass.Overlord || Choice.Source.Type == DominionBase.Cards.Empires.TypeClass.SaltTheEarth //|| Choice.Source.Type == DominionBase.Cards.Empires2019Errata.TypeClass.Overlord ) sc.Clickability = SupplyVisibility.Selectable; else sc.Clickability = SupplyVisibility.Gainable; sc.SupplyClick += SupplyControl_SupplyClick; } else sc.Clickability = SupplyVisibility.NotClickable; } cbAutoClick.IsChecked = true; if (Choice.Minimum > 0) wpButtons.Visibility = Visibility.Collapsed; break; case ChoiceType.SuppliesAndCards: foreach (var card in Choice.Cards) wrapPanel1.Children.Add(CreateCardButton(card)); var tbSupplyCardNotification = new TextBlock { Text = "<-- Select a Supply pile to the left" }; if (Choice.Cards.Any()) tbSupplyCardNotification.Text += " or a card above"; tbSupplyCardNotification.FontSize = 14; wrapPanel1.Children.Add(tbSupplyCardNotification); foreach (var sc in SupplyControls) { if (Choice.Supplies.Values.Contains(sc.Supply)) { if (Choice.Source.Type == DominionBase.Cards.Intrigue.TypeClass.WishingWell || Choice.Source.Type == DominionBase.Cards.Intrigue2ndEdition.TypeClass.WishingWell || Choice.Source.Type == DominionBase.Cards.Prosperity.TypeClass.Contraband || Choice.Source.Type == DominionBase.Cards.DarkAges.TypeClass.BandOfMisfits || Choice.Source.Type == DominionBase.Cards.DarkAges.TypeClass.Mystic || Choice.Source.Type == DominionBase.Cards.DarkAges.TypeClass.Rebuild || Choice.Source.Type == DominionBase.Cards.DarkAges2ndEdition.TypeClass.BandOfMisfits || Choice.Source.Type == DominionBase.Cards.DarkAges2ndEdition.TypeClass.Mystic || Choice.Source.Type == DominionBase.Cards.DarkAges2ndEdition.TypeClass.Rebuild //|| Choice.Source.Type == DominionBase.Cards.DarkAges2019Errata.TypeClass.BandOfMisfits || Choice.Source.Type == DominionBase.Cards.Guilds.TypeClass.Doctor || Choice.Source.Type == DominionBase.Cards.Guilds.TypeClass.Journeyman || Choice.Source.Type == DominionBase.Cards.Guilds2ndEdition.TypeClass.Doctor || Choice.Source.Type == DominionBase.Cards.Guilds2ndEdition.TypeClass.Journeyman || Choice.Source.Type == DominionBase.Cards.Empires.TypeClass.Overlord //|| Choice.Source.Type == DominionBase.Cards.Empires2019Errata.TypeClass.Overlord ) sc.Clickability = SupplyVisibility.Selectable; else sc.Clickability = SupplyVisibility.Gainable; sc.SupplyClick += SupplyControl_SupplyClick; } else sc.Clickability = SupplyVisibility.NotClickable; } cbAutoClick.IsChecked = true; if (Choice.Minimum > 0) wpButtons.Visibility = Visibility.Collapsed; break; case ChoiceType.Boons: foreach (var boon in Choice.Boons) wrapPanel1.Children.Add(CreateCardButton(boon)); if (Choice.Maximum > 1 && Choice.Maximum >= wrapPanel1.Children.OfType().Count()) bAll.Visibility = Visibility.Visible; break; } bMain.Background = BrushRepository.GetOutcomeBrush(Choice.ChoiceOutcome); bMain.BorderBrush = BrushRepository.GetOutcomeBrush(Choice.ChoiceOutcome, true); if (wrapPanel1.Visibility == Visibility.Visible) { bNone.Visibility = Choice.Minimum == 0 ? Visibility.Visible : Visibility.Collapsed; if ((bAll.Visibility == Visibility.Collapsed && bNone.Visibility == Visibility.Collapsed) || (bOK.Visibility == Visibility.Collapsed && cbAutoClick.Visibility == Visibility.Collapsed)) bButtonDiv.Visibility = Visibility.Collapsed; else bButtonDiv.Visibility = Visibility.Visible; } if (WMain.Settings != null && cbAutoClick.Visibility == Visibility.Visible) cbAutoClick.IsChecked = WMain.Settings.ChooserAutomaticallyClickWhenSatisfied; FilterAutoYields(); // Automatic chooser clicking! if (WMain.Settings != null && WMain.Settings.ChooserAutomaticallyRevealMoat && Choice.EventArgs is AttackedEventArgs && Choice.ChoiceType == ChoiceType.Cards && Choice.Text == ResourcesHelper.Get("ShouldReveal") && Choice.Cards.Any(c => c is DominionBase.Cards.Base.Moat || c is DominionBase.Cards.Base2ndEdition.Moat )) { var icbMoat = wrapPanel1.Children.OfType().FirstOrDefault( icb => icb.Card is Card && (icb.Card.Type == DominionBase.Cards.Base.TypeClass.Moat || icb.Card.Type == DominionBase.Cards.Base2ndEdition.TypeClass.Moat) ); if (icbMoat != null) { cbAutoClick.IsChecked = true; icbMoat.IsChecked = true; ToggleButton_Checked(icbMoat, null); } } else if (WMain.Settings != null && WMain.Settings.ChooserAutomaticallyRevealProvince && Choice.EventArgs == null && Choice.Source != null && (Choice.Source.Type == DominionBase.Cards.Cornucopia.TypeClass.Tournament || Choice.Source.Type == DominionBase.Cards.Cornucopia2ndEdition.TypeClass.Tournament) && Choice.ChoiceType == ChoiceType.Options && Choice.Text == "Do you want to reveal a Province from your hand?") { var tbYes = wrapPanel1.Children.OfType().FirstOrDefault( tb => ((Option)tb.Tag).Text == DominionBase.ResourcesHelper.Get("Yes")); if (tbYes != null) { cbAutoClick.IsChecked = true; tbYes.IsChecked = true; ToggleButton_Checked(tbYes, null); } } } } } #endregion Properties public void ClearAutoYields(AutoYieldDuration duration) { AutoYields.ClearByDuration(duration); } private void FilterAutoYields() { if (Choice.Options == null) return; var anyRequired = Choice.Options.Any(o => o.IsRequired); var children = wrapPanel1.Children.OfType().ToList(); foreach (var item in children) { if (item.Tag is Option option) { var action = AutoYields.GetAction(Choice.EventArgs.GetType(), option.Source.Type, option.Value, Choice.Triggers.FirstOrDefault()?.Type); switch (action) { case AutoYieldAction.Skip: wrapPanel1.Children.Remove(item); break; case AutoYieldAction.Yield: if (!anyRequired) SplitButton_Clicked(item, null); break; } } } if (!anyRequired && wrapPanel1.Children.Count == 0) BNone_Click(bNone, null); } private void ToggleButton_MouseLeave(object sender, MouseEventArgs e) { var button = (ToggleButton)sender; var option = (Option)button.Tag; HighlightSource(option.Source, HighlightMode.None); } private void ToggleButton_MouseEnter(object sender, MouseEventArgs e) { var button = (ToggleButton)sender; var option = (Option)button.Tag; HighlightSource(option.Source, HighlightMode.Primary); } private void tbText_MouseLeave(object sender, MouseEventArgs e) { HighlightSource(Choice.Triggers.FirstOrDefault() ?? Choice.Source, HighlightMode.None); } private void tbText_MouseEnter(object sender, MouseEventArgs e) { HighlightSource(Choice.Triggers.FirstOrDefault() ?? Choice.Source, HighlightMode.Primary); } private void HighlightSource(IGameObject source, HighlightMode mode) { Control gameObject = null; if (Window.GetWindow(this) is WMain window && source != null) gameObject = window.FindGameObject(source); if (gameObject is CardStackControl csc) csc.Highlight = mode; else if (gameObject is SupplyControl sc) sc.Highlight = mode; // Also highlight "ModifiedBy" chain if (source is Card card && card.ModifiedBy != null) HighlightSource(card.ModifiedBy, mode == HighlightMode.None ? HighlightMode.None : HighlightMode.Secondary); } private int FindShortcutIndex(string text) { var inTag = false; var inElement = false; // Scan through the text to make sure we're not in an XML-like element or tag definition // e.g. "5 Currency" would return 15, the index for 'C' for (var index = 0; index < text.Length; index++) { if (!inTag && text[index] == '<') { inTag = true; inElement = true; } if (inTag && text[index] == '>') inTag = false; if (inTag && text[index] == '/') inElement = false; if (inTag) continue; if ((char.IsUpper(text[index]) || (char.IsNumber(text[index]) && !inElement)) && !_usedHotkeys.Contains(text[index])) { _usedHotkeys.Add(text[index]); return index; } } return -1; } private void SupplyControl_SupplyClick(object sender, RoutedEventArgs e) { if ((e.Source as SupplyControl)?.Supply is Supply supply) { bOK.IsEnabled = false; ChoiceResult = new ChoiceResult(supply); if (ChoiceResult != null) bOK.IsEnabled = true; if (bOK.IsEnabled && ChoiceResult.Supply != null && cbAutoClick.IsChecked == true) BOK_Click(bOK, null); } } private void SplitButton_Clicked(object sender, RoutedEventArgs e) { if (sender is SplitButton button && button.Tag is Option option) { ChoiceResult = new ChoiceResult(new List { option.Text }); BOK_Click(bOK, null); } } private void ToggleButton_Checked(object sender, RoutedEventArgs e) { bool? isChecked = false; object tag = (sender as FrameworkElement)?.Tag; if (sender is ToggleButton button) isChecked = button.IsChecked; else if (sender is ucICardButton icb) isChecked = icb.IsChecked; bOK.IsEnabled = false; switch (Choice.ChoiceType) { case ChoiceType.Options: if (ChoiceResult == null) ChoiceResult = new ChoiceResult(new List()); var option = ((Option)tag)?.Text; if (Choice.Maximum == 1) { foreach (var chkdToggleButton in wrapPanel1.Children.OfType().Where(tb => ChoiceResult.Options.Contains(((Option)tb.Tag).Text))) { chkdToggleButton.IsChecked = false; ChoiceResult.Options.Remove(((Option)chkdToggleButton.Tag).Text); } } if (isChecked == true) ChoiceResult.Options.Add(option); else if (ChoiceResult.Options.Contains(option)) ChoiceResult.Options.Remove(option); if ((Choice.Minimum > 0 || ChoiceResult.Options.Any()) && ChoiceResult.Options.Count >= Choice.Minimum && ChoiceResult.Options.Count <= Choice.Maximum) bOK.IsEnabled = true; break; case ChoiceType.Cards: case ChoiceType.SuppliesAndCards: //case DominionBase.ChoiceType.Pile: if (ChoiceResult == null) ChoiceResult = new ChoiceResult(new CardCollection()); var card = tag as Card; if (isChecked == true) ChoiceResult.Cards.Add(card); else if (ChoiceResult.Cards.Contains(card)) ChoiceResult.Cards.Remove(card); if ((Choice.Minimum > 0 || ChoiceResult.Cards.Any()) && ChoiceResult.Cards.Count >= Choice.Minimum && ChoiceResult.Cards.Count <= Choice.Maximum) bOK.IsEnabled = true; break; case ChoiceType.Supplies: ChoiceResult = isChecked == true ? new ChoiceResult(tag as Supply) : null; if (ChoiceResult != null) bOK.IsEnabled = true; break; case ChoiceType.Boons: if (ChoiceResult == null) ChoiceResult = new ChoiceResult(new ItemCollection()); var boon = tag as IBoon; if (isChecked == true) ChoiceResult.Boons.Add(boon); else if (ChoiceResult.Boons.Contains(boon)) ChoiceResult.Boons.Remove(boon); if ((Choice.Minimum > 0 || ChoiceResult.Boons.Any()) && ChoiceResult.Boons.Count >= Choice.Minimum && ChoiceResult.Boons.Count <= Choice.Maximum) bOK.IsEnabled = true; break; } foreach (var control in wrapPanel1.Children.OfType()) { var pButtonText = (Panel)((Border)control.Content).Child; var option = ((Option)control.Tag).Text; if (Choice.IsOrdered) { pButtonText.Visibility = Visibility.Visible; var ordinal = string.Empty; switch (Choice.ChoiceType) { case ChoiceType.Options: if (ChoiceResult?.Options.Contains(option) == true) ordinal = Utilities.Ordinal(ChoiceResult.Options.IndexOf(option) + 1); break; } if (pButtonText.Children[0] is TextBlock textBlock) textBlock.Text = ordinal != string.Empty ? $"{ordinal}: " : string.Empty; } } foreach (var control in wrapPanel1.Children.OfType()) { var card = control.Tag as Card; if (Choice.IsOrdered) { switch (Choice.ChoiceType) { case ChoiceType.Cards: //case DominionBase.ChoiceType.Pile: if (ChoiceResult.Cards.Contains(card)) control.Order = ChoiceResult.Cards.IndexOf(card) + 1; else control.Order = 0; break; } } } if (bOK.IsEnabled && (ChoiceResult.Supply != null || (ChoiceResult.Cards != null && (ChoiceResult.Cards.Count == Choice.Maximum || ChoiceResult.Cards.Count == Choice.Cards.Count())) || (ChoiceResult.Options != null && (ChoiceResult.Options.Count == Choice.Maximum || ChoiceResult.Options.Count == Choice.Options.Count)) || (ChoiceResult.Boons != null && (ChoiceResult.Boons.Count == Choice.Maximum || ChoiceResult.Boons.Count == Choice.Boons.Count())) ) && cbAutoClick.IsChecked == true) BOK_Click(bOK, null); } private FrameworkElement CreateCardButton(IDisplayable card) { var icb = new ucICardButton { Tag = card, Card = card, IsOrdered = Choice.IsOrdered, }; icb.CardButtonClick += ToggleButton_Checked; return icb; } private FrameworkElement CreateButton(object tag, EventArgs eventArgs, bool isRequired = false, ICommand command = null, string[] buttonTexts = null) { var wp = new WrapPanel { Orientation = Orientation.Horizontal, VerticalAlignment = VerticalAlignment.Center }; var border = new Border { Padding = new Thickness(10, 0, 10, 0), Child = wp }; ToggleButton tb; if (eventArgs == null || isRequired) { tb = new ToggleButton { Command = command }; if (command == null) tb.Click += ToggleButton_Checked; } else { var cm = new ContextMenu { ItemsSource = Yields.Select(y => new MenuItem { Header = string.Format(y, Choice.Triggers.FirstOrDefault()?.Name ?? "card"), Tag = y }), Tag = tag }; cm.AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(Sbmi_Click)); tb = new SplitButton { MainButtonCommand = command, DropDownContextMenu = cm, }; if (command == null) tb.Click += SplitButton_Clicked; } tb.Margin = new Thickness(5, 0, 5, 0); tb.Height = double.NaN; tb.Width = double.NaN; tb.MinHeight = 40; tb.MinWidth = 40; tb.MaxHeight = 100; tb.MaxWidth = 200; tb.Background = (VisualBrush)FindResource("StandardBlueBrush"); tb.VerticalContentAlignment = VerticalAlignment.Stretch; tb.Content = border; tb.Tag = tag; tb.MouseEnter += ToggleButton_MouseEnter; tb.MouseLeave += ToggleButton_MouseLeave; if (isRequired) { border.BorderThickness = new Thickness(2); border.BorderBrush = Brushes.Crimson; } else { tb.ToolTip = "Optional"; } if (buttonTexts != null) { var buttonText = new TextBlock { TextWrapping = TextWrapping.Wrap }; if (!string.IsNullOrEmpty(buttonTexts[0])) { var temp = (TextBlock)Utilities.RenderText(buttonTexts[0], NET_WPF.RenderSize.Small, false)[0]; buttonText.Inlines.AddRange(temp.Inlines.ToList()); } if (!string.IsNullOrEmpty(buttonTexts[1])) { buttonText.Inlines.Add(new Run(buttonTexts[1].Substring(1)) { FontWeight = FontWeights.Bold, Foreground = Brushes.Crimson, TextDecorations = TextDecorations.Underline }); } if (!string.IsNullOrEmpty(buttonTexts[2])) { var temp = (TextBlock)Utilities.RenderText(buttonTexts[2], NET_WPF.RenderSize.Small, false)[0]; buttonText.Inlines.AddRange(temp.Inlines.ToList()); } wp.Children.Add(new AccessText { Width = 0, Text = buttonTexts[1] }); wp.Children.Add(buttonText); } //else // //tb.Command = command; // tb.MainButtonCommand = command; return tb; } private void Sbmi_Click(object sender, RoutedEventArgs e) { if (e.OriginalSource is MenuItem item && sender is ContextMenu cm && cm.Tag is Option option) { switch ((string)item.Tag) { case "Always for {0}": AutoYields.Add(new AutoYield { Event = Choice.EventArgs.GetType(), Duration = AutoYieldDuration.Game, Action = AutoYieldAction.Yield, Source = option.Source.Type, SourceValue = option.Value, Target = Choice.Triggers.FirstOrDefault()?.Type }); break; case "Never for {0}": AutoYields.Add(new AutoYield { Event = Choice.EventArgs.GetType(), Source = option.Source.Type, SourceValue = option.Value, Duration = AutoYieldDuration.Game, Action = AutoYieldAction.Skip, Target = Choice.Triggers.FirstOrDefault()?.Type }); break; case "Always for {0} this turn": AutoYields.Add(new AutoYield { Event = Choice.EventArgs.GetType(), Duration = AutoYieldDuration.Turn, Action = AutoYieldAction.Yield, Source = option.Source.Type, SourceValue = option.Value, Target = Choice.Triggers.FirstOrDefault()?.Type }); break; case "No more for {0} this turn": AutoYields.Add(new AutoYield { Event = Choice.EventArgs.GetType(), Source = option.Source.Type, SourceValue = option.Value, Duration = AutoYieldDuration.Turn, Action = AutoYieldAction.Skip, Target = Choice.Triggers.FirstOrDefault()?.Type }); break; case "Always this turn": AutoYields.Add(new AutoYield { Event = Choice.EventArgs.GetType(), Source = option.Source.Type, SourceValue = option.Value, Duration = AutoYieldDuration.Turn, Action = AutoYieldAction.Yield, Target = null }); break; case "No more this turn": AutoYields.Add(new AutoYield { Event = Choice.EventArgs.GetType(), Source = option.Source.Type, SourceValue = option.Value, Duration = AutoYieldDuration.Turn, Action = AutoYieldAction.Skip, Target = null }); break; case "Always": AutoYields.Add(new AutoYield { Event = Choice.EventArgs.GetType(), Source = option.Source.Type, SourceValue = option.Value, Duration = AutoYieldDuration.Game, Action = AutoYieldAction.Yield, Target = null }); break; case "Never": AutoYields.Add(new AutoYield { Event = Choice.EventArgs.GetType(), Source = option.Source.Type, SourceValue = option.Value, Duration = AutoYieldDuration.Game, Action = AutoYieldAction.Skip, Target = null }); break; default: return; } FilterAutoYields(); } } private void BOK_Click(object sender, RoutedEventArgs e) { ((UIElement)sender).IsEnabled = false; if (ChoiceResult == null) ChoiceResult = new ChoiceResult(); if (bReorder.Visibility == Visibility.Visible) { ChoiceResult = new ChoiceResult(new CardCollection()); // Must add the cards back in reverse order var cardViewModels = (lbReorder.DataContext as ViewModel.CardListViewModel)?.Cards.Reverse(); if (cardViewModels != null) foreach (var cvm in cardViewModels) ChoiceResult.Cards.Add(cvm.Card); } else if (bHidden.Visibility == Visibility.Visible) { ChoiceResult = new ChoiceResult(new CardCollection()); // Must add the cards back in reverse order var cardViewModels = (lbHidden.DataContext as ViewModel.CardListViewModel)?.Cards.Reverse(); if (cardViewModels != null) foreach (var cvm in cardViewModels) ChoiceResult.Cards.Add(cvm.Card); } foreach (var sc in SupplyControls) sc.SupplyClick -= SupplyControl_SupplyClick; _LastChoiceId = Choice.UniqueId; _LastChoiceResult = ChoiceResult; RaiseEvent(new RoutedEventArgs(ChooserOkClickEvent)); ((UIElement)sender).IsEnabled = true; } private void BNone_Click(object sender, RoutedEventArgs e) { cbAutoClick.IsChecked = false; foreach (FrameworkElement control in wrapPanel1.Children) { if (control is ToggleButton button) { button.IsChecked = false; ToggleButton_Checked(control, null); } else if (control is ucICardButton cb) { cb.IsChecked = false; ToggleButton_Checked(control, null); } } BOK_Click(bOK, null); } private void BAll_Click(object sender, RoutedEventArgs e) { cbAutoClick.IsChecked = false; foreach (FrameworkElement control in wrapPanel1.Children) { if (control is ToggleButton button) button.IsChecked = false; else if (control is ucICardButton cb) cb.IsChecked = false; ToggleButton_Checked(control, null); } foreach (FrameworkElement control in wrapPanel1.Children) { if (control is ToggleButton button) button.IsChecked = true; else if (control is ucICardButton cb) cb.IsChecked = true; ToggleButton_Checked(control, null); } BOK_Click(bOK, null); } private void LbReorder_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { if (Choice == null) return; if (((ItemCollection)sender).Count >= Choice.Minimum && ((ItemCollection)sender).Count <= Choice.Maximum) bOK.IsEnabled = true; else bOK.IsEnabled = false; } private void LbCardPool_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if ((e.Source as ListBox)?.SelectedItem != null) { var item = ((ListBox)e.Source).SelectedItem; var list = ((ListBox)e.Source).ItemsSource as IList; list?.Remove(item); (lbReorder.ItemsSource as IList)?.Add(item); } } private void LbReorder_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if ((e.Source as ListBox)?.SelectedItem != null && lbCardPool.Visibility == Visibility.Visible) { var item = ((ListBox)e.Source).SelectedItem; var list = ((ListBox)e.Source).ItemsSource as IList; list?.Remove(item); (lbCardPool.ItemsSource as IList)?.Add(item); } } } }