Added a placeholder text in the text box, and made a few other UI tweaks.
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
<Window.DataContext>
|
||||
<local:CharacterInspectorViewModel />
|
||||
</Window.DataContext>
|
||||
<Grid Margin="10">
|
||||
<Grid Margin="10">
|
||||
<Grid.Resources>
|
||||
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource ResourceKey={x:Type Label}}">
|
||||
<Setter Property="Margin" Value="3" />
|
||||
@@ -37,7 +37,7 @@
|
||||
<ColumnDefinition Width="120" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBox Grid.ColumnSpan="2" ScrollViewer.VerticalScrollBarVisibility="Auto" MinLines="1" MaxLines="5" AcceptsReturn="True" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<TextBox Grid.ColumnSpan="2" ScrollViewer.VerticalScrollBarVisibility="Auto" MinLines="1" MaxLines="5" AcceptsTab="True" AcceptsReturn="True" local:Placeholder.Text="Text to analyse" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ListBox Grid.Row="1" Grid.RowSpan="3" ItemsSource="{Binding Characters}" SelectedIndex="{Binding SelectedCharacterIndex}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
@@ -45,7 +45,7 @@
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" TextOptions.TextFormattingMode="Ideal" TextOptions.TextRenderingMode="Grayscale" Text="{Binding SelectedCharacterInfo.DisplayText}" FontSize="96" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" TextOptions.TextHintingMode="Fixed" TextOptions.TextFormattingMode="Ideal" TextOptions.TextRenderingMode="Grayscale" Text="{Binding SelectedCharacterInfo.DisplayText}" FontSize="96" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
<ScrollViewer Grid.Row="2" Grid.Column="1" VerticalScrollBarVisibility="Auto">
|
||||
<Grid>
|
||||
<Grid.Resources>
|
||||
@@ -126,11 +126,11 @@
|
||||
<TextBlock Grid.Row="19" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.UnihanNumericType, Converter={StaticResource ZeroToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.UnihanNumericType}" />
|
||||
<TextBlock Grid.Row="20" Grid.Column="0" Visibility="{Binding SelectedCharacterInfo.NumericValue, Converter={StaticResource NullToVisibilityConverter}}" Text="Numeric Value" />
|
||||
<TextBlock Grid.Row="20" Grid.Column="1" Visibility="{Binding SelectedCharacterInfo.NumericValue, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.NumericValue}" />
|
||||
<TextBlock Grid.Row="21" Grid.Column="0" VerticalAlignment="Top" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource NullToVisibilityConverter}}" Text="Contributory Properties" />
|
||||
<TextBlock Grid.Row="21" Grid.Column="1" VerticalAlignment="Top" TextWrapping="WrapWithOverflow" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.ContributoryProperties}" />
|
||||
<TextBlock Grid.Row="22" Grid.Column="0" VerticalAlignment="Top" Visibility="{Binding SelectedCharacterInfo.CoreProperties, Converter={StaticResource NullToVisibilityConverter}}" Text="Core Properties" />
|
||||
<TextBlock Grid.Row="22" Grid.Column="1" VerticalAlignment="Top" TextWrapping="WrapWithOverflow" Visibility="{Binding SelectedCharacterInfo.CoreProperties, Converter={StaticResource NullToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.CoreProperties}" />
|
||||
<TextBlock Grid.Row="21" Grid.Column="0" VerticalAlignment="Top" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource ZeroToVisibilityConverter}}" Text="Contributory Properties" />
|
||||
<TextBlock Grid.Row="21" Grid.Column="1" VerticalAlignment="Top" TextWrapping="WrapWithOverflow" Visibility="{Binding SelectedCharacterInfo.ContributoryProperties, Converter={StaticResource ZeroToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.ContributoryProperties}" />
|
||||
<TextBlock Grid.Row="22" Grid.Column="0" VerticalAlignment="Top" Visibility="{Binding SelectedCharacterInfo.CoreProperties, Converter={StaticResource ZeroToVisibilityConverter}}" Text="Core Properties" />
|
||||
<TextBlock Grid.Row="22" Grid.Column="1" VerticalAlignment="Top" TextWrapping="WrapWithOverflow" Visibility="{Binding SelectedCharacterInfo.CoreProperties, Converter={StaticResource ZeroToVisibilityConverter}}" Text="{Binding SelectedCharacterInfo.CoreProperties}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace UnicodeCharacterInspector
|
||||
{
|
||||
// Inspired by http://stackoverflow.com/questions/833943/watermark-hint-text-placeholder-textbox-in-wpf
|
||||
internal static partial class Placeholder
|
||||
{
|
||||
public static string GetText(DependencyObject obj)
|
||||
{
|
||||
return (string)obj.GetValue(TextProperty);
|
||||
}
|
||||
|
||||
public static void SetText(DependencyObject obj, string value)
|
||||
{
|
||||
obj.SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.RegisterAttached("Text", typeof(string), typeof(Placeholder), new PropertyMetadata(OnTextChanged));
|
||||
|
||||
private static readonly HashSet<Control> handledControls = new HashSet<Control>();
|
||||
|
||||
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var control = d as TextBoxBase;
|
||||
|
||||
if (d == null) return;
|
||||
|
||||
if (e.NewValue == null || "".Equals(e.NewValue)) UnregisterControl(control);
|
||||
else UpdateControl(control, (string)e.NewValue);
|
||||
}
|
||||
|
||||
private static void OnControlLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var control = (Control)sender;
|
||||
UpdateControl(control, GetText(control));
|
||||
}
|
||||
|
||||
private static void OnTextBoxGotKeyboardFocus(object sender, System.Windows.Input.KeyboardFocusChangedEventArgs e)
|
||||
{
|
||||
var control = (Control)sender;
|
||||
RemoveAdorner(control);
|
||||
}
|
||||
|
||||
private static void UpdateControl(Control control, string placeholderText)
|
||||
{
|
||||
if (handledControls.Add(control))
|
||||
{
|
||||
RegisterControl(control);
|
||||
}
|
||||
|
||||
if (IsEmpty(control))
|
||||
{
|
||||
var adorner = GetAdorner(control) ?? AddAdorner(control);
|
||||
if (adorner != null) adorner.Text = placeholderText;
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveAdorner(control);
|
||||
}
|
||||
}
|
||||
|
||||
private static void RegisterControl(Control control)
|
||||
{
|
||||
control.Loaded += OnControlLoaded;
|
||||
|
||||
var textBox = control as TextBoxBase;
|
||||
if (textBox != null) RegisterTextBox(textBox);
|
||||
}
|
||||
|
||||
private static void RegisterTextBox(TextBoxBase textBox)
|
||||
{
|
||||
textBox.GotKeyboardFocus += OnTextBoxGotKeyboardFocus;
|
||||
textBox.LostKeyboardFocus += OnControlLoaded;
|
||||
}
|
||||
|
||||
private static void UnregisterControl(Control control)
|
||||
{
|
||||
if (handledControls.Remove(control))
|
||||
{
|
||||
control.Loaded -= OnControlLoaded;
|
||||
|
||||
var textBox = control as TextBoxBase;
|
||||
if (textBox != null) UnregisterTextBox(textBox);
|
||||
|
||||
RemoveAdorner(control);
|
||||
}
|
||||
}
|
||||
|
||||
private static void UnregisterTextBox(TextBoxBase textBox)
|
||||
{
|
||||
textBox.GotKeyboardFocus -= OnTextBoxGotKeyboardFocus;
|
||||
textBox.LostKeyboardFocus -= OnControlLoaded;
|
||||
}
|
||||
|
||||
private static bool IsEmpty(Control control)
|
||||
{
|
||||
var textBox = control as TextBox;
|
||||
|
||||
if (textBox != null) return string.IsNullOrEmpty(textBox.Text);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static PlaceholderAdorner GetAdorner(Control control)
|
||||
{
|
||||
var layer = AdornerLayer.GetAdornerLayer(control);
|
||||
|
||||
if (layer != null)
|
||||
{
|
||||
var adorners = layer.GetAdorners(control);
|
||||
|
||||
if (adorners != null)
|
||||
{
|
||||
foreach (var adorner in adorners)
|
||||
{
|
||||
var placeholder = adorner as PlaceholderAdorner;
|
||||
|
||||
if (placeholder != null) return placeholder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PlaceholderAdorner AddAdorner(Control control)
|
||||
{
|
||||
var layer = AdornerLayer.GetAdornerLayer(control);
|
||||
|
||||
if (layer == null) return null;
|
||||
|
||||
var placeholder = new PlaceholderAdorner(control);
|
||||
|
||||
layer.Add(placeholder);
|
||||
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
private static void RemoveAdorner(Control control)
|
||||
{
|
||||
var layer = AdornerLayer.GetAdornerLayer(control);
|
||||
|
||||
if (layer == null) return;
|
||||
|
||||
var adorners = layer.GetAdorners(control);
|
||||
|
||||
if (adorners == null) return;
|
||||
|
||||
foreach (var adorner in adorners)
|
||||
{
|
||||
var placeholder = adorner as PlaceholderAdorner;
|
||||
|
||||
if (placeholder != null)
|
||||
{
|
||||
layer.Remove(placeholder);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
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.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace UnicodeCharacterInspector
|
||||
{
|
||||
internal static partial class Placeholder
|
||||
{
|
||||
private sealed class PlaceholderAdorner : Adorner
|
||||
{
|
||||
public string Text { get; set; }
|
||||
|
||||
public PlaceholderAdorner(UIElement adornedElement)
|
||||
: base(adornedElement)
|
||||
{
|
||||
IsHitTestVisible = false;
|
||||
}
|
||||
|
||||
protected override Visual GetVisualChild(int index) { throw new InvalidOperationException(); }
|
||||
|
||||
protected override int VisualChildrenCount { get { return 0; } }
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext)
|
||||
{
|
||||
var control = ((Control)AdornedElement);
|
||||
|
||||
Rect adornedElementRect = new Rect(AdornedElement.RenderSize);
|
||||
drawingContext.DrawText
|
||||
(
|
||||
new FormattedText
|
||||
(
|
||||
Text,
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
new Typeface
|
||||
(
|
||||
control.FontFamily,
|
||||
control.FontStyle,
|
||||
control.FontWeight,
|
||||
control.FontStretch,
|
||||
SystemFonts.MessageFontFamily
|
||||
),
|
||||
control.FontSize,
|
||||
SystemColors.GrayTextBrush
|
||||
),
|
||||
// The offsets where experimentally determined on a Windows 8.1 machine. I'm willing to accept anything better. 😉
|
||||
new Point(control.BorderThickness.Left + control.Padding.Left + 5, control.BorderThickness.Top + control.Padding.Top + 3)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,10 @@
|
||||
<Compile Include="BindableObject.cs" />
|
||||
<Compile Include="CharacterInfoViewModel.cs" />
|
||||
<Compile Include="CharacterInspectorViewModel.cs" />
|
||||
<Compile Include="Placeholder.cs" />
|
||||
<Compile Include="PlaceholderAdorner.cs">
|
||||
<DependentUpon>Placeholder.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ZeroToVisibilityConverter.cs" />
|
||||
<Compile Include="MainWindow.xaml.cs">
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
|
||||
Reference in New Issue
Block a user