Integrated the data in resources, and used it in the application.
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
<Application x:Class="UnicodeCharacterInspector.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:UnicodeCharacterInspector"
|
||||
StartupUri="MainWindow.xaml">
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:UnicodeCharacterInspector"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
|
||||
<local:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Unicode;
|
||||
|
||||
namespace UnicodeCharacterInspector
|
||||
{
|
||||
@@ -11,7 +12,7 @@ namespace UnicodeCharacterInspector
|
||||
{
|
||||
private string character;
|
||||
private int codePoint;
|
||||
private UnicodeCategory category = CharUnicodeInfo.GetUnicodeCategory('\0');
|
||||
private UnicodeCharacterData characterData = UnicodeData.Default.Get(0);
|
||||
|
||||
public CharacterInfoViewModel()
|
||||
{
|
||||
@@ -39,17 +40,20 @@ namespace UnicodeCharacterInspector
|
||||
if ((character = value) != null)
|
||||
{
|
||||
codePoint = char.ConvertToUtf32(character, 0);
|
||||
category = CharUnicodeInfo.GetUnicodeCategory(character, 0);
|
||||
characterData = UnicodeData.Default.Get(codePoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
codePoint = 0;
|
||||
category = CharUnicodeInfo.GetUnicodeCategory('\0');
|
||||
characterData = UnicodeData.Default.Get(0);
|
||||
}
|
||||
|
||||
NotifyPropertyChanged();
|
||||
NotifyPropertyChanged("CodePoint");
|
||||
NotifyPropertyChanged("Name");
|
||||
NotifyPropertyChanged("OldName");
|
||||
NotifyPropertyChanged("Category");
|
||||
NotifyPropertyChanged("ContributoryProperties");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,9 +63,24 @@ namespace UnicodeCharacterInspector
|
||||
get { return character != null ? codePoint : null as int?; }
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return character != null && characterData != null ? characterData.Name : null; }
|
||||
}
|
||||
|
||||
public string OldName
|
||||
{
|
||||
get { return character != null && characterData != null ? characterData.OldName : null; }
|
||||
}
|
||||
|
||||
public UnicodeCategory? Category
|
||||
{
|
||||
get { return character != null ? category : null as UnicodeCategory?; }
|
||||
get { return character != null ? characterData != null ? characterData.Category : UnicodeCategory.OtherNotAssigned : null as UnicodeCategory?; }
|
||||
}
|
||||
|
||||
public ContributoryProperties? ContributoryProperties
|
||||
{
|
||||
get { return character != null ? characterData != null ? characterData.ContributoryProperties : 0 : null as ContributoryProperties?; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,25 +27,47 @@
|
||||
<Style TargetType="{x:Type ListBox}" BasedOn="{StaticResource ResourceKey={x:Type ListBox}}">
|
||||
<Setter Property="Margin" Value="3" />
|
||||
</Style>
|
||||
<Style TargetType="{x:Type ScrollViewer}" BasedOn="{StaticResource ResourceKey={x:Type ScrollViewer}}">
|
||||
<Setter Property="Margin" Value="3" />
|
||||
</Style>
|
||||
</Grid.Resources>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="150" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.ColumnSpan="3" MaxLines="1" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ListBox Grid.Row="1" Grid.RowSpan="4" ItemsSource="{Binding Characters}" SelectedIndex="{Binding SelectedCharacterIndex}" />
|
||||
<TextBox Grid.ColumnSpan="2" MaxLines="1" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ListBox Grid.Row="1" Grid.RowSpan="3" ItemsSource="{Binding Characters}" SelectedIndex="{Binding SelectedCharacterIndex}" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" TextOptions.TextFormattingMode="Ideal" TextOptions.TextRenderingMode="Grayscale" Text="{Binding SelectedCharacterInfo.Character}" FontSize="96" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
<Label Grid.Row="2" Grid.Column="1" Content="Code point" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="2" Text="{Binding SelectedCharacterInfo.CodePoint, StringFormat=U+{0:X4}, TargetNullValue={x:Static System:String.Empty}}" VerticalAlignment="Center" />
|
||||
<Label Grid.Row="3" Grid.Column="1" Content="Category" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="2" Text="{Binding SelectedCharacterInfo.Category}" VerticalAlignment="Center" />
|
||||
<ScrollViewer Grid.Row="2" Grid.Column="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width ="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Label Grid.Row="0" Grid.Column="0" Content="Code point" />
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding SelectedCharacterInfo.CodePoint, StringFormat=U+{0:X4}, TargetNullValue={x:Static System:String.Empty}}" VerticalAlignment="Center" />
|
||||
<Label Grid.Row="1" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.Name, Converter={StaticResource NullToVisibilityConverter}}" Content="Name" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.Name, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.Name}" VerticalAlignment="Center" />
|
||||
<Label Grid.Row="2" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.OldName, Converter={StaticResource NullToVisibilityConverter}}" Content="Old Name" />
|
||||
<TextBlock Grid.Row="2" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.OldName, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.OldName}" VerticalAlignment="Center" />
|
||||
<Label Grid.Row="3" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.Category, Converter={StaticResource NullToVisibilityConverter}}" Content="Category" />
|
||||
<TextBlock Grid.Row="3" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.Category, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.Category}" VerticalAlignment="Center" />
|
||||
<Label Grid.Row="4" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource NullToVisibilityConverter}}" Content="Contributory Properties" />
|
||||
<TextBlock Grid.Row="4" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.ContributoryProperties}" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace UnicodeCharacterInspector
|
||||
{
|
||||
class NullToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value != null ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,6 +70,7 @@
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="NullToVisibilityConverter.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
|
||||
@@ -9,19 +9,10 @@ namespace System.Unicode.Builder
|
||||
{
|
||||
internal static class BinaryWriterExtensions
|
||||
{
|
||||
//public static void WriteUInt24(this BinaryWriter writer, int value)
|
||||
//{
|
||||
// if (value < 0 || value > 0xFFFFFF) throw new ArgumentOutOfRangeException("value");
|
||||
|
||||
// writer.Write((byte)(value));
|
||||
// writer.Write((byte)(value >> 8));
|
||||
// writer.Write((byte)(value >> 16));
|
||||
//}
|
||||
|
||||
/// <summary>Writes code point in a custom, but compact encoding.</summary>
|
||||
/// <remarks>
|
||||
/// Unlike UTF-8, this encoding will consume at most 3 bytes.
|
||||
/// It could ideally store values between 0x0 and 0x40407F, but this range is useless at the moment.
|
||||
/// It could ideally store values between 0x0 and 0x40409F, but this range is useless at the moment.
|
||||
/// </remarks>
|
||||
/// <param name="writer">The binary writer to use.</param>
|
||||
/// <param name="value">The value to write</param>
|
||||
|
||||
@@ -17,6 +17,10 @@ namespace System.Unicode.Builder
|
||||
this.baseDirectory = Path.GetFullPath(baseDirectory);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public Task<Stream> OpenDataFileAsync(string fileName)
|
||||
{
|
||||
return Task.FromResult<Stream>(File.OpenRead(Path.Combine(baseDirectory, fileName)));
|
||||
|
||||
@@ -26,6 +26,11 @@ namespace System.Unicode.Builder
|
||||
this.baseUri = baseUri;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
httpClient.Dispose();
|
||||
}
|
||||
|
||||
public Task<Stream> OpenDataFileAsync(string fileName)
|
||||
{
|
||||
return httpClient.GetStreamAsync(baseUri + fileName);
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode.Builder
|
||||
{
|
||||
public interface IUcdSource
|
||||
public interface IUcdSource : IDisposable
|
||||
{
|
||||
Task<Stream> OpenDataFileAsync(string fileName);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,127 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode.Builder
|
||||
{
|
||||
class Program
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
public const string UcdDirectoryName = "UCD";
|
||||
public const string UcdArchiveName = "UCD.zip";
|
||||
|
||||
public static readonly string[] ucdRequiredFiles = new[]
|
||||
{
|
||||
"UnicodeData.txt",
|
||||
"PropList.txt",
|
||||
"Jamo.txt"
|
||||
};
|
||||
|
||||
private static byte[] DownloadUcdArchive()
|
||||
{
|
||||
using (var httpClient = new HttpClient())
|
||||
{
|
||||
return httpClient.GetByteArrayAsync(HttpUcdSource.UnicodeCharacterDataUri + UcdArchiveName).Result;
|
||||
}
|
||||
}
|
||||
|
||||
internal static IUcdSource GetUcdSource(bool? shouldDownload, bool? shouldSaveArchive, bool? shouldExtract)
|
||||
{
|
||||
string baseDirectory = Environment.CurrentDirectory;
|
||||
string ucdDirectory = Path.Combine(baseDirectory, UcdDirectoryName);
|
||||
string ucdArchiveFileName = Path.Combine(baseDirectory, UcdArchiveName);
|
||||
|
||||
if (shouldDownload != true)
|
||||
{
|
||||
bool hasValidDirectory = Directory.Exists(ucdDirectory);
|
||||
|
||||
if (hasValidDirectory)
|
||||
{
|
||||
foreach (string ucdRequiredFile in ucdRequiredFiles)
|
||||
{
|
||||
if (!File.Exists(Path.Combine(ucdDirectory, ucdRequiredFile)))
|
||||
{
|
||||
hasValidDirectory = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasValidDirectory)
|
||||
{
|
||||
return new FileUcdSource(ucdDirectory);
|
||||
}
|
||||
|
||||
if (File.Exists(ucdArchiveFileName))
|
||||
{
|
||||
if (shouldExtract == true)
|
||||
{
|
||||
ZipFile.ExtractToDirectory(ucdArchiveFileName, ucdDirectory);
|
||||
return new FileUcdSource(ucdDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ZipUcdSource(File.OpenRead(ucdArchiveFileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldDownload != false)
|
||||
{
|
||||
var ucdArchiveData = DownloadUcdArchive();
|
||||
|
||||
if (shouldSaveArchive == true)
|
||||
{
|
||||
var stream = File.Open(ucdArchiveFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
|
||||
try
|
||||
{
|
||||
stream.Write(ucdArchiveData, 0, ucdArchiveData.Length);
|
||||
ucdArchiveData = null; // Release the reference now, since we won't need it anymore.
|
||||
|
||||
if (shouldExtract == true)
|
||||
{
|
||||
using (var archive = new ZipArchive(stream, ZipArchiveMode.Read, false))
|
||||
{
|
||||
archive.ExtractToDirectory(ucdDirectory);
|
||||
|
||||
return new FileUcdSource(ucdDirectory);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ZipUcdSource(stream);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
stream.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return new ZipUcdSource(new MemoryStream(ucdArchiveData));
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
UnicodeDataBuilder data;
|
||||
|
||||
using (var ucdSource = GetUcdSource(null, null, null))
|
||||
{
|
||||
data = UnicodeDataManager.BuildDataAsync(ucdSource).Result;
|
||||
}
|
||||
|
||||
using (var stream = new DeflateStream(File.Create("ucd.dat"), CompressionLevel.Optimal, false))
|
||||
data.WriteToStream(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.IO.Compression.FileSystem" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
@@ -58,6 +60,7 @@
|
||||
<Compile Include="UnicodeDataBuilder.cs" />
|
||||
<Compile Include="UnicodeDataFileReader.cs" />
|
||||
<Compile Include="UnicodeDataManager.cs" />
|
||||
<Compile Include="ZipUcdSource.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\System.Unicode.snk">
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace System.Unicode.Builder
|
||||
{
|
||||
public sealed class ZipUcdSource : IUcdSource
|
||||
{
|
||||
private readonly ZipArchive archive;
|
||||
|
||||
public ZipUcdSource(Stream stream)
|
||||
{
|
||||
archive = new ZipArchive(stream, ZipArchiveMode.Read, false);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
archive.Dispose();
|
||||
}
|
||||
|
||||
public Task<Stream> OpenDataFileAsync(string fileName)
|
||||
{
|
||||
var entry = archive.Entries.Where(e => e.FullName == fileName).FirstOrDefault();
|
||||
|
||||
if (entry == null) throw new FileNotFoundException();
|
||||
|
||||
return Task.FromResult(entry.Open());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ namespace System.Unicode
|
||||
[Flags]
|
||||
public enum ContributoryProperties : int
|
||||
{
|
||||
None = 0x00000000,
|
||||
[ValueName("ASCII_Hex_Digit"), Display(Name = "ASCII_Hex_Digit", Description = "ASCII characters commonly used for the representation of hexadecimal numbers.")]
|
||||
AsciiHexDigit = 0x00000001,
|
||||
[ValueName("Bidi_Control"), Display(Name = "Bidi_Control", Description = "Format control characters which have specific functions in the Unicode Bidirectional Algorithm [UAX9].")]
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -10,6 +12,17 @@ namespace System.Unicode
|
||||
{
|
||||
public sealed class UnicodeData
|
||||
{
|
||||
private static readonly UnicodeData @default = ReadEmbeddedUnicodeData();
|
||||
public static UnicodeData Default { get { return @default; } }
|
||||
|
||||
private static UnicodeData ReadEmbeddedUnicodeData()
|
||||
{
|
||||
using (var stream = new DeflateStream(typeof(UnicodeData).GetTypeInfo().Assembly.GetManifestResourceStream("System.Unicode.ucd.dat"), CompressionMode.Decompress, false))
|
||||
{
|
||||
return FromStream(stream);
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Version unicodeVersion;
|
||||
private readonly UnicodeCharacterData[] characterData;
|
||||
|
||||
@@ -82,11 +95,6 @@ namespace System.Unicode
|
||||
);
|
||||
}
|
||||
|
||||
//private static int ReadInt24(BinaryReader reader)
|
||||
//{
|
||||
// return reader.ReadByte() | ((reader.ReadByte() | (reader.ReadByte() << 8)) << 8);
|
||||
//}
|
||||
|
||||
#if DEBUG
|
||||
internal static int ReadCodePoint(BinaryReader reader)
|
||||
#else
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<Link>System.Unicode.snk</Link>
|
||||
</None>
|
||||
<None Include="app.config" />
|
||||
<EmbeddedResource Include="ucd.dat" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BidirectionalClass.cs" />
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user