Skip to content

Commit

Permalink
Simple Tags UI
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Dec 5, 2019
1 parent 82a21fd commit 8336391
Show file tree
Hide file tree
Showing 15 changed files with 292 additions and 29 deletions.
20 changes: 20 additions & 0 deletions Core/Extensions/DictionaryExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;

namespace CKAN.Extensions
{
public static class DictionaryExtensions
{

public static V GetOrDefault<K, V>(this Dictionary<K, V> dict, K key)
{
V val = default(V);
if (key != null)
{
dict.TryGetValue(key, out val);
}
return val;
}

}
}
13 changes: 12 additions & 1 deletion Core/Registry/Registry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ public void SetDownloadCounts(SortedDictionary<string, int> counts)
// Index of which mods provide what, format:
// providers[provided] = { provider1, provider2, ... }
// Built by BuildProvidesIndex, makes LatestAvailableWithProvides much faster.
[JsonIgnore] private Dictionary<string, HashSet<AvailableModule>> providers
[JsonIgnore]
private Dictionary<string, HashSet<AvailableModule>> providers
= new Dictionary<string, HashSet<AvailableModule>>();

/// <summary>
Expand Down Expand Up @@ -686,6 +687,16 @@ private void BuildProvidesIndexFor(AvailableModule am)
}
}

public void BuildTagIndex(ModuleTagList tags)
{
tags.Tags.Clear();
tags.Untagged.Clear();
foreach (AvailableModule am in available_modules.Values)
{
tags.BuildTagIndexFor(am);
}
}

/// <summary>
/// <see cref="IRegistryQuerier.LatestAvailableWithProvides" />
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions Core/Registry/Tags/ModuleTag.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;

namespace CKAN
{
public class ModuleTag
{
public string Name;
public bool Visible;
public HashSet<string> Modules;
}
}
80 changes: 80 additions & 0 deletions Core/Registry/Tags/ModuleTagList.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace CKAN
{
public class ModuleTagList
{
[JsonIgnore]
public Dictionary<string, ModuleTag> Tags = new Dictionary<string, ModuleTag>();

[JsonIgnore]
public HashSet<string> Untagged = new HashSet<string>();

[JsonProperty("hidden_tags")]
public HashSet<string> HiddenTags = new HashSet<string>();

public static readonly string DefaultPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"CKAN",
"tags.json"
);

public void BuildTagIndexFor(AvailableModule am)
{
bool tagged = false;
foreach (CkanModule m in am.AllAvailable())
{
if (m.Tags != null)
{
tagged = true;
foreach (string tagName in m.Tags)
{
ModuleTag tag = null;
if (Tags.TryGetValue(tagName, out tag))
tag.Modules.Add(m.identifier);
else
Tags.Add(tagName, new ModuleTag()
{
Name = tagName,
Visible = !HiddenTags.Contains(tagName),
Modules = new HashSet<string>() { m.identifier },
});
}
}
}
if (!tagged)
{
Untagged.Add(am.AllAvailable().First().identifier);
}
}

public static ModuleTagList Load(string path)
{
try
{
return JsonConvert.DeserializeObject<ModuleTagList>(File.ReadAllText(path));
}
catch (FileNotFoundException ex)
{
return null;
}
}

public bool Save(string path)
{
try
{
File.WriteAllText(path, JsonConvert.SerializeObject(this, Formatting.Indented));
return true;
}
catch
{
return false;
}
}
}
}
5 changes: 4 additions & 1 deletion Core/Types/CkanModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ public class CkanModule : IEquatable<CkanModule>

[JsonProperty("install", NullValueHandling = NullValueHandling.Ignore)]
public ModuleInstallDescriptor[] install;

[JsonProperty("localizations", NullValueHandling = NullValueHandling.Ignore)]
public string[] localizations;

Expand Down Expand Up @@ -469,6 +469,9 @@ public ModuleVersion spec_version
}
}

[JsonProperty("tags", NullValueHandling = NullValueHandling.Ignore)]
public HashSet<string> Tags;

// A list of eveything this mod provides.
public List<string> ProvidesList
{
Expand Down
5 changes: 5 additions & 0 deletions GUI/GUIConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ public class GUIConfiguration

public int ActiveFilter = 0;

/// <summary>
/// Name of the tag filter the user chose, if any
/// </summary>
public string TagFilter = null;

/// <summary>
/// Name of the label filter the user chose, if any
/// </summary>
Expand Down
12 changes: 12 additions & 0 deletions GUI/GUIMod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,18 @@ public CkanModule ToModule()
return Mod;
}

public bool HasTag(string tag)
{
if (string.IsNullOrEmpty(tag))
{
return !Mod?.Tags?.Any() ?? true;
}
else
{
return Mod?.Tags?.Contains(tag) ?? false;
}
}

public IEnumerable<ModChange> GetModChanges()
{
bool selectedIsInstalled = SelectedMod?.Equals(InstalledMod?.Module)
Expand Down
17 changes: 8 additions & 9 deletions GUI/Labels/ModuleLabelList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ public class ModuleLabelList

public static ModuleLabelList GetDefaultLabels()
{
return new ModuleLabelList() {
Labels = new ModuleLabel[] {
new ModuleLabel() {
return new ModuleLabelList()
{
Labels = new ModuleLabel[]
{
new ModuleLabel()
{
Name = Properties.Resources.ModuleLabelListFavourites,
Color = Color.PaleGreen,
},
new ModuleLabel() {
new ModuleLabel()
{
Name = Properties.Resources.ModuleLabelListHidden,
Hide = true,
Color = Color.PaleVioletRed,
Expand All @@ -34,11 +38,6 @@ public static ModuleLabelList GetDefaultLabels()
};
}

public string[] LabelsMatchingModule(string identifier)
{
return new string[] {};
}

public static ModuleLabelList Load(string path)
{
try
Expand Down
3 changes: 3 additions & 0 deletions GUI/Main.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions GUI/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Linq;
using CKAN.Versioning;
using CKAN.Exporters;
using CKAN.Extensions;
using CKAN.Properties;
using CKAN.Types;
using log4net;
Expand Down Expand Up @@ -591,6 +592,7 @@ void filterUpdate (object sender, RunWorkerCompletedEventArgs e)
{
Filter(
(GUIModFilter)configuration.ActiveFilter,
mainModList.ModuleTags.Tags.GetOrDefault(configuration.TagFilter),
mainModList.ModuleLabels.Labels
.FirstOrDefault(l => l.Name == configuration.CustomLabelFilter)
);
Expand All @@ -604,6 +606,7 @@ void filterUpdate (object sender, RunWorkerCompletedEventArgs e)
UpdateModsList();
Filter(
(GUIModFilter)configuration.ActiveFilter,
mainModList.ModuleTags.Tags.GetOrDefault(configuration.TagFilter),
mainModList.ModuleLabels.Labels
.FirstOrDefault(l => l.Name == configuration.CustomLabelFilter)
);
Expand Down Expand Up @@ -862,15 +865,17 @@ private void FilterAllButton_Click(object sender, EventArgs e)
/// Called when the modlist filter (all, compatible, incompatible...) is changed.
/// </summary>
/// <param name="filter">Filter.</param>
private void Filter(GUIModFilter filter, ModuleLabel label = null)
private void Filter(GUIModFilter filter, ModuleTag tag = null, ModuleLabel label = null)
{
// Triggers mainModList.ModFiltersUpdated()
mainModList.ModFilter = filter;
mainModList.TagFilter = tag;
mainModList.CustomLabelFilter = label;

// Save new filter to the configuration.
configuration.ActiveFilter = (int)mainModList.ModFilter;
configuration.CustomLabelFilter = label?.Name;
configuration.TagFilter = tag?.Name;
configuration.Save();

// Ask the configuration which columns to show.
Expand Down Expand Up @@ -900,7 +905,12 @@ private void Filter(GUIModFilter filter, ModuleLabel label = null)
ModList.Columns["InstallDate"].Visible = false;
ModList.Columns["AutoInstalled"].Visible = false;
FilterToolButton.Text = Properties.Resources.MainFilterNotInstalled; break;
case GUIModFilter.CustomLabel: FilterToolButton.Text = label?.Name ?? "CUSTOM"; break;
case GUIModFilter.CustomLabel: FilterToolButton.Text = string.Format(Properties.Resources.MainFilterLabel, label?.Name ?? "CUSTOM"); break;
case GUIModFilter.Tag:
FilterToolButton.Text = tag == null
? Properties.Resources.MainFilterUntagged
: string.Format(Properties.Resources.MainFilterTag, tag.Name);
break;
default: FilterToolButton.Text = Properties.Resources.MainFilterCompatible; break;
}
}
Expand Down
32 changes: 29 additions & 3 deletions GUI/MainLabels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,33 @@ private void FilterToolButton_DrodDown_Opening(object sender, System.ComponentMo
// Remove any existing custom labels from the list
for (int i = FilterToolButton.DropDownItems.Count - 1; i >= 0; --i)
{
if (FilterToolButton.DropDownItems[i] is ToolStripSeparator)
if (FilterToolButton.DropDownItems[i] == tagFilterToolStripSeparator)
{
// Stop when we get to the separator
// Stop when we get to the first separator
break;
}
FilterToolButton.DropDownItems.RemoveAt(i);
}
// Tags
foreach (var kvp in mainModList.ModuleTags.Tags.OrderBy(kvp => kvp.Key))
{
FilterToolButton.DropDownItems.Add(new ToolStripMenuItem(
$"{kvp.Key} ({kvp.Value.Modules.Count})",
null, tagFilterButton_Click
)
{
Tag = kvp.Key
});
}
FilterToolButton.DropDownItems.Add(new ToolStripMenuItem(
string.Format(Properties.Resources.MainLabelsUntagged, mainModList.ModuleTags.Untagged.Count),
null, tagFilterButton_Click
)
{
Tag = null
});
FilterToolButton.DropDownItems.Add(customFilterToolStripSeparator);
// Labels
foreach (ModuleLabel mlbl in mainModList.ModuleLabels.Labels)
{
FilterToolButton.DropDownItems.Add(new ToolStripMenuItem(
Expand All @@ -34,10 +54,16 @@ private void FilterToolButton_DrodDown_Opening(object sender, System.ComponentMo
}
}

private void tagFilterButton_Click(object sender, EventArgs e)
{
var clicked = sender as ToolStripMenuItem;
Filter(GUIModFilter.Tag, clicked.Tag as ModuleTag, null);
}

private void customFilterButton_Click(object sender, EventArgs e)
{
var clicked = sender as ToolStripMenuItem;
Filter(GUIModFilter.CustomLabel, clicked.Tag as ModuleLabel);
Filter(GUIModFilter.CustomLabel, null, clicked.Tag as ModuleLabel);
}

#endregion
Expand Down
Loading

0 comments on commit 8336391

Please sign in to comment.