168 lines
5.2 KiB
C#
168 lines
5.2 KiB
C#
using Tool.Layout.ViewModels;
|
|
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.Data;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Media.Imaging;
|
|
using System.Windows.Navigation;
|
|
using System.Windows.Shapes;
|
|
using Tool.ViewModels;
|
|
using System.Collections.ObjectModel;
|
|
|
|
namespace Tool.Layout.Views
|
|
{
|
|
public class ViewBase : UserControl
|
|
{
|
|
public ViewBase()
|
|
{
|
|
this.Loaded += ViewBase_Loaded;
|
|
this.Unloaded += ViewBase_Unloaded;
|
|
Dispatcher.ShutdownStarted += Dispatcher_ShutdownStarted;
|
|
}
|
|
|
|
void Dispatcher_ShutdownStarted(object sender, EventArgs e)
|
|
{
|
|
if (ViewModel != null)
|
|
{
|
|
ViewModel.RemoveView(this);
|
|
}
|
|
}
|
|
|
|
protected virtual void ViewBase_Unloaded(object sender, RoutedEventArgs e)
|
|
{
|
|
if (ViewModel != null)
|
|
{
|
|
ViewModel.RemoveView(this);
|
|
}
|
|
}
|
|
|
|
protected virtual void ViewBase_Loaded(object sender, RoutedEventArgs e)
|
|
{
|
|
if (ViewModel != null)
|
|
{
|
|
ViewModel.AddView(this);
|
|
}
|
|
}
|
|
|
|
public static DependencyProperty LeafProperty = DependencyProperty.Register("Leaf", typeof(LeafViewModel), typeof(ViewBase), new FrameworkPropertyMetadata());
|
|
public LeafViewModel Leaf
|
|
{
|
|
get
|
|
{
|
|
return GetValue(LeafProperty) as LeafViewModel;
|
|
}
|
|
set
|
|
{
|
|
SetValue(LeafProperty, value);
|
|
}
|
|
}
|
|
|
|
public static readonly DependencyProperty ToolBarTemplateProperty = DependencyProperty.Register("ToolBarTemplate", typeof(ControlTemplate), typeof(LeafView), new FrameworkPropertyMetadata());
|
|
public ControlTemplate ToolBarTemplate
|
|
{
|
|
get
|
|
{
|
|
return GetValue(ToolBarTemplateProperty) as ControlTemplate;
|
|
}
|
|
set
|
|
{
|
|
SetValue(ToolBarTemplateProperty, value);
|
|
}
|
|
}
|
|
|
|
public ViewModelBase ViewModel
|
|
{
|
|
get
|
|
{
|
|
return this.DataContext as ViewModelBase;
|
|
}
|
|
}
|
|
|
|
public static void DrawText(DrawingContext _context, Brush _brush, Point _point, string _sText, Brush _backgroundBrush = null, HorizontalAlignment _eHAlignment = HorizontalAlignment.Left, VerticalAlignment _eVAlignment = VerticalAlignment.Top)
|
|
{
|
|
var rect = new Rect(_point, new Size());
|
|
DrawText(_context, _brush, ref rect, _sText, _backgroundBrush, _eHAlignment, _eVAlignment);
|
|
}
|
|
|
|
public static void DrawText(DrawingContext _context, Brush _brush, ref Rect _rect, string _sText, Brush _backgroundBrush = null, HorizontalAlignment _eHAlignment = HorizontalAlignment.Left, VerticalAlignment _eVAlignment = VerticalAlignment.Top)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(_sText))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var geo = CreateTextGeometry(_sText, 12.0, _rect.Location, _eHAlignment, _eVAlignment);
|
|
if (_backgroundBrush != null)
|
|
{
|
|
_rect = new Rect(_rect.Location, new Size(Math.Max(_rect.Width, geo.Item2), Math.Max(_rect.Height, geo.Item3)));
|
|
_context.DrawRectangle(_backgroundBrush, null, _rect);
|
|
}
|
|
_context.DrawGlyphRun(_brush, geo.Item1);
|
|
}
|
|
|
|
public static Tuple<GlyphRun, double, double> CreateTextGeometry(string _sText, double _fSize, Point _position, HorizontalAlignment _eHAlignment = HorizontalAlignment.Left, VerticalAlignment _eVAlignment = VerticalAlignment.Top)
|
|
{
|
|
if (s_GlyphTypeface == null)
|
|
{
|
|
Typeface typeface = new Typeface("Consolas");
|
|
if (!typeface.TryGetGlyphTypeface(out s_GlyphTypeface))
|
|
{
|
|
throw new InvalidOperationException("No glyphtypeface found");
|
|
}
|
|
}
|
|
|
|
var key = Tuple.Create(_sText, _fSize);
|
|
Tuple<double, ushort[], double[]> cache;
|
|
if (!s_dGlyphCache.TryGetValue(key, out cache))
|
|
{
|
|
var totalWidth = 0d;
|
|
int n = 0;
|
|
var aGlyphIndices = new ushort[_sText.Length];
|
|
var aAdvanceWidths = new double[_sText.Length];
|
|
for (; n < _sText.Length; n++)
|
|
{
|
|
ushort glyphIndex = s_GlyphTypeface.CharacterToGlyphMap[_sText[n]];
|
|
|
|
var glyphWidth = s_aGlyphWidths[glyphIndex];
|
|
if (glyphWidth == 0.0)
|
|
{
|
|
glyphWidth = s_GlyphTypeface.AdvanceWidths[glyphIndex] * _fSize;
|
|
s_aGlyphWidths[glyphIndex] = glyphWidth;
|
|
}
|
|
|
|
aGlyphIndices[n] = glyphIndex;
|
|
aAdvanceWidths[n] = glyphWidth;
|
|
totalWidth += glyphWidth;
|
|
}
|
|
s_dGlyphCache[key] = cache = Tuple.Create(totalWidth, aGlyphIndices, aAdvanceWidths);
|
|
}
|
|
|
|
var offsetPosition = new Point(Math.Floor(_position.X), Math.Floor(_position.Y + _fSize));
|
|
switch (_eHAlignment)
|
|
{
|
|
case HorizontalAlignment.Center: offsetPosition.X -= cache.Item1 * 0.5; break;
|
|
case HorizontalAlignment.Right: offsetPosition.X -= cache.Item1; break;
|
|
}
|
|
switch (_eVAlignment)
|
|
{
|
|
case VerticalAlignment.Center: offsetPosition.Y -= _fSize * 0.5; break;
|
|
case VerticalAlignment.Bottom: offsetPosition.Y -= _fSize; break;
|
|
}
|
|
|
|
var gr = new GlyphRun(s_GlyphTypeface, 0, false, _fSize, cache.Item2, offsetPosition, cache.Item3, null, null, null, null, null, null);
|
|
return Tuple.Create(gr, cache.Item1, _fSize);
|
|
}
|
|
|
|
private static GlyphTypeface s_GlyphTypeface;
|
|
private static Dictionary<Tuple<string, double>, Tuple<double, ushort[], double[]>> s_dGlyphCache = new Dictionary<Tuple<string, double>, Tuple<double, ushort[], double[]>>();
|
|
private static double[] s_aGlyphWidths = new double[1024];
|
|
}
|
|
}
|