mirror of
https://github.com/greenshot/greenshot
synced 2025-08-24 07:06:23 -07:00
Add xml serialization
This commit is contained in:
parent
0f7c4f3619
commit
9bea81ecda
3 changed files with 81 additions and 75 deletions
|
@ -16,59 +16,34 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
using SixLabors.Fonts.Unicode;
|
using SixLabors.Fonts.Unicode;
|
||||||
|
|
||||||
namespace Greenshot.Editor.Controls
|
namespace Greenshot.Editor.Controls
|
||||||
{
|
{
|
||||||
public static class EmojiData
|
public static class EmojiData
|
||||||
{
|
{
|
||||||
private static Task _init;
|
private const string FilePath = "emojis.xml";
|
||||||
public static IList<Group> AllGroups { get; private set; }
|
|
||||||
|
public static Emojis Data { get; private set; } = new Emojis();
|
||||||
|
|
||||||
public static void Load()
|
public static void Load()
|
||||||
{
|
{
|
||||||
_init ??= Task.Run(ParseEmojiList);
|
var x = new XmlSerializer(typeof(Emojis));
|
||||||
}
|
|
||||||
|
|
||||||
public class Emoji
|
if (File.Exists(FilePath))
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
Data = (Emojis)x.Deserialize(new XmlTextReader(FilePath));
|
||||||
public string Text { get; set; }
|
}
|
||||||
public bool HasVariations => VariationList.Count > 0;
|
else
|
||||||
|
{
|
||||||
public Group Group => SubGroup.Group;
|
// To be removed
|
||||||
public SubGroup SubGroup;
|
ParseEmojiList();
|
||||||
|
x.Serialize(new XmlTextWriter(FilePath, Encoding.UTF8), Data);
|
||||||
public IList<Emoji> VariationList { get; } = new List<Emoji>();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public class SubGroup
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public Group Group;
|
|
||||||
|
|
||||||
public IList<Emoji> EmojiList { get; } = new List<Emoji>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Group
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string Icon => SubGroups.FirstOrDefault()?.EmojiList.FirstOrDefault()?.Text;
|
|
||||||
|
|
||||||
public IList<SubGroup> SubGroups { get; } = new List<SubGroup>();
|
|
||||||
|
|
||||||
public int EmojiCount
|
|
||||||
=> SubGroups.Select(s => s.EmojiList.Count).Sum();
|
|
||||||
|
|
||||||
public IEnumerable<IEnumerable<Emoji>> EmojiChunkList
|
|
||||||
=> new ChunkHelper<Emoji>(EmojiList, 8);
|
|
||||||
|
|
||||||
public IEnumerable<Emoji> EmojiList
|
|
||||||
=> from s in SubGroups
|
|
||||||
from e in s.EmojiList
|
|
||||||
select e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<string> SkinToneComponents = new List<string>
|
private static List<string> SkinToneComponents = new List<string>
|
||||||
|
@ -93,7 +68,7 @@ namespace Greenshot.Editor.Controls
|
||||||
|
|
||||||
private static void ParseEmojiList()
|
private static void ParseEmojiList()
|
||||||
{
|
{
|
||||||
var lookup_by_name = new Dictionary<string, Emoji>();
|
var lookup_by_name = new Dictionary<string, Emojis.Emoji>();
|
||||||
var match_group = new Regex(@"^# group: (.*)");
|
var match_group = new Regex(@"^# group: (.*)");
|
||||||
var match_subgroup = new Regex(@"^# subgroup: (.*)");
|
var match_subgroup = new Regex(@"^# subgroup: (.*)");
|
||||||
var match_sequence = new Regex(@"^([0-9a-fA-F ]+[0-9a-fA-F]).*; *([-a-z]*) *# [^ ]* (E[0-9.]* )?(.*)");
|
var match_sequence = new Regex(@"^([0-9a-fA-F ]+[0-9a-fA-F]).*; *([-a-z]*) *# [^ ]* (E[0-9.]* )?(.*)");
|
||||||
|
@ -105,26 +80,25 @@ namespace Greenshot.Editor.Controls
|
||||||
var match_family = new Regex($"{adult}(\u200d{adult})*(\u200d{child})+");
|
var match_family = new Regex($"{adult}(\u200d{adult})*(\u200d{child})+");
|
||||||
|
|
||||||
var qualified_lut = new Dictionary<string, string>();
|
var qualified_lut = new Dictionary<string, string>();
|
||||||
var list = new List<Group>();
|
|
||||||
var alltext = new List<string>();
|
var alltext = new List<string>();
|
||||||
|
|
||||||
Group current_group = null;
|
Emojis.Group current_group = null;
|
||||||
SubGroup current_subgroup = null;
|
Emojis.Group current_subgroup = null;
|
||||||
|
|
||||||
foreach (var line in EmojiDescriptionLines())
|
foreach (var line in EmojiDescriptionLines())
|
||||||
{
|
{
|
||||||
var m = match_group.Match(line);
|
var m = match_group.Match(line);
|
||||||
if (m.Success)
|
if (m.Success)
|
||||||
{
|
{
|
||||||
current_group = new Group { Name = m.Groups[1].ToString() };
|
current_group = new Emojis.Group { Name = m.Groups[1].ToString() };
|
||||||
list.Add(current_group);
|
Data.Groups.Add(current_group);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m = match_subgroup.Match(line);
|
m = match_subgroup.Match(line);
|
||||||
if (m.Success)
|
if (m.Success)
|
||||||
{
|
{
|
||||||
current_subgroup = new SubGroup { Name = m.Groups[1].ToString(), Group = current_group };
|
current_subgroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
||||||
current_group.SubGroups.Add(current_subgroup);
|
current_group.SubGroups.Add(current_subgroup);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -181,12 +155,7 @@ namespace Greenshot.Editor.Controls
|
||||||
|
|
||||||
qualified_lut[unqualified] = text;
|
qualified_lut[unqualified] = text;
|
||||||
|
|
||||||
var emoji = new Emoji
|
var emoji = new Emojis.Emoji { Name = name, Text = text, };
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Text = text,
|
|
||||||
SubGroup = current_subgroup,
|
|
||||||
};
|
|
||||||
|
|
||||||
lookup_by_name[ToColonSyntax(name)] = emoji;
|
lookup_by_name[ToColonSyntax(name)] = emoji;
|
||||||
|
|
||||||
|
@ -195,18 +164,15 @@ namespace Greenshot.Editor.Controls
|
||||||
// FIXME: does not work properly because variations can appear before the generic emoji
|
// FIXME: does not work properly because variations can appear before the generic emoji
|
||||||
if (name.Contains(":") && lookup_by_name.TryGetValue(ToColonSyntax(name.Split(':')[0]), out var parent_emoji))
|
if (name.Contains(":") && lookup_by_name.TryGetValue(ToColonSyntax(name.Split(':')[0]), out var parent_emoji))
|
||||||
{
|
{
|
||||||
if (parent_emoji.VariationList.Count == 0)
|
parent_emoji.Variations.Add(emoji);
|
||||||
parent_emoji.VariationList.Add(parent_emoji);
|
|
||||||
parent_emoji.VariationList.Add(emoji);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
current_subgroup.EmojiList.Add(emoji);
|
current_subgroup.Emojis.Add(emoji);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the Component group. Not sure we want to have the skin tones in the picker.
|
// Remove the Component group. Not sure we want to have the skin tones in the picker.
|
||||||
list.RemoveAll(g => g.Name == "Component");
|
Data.Groups.RemoveAll(g => g.Name == "Component");
|
||||||
AllGroups = list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IEnumerable<string> EmojiDescriptionLines()
|
private static IEnumerable<string> EmojiDescriptionLines()
|
||||||
|
@ -217,6 +183,49 @@ namespace Greenshot.Editor.Controls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Emojis
|
||||||
|
{
|
||||||
|
[XmlElement(ElementName = "Group")]
|
||||||
|
public List<Group> Groups { get; set; } = new();
|
||||||
|
|
||||||
|
public class Group
|
||||||
|
{
|
||||||
|
[XmlAttribute]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "Group")]
|
||||||
|
public List<Group> SubGroups { get; set; } = new();
|
||||||
|
|
||||||
|
[XmlElement(ElementName = "Emoji")]
|
||||||
|
public List<Emoji> Emojis { get; set; } = new();
|
||||||
|
|
||||||
|
public IEnumerable<IEnumerable<Emoji>> EmojiChunkList => new ChunkHelper<Emoji>(EmojiList, 8);
|
||||||
|
|
||||||
|
public string Icon => SubGroups.FirstOrDefault()?.Emojis.FirstOrDefault()?.Text;
|
||||||
|
|
||||||
|
public IEnumerable<Emoji> EmojiList
|
||||||
|
=> from s in SubGroups
|
||||||
|
from e in s.Emojis
|
||||||
|
select e;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Emoji
|
||||||
|
{
|
||||||
|
[XmlAttribute]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[XmlAttribute]
|
||||||
|
public string Text { get; set; }
|
||||||
|
|
||||||
|
[XmlArray]
|
||||||
|
public List<Emoji> Variations { get; set; }
|
||||||
|
|
||||||
|
public bool HasVariations => Variations.Count > 0;
|
||||||
|
|
||||||
|
public IEnumerable<Emoji> AllVariations => HasVariations ? new[] { this }.Union(Variations) : Array.Empty<Emoji>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class ChunkHelper<T> : IEnumerable<IEnumerable<T>>
|
sealed class ChunkHelper<T> : IEnumerable<IEnumerable<T>>
|
||||||
{
|
{
|
||||||
public ChunkHelper(IEnumerable<T> elements, int size)
|
public ChunkHelper(IEnumerable<T> elements, int size)
|
||||||
|
@ -227,12 +236,10 @@ namespace Greenshot.Editor.Controls
|
||||||
|
|
||||||
public IEnumerator<IEnumerable<T>> GetEnumerator()
|
public IEnumerator<IEnumerable<T>> GetEnumerator()
|
||||||
{
|
{
|
||||||
using (var enumerator = m_elements.GetEnumerator())
|
using var enumerator = m_elements.GetEnumerator();
|
||||||
{
|
m_has_more = enumerator.MoveNext();
|
||||||
m_has_more = enumerator.MoveNext();
|
while (m_has_more)
|
||||||
while (m_has_more)
|
yield return GetNextBatch(enumerator).ToList();
|
||||||
yield return GetNextBatch(enumerator).ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<T> GetNextBatch(IEnumerator<T> enumerator)
|
private IEnumerable<T> GetNextBatch(IEnumerator<T> enumerator)
|
||||||
|
@ -246,8 +253,7 @@ namespace Greenshot.Editor.Controls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator()
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||||
=> GetEnumerator();
|
|
||||||
|
|
||||||
private readonly IEnumerable<T> m_elements;
|
private readonly IEnumerable<T> m_elements;
|
||||||
private readonly int m_size;
|
private readonly int m_size;
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
|
||||||
|
|
||||||
<ControlTemplate x:Key="VariationPopupTemplate" TargetType="ContentControl">
|
<ControlTemplate x:Key="VariationPopupTemplate" TargetType="ContentControl">
|
||||||
<ListView Name="VariationListView" ItemsSource="{Binding VariationList}"
|
<ListView Name="VariationListView" ItemsSource="{Binding AllVariations}"
|
||||||
BorderThickness="1" Height="Auto" Padding="0" Margin="1"
|
BorderThickness="1" Height="Auto" Padding="0" Margin="1"
|
||||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace Greenshot.Editor.Controls
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IList<EmojiData.Group> EmojiGroups => EmojiData.AllGroups;
|
public IList<Emojis.Group> EmojiGroups => EmojiData.Data.Groups;
|
||||||
|
|
||||||
// Backwards compatibility for when the backend was a TextBlock.
|
// Backwards compatibility for when the backend was a TextBlock.
|
||||||
public double FontSize
|
public double FontSize
|
||||||
|
@ -77,8 +77,8 @@ namespace Greenshot.Editor.Controls
|
||||||
|
|
||||||
private void OnEmojiPicked(object sender, RoutedEventArgs e)
|
private void OnEmojiPicked(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is not Control { DataContext: EmojiData.Emoji emoji }) return;
|
if (sender is not Control { DataContext: Emojis.Emoji emoji }) return;
|
||||||
if (emoji.VariationList.Count != 0 && sender is not Button) return;
|
if (emoji.Variations.Count != 0 && sender is not Button) return;
|
||||||
|
|
||||||
Selection = emoji.Text;
|
Selection = emoji.Text;
|
||||||
Button_INTERNAL.IsChecked = false;
|
Button_INTERNAL.IsChecked = false;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue