using Dominion.NET_WPF.Caching; using Dominion.NET_WPF.Controls; using DominionBase.Cards; using DominionBase.Enums; using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; namespace Dominion.NET_WPF { /// /// Interaction logic for wSettings.xaml /// public partial class wSettings : Window { private readonly Settings _masterSettings; public DisplayObjects CardObjects; public DisplayObjects LandscapeCardObjects; public Settings Settings { get; private set; } public wSettings(ref Settings settings) { _masterSettings = settings; Settings = new Settings(settings); CardObjects = new DisplayObjects(c => c.Location == Location.Kingdom, settings.EditionUsage); LandscapeCardObjects = new DisplayObjects(c => c.Location == Location.LandscapeCard, settings.EditionUsage); //this.DataContext = this.Settings; InitializeComponent(); #region Tab #1 -- Players slidNumPlayers.Value = Settings.NumberOfPlayers; slidHumanPlayers.Value = Settings.NumberOfHumanPlayers; var aiTypes = DominionBase.Players.PlayerCollection.GetAllAIs().ToList(); var playerSettings = spPlayers.Children.OfType().ToList(); for (var count = 0; count < Settings.PlayerSettings.Count; count++) { playerSettings.ElementAt(count).AITypes = aiTypes; playerSettings.ElementAt(count).PlayerSettings = Settings.PlayerSettings[count]; } // For now, limit the number of human players to 1 slidHumanPlayers.Maximum = 1; slidNumPlayers_ValueChanged(slidNumPlayers, null); slidHumanPlayers_ValueChanged(slidHumanPlayers, null); lbAISelection.DataContext = new ViewModel.AIListViewModel(aiTypes.Where(t => t != typeof(DominionBase.Players.AI.RandomAI)), settings.RandomAIAllowedAIs); lbAISelection.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("AIs")); cbAISpeed.SelectedValue = Settings.AISpeed; #endregion #region Tab #2 -- Automation if (Settings.AutoPlayTreasuresLoanFirst) rbChooser_AutomaticallyPlayTreasuresLoanBeforeVenture.IsChecked = true; else rbChooser_AutomaticallyPlayTreasuresVentureBeforeLoan.IsChecked = true; if (Settings.AutoPlayTreasuresHornOfPlentyFirst) rbChooser_AutomaticallyPlayTreasuresHornOfPlentyBeforeBank.IsChecked = true; else rbChooser_AutomaticallyPlayTreasuresBankBeforeHornOfPlenty.IsChecked = true; #endregion #region Tab #3 -- Interface cbLayoutStyle.SelectedValue = Settings.LayoutStyle; cbGameLogLocation.SelectedValue = Settings.GameLogLocation; slidToolTipDuration_ValueChanged(slidToolTipDuration, null); sbpBackground.Clear(); if (!DesignerProperties.GetIsInDesignMode(this)) { var iRepo = ImageRepository.Acquire(); var path = iRepo.GetImagePath("background"); if (Directory.Exists(path)) { foreach (var filename in Directory.EnumerateFiles(path)) { try { var bgImage = iRepo.GetBitmapImage(filename, "background"); if (bgImage == null) continue; var bg = new ImageBrush(bgImage) { Stretch = Stretch.Fill, TileMode = TileMode.Tile, ViewportUnits = BrushMappingMode.Absolute }; bg.Viewport = new Rect(0, 0, bg.ImageSource.Height / 2, bg.ImageSource.Width / 2); sbpBackground.AddBrush(bg); } catch { } } } ImageRepository.Release(); } string brushLocation = null; if ((Settings.BackgroundBrush as ImageBrush)?.ImageSource is BitmapImage image) brushLocation = image.SourcePath(); Brush bgBrush = null; if (brushLocation != null) { bgBrush = sbpBackground.AvailableBrushes.FirstOrDefault(b => (b as ImageBrush)?.ImageSource is BitmapImage im && im.SourcePath() == brushLocation); if (bgBrush != null) sbpBackground.SelectedItem = bgBrush; } if (bgBrush == null && sbpBackground.AvailableBrushes.Any()) sbpBackground.SelectedItem = sbpBackground.AvailableBrushes.First(); #endregion #region Tab #4 -- Kingdom Card Setup cbUsePreset.IsChecked = Settings.UsePreset; cbShowPresetCards.IsChecked = Settings.SettingsShowPresetCards; cbUsePreset_Checked(cbUsePreset, null); cbShowPresetCards_Checked(cbShowPresetCards, null); cbPresets.ItemsSource = Settings.Presets; cbPresets.SelectedItem = Settings.Presets.SingleOrDefault(p => p.Name == Settings.PresetName); #endregion #region Tab #5 -- Landscape Card Setup ucccLandscapeCardConstraints.DisplayObjects = LandscapeCardObjects; ucccLandscapeCardConstraints.ConstraintCollection = Settings.LandscapeCardConstraints; #endregion #region Tab #6 -- Kingdom Card Constraints ucccConstraints.DisplayObjects = CardObjects; ucccConstraints.ConstraintCollection = Settings.Constraints; #endregion #region Tab #7 -- Card Settings foreach (var cardsSettings in Settings.CardSettings) icCardSettings.Items.Add(new ucCardSettings { CardsSettings = cardsSettings, DisplayObjects = CardObjects }); #endregion #region Tab #8 -- Set & Trait Information var sets = Enum.GetValues(typeof(Source)).Cast(); cbSet.ItemsSource = sets.Where(s => s != Source.All); var categories = Enum.GetValues(typeof(Categories)).Cast(); cbCategory.ItemsSource = categories.Where(c => c != Categories.Unknown && c != Categories.Card && (CardObjects.Cards.Any(card => card.Category.HasFlag(c)) || LandscapeCardObjects.Cards.Any(card => card.Category.HasFlag(c)) ) ); cbTrait.ItemsSource = CardObjects.Trait.OrderBy(kvp => (int)kvp.Key); #endregion } private void slidNumPlayers_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { var slider = sender as Slider; if (tbPlayersNum != null) tbPlayersNum.Text = slider?.Value.ToString(); if (Settings != null) { if (slidHumanPlayers != null) { if (slider != null) { Settings.NumberOfPlayers = (int)slider.Value; if (textBox1 != null) { if (Math.Abs(slider.Value - 1) < 0.001 && textBox1.Text.EndsWith("s")) textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length - 1); if (Math.Abs(slider.Value - 1) > 0.001 && !textBox1.Text.EndsWith("s")) textBox1.Text += "s"; } } slidHumanPlayers.Value = Settings.NumberOfHumanPlayers; slidHumanPlayers.Maximum = Settings.NumberOfPlayers; // For now, limit the number of human players to 1 slidHumanPlayers.Maximum = 1; } } } private void slidHumanPlayers_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { var slider = sender as Slider; if (tbPlayersHuman != null) tbPlayersHuman.Text = slider?.Value.ToString(); if (Settings != null) { if (textBox2 != null) { if (slider != null) { Settings.NumberOfHumanPlayers = (int)slider.Value; if (Math.Abs(slider.Value - 1) < 0.001 && textBox2.Text.EndsWith("s")) textBox2.Text = textBox2.Text.Remove(textBox2.Text.Length - 1); if (Math.Abs(slider.Value - 1) > 0.001 && !textBox2.Text.EndsWith("s")) textBox2.Text += "s"; } } if (spPlayers != null) { for (var count = 0; count < Settings.PlayerSettings.Count; count++) { var pt = DominionBase.Players.PlayerType.Computer; if (Settings.NumberOfHumanPlayers > count) pt = DominionBase.Players.PlayerType.Human; spPlayers.Children.OfType().ElementAt(count).PlayerType = pt; } } } } private void bOk_Click(object sender, RoutedEventArgs e) { var ucPSs = spPlayers.Children.OfType().ToList(); for (var count = 0; count < Settings.PlayerSettings.Count; count++) { Settings.PlayerSettings[count] = ucPSs.ElementAt(count).PlayerSettings; } Settings.RandomAIAllowedAIs.Clear(); Settings.RandomAIAllowedAIs.AddRange((lbAISelection.DataContext as ViewModel.AIListViewModel)?.AIs.Where(avm => avm.IsChecked).Select(avm => avm.AI.FullName)); Settings.AISpeed = (DominionBase.AISpeed)cbAISpeed.SelectedValue; Settings.LayoutStyle = (LayoutStyle)cbLayoutStyle.SelectedValue; Settings.GameLogLocation = (GameLogLocation)cbGameLogLocation.SelectedValue; _masterSettings.CopyFrom(Settings); DialogResult = true; Close(); } private void cbUsePreset_Checked(object sender, RoutedEventArgs e) { Settings.UsePreset = cbUsePreset.IsChecked == true; if (Settings.UsePreset) { gbCardConstraints.IsEnabled = gbLandscapeCardConstraints.IsEnabled = false; gbCardConstraints.ToolTip = gbLandscapeCardConstraints.ToolTip = "This section is disabled if you're using a preset"; } else { gbCardConstraints.IsEnabled = gbLandscapeCardConstraints.IsEnabled = true; gbCardConstraints.ToolTip = null; } } private void cbShowPresetCards_Checked(object sender, RoutedEventArgs e) { Settings.SettingsShowPresetCards = cbShowPresetCards.IsChecked == true; cbPresets_SelectionChanged(cbPresets, null); } private void slidToolTipDuration_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (tbToolTipDuration != null) { tbToolTipDuration.Text = ((int)Settings.ToolTipShowDuration / 1000).ToString(); tbToolTipExtra.Text = Settings.ToolTipShowDuration == ToolTipShowDuration.Off ? "(Off)" : string.Empty; } } private void cbToolTipClick_Checked(object sender, RoutedEventArgs e) { if ((sender as CheckBox)?.IsChecked == true) slidToolTipDuration.Value = 1; } private void cbPresets_SelectionChanged(object sender, SelectionChangedEventArgs e) { var selectedPreset = (sender as ComboBox)?.SelectedItem as Preset; if (selectedPreset != null) Settings.PresetName = selectedPreset.Name; if (selectedPreset == null || !Settings.SettingsShowPresetCards) { olCardsUsed.Objects = null; olCardsUsed.Visibility = Visibility.Collapsed; } else { var cardTokenObjects = new List(selectedPreset.Cards.OrderBy(card => card.Location == Location.Kingdom ? 1 : 0).ThenBy(card => card.Name)); foreach (var randomizable in selectedPreset.CardCards.Keys) { var specialCard = (Card) randomizable; if (specialCard is DominionBase.Cards.Cornucopia.YoungWitch) { cardTokenObjects.Add(null); cardTokenObjects.Add(new DominionBase.Cards.Cornucopia.BaneMarker()); cardTokenObjects.AddRange(selectedPreset.CardCards[specialCard]); } } if (selectedPreset.ColonyPlatinumSelected == DominionBase.ColonyPlatinumSelected.Yes) { cardTokenObjects.Add(new DominionBase.Cards.Prosperity.Platinum()); cardTokenObjects.Add(new DominionBase.Cards.Prosperity.Colony()); } if (selectedPreset.ShelterSelected == DominionBase.ShelterSelected.Yes) { cardTokenObjects.Add(new DominionBase.Cards.DarkAges.Shelters()); } olCardsUsed.Objects = cardTokenObjects; olCardsUsed.Visibility = Visibility.Visible; } } private void rbChooser_AutomaticallyPlayTreasuresLoanBeforeVenture_Checked(object sender, RoutedEventArgs e) { Settings.AutoPlayTreasuresLoanFirst = true; } private void rbChooser_AutomaticallyPlayTreasuresVentureBeforeLoan_Checked(object sender, RoutedEventArgs e) { Settings.AutoPlayTreasuresLoanFirst = false; } private void rbChooser_AutomaticallyPlayTreasuresHornOfPlentyBeforeBank_Checked(object sender, RoutedEventArgs e) { Settings.AutoPlayTreasuresHornOfPlentyFirst = true; } private void rbChooser_AutomaticallyPlayTreasuresBankBeforeHornOfPlenty_Checked(object sender, RoutedEventArgs e) { Settings.AutoPlayTreasuresHornOfPlentyFirst = false; } private void cbSet_SelectionChanged(object sender, SelectionChangedEventArgs e) { var cb = sender as ComboBox; if (cb?.SelectedItem == null) return; cbCategory.SelectedItem = null; cbTrait.SelectedItem = null; var constraint = new Constraint(ConstraintType.SetIs, cb.SelectedItem, 0, 10); IEnumerable cards = constraint.GetMatchingCards(CardObjects.Cards).Union(constraint.GetMatchingCards(LandscapeCardObjects.Cards)).ToList(); cccSetCategoryTraitDisplay.Pile = cards; gbSetCategoryTraitDisplay.Header = $"Cards where Set is {cb.SelectedItem}"; tbMatchingCount.Text = cards.Count().ToString(); } private void cbCategory_SelectionChanged(object sender, SelectionChangedEventArgs e) { var cb = sender as ComboBox; if (cb?.SelectedItem == null) return; cbSet.SelectedItem = null; cbTrait.SelectedItem = null; var constraint = new Constraint(ConstraintType.CategoryContains, cb.SelectedItem, 0, 10); IEnumerable cards = constraint.GetMatchingCards(CardObjects.Cards).Union(constraint.GetMatchingCards(LandscapeCardObjects.Cards)).ToList(); cccSetCategoryTraitDisplay.Pile = cards; gbSetCategoryTraitDisplay.Header = $"Cards where Category has {cb.SelectedItem} in it"; tbMatchingCount.Text = cards.Count().ToString(); } private void cbTrait_SelectionChanged(object sender, SelectionChangedEventArgs e) { var cb = sender as ComboBox; if (cb?.SelectedItem == null) return; cbSet.SelectedItem = null; cbCategory.SelectedItem = null; var trait = ((KeyValuePair)cb.SelectedItem).Key; var constraint = new Constraint(ConstraintType.HasTrait, trait, 0, 10); var cards = constraint.GetMatchingCards(CardObjects.Cards).Union(constraint.GetMatchingCards(LandscapeCardObjects.Cards)).ToList(); cccSetCategoryTraitDisplay.Pile = cards; gbSetCategoryTraitDisplay.Header = $"Cards that have the Trait: {trait.ToDescription()}"; tbMatchingCount.Text = cards.Count.ToString(); } private void svSetCategoryTraitDisplay_ScrollChanged(object sender, ScrollChangedEventArgs e) { var sv = sender as ScrollViewer; bSetCategoryTraitDisplayHorizontal.Width = sv.ViewportWidth * sv.ViewportWidth / sv.ExtentWidth; bSetCategoryTraitDisplayVertical.Height = sv.ViewportHeight * sv.ViewportHeight / sv.ExtentHeight; bSetCategoryTraitDisplayHorizontal.Margin = new Thickness(sv.ViewportWidth * sv.HorizontalOffset / sv.ExtentWidth, 0, 0, 0); bSetCategoryTraitDisplayVertical.Margin = new Thickness(0, sv.ViewportHeight * sv.VerticalOffset / sv.ExtentHeight, 0, 0); bOpacityLayerLeft.Visibility = bOpacityLayerRight.Visibility = Visibility.Visible; if (bSetCategoryTraitDisplayHorizontal.Width >= sv.ViewportWidth) bOpacityLayerLeft.Visibility = bOpacityLayerRight.Visibility = Visibility.Collapsed; else if (bSetCategoryTraitDisplayHorizontal.Margin.Left <= 0) bOpacityLayerLeft.Visibility = Visibility.Collapsed; else if (bSetCategoryTraitDisplayHorizontal.Margin.Left + bSetCategoryTraitDisplayHorizontal.Width >= sv.ViewportWidth) bOpacityLayerRight.Visibility = Visibility.Collapsed; bOpacityLayerTop.Visibility = bOpacityLayerBottom.Visibility = Visibility.Visible; if (bSetCategoryTraitDisplayVertical.Height >= sv.ViewportHeight) bOpacityLayerTop.Visibility = bOpacityLayerBottom.Visibility = Visibility.Collapsed; else if (bSetCategoryTraitDisplayVertical.Margin.Top <= 0) bOpacityLayerTop.Visibility = Visibility.Collapsed; else if (bSetCategoryTraitDisplayVertical.Margin.Top + bSetCategoryTraitDisplayVertical.Height >= sv.ViewportHeight) bOpacityLayerBottom.Visibility = Visibility.Collapsed; } private void tabControl1_SelectionChanged(object sender, SelectionChangedEventArgs e) { } private void smallCardIconBrowse_Click(object sender, RoutedEventArgs e) { var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog { RootFolder = Environment.SpecialFolder.MyPictures, SelectedPath = Settings.CustomImagesPathSmall }; if (!System.IO.Path.IsPathRooted(dialog.SelectedPath)) dialog.SelectedPath = System.IO.Path.Combine(Caching.ImageRepository.ImageRoot, dialog.SelectedPath); dialog.ShowNewFolderButton = false; if (dialog.ShowDialog() == true) { // I don't like doing it this way, but I'm stumped as to how to get the TextBox to update // its Text property property using the commented-out line here. The Binding doesn't seem // to work the way I thought it should //this.Settings.CustomImagesPathSmall = dialog.SelectedPath; tbCustomImagesPathSmall.Text = dialog.SelectedPath; } } private void mediumCardIconBrowse_Click(object sender, RoutedEventArgs e) { var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog { RootFolder = Environment.SpecialFolder.MyPictures, SelectedPath = Settings.CustomImagesPathMedium }; if (!System.IO.Path.IsPathRooted(dialog.SelectedPath)) dialog.SelectedPath = System.IO.Path.Combine(Caching.ImageRepository.ImageRoot, dialog.SelectedPath); dialog.ShowNewFolderButton = false; if (dialog.ShowDialog() == true) { // I don't like doing it this way, but I'm stumped as to how to get the TextBox to update // its Text property property using the commented-out line here. The Binding doesn't seem // to work the way I thought it should //this.Settings.CustomImagesPathMedium = dialog.SelectedPath; tbCustomImagesPathMedium.Text = dialog.SelectedPath; } } private void cardToolTipBrowse_Click(object sender, RoutedEventArgs e) { var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog { RootFolder = Environment.SpecialFolder.MyPictures, SelectedPath = Settings.CustomToolTipsPath }; if (!System.IO.Path.IsPathRooted(dialog.SelectedPath)) dialog.SelectedPath = System.IO.Path.Combine(Caching.ImageRepository.ImageRoot, dialog.SelectedPath); dialog.ShowNewFolderButton = false; if (dialog.ShowDialog() == true) { // I don't like doing it this way, but I'm stumped as to how to get the TextBox to update // its Text property property using the commented-out line here. The Binding doesn't seem // to work the way I thought it should tbCustomToolTipsPath.Text = dialog.SelectedPath; } } private void backgroundBrowse_Click(object sender, RoutedEventArgs e) { var dialog = new Ookii.Dialogs.Wpf.VistaFolderBrowserDialog { RootFolder = Environment.SpecialFolder.MyPictures, SelectedPath = Settings.CustomBackgroundPath }; if (!System.IO.Path.IsPathRooted(dialog.SelectedPath)) dialog.SelectedPath = System.IO.Path.Combine(Caching.ImageRepository.ImageRoot, dialog.SelectedPath); dialog.ShowNewFolderButton = false; if (dialog.ShowDialog() == true) { // I don't like doing it this way, but I'm stumped as to how to get the TextBox to update // its Text property property using the commented-out line here. The Binding doesn't seem // to work the way I thought it should tbCustomBackgroundPath.Text = dialog.SelectedPath; } } private void cbFullCardView_Checked(object sender, RoutedEventArgs e) { switch (((CheckBox)sender).IsChecked) { case true: cccSetCategoryTraitDisplay.CardSize = CardSize.Full; break; default: cccSetCategoryTraitDisplay.CardSize = CardSize.Text; break; } } private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var g = (Grid)sender; g.CaptureMouse(); g.Cursor = Cursors.ScrollNS; svSetCategoryTraitDisplay.ScrollToVerticalOffset(e.GetPosition(g).Y / g.ActualHeight * svSetCategoryTraitDisplay.ExtentHeight); } private void Grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { var g = (Grid)sender; g.ReleaseMouseCapture(); g.Cursor = Cursors.Arrow; } private void Grid_MouseMove(object sender, MouseEventArgs e) { var g = (Grid)sender; if (g.IsMouseCaptured) svSetCategoryTraitDisplay.ScrollToVerticalOffset(e.GetPosition(g).Y / g.ActualHeight * svSetCategoryTraitDisplay.ExtentHeight); } private void sbpBackground_BrushChanged(object sender, RoutedPropertyChangedEventArgs e) { var selectedBrush = (Brush)(sender as ucSmallBrushPicker)?.SelectedItem; spLayout.Background = selectedBrush; if (Settings != null) Settings.BackgroundBrush = selectedBrush; } } [ValueConversion(typeof(double?), typeof(bool))] public class PlayerDisplayConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (double)value >= int.Parse((string)parameter); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } public class AITypeConverterName : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var type = value as Type; if (type == null) return value.ToString(); if (type == typeof(DominionBase.Players.AI.Basic) || type.IsSubclassOf(typeof(DominionBase.Players.AI.Basic))) { return (string)type.GetProperty("AIName", BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy).GetValue(null, null); } if (type == typeof(DominionBase.Players.AI.RandomAI) || type.IsSubclassOf(typeof(DominionBase.Players.AI.RandomAI))) { return (string)type.GetProperty("AIName", BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy).GetValue(null, null); } return value.ToString(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } } public class AITypeConverterDescription : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var type = value as Type; if (type == null) return value.ToString(); if (type == typeof(DominionBase.Players.AI.Basic) || type.IsSubclassOf(typeof(DominionBase.Players.AI.Basic))) { return (string)type.GetProperty("AIDescription", BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy).GetValue(null, null); } if (type == typeof(DominionBase.Players.AI.RandomAI) || type.IsSubclassOf(typeof(DominionBase.Players.AI.RandomAI))) { return (string)type.GetProperty("AIDescription", BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy).GetValue(null, null); } return value.ToString(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } } public class ToolTipShowDurationConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { switch ((ToolTipShowDuration)value) { case ToolTipShowDuration.Off: return 1; case ToolTipShowDuration.Short: return 2; case ToolTipShowDuration.Normal: return 3; case ToolTipShowDuration.Long: return 4; case ToolTipShowDuration.SuperLong: return 5; } return 3; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { switch (System.Convert.ToInt32(value)) { case 1: return ToolTipShowDuration.Off; case 2: return ToolTipShowDuration.Short; case 3: return ToolTipShowDuration.Normal; case 4: return ToolTipShowDuration.Long; case 5: return ToolTipShowDuration.SuperLong; } return ToolTipShowDuration.Normal; } } }