forked from AnnoDesigner/anno-designer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created layout preset library dialog (AnnoDesigner#375)
- Loading branch information
Showing
9 changed files
with
661 additions
and
127 deletions.
There are no files selected for viewing
211 changes: 211 additions & 0 deletions
211
AnnoDesigner.Core/Layout/PreparedLayout/PresetLayoutLoader.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,211 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.IO.Compression; | ||
using System.Linq; | ||
using System.Windows.Media; | ||
using System.Windows.Media.Imaging; | ||
using AnnoDesigner.Core.Layout.Models; | ||
using Newtonsoft.Json; | ||
|
||
namespace AnnoDesigner.Core.Layout.PreparedLayout | ||
{ | ||
public interface IPresetLayoutBase | ||
{ | ||
public MultilangInfo Name { get; } | ||
} | ||
|
||
public class PresetLayoutDirectory : IPresetLayoutBase | ||
{ | ||
public MultilangInfo Name { get; set; } | ||
|
||
public List<PresetLayoutDirectory> Directories { get; set; } = new List<PresetLayoutDirectory>(); | ||
|
||
public List<PresetLayout> Layouts { get; set; } = new List<PresetLayout>(); | ||
|
||
public IEnumerable<IPresetLayoutBase> Presets => Directories.Cast<IPresetLayoutBase>().Concat(Layouts); | ||
} | ||
|
||
[JsonConverter(typeof(MultilangInfoConverter))] | ||
public class MultilangInfo | ||
{ | ||
private class MultilangInfoConverter : JsonConverter<MultilangInfo> | ||
{ | ||
public override MultilangInfo ReadJson(JsonReader reader, Type objectType, MultilangInfo existingValue, bool hasExistingValue, JsonSerializer serializer) | ||
{ | ||
switch (reader.TokenType) | ||
{ | ||
case JsonToken.String: | ||
return reader.Value as string; | ||
case JsonToken.StartObject: | ||
return serializer.Deserialize<Dictionary<string, string>>(reader); | ||
default: | ||
throw new JsonSerializationException($"Unexpected token during deserialization of {nameof(MultilangInfo)}"); | ||
} | ||
} | ||
|
||
public override void WriteJson(JsonWriter writer, MultilangInfo value, JsonSerializer serializer) | ||
{ | ||
serializer.Serialize(writer, (object)value.Default ?? value.Translations); | ||
} | ||
} | ||
|
||
private Dictionary<string, string> Translations { get; set; } | ||
|
||
private string Default { get; set; } | ||
|
||
public string this[string language] | ||
{ | ||
set | ||
{ | ||
Translations ??= new Dictionary<string, string>(); | ||
Translations[language] = value; | ||
} | ||
} | ||
|
||
public string Translate(string language) | ||
{ | ||
return Default ?? ( | ||
Translations.TryGetValue(language, out var translation) | ||
? translation | ||
: Translations.Count > 0 | ||
? $"{Translations.FirstOrDefault().Value} ({Translations.FirstOrDefault().Key})" | ||
: string.Empty | ||
); | ||
} | ||
|
||
public static implicit operator MultilangInfo(string value) | ||
{ | ||
return new MultilangInfo() | ||
{ | ||
Default = value | ||
}; | ||
} | ||
|
||
public static implicit operator MultilangInfo(Dictionary<string, string> value) | ||
{ | ||
return new MultilangInfo() | ||
{ | ||
Translations = value | ||
}; | ||
} | ||
|
||
public static explicit operator string(MultilangInfo info) | ||
{ | ||
var first = info.Translations.FirstOrDefault(); | ||
return info.Default ?? (info.Translations.Count > 0 ? $"{first.Value} ({first.Key})" : string.Empty); | ||
} | ||
} | ||
|
||
public class LayoutPresetInfo | ||
{ | ||
public MultilangInfo Name { get; set; } | ||
|
||
public MultilangInfo Description { get; set; } | ||
|
||
public string Author { get; set; } | ||
|
||
public string AuthorContact { get; set; } | ||
} | ||
|
||
public class PresetLayout : IPresetLayoutBase | ||
{ | ||
public MultilangInfo Name => Info.Name; | ||
|
||
public LayoutPresetInfo Info { get; set; } | ||
|
||
public LayoutFile Layout { get; set; } | ||
|
||
public List<ImageSource> Images { get; set; } | ||
} | ||
|
||
public class PresetLayoutLoader | ||
{ | ||
public Func<LayoutFile, ImageSource> RenderLayoutToImage { get; set; } | ||
|
||
public PresetLayoutLoader(Func<LayoutFile, ImageSource> renderLayoutToImage) | ||
{ | ||
RenderLayoutToImage = renderLayoutToImage; | ||
} | ||
|
||
public List<IPresetLayoutBase> Load(string rootDirectory) | ||
{ | ||
var data = LoadDirectory(rootDirectory); | ||
|
||
return data.Directories.Cast<IPresetLayoutBase>().Concat(data.Layouts).ToList(); | ||
} | ||
|
||
private PresetLayoutDirectory LoadDirectory(string directory) | ||
{ | ||
try | ||
{ | ||
return new PresetLayoutDirectory() | ||
{ | ||
Name = Path.GetFileName(directory), | ||
Directories = Directory.GetDirectories(directory).Select(LoadDirectory).Where(d => d != null).ToList(), | ||
Layouts = Directory.GetFiles(directory, "*.zip").Select(LoadLayout).Where(f => f != null).ToList() | ||
}; | ||
} | ||
catch { /* TODO log */ } | ||
|
||
return null; | ||
} | ||
|
||
private PresetLayout LoadLayout(string file) | ||
{ | ||
try | ||
{ | ||
var images = new List<ImageSource>(); | ||
LayoutFile layout = null; | ||
var info = new LayoutPresetInfo() | ||
{ | ||
Name = Path.GetFileNameWithoutExtension(file) | ||
}; | ||
|
||
using var zipFile = ZipFile.OpenRead(file); | ||
foreach (var item in zipFile.Entries) | ||
{ | ||
using var stream = item.Open(); | ||
switch (Path.GetExtension(item.FullName).ToLowerInvariant()) | ||
{ | ||
case ".png": | ||
case ".jpg": | ||
case ".jpeg": | ||
var imageStream = new MemoryStream(); | ||
stream.CopyTo(imageStream); | ||
var image = new BitmapImage(); | ||
image.BeginInit(); | ||
image.StreamSource = imageStream; | ||
image.EndInit(); | ||
image.Freeze(); | ||
images.Add(image); | ||
break; | ||
case ".ad": | ||
layout = new LayoutLoader().LoadLayout(stream, true); | ||
images.Insert(0, RenderLayoutToImage(layout)); | ||
break; | ||
case ".json": | ||
using (var streamReader = new StreamReader(stream)) | ||
{ | ||
info = JsonConvert.DeserializeObject<LayoutPresetInfo>(streamReader.ReadToEnd()); | ||
} | ||
break; | ||
} | ||
} | ||
|
||
if (layout != null) | ||
{ | ||
return new PresetLayout() | ||
{ | ||
Info = info, | ||
Layout = layout, | ||
Images = images | ||
}; | ||
} | ||
} | ||
catch { /* TODO log */ } | ||
|
||
return null; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
using System; | ||
using System.Globalization; | ||
using System.Windows.Data; | ||
|
||
namespace AnnoDesigner.Converters | ||
{ | ||
[ValueConversion(typeof(object), typeof(bool))] | ||
public class ReferenceToBooleanConverter : IValueConverter | ||
{ | ||
public bool NullValue { get; set; } | ||
|
||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | ||
{ | ||
return value == null == NullValue; | ||
} | ||
|
||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
|
||
[ValueConversion(typeof(object), typeof(bool))] | ||
public class ReferenceTypeToBooleanConverter : IValueConverter | ||
{ | ||
public Type ExpectedType { get; set; } | ||
|
||
public bool ValueOnCorrectType { get; set; } | ||
|
||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) | ||
{ | ||
return (value != null && value.GetType() == ExpectedType) == ValueOnCorrectType; | ||
} | ||
|
||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) | ||
{ | ||
throw new NotImplementedException(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.