using Noesis; using NoesisGUIExtensions; using StellarConquest.Model.Universe; namespace StellarConquest.Presentation.Unity.UI { public partial class BorderControlBorderless : ContentControl { private Path _PanelBlur; private Path _PanelColor; private Path _DecorTop; private Path _DecorBottom; public event EventHandler Ready; private float _ContentWidth = 0; private float _ContentHeight = 0; public static readonly DependencyProperty PanelFillBrushProperty = DependencyProperty.Register("PanelFillBrush", typeof(Brush), typeof(BorderControlBorderless)); public static readonly DependencyProperty PanelStrokeBrushProperty = DependencyProperty.Register("PanelStrokeBrush", typeof(Brush), typeof(BorderControlBorderless)); public static readonly DependencyProperty BlurLayerProperty = DependencyProperty.Register("BlurLayer", typeof(FrameworkElement), typeof(BorderControlBorderless), new PropertyMetadata(null)); private bool _TemplateApplied = false; public Brush PanelFillBrush { get { return GetValue(PanelFillBrushProperty) as Brush; } set { SetValue(PanelFillBrushProperty, value); } } public Brush PanelStrokeBrush { get { return GetValue(PanelStrokeBrushProperty) as Brush; } set { SetValue(PanelStrokeBrushProperty, value); } } public FrameworkElement BlurLayer { get { return (FrameworkElement)GetValue(BlurLayerProperty); } set { SetValue(BlurLayerProperty, value); } } public BorderControlBorderless() { Style = FindResource("BorderControlBorderless") as Style; Loaded += (sender, e) => Build(); SizeChanged += (sender, e) => Build(); PanelFillBrush = FindResource("DefaultUI.Brush.Bottom.Gradient") as Brush; PanelStrokeBrush = FindResource("DefaultUI.Brush.Border") as Brush; } public override void OnApplyTemplate() { base.OnApplyTemplate(); if (Template != null) { _PanelBlur = GetTemplateChild("_PanelBlur") as Path; _PanelColor = GetTemplateChild("_PanelColor") as Path; _DecorTop = GetTemplateChild("_DecorTop") as Path; _DecorBottom = GetTemplateChild("_DecorBottom") as Path; _TemplateApplied = true; } } public void Resize() { if (_TemplateApplied && Parent != null && View != null) { _ContentWidth = 0; _ContentHeight = 0; _PanelBlur.Data = null; _PanelColor.Data = null; UpdateLayout(); Build(); } } private void Build() { if (!_TemplateApplied) return; FrameworkElement content = (FrameworkElement)Content; float contentWidth; float contentHeight; if (content != null) { contentWidth = content.ActualWidth + content.Margin.Left + content.Margin.Right - 2; contentHeight = content.ActualHeight + content.Margin.Top + content.Margin.Bottom - 2; } else { contentWidth = Width; contentHeight = Height; } // we should compare via equals. But here we do a less than comparison due to rounding // errors in the path data. The ideal solution is to recreate the path using integer values // to eliminate rounding errors if (contentWidth <= _ContentWidth && contentHeight <= _ContentHeight) return; // Noesis Bug FIX. Noesis sometimes resets ResourcesCommon which // affects TopBlurRadius and BottomBlurRadius. To prevent a zero value // from affecting background effects, here, we reapply the values. PlayerPreferences.Instance.ApplyBackgroundBlur(); _ContentWidth = contentWidth; _ContentHeight = contentHeight; // primary dimensions float width = _ContentWidth; float height = _ContentHeight; // main panel float bevelSize = 10.0f; StreamGeometry geometry = new StreamGeometry(); using (StreamGeometryContext ctx = geometry.Open()) { // Top Left Bevel ctx.BeginFigure(new Point(bevelSize, 0.0f), true, true); ctx.LineTo(new Point(width - bevelSize, 0.0f), true, false); // Top Edge // Top Right Bevel ctx.LineTo(new Point(width, bevelSize), true, false); ctx.LineTo(new Point(width, height - bevelSize), true, false); // Right Edge // Bottom Right Bevel ctx.LineTo(new Point(width - bevelSize, height), true, false); ctx.LineTo(new Point(bevelSize, height), true, false); // Bottom Edge // Bottom Left Bevel ctx.LineTo(new Point(0.0f, height - bevelSize), true, false); ctx.LineTo(new Point(0.0f, bevelSize), true, false); // Left Edge ctx.Close(); } _PanelBlur.Data = geometry; _PanelColor.Data = geometry; // top decor float thickness = 1.5f; StreamGeometry topGeometry = new StreamGeometry(); using (StreamGeometryContext ctx = topGeometry.Open()) { ctx.BeginFigure(new Point(0f, bevelSize), true, true); ctx.LineTo(new Point(bevelSize, 0f), true, false); ctx.LineTo(new Point(width - bevelSize, 0f), true, false); ctx.LineTo(new Point(width, bevelSize), true, false); ctx.LineTo(new Point(width - bevelSize, thickness), true, false); ctx.LineTo(new Point(bevelSize, thickness), true, false); ctx.Close(); } _DecorTop.Data = topGeometry; // bottom decor StreamGeometry bottomGeometry = new StreamGeometry(); using (StreamGeometryContext ctx = bottomGeometry.Open()) { ctx.BeginFigure(new Point(0f, thickness - bevelSize), true, true); ctx.LineTo(new Point(bevelSize, thickness), true, false); ctx.LineTo(new Point(width - bevelSize, thickness), true, false); ctx.LineTo(new Point(width, thickness - bevelSize), true, false); ctx.LineTo(new Point(width - bevelSize, 0f), true, false); ctx.LineTo(new Point(bevelSize, 0f), true, false); ctx.Close(); } _DecorBottom.Data = bottomGeometry; Ready?.Invoke(this, EventArgs.Empty); } public Geometry ContentGeometry { get { return _PanelColor.Data; } } public void SetAlertLevel(AlertLevelType value) { switch (value) { case AlertLevelType.Nominal: PanelFillBrush = FindResource("DefaultUI.Brush.Bottom.Gradient") as Brush; PanelStrokeBrush = FindResource("DefaultUI.Brush.Border") as Brush; //DecorFillBrush = FindResource("DefaultUI.Brush.Decor.Gradient") as Brush; break; case AlertLevelType.Medium: PanelFillBrush = FindResource("DefaultUI.Brush.Bottom.Gradient.HighAlert") as Brush; PanelStrokeBrush = FindResource("DefaultUI.Brush.Border.HighAlert") as Brush; //DecorFillBrush = FindResource("DefaultUI.Brush.Decor.Gradient.HighAlert") as Brush; break; case AlertLevelType.High: PanelFillBrush = FindResource("DefaultUI.Brush.Bottom.Gradient.HighAlert") as Brush; PanelStrokeBrush = FindResource("DefaultUI.Brush.Border.HighAlert") as Brush; //DecorFillBrush = FindResource("DefaultUI.Brush.Decor.Gradient.HighAlert") as Brush; break; default: break; } } } }