mirror of
https://github.com/4sval/FModel.git
synced 2026-03-21 17:24:26 -05:00
This commit is contained in:
parent
fbbf3c9c57
commit
3df3e802d4
|
|
@ -1 +1 @@
|
|||
Subproject commit 2f5fbe8a852a4c91d19616d45b784b62efca4753
|
||||
Subproject commit 2249deefcbe5e5858229db2f8694623c69009036
|
||||
|
|
@ -33,28 +33,16 @@ public class GameSelectorViewModel : ViewModel
|
|||
public IList<CustomDirectory> CustomDirectories { get; set; }
|
||||
}
|
||||
|
||||
private bool _useCustomEGames;
|
||||
public bool UseCustomEGames
|
||||
{
|
||||
get => _useCustomEGames;
|
||||
set => SetProperty(ref _useCustomEGames, value);
|
||||
}
|
||||
|
||||
private DirectorySettings _selectedDirectory;
|
||||
public DirectorySettings SelectedDirectory
|
||||
{
|
||||
get => _selectedDirectory;
|
||||
set
|
||||
{
|
||||
SetProperty(ref _selectedDirectory, value);
|
||||
if (_selectedDirectory != null) UseCustomEGames = EnumerateUeGames().ElementAt(1).Contains(_selectedDirectory.UeVersion);
|
||||
}
|
||||
set => SetProperty(ref _selectedDirectory, value);
|
||||
}
|
||||
|
||||
private readonly ObservableCollection<DirectorySettings> _detectedDirectories;
|
||||
public ReadOnlyObservableCollection<DirectorySettings> DetectedDirectories { get; }
|
||||
public ReadOnlyObservableCollection<EGame> UeGames { get; }
|
||||
public ReadOnlyObservableCollection<EGame> CustomUeGames { get; }
|
||||
|
||||
public GameSelectorViewModel(string gameDirectory)
|
||||
{
|
||||
|
|
@ -73,9 +61,7 @@ public class GameSelectorViewModel : ViewModel
|
|||
else
|
||||
SelectedDirectory = DetectedDirectories.FirstOrDefault();
|
||||
|
||||
var ueGames = EnumerateUeGames().ToArray();
|
||||
UeGames = new ReadOnlyObservableCollection<EGame>(new ObservableCollection<EGame>(ueGames[0]));
|
||||
CustomUeGames = new ReadOnlyObservableCollection<EGame>(new ObservableCollection<EGame>(ueGames[1]));
|
||||
UeGames = new ReadOnlyObservableCollection<EGame>(new ObservableCollection<EGame>(EnumerateUeGames()));
|
||||
}
|
||||
|
||||
public void AddUndetectedDir(string gameDirectory) => AddUndetectedDir(gameDirectory.SubstringAfterLast('\\'), gameDirectory);
|
||||
|
|
@ -94,11 +80,11 @@ public class GameSelectorViewModel : ViewModel
|
|||
SelectedDirectory = DetectedDirectories.Last();
|
||||
}
|
||||
|
||||
private IEnumerable<IGrouping<bool, EGame>> EnumerateUeGames()
|
||||
private IEnumerable<EGame> EnumerateUeGames()
|
||||
=> Enum.GetValues<EGame>()
|
||||
.GroupBy(value => (int)value)
|
||||
.Select(group => group.First())
|
||||
.GroupBy(value => (int)value == ((int)value & ~0xF));
|
||||
.OrderBy(value => (int)value == ((int)value & ~0xF));
|
||||
private IEnumerable<DirectorySettings> EnumerateDetectedGames()
|
||||
{
|
||||
yield return GetUnrealEngineGame("Fortnite", "\\FortniteGame\\Content\\Paks", EGame.GAME_UE5_5);
|
||||
|
|
|
|||
|
|
@ -27,13 +27,6 @@ public class SettingsViewModel : ViewModel
|
|||
set => SetProperty(ref _useCustomOutputFolders, value);
|
||||
}
|
||||
|
||||
private bool _useCustomEGames;
|
||||
public bool UseCustomEGames
|
||||
{
|
||||
get => _useCustomEGames;
|
||||
set => SetProperty(ref _useCustomEGames, value);
|
||||
}
|
||||
|
||||
private EUpdateMode _selectedUpdateMode;
|
||||
public EUpdateMode SelectedUpdateMode
|
||||
{
|
||||
|
|
@ -177,7 +170,6 @@ public class SettingsViewModel : ViewModel
|
|||
|
||||
public ReadOnlyObservableCollection<EUpdateMode> UpdateModes { get; private set; }
|
||||
public ReadOnlyObservableCollection<EGame> UeGames { get; private set; }
|
||||
public ReadOnlyObservableCollection<EGame> CustomUeGames { get; private set; }
|
||||
public ReadOnlyObservableCollection<ELanguage> AssetLanguages { get; private set; }
|
||||
public ReadOnlyObservableCollection<EAesReload> AesReloads { get; private set; }
|
||||
public ReadOnlyObservableCollection<EDiscordRpc> DiscordRpcs { get; private set; }
|
||||
|
|
@ -273,12 +265,8 @@ public class SettingsViewModel : ViewModel
|
|||
SelectedAesReload = UserSettings.Default.AesReload;
|
||||
SelectedDiscordRpc = UserSettings.Default.DiscordRpc;
|
||||
|
||||
var ueGames = EnumerateUeGames().ToArray();
|
||||
UseCustomEGames = ueGames[1].Contains(SelectedUeGame);
|
||||
|
||||
UpdateModes = new ReadOnlyObservableCollection<EUpdateMode>(new ObservableCollection<EUpdateMode>(EnumerateUpdateModes()));
|
||||
UeGames = new ReadOnlyObservableCollection<EGame>(new ObservableCollection<EGame>(ueGames[0]));
|
||||
CustomUeGames = new ReadOnlyObservableCollection<EGame>(new ObservableCollection<EGame>(ueGames[1]));
|
||||
UeGames = new ReadOnlyObservableCollection<EGame>(new ObservableCollection<EGame>(EnumerateUeGames()));
|
||||
AssetLanguages = new ReadOnlyObservableCollection<ELanguage>(new ObservableCollection<ELanguage>(EnumerateAssetLanguages()));
|
||||
AesReloads = new ReadOnlyObservableCollection<EAesReload>(new ObservableCollection<EAesReload>(EnumerateAesReloads()));
|
||||
DiscordRpcs = new ReadOnlyObservableCollection<EDiscordRpc>(new ObservableCollection<EDiscordRpc>(EnumerateDiscordRpcs()));
|
||||
|
|
@ -343,11 +331,11 @@ public class SettingsViewModel : ViewModel
|
|||
}
|
||||
|
||||
private IEnumerable<EUpdateMode> EnumerateUpdateModes() => Enum.GetValues<EUpdateMode>();
|
||||
private IEnumerable<IGrouping<bool, EGame>> EnumerateUeGames()
|
||||
private IEnumerable<EGame> EnumerateUeGames()
|
||||
=> Enum.GetValues<EGame>()
|
||||
.GroupBy(value => (int)value)
|
||||
.Select(group => group.First())
|
||||
.GroupBy(value => (int)value == ((int)value & ~0xF));
|
||||
.OrderBy(value => (int)value == ((int)value & ~0xF));
|
||||
private IEnumerable<ELanguage> EnumerateAssetLanguages() => Enum.GetValues<ELanguage>();
|
||||
private IEnumerable<EAesReload> EnumerateAesReloads() => Enum.GetValues<EAesReload>();
|
||||
private IEnumerable<EDiscordRpc> EnumerateDiscordRpcs() => Enum.GetValues<EDiscordRpc>();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<adonisControls:AdonisWindow x:Class="FModel.Views.DirectorySelector"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:FModel.Views.Resources.Controls"
|
||||
xmlns:converters="clr-namespace:FModel.Views.Resources.Converters"
|
||||
xmlns:adonisUi="clr-namespace:AdonisUI;assembly=AdonisUI"
|
||||
xmlns:adonisControls="clr-namespace:AdonisUI.Controls;assembly=AdonisUI"
|
||||
|
|
@ -61,27 +62,16 @@
|
|||
</ComboBox>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="UE Versions" VerticalAlignment="Center" Margin="0 0 0 5" />
|
||||
<ComboBox Grid.Row="1" Grid.Column="2" Margin="0 0 0 5"
|
||||
VerticalAlignment="Center" SelectedItem="{Binding SelectedDirectory.UeVersion, Mode=TwoWay}">
|
||||
<ComboBox.Style>
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
|
||||
<Setter Property="ItemsSource" Value="{Binding UeGames}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding UseCustomEGames}" Value="True">
|
||||
<Setter Property="ItemsSource" Value="{Binding CustomUeGames}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ComboBox.Style>
|
||||
<controls:FilterableComboBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="3" Margin="0 0 0 5"
|
||||
ItemsSource="{Binding UeGames}"
|
||||
Style="{StaticResource UComboBox}"
|
||||
VerticalAlignment="Center" SelectedItem="{Binding SelectedDirectory.UeVersion, Mode=TwoWay}">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<CheckBox Grid.Row="1" Grid.Column="4" Margin="5 0 0 5" ToolTip="Enable custom UE versions"
|
||||
IsChecked="{Binding UseCustomEGames, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
BorderBrush="White" Style="{StaticResource HighlightedCheckBox}" />
|
||||
</controls:FilterableComboBox>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Directory" VerticalAlignment="Center" />
|
||||
<TextBox Grid.Row="2" Grid.Column="2" Text="{Binding SelectedDirectory.GameDirectory, Mode=TwoWay}" />
|
||||
|
|
|
|||
273
FModel/Views/Resources/Controls/FilterableComboBox.cs
Normal file
273
FModel/Views/Resources/Controls/FilterableComboBox.cs
Normal file
|
|
@ -0,0 +1,273 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace FModel.Views.Resources.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// https://stackoverflow.com/a/58066259/13389331
|
||||
/// </summary>
|
||||
public class FilterableComboBox : ComboBox
|
||||
{
|
||||
/// <summary>
|
||||
/// If true, on lost focus or enter key pressed, checks the text in the combobox. If the text is not present
|
||||
/// in the list, it leaves it blank.
|
||||
/// </summary>
|
||||
public bool OnlyValuesInList {
|
||||
get => (bool)GetValue(OnlyValuesInListProperty);
|
||||
set => SetValue(OnlyValuesInListProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty OnlyValuesInListProperty =
|
||||
DependencyProperty.Register(nameof(OnlyValuesInList), typeof(bool), typeof(FilterableComboBox));
|
||||
|
||||
/// <summary>
|
||||
/// Selected item, changes only on lost focus or enter key pressed
|
||||
/// </summary>
|
||||
public object EffectivelySelectedItem {
|
||||
get => (bool)GetValue(EffectivelySelectedItemProperty);
|
||||
set => SetValue(EffectivelySelectedItemProperty, value);
|
||||
}
|
||||
public static readonly DependencyProperty EffectivelySelectedItemProperty =
|
||||
DependencyProperty.Register(nameof(EffectivelySelectedItem), typeof(object), typeof(FilterableComboBox));
|
||||
|
||||
private string CurrentFilter = string.Empty;
|
||||
private bool TextBoxFreezed;
|
||||
protected TextBox EditableTextBox => GetTemplateChild("PART_EditableTextBox") as TextBox;
|
||||
private UserChange<bool> IsDropDownOpenUC;
|
||||
|
||||
/// <summary>
|
||||
/// Triggers on lost focus or enter key pressed, if the selected item changed since the last time focus was lost or enter was pressed.
|
||||
/// </summary>
|
||||
public event Action<FilterableComboBox, object> SelectionEffectivelyChanged;
|
||||
|
||||
public FilterableComboBox()
|
||||
{
|
||||
IsDropDownOpenUC = new UserChange<bool>(v => IsDropDownOpen = v);
|
||||
DropDownOpened += FilteredComboBox_DropDownOpened;
|
||||
|
||||
Focusable = true;
|
||||
IsEditable = true;
|
||||
IsTextSearchEnabled = true;
|
||||
StaysOpenOnEdit = true;
|
||||
IsReadOnly = false;
|
||||
|
||||
Loaded += (s, e) => {
|
||||
if (EditableTextBox != null)
|
||||
new TextBoxBaseUserChangeTracker(EditableTextBox).UserTextChanged += FilteredComboBox_UserTextChange;
|
||||
};
|
||||
|
||||
SelectionChanged += (_, __) => shouldTriggerSelectedItemChanged = true;
|
||||
|
||||
SelectionEffectivelyChanged += (_, o) => EffectivelySelectedItem = o;
|
||||
}
|
||||
|
||||
protected override void OnPreviewKeyDown(KeyEventArgs e)
|
||||
{
|
||||
base.OnPreviewKeyDown(e);
|
||||
if (e.Key == Key.Down && !IsDropDownOpen) {
|
||||
IsDropDownOpen = true;
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (e.Key == Key.Escape) {
|
||||
ClearFilter();
|
||||
Text = "";
|
||||
IsDropDownOpen = true;
|
||||
}
|
||||
else if (e.Key == Key.Enter || e.Key == Key.Tab) {
|
||||
CheckSelectedItem();
|
||||
TriggerSelectedItemChanged();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e)
|
||||
{
|
||||
base.OnPreviewLostKeyboardFocus(e);
|
||||
CheckSelectedItem();
|
||||
if ((e.OldFocus == this || e.OldFocus == EditableTextBox) && e.NewFocus != this && e.NewFocus != EditableTextBox)
|
||||
TriggerSelectedItemChanged();
|
||||
}
|
||||
|
||||
private void CheckSelectedItem()
|
||||
{
|
||||
if (OnlyValuesInList)
|
||||
Text = SelectedItem?.ToString() ?? "";
|
||||
}
|
||||
|
||||
private bool shouldTriggerSelectedItemChanged = false;
|
||||
private void TriggerSelectedItemChanged()
|
||||
{
|
||||
if (shouldTriggerSelectedItemChanged) {
|
||||
SelectionEffectivelyChanged?.Invoke(this, SelectedItem);
|
||||
shouldTriggerSelectedItemChanged = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearFilter()
|
||||
{
|
||||
if (string.IsNullOrEmpty(CurrentFilter)) return;
|
||||
CurrentFilter = "";
|
||||
CollectionViewSource.GetDefaultView(ItemsSource).Refresh();
|
||||
}
|
||||
|
||||
private void FilteredComboBox_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
if (IsDropDownOpenUC.IsUserChange)
|
||||
ClearFilter();
|
||||
}
|
||||
|
||||
private void FilteredComboBox_UserTextChange(object sender, EventArgs e)
|
||||
{
|
||||
if (TextBoxFreezed) return;
|
||||
var tb = EditableTextBox;
|
||||
if (tb.SelectionStart + tb.SelectionLength == tb.Text.Length)
|
||||
CurrentFilter = tb.Text.Substring(0, tb.SelectionStart).ToLower();
|
||||
else
|
||||
CurrentFilter = tb.Text.ToLower();
|
||||
RefreshFilter();
|
||||
}
|
||||
|
||||
protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
|
||||
{
|
||||
if (newValue != null) {
|
||||
var view = CollectionViewSource.GetDefaultView(newValue);
|
||||
view.Filter += FilterItem;
|
||||
}
|
||||
|
||||
if (oldValue != null) {
|
||||
var view = CollectionViewSource.GetDefaultView(oldValue);
|
||||
if (view != null) view.Filter -= FilterItem;
|
||||
}
|
||||
|
||||
base.OnItemsSourceChanged(oldValue, newValue);
|
||||
}
|
||||
|
||||
private void RefreshFilter()
|
||||
{
|
||||
if (ItemsSource == null) return;
|
||||
|
||||
var view = CollectionViewSource.GetDefaultView(ItemsSource);
|
||||
FreezTextBoxState(() => {
|
||||
var isDropDownOpen = IsDropDownOpen;
|
||||
//always hide because showing it enables the user to pick with up and down keys, otherwise it's not working because of the glitch in view.Refresh()
|
||||
IsDropDownOpenUC.Set(false);
|
||||
view.Refresh();
|
||||
|
||||
if (!string.IsNullOrEmpty(CurrentFilter) || isDropDownOpen)
|
||||
IsDropDownOpenUC.Set(true);
|
||||
|
||||
if (SelectedItem == null) {
|
||||
foreach (var itm in ItemsSource)
|
||||
if (itm.ToString() == Text) {
|
||||
SelectedItem = itm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void FreezTextBoxState(Action action)
|
||||
{
|
||||
TextBoxFreezed = true;
|
||||
var tb = EditableTextBox;
|
||||
var text = Text;
|
||||
var selStart = tb.SelectionStart;
|
||||
var selLen = tb.SelectionLength;
|
||||
action();
|
||||
Text = text;
|
||||
tb.SelectionStart = selStart;
|
||||
tb.SelectionLength = selLen;
|
||||
TextBoxFreezed = false;
|
||||
}
|
||||
|
||||
private bool FilterItem(object value)
|
||||
{
|
||||
if (value == null) return false;
|
||||
if (CurrentFilter.Length == 0) return true;
|
||||
|
||||
return value.ToString().ToLower().Contains(CurrentFilter);
|
||||
}
|
||||
|
||||
private class TextBoxBaseUserChangeTracker
|
||||
{
|
||||
private bool IsTextInput { get; set; }
|
||||
|
||||
public TextBox TextBoxBase { get; set; }
|
||||
private List<Key> PressedKeys = new List<Key>();
|
||||
public event EventHandler UserTextChanged;
|
||||
private string LastText;
|
||||
|
||||
public TextBoxBaseUserChangeTracker(TextBox textBoxBase)
|
||||
{
|
||||
TextBoxBase = textBoxBase;
|
||||
LastText = TextBoxBase.ToString();
|
||||
|
||||
textBoxBase.PreviewTextInput += (s, e) => {
|
||||
IsTextInput = true;
|
||||
};
|
||||
|
||||
textBoxBase.TextChanged += (s, e) => {
|
||||
var isUserChange = PressedKeys.Count > 0 || IsTextInput || LastText == TextBoxBase.ToString();
|
||||
IsTextInput = false;
|
||||
LastText = TextBoxBase.ToString();
|
||||
if (isUserChange)
|
||||
UserTextChanged?.Invoke(this, e);
|
||||
};
|
||||
|
||||
textBoxBase.PreviewKeyDown += (s, e) => {
|
||||
switch (e.Key) {
|
||||
case Key.Back:
|
||||
case Key.Space:
|
||||
if (!PressedKeys.Contains(e.Key))
|
||||
PressedKeys.Add(e.Key);
|
||||
break;
|
||||
}
|
||||
if (e.Key == Key.Back) {
|
||||
var textBox = textBoxBase as TextBox;
|
||||
if (textBox.SelectionStart > 0 && textBox.SelectionLength > 0 && (textBox.SelectionStart + textBox.SelectionLength) == textBox.Text.Length) {
|
||||
textBox.SelectionStart--;
|
||||
textBox.SelectionLength++;
|
||||
e.Handled = true;
|
||||
UserTextChanged?.Invoke(this, e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
textBoxBase.PreviewKeyUp += (s, e) => {
|
||||
if (PressedKeys.Contains(e.Key))
|
||||
PressedKeys.Remove(e.Key);
|
||||
};
|
||||
|
||||
textBoxBase.LostFocus += (s, e) => {
|
||||
PressedKeys.Clear();
|
||||
IsTextInput = false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private class UserChange<T>
|
||||
{
|
||||
private Action<T> action;
|
||||
|
||||
public bool IsUserChange { get; private set; } = true;
|
||||
|
||||
public UserChange(Action<T> action)
|
||||
{
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public void Set(T val)
|
||||
{
|
||||
try {
|
||||
IsUserChange = false;
|
||||
action(val);
|
||||
}
|
||||
finally {
|
||||
IsUserChange = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1471,6 +1471,222 @@
|
|||
<Setter Property="Focusable" Value="False" />
|
||||
</Style>
|
||||
|
||||
<Style x:Key="UComboBox" TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
|
||||
<Setter Property="adonisExtensions:WatermarkExtension.Watermark" Value="UE5 / UE4 / GameName..." />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="ComboBox">
|
||||
<Grid>
|
||||
<Border x:Name="Border"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding adonisExtensions:CornerRadiusExtension.CornerRadius}"/>
|
||||
|
||||
<Border x:Name="SpotlightLayer"
|
||||
Background="{TemplateBinding adonisExtensions:CursorSpotlightExtension.BackgroundBrush}"
|
||||
BorderBrush="{TemplateBinding adonisExtensions:CursorSpotlightExtension.BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding adonisExtensions:CornerRadiusExtension.CornerRadius}"
|
||||
adonisExtensions:CursorSpotlightExtension.MouseEventSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=ComboBox}}"
|
||||
SnapsToDevicePixels="False"/>
|
||||
|
||||
<ToggleButton x:Name="ToggleButton"
|
||||
ClickMode="Press"
|
||||
Focusable="False"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
adonisExtensions:CornerRadiusExtension.CornerRadius="{TemplateBinding adonisExtensions:CornerRadiusExtension.CornerRadius}"
|
||||
IsChecked="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
|
||||
Template="{StaticResource ComboBoxToggleButtonTemplate}"/>
|
||||
|
||||
<Border Margin="0, 0, 11, 0">
|
||||
|
||||
<DockPanel Margin="{TemplateBinding Padding}">
|
||||
|
||||
<adonisControls:ValidationErrorIndicator x:Name="ErrorAlertHost"
|
||||
ValidatedElement="{Binding ., RelativeSource={RelativeSource TemplatedParent}}"
|
||||
IsValidatedElementFocused="False"
|
||||
IsErrorMessageDisplayOnFocusEnabled="{TemplateBinding adonisExtensions:ValidationExtension.IsErrorMessageVisibleOnFocus}"
|
||||
IsErrorMessageDisplayOnMouseOverEnabled="{TemplateBinding adonisExtensions:ValidationExtension.IsErrorMessageVisibleOnMouseOver}"
|
||||
ErrorMessagePlacement="{TemplateBinding adonisExtensions:ValidationExtension.ErrorMessagePlacement}"
|
||||
Visibility="Collapsed"
|
||||
DockPanel.Dock="Left"
|
||||
Margin="0, 0, 4, 0"/>
|
||||
|
||||
<ContentPresenter x:Name="ContentSite"
|
||||
IsHitTestVisible="False"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding ComboBox.SelectionBoxItem}"
|
||||
ContentTemplate="{TemplateBinding ComboBox.SelectionBoxItemTemplate}"
|
||||
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"/>
|
||||
|
||||
|
||||
<TextBox x:Name="PART_EditableTextBox"
|
||||
IsReadOnly="{TemplateBinding IsReadOnly}"
|
||||
Background="{TemplateBinding Background}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Visibility="Hidden"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Focusable="True">
|
||||
<TextBox.Template>
|
||||
<ControlTemplate TargetType="TextBox" >
|
||||
<Grid>
|
||||
<ContentPresenter x:Name="PlaceholderHost"
|
||||
Content="{Binding Path=(adonisExtensions:WatermarkExtension.Watermark), RelativeSource={RelativeSource FindAncestor, AncestorType=ComboBox}}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Opacity="0.5"
|
||||
IsHitTestVisible="False"
|
||||
Visibility="Collapsed"/>
|
||||
|
||||
<ScrollViewer Name="PART_ContentHost"
|
||||
Focusable="False"
|
||||
HorizontalScrollBarVisibility="Hidden"
|
||||
VerticalScrollBarVisibility="Hidden"
|
||||
Template="{StaticResource TextBoxScrollViewerTemplate}"/>
|
||||
</Grid>
|
||||
|
||||
<ControlTemplate.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=(adonisExtensions:WatermarkExtension.IsWatermarkVisible), RelativeSource={RelativeSource FindAncestor, AncestorType=ComboBox}}" Value="True">
|
||||
<Setter Property="Visibility" TargetName="PlaceholderHost" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</TextBox.Template>
|
||||
</TextBox>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Popup showing items -->
|
||||
<Popup x:Name="PART_Popup"
|
||||
Placement="Bottom"
|
||||
Focusable="False"
|
||||
AllowsTransparency="True"
|
||||
IsOpen="{TemplateBinding ComboBox.IsDropDownOpen}"
|
||||
PopupAnimation="Slide"
|
||||
adonisExtensions:LayerExtension.IncreaseLayer="True">
|
||||
|
||||
<Grid x:Name="DropDown"
|
||||
SnapsToDevicePixels="True"
|
||||
MinWidth="{TemplateBinding FrameworkElement.ActualWidth}"
|
||||
MaxHeight="{TemplateBinding ComboBox.MaxDropDownHeight}">
|
||||
|
||||
<Border x:Name="DropDownBorder"
|
||||
Background="{TemplateBinding Background}"
|
||||
Margin="0, 1, 0, 0"
|
||||
CornerRadius="{TemplateBinding adonisExtensions:CornerRadiusExtension.CornerRadius}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}">
|
||||
|
||||
<ScrollViewer x:Name="DropDownScroller"
|
||||
SnapsToDevicePixels="True"
|
||||
adonisExtensions:ScrollViewerExtension.VerticalScrollBarExpansionMode="{Binding Path=(adonisExtensions:ScrollViewerExtension.VerticalScrollBarExpansionMode), RelativeSource={RelativeSource TemplatedParent}}"
|
||||
adonisExtensions:ScrollViewerExtension.HorizontalScrollBarExpansionMode="{Binding Path=(adonisExtensions:ScrollViewerExtension.HorizontalScrollBarExpansionMode), RelativeSource={RelativeSource TemplatedParent}}"
|
||||
adonisExtensions:ScrollViewerExtension.VerticalScrollBarPlacement="{Binding Path=(adonisExtensions:ScrollViewerExtension.VerticalScrollBarPlacement), RelativeSource={RelativeSource TemplatedParent}}"
|
||||
adonisExtensions:ScrollViewerExtension.HorizontalScrollBarPlacement="{Binding Path=(adonisExtensions:ScrollViewerExtension.HorizontalScrollBarPlacement), RelativeSource={RelativeSource TemplatedParent}}"
|
||||
adonisExtensions:ScrollViewerExtension.HideScrollBarsUntilMouseOver="{Binding Path=(adonisExtensions:ScrollViewerExtension.HideScrollBarsUntilMouseOver), RelativeSource={RelativeSource TemplatedParent}}">
|
||||
<ItemsPresenter KeyboardNavigation.DirectionalNavigation="Contained" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
|
||||
<StackPanel x:Name="BlindIndicator"
|
||||
Grid.ZIndex="1"
|
||||
Focusable="False"
|
||||
Margin="0 7 0 0"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
Visibility="Visible"
|
||||
MinHeight="15">
|
||||
<ContentControl ContentTemplate="{DynamicResource {x:Static adonisUi:Templates.Expander}}"
|
||||
Foreground="{TemplateBinding Foreground}"
|
||||
Focusable="False"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
RenderTransformOrigin="0.5 0.5">
|
||||
<ContentControl.RenderTransform>
|
||||
<TransformGroup>
|
||||
<RotateTransform Angle="180"/>
|
||||
<TranslateTransform Y="0"/>
|
||||
</TransformGroup>
|
||||
</ContentControl.RenderTransform>
|
||||
<ContentControl.Triggers>
|
||||
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
|
||||
<BeginStoryboard>
|
||||
<BeginStoryboard.Storyboard>
|
||||
<Storyboard RepeatBehavior="Forever">
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetProperty="RenderTransform.Children[0].Angle"
|
||||
From="190" To="170" Duration="0:0:0.3"
|
||||
AutoReverse="True" />
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetProperty="RenderTransform.Children[1].Y"
|
||||
From="-1" To="1" Duration="0:0:0.2"
|
||||
AutoReverse="True" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard.Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
</ContentControl.Triggers>
|
||||
</ContentControl>
|
||||
<!-- <TextBlock Text="Game-Specific Versions" -->
|
||||
<!-- Foreground="{TemplateBinding Foreground}" -->
|
||||
<!-- FontSize="9" -->
|
||||
<!-- TextAlignment="Center"> -->
|
||||
<!-- </TextBlock> -->
|
||||
|
||||
<!-- <StackPanel.Background> -->
|
||||
<!-- <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> -->
|
||||
<!-- <GradientStop Color="#35000000" Offset="0" /> -->
|
||||
<!-- <GradientStop Color="#00000000" Offset="1" /> -->
|
||||
<!-- </LinearGradientBrush> -->
|
||||
<!-- </StackPanel.Background> -->
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Popup>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
|
||||
<Trigger Property="HasItems" Value="False">
|
||||
<Setter Property="FrameworkElement.MinHeight" TargetName="DropDownBorder" Value="95"/>
|
||||
<Setter Property="Visibility" TargetName="BlindIndicator" Value="Collapsed" />
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsGrouping" Value="True">
|
||||
<Setter Property="ScrollViewer.CanContentScroll" Value="False"/>
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsEditable" Value="True">
|
||||
<Setter Property="KeyboardNavigation.IsTabStop" Value="False"/>
|
||||
<Setter Property="UIElement.Visibility" TargetName="PART_EditableTextBox" Value="Visible"/>
|
||||
<Setter Property="UIElement.Visibility" TargetName="ContentSite" Value="Collapsed"/>
|
||||
<Setter Property="HorizontalAlignment" TargetName="ToggleButton" Value="Right"/>
|
||||
<Setter Property="HorizontalAlignment" TargetName="ToggleButton" Value="Right"/>
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="Validation.HasError" Value="True">
|
||||
<Setter Property="Visibility" TargetName="ErrorAlertHost" Value="Visible"/>
|
||||
<Setter Property="BorderBrush" TargetName="Border" Value="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}"/>
|
||||
<Setter Property="BorderBrush" TargetName="SpotlightLayer" Value="{DynamicResource {x:Static adonisUi:Brushes.ErrorBrush}}"/>
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsFocused" SourceName="PART_EditableTextBox" Value="True">
|
||||
<Setter Property="IsValidatedElementFocused" TargetName="ErrorAlertHost" Value="True"/>
|
||||
</Trigger>
|
||||
|
||||
<Trigger Property="IsDropDownOpen" Value="True">
|
||||
<Setter Property="IsValidatedElementFocused" TargetName="ErrorAlertHost" Value="True"/>
|
||||
</Trigger>
|
||||
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="{x:Type Button}" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
|
||||
<Setter Property="Focusable" Value="False" />
|
||||
</Style>
|
||||
|
|
|
|||
|
|
@ -122,29 +122,17 @@
|
|||
<Button Grid.Row="5" Grid.Column="6" Content="..." HorizontalAlignment="Right" Click="OnBrowseDirectories" Margin="0 0 0 5" />
|
||||
|
||||
<TextBlock Grid.Row="6" Grid.Column="0" Text="UE Versions *" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Override the UE version to use when parsing packages" />
|
||||
<ComboBox Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="3" SelectedItem="{Binding SettingsView.SelectedUeGame, Mode=TwoWay}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}"
|
||||
Margin="0 0 0 5">
|
||||
<ComboBox.Style>
|
||||
<Style TargetType="ComboBox" BasedOn="{StaticResource {x:Type ComboBox}}">
|
||||
<Setter Property="ItemsSource" Value="{Binding SettingsView.UeGames}" />
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding SettingsView.UseCustomEGames}" Value="True">
|
||||
<Setter Property="ItemsSource" Value="{Binding SettingsView.CustomUeGames}" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</ComboBox.Style>
|
||||
<controls:FilterableComboBox Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="5" SelectedItem="{Binding SettingsView.SelectedUeGame, Mode=TwoWay}"
|
||||
ItemsSource="{Binding SettingsView.UeGames}"
|
||||
Style="{StaticResource UComboBox}"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}"
|
||||
Margin="0 0 0 5">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Converter={x:Static converters:EnumToStringConverter.Instance}}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<CheckBox Grid.Row="6" Grid.Column="6" Margin="5 0 0 5" ToolTip="Enable custom UE versions"
|
||||
DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Views.SettingsView}}}"
|
||||
IsChecked="{Binding SettingsView.UseCustomEGames, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
BorderBrush="White" Style="{StaticResource HighlightedCheckBox}" />
|
||||
</controls:FilterableComboBox>
|
||||
|
||||
<TextBlock Grid.Row="7" Grid.Column="0" Text="Texture Platform *" VerticalAlignment="Center" Margin="0 0 0 5" ToolTip="Override the game's platform to ensure texture compatibility" />
|
||||
<ComboBox Grid.Row="7" Grid.Column="2" Grid.ColumnSpan="5" ItemsSource="{Binding SettingsView.Platforms}" SelectedItem="{Binding SettingsView.SelectedUePlatform, Mode=TwoWay}"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user