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 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 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> s_dGlyphCache = new Dictionary, Tuple>(); private static double[] s_aGlyphWidths = new double[1024]; } }