Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ModManager] Add column for applied state and filter applied/not applied mods #346

Open
wants to merge 2 commits into
base: 1.0.6.3
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions FrostyModManager/FrostyModManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,8 @@
<Resource Include="Images\PrimaryActionMerge.png" />
<Resource Include="Images\Open.png" />
<Resource Include="Images\SaveAs.png" />
<Resource Include="Images\CircleCheck.png" />
<Resource Include="Images\CircleX.png" />
<Content Include="ThirdParty\Newtonsoft.Json.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Expand Down
Binary file added FrostyModManager/Images/CircleCheck.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added FrostyModManager/Images/CircleX.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
52 changes: 42 additions & 10 deletions FrostyModManager/Windows/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -745,14 +745,34 @@
</DockPanel>
</Border>

<ctrl:FrostyWatermarkTextBox Grid.Row="1"
x:Name="availableModsFilterTextBox"
WatermarkText="Filter"
BorderThickness="1"
Margin="1,1,1,0"
VerticalContentAlignment="Center"
KeyUp="availableModsFilter_KeyUp"
LostFocus="availableModsFilter_LostFocus" />
<DockPanel Grid.Row="1"
VerticalAlignment="Center"
Width="Auto"
HorizontalAlignment="Stretch">
<ToggleButton x:Name="appliedModsFilterButton"
Click="appliedModsFilterButton_Click"
ToolTip="Filter applied mods">
<Image Source="/FrostyModManager;component/Images/CircleCheck.png"
Height="16"
Width="16"
Margin="0,0,2,0" />
</ToggleButton>
<ToggleButton x:Name="notAppliedModsFilterButton"
Click="notAppliedModsFilterButton_Click"
ToolTip="Filter not applied mods">
<Image Source="/FrostyModManager;component/Images/CircleX.png"
Height="16"
Width="16"
Margin="0,0,2,0" />
</ToggleButton>
<ctrl:FrostyWatermarkTextBox x:Name="availableModsFilterTextBox"
WatermarkText="Filter"
BorderThickness="1"
Margin="1,1,1,0"
VerticalContentAlignment="Center"
KeyUp="availableModsFilter_KeyUp"
LostFocus="availableModsFilter_LostFocus" />
</DockPanel>

<ListView x:Name="availableModsList"
Grid.Row="2"
Expand Down Expand Up @@ -953,6 +973,10 @@
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Applied"
Width="74">
<!-- GridViewColumn.CellTemplate created in code -->
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
Expand Down Expand Up @@ -1088,8 +1112,16 @@

<ctrl:FrostyDetachedTabControl Grid.Row="2"
x:Name="availableModsTabContent"
Foreground="{StaticResource FontColor}"
Grid.ColumnSpan="2" />
Foreground="{StaticResource FontColor}" Margin="0,0,0,26" />
<ctrl:FrostyWatermarkTextBox Grid.Row="3"
x:Name="availableModsStatusBar"
WatermarkText=""
IsEnabled="False"
BorderThickness="1"
Margin="1,1,1,0"
VerticalAlignment="Bottom"
VerticalContentAlignment="Center"
Background="{StaticResource ControlBackground}" />
</Grid>
</ctrl:FrostyDockablePanel>

Expand Down
128 changes: 122 additions & 6 deletions FrostyModManager/Windows/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
using Newtonsoft.Json;
using System.Threading.Tasks;
using System.Media;
using System.Reflection;

namespace FrostyModManager
{
Expand Down Expand Up @@ -192,6 +193,29 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu
throw new NotImplementedException();
}
}
public class ModAppliedConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
String title = (String)value;
MainWindow mainWindow = (MainWindow)parameter;

if (mainWindow.selectedPack != null)
{
if (mainWindow.selectedPack.AppliedMods.Exists(x => x.ModName == title))
{
return Visibility.Visible;
}
}

return Visibility.Hidden;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

public enum ModPrimaryActionType
{
Expand Down Expand Up @@ -281,7 +305,7 @@ public partial class MainWindow : FrostyWindow
{
private List<IFrostyMod> availableMods = new List<IFrostyMod>();
private List<FrostyPack> packs = new List<FrostyPack>();
private FrostyPack selectedPack;
public FrostyPack selectedPack { get; private set; }
private FileSystem fs;
private DirectoryInfo modsDir = new DirectoryInfo(Path.Combine("Mods", ProfilesLibrary.ProfileName));

Expand Down Expand Up @@ -397,6 +421,9 @@ private void FrostyWindow_FrostyLoaded(object sender, EventArgs e)
availableMods = availableMods.OrderBy(o => o.Filename).ToList();
availableModsList.ItemsSource = availableMods;

// Re-run filter to update the status bar text.
RefreshFilter();

CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(availableModsList.ItemsSource);
PropertyGroupDescription groupDescription = new PropertyGroupDescription("ModDetails.Category", null, StringComparison.OrdinalIgnoreCase);
view.GroupDescriptions.Add(groupDescription);
Expand Down Expand Up @@ -490,6 +517,23 @@ private void FrostyWindow_FrostyLoaded(object sender, EventArgs e)
orderComboBox.SelectedIndex = 1;
}

FrameworkElementFactory factory = new FrameworkElementFactory(typeof(Image));
factory.SetValue(Image.SourceProperty, new ImageSourceConverter().ConvertFromString("pack://application:,,,/FrostyModManager;component/Images/CircleCheck.png") as ImageSource);
factory.SetValue(Image.HeightProperty, 16.0d);
factory.SetValue(Image.WidthProperty, 16.0d);
factory.SetValue(Image.HorizontalAlignmentProperty, HorizontalAlignment.Center);
factory.SetValue(Image.VerticalAlignmentProperty, VerticalAlignment.Center);
factory.SetBinding(Image.VisibilityProperty, new Binding("ModDetails.Title")
{
Converter = new ModAppliedConverter(),
ConverterParameter = this,
Mode = BindingMode.OneWay,
});
DataTemplate dt = new DataTemplate();
dt.VisualTree = factory;
GridViewColumn appliedBindingColumn = (availableModsList.View as GridView).Columns[2];
appliedBindingColumn.CellTemplate = dt;

GC.Collect();
}

Expand Down Expand Up @@ -617,6 +661,9 @@ private void removeButton_Click(object sender, RoutedEventArgs e)

appliedModsList.SelectedIndex = selectedIndex;
updateAppliedModButtons();

// Re-run filter since we might be filtering on applied mods.
RefreshFilter();
}

private void upButton_Click(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -839,6 +886,9 @@ private void uninstallModButton_Click(object sender, RoutedEventArgs e)
appliedModsList.Items.Refresh();

FrostyMessageBox.Show("Mod(s) has been successfully uninstalled", "Frosty Mod Manager");

// Re-run filter since we might be filtering on applied mods.
RefreshFilter();
}

private int VerifyMod(Stream stream)
Expand Down Expand Up @@ -1514,6 +1564,9 @@ private void InstallMods(string[] filenames)
FrostyMessageBox.Show("Pack has been successfully imported", "Frosty Mod Manager");
}
}

// Re-run filter since we might be filtering on applied mods.
RefreshFilter();
}

private bool IsCompressed(FileInfo fi) => fi.Extension == ".rar" || fi.Extension == ".zip" || fi.Extension == ".7z" || fi.Extension == ".fbpack";
Expand Down Expand Up @@ -1574,6 +1627,9 @@ private void availableModsList_MouseDoubleClick(object sender, MouseButtonEventA

// focus on tab item
appliedModsTabItem.IsSelected = true;

// Re-run filter since we might be filtering on applied mods.
RefreshFilter();
}

public List<Control> AllChildren(DependencyObject parent)
Expand Down Expand Up @@ -1608,6 +1664,9 @@ private void addModButton_Click(object sender, RoutedEventArgs e)

// focus on tab item
appliedModsTabItem.IsSelected = true;

// Re-run filter since we might be filtering on applied mods.
RefreshFilter();
}

private void SelectedProfile_AppliedModsUpdated(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -1843,18 +1902,72 @@ private void logTextBox_TextChanged(object sender, TextChangedEventArgs e)
private void availableModsFilter_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
availableModsFilter_LostFocus(this, new RoutedEventArgs());
RefreshFilter();
}

private void availableModsFilter_LostFocus(object sender, RoutedEventArgs e)
{
if (availableModsFilterTextBox.Text == "")
RefreshFilter();
}

private void RefreshFilter()
{
Func<IFrostyMod, bool> nameFilter = a =>
{
availableModsList.Items.Filter = null;
return;
if (availableModsFilterTextBox.Text != "")
{
return (a).ModDetails.Title.ToLower().Contains(availableModsFilterTextBox.Text.ToLower());
}

return true;
};

Func<IFrostyMod, bool> appliedOrNotFilter = a =>
{
if (appliedModsFilterButton.IsChecked.GetValueOrDefault())
{
return selectedPack.AppliedMods.Exists(x => x.ModName == ((IFrostyMod)a).ModDetails.Title);
}
else if (notAppliedModsFilterButton.IsChecked.GetValueOrDefault())
{
return !selectedPack.AppliedMods.Exists(x => x.ModName == ((IFrostyMod)a).ModDetails.Title);
}

return true;
};

availableModsList.Items.Filter = new Predicate<object>((object a) => appliedOrNotFilter((IFrostyMod)a) && nameFilter((IFrostyMod)a));

if (availableModsFilterTextBox.Text != "" || appliedModsFilterButton.IsChecked.GetValueOrDefault() || notAppliedModsFilterButton.IsChecked.GetValueOrDefault())
{
availableModsStatusBar.Text = string.Format("{0} mods pass filter.", availableModsList.Items.Count);
}
else
{
availableModsStatusBar.Text = string.Format("{0} mods available.", availableModsList.Items.Count);
}
}

private void appliedModsFilterButton_Click(object sender, RoutedEventArgs e)
{
// NotApplied + Applied both checked makes no sense, same as neither checked.
if (appliedModsFilterButton.IsChecked.GetValueOrDefault())
{
notAppliedModsFilterButton.IsChecked = false;
}

availableModsList.Items.Filter = new Predicate<object>((object a) => ((IFrostyMod)a).ModDetails.Title.ToLower().Contains(availableModsFilterTextBox.Text.ToLower()));
RefreshFilter();
}

private void notAppliedModsFilterButton_Click(object sender, RoutedEventArgs e)
{
// NotApplied + Applied both checked makes no sense, same as neither checked.
if (notAppliedModsFilterButton.IsChecked.GetValueOrDefault())
{
appliedModsFilterButton.IsChecked = false;
}

RefreshFilter();
}

private void PART_ShowOnlyReplacementsCheckBox_Checked(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -1978,6 +2091,9 @@ private void collectionModsList_MouseDoubleClick(object sender, MouseButtonEvent

// focus on tab item
appliedModsTabItem.IsSelected = true;

// Re-run filter since we might be filtering on applied mods.
RefreshFilter();
}

private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
Expand Down