This commit is contained in:
Bret Johnson 2021-10-12 12:05:47 -04:00
Родитель d4a6183103
Коммит 2c63ccdd39
13 изменённых файлов: 172 добавлений и 225 удалений

Просмотреть файл

@ -4,7 +4,7 @@ namespace Microsoft.StandardUI.VisualEnvironment.WpfNative
{
public class WpfNativeVisualEnvironment : IVisualEnvironment
{
public IVisualizer CreateVisualizer(in Rect cullingRect) => new WpfNativeVisualizer(cullingRect);
public IDrawingContext CreateDrawingContext(in Rect cullingRect) => new WpfNativeVisualizer(cullingRect);
public void RenderToBuffer(IVisual visual, IntPtr pixels, int width, int height, int rowBytes)
{

Просмотреть файл

@ -1,52 +1,60 @@
using Microsoft.StandardUI.Controls;
using System;
using System.Windows;
using System.Windows.Media;
namespace Microsoft.StandardUI.Wpf
{
public class StandardUIControlWpf : System.Windows.Controls.Control, IStandardUIControlEnvironmentPeer
public class StandardControl<TControl> : System.Windows.Controls.Control, IControl, IStandardControlEnvironmentPeer where TControl : IControl
{
private StandardUIControl _standardUIControl;
private ControlTemplateWpf? _controlTemplateWpf;
private StandardControlImplementation<TControl> _implementation;
private StandardUIFrameworkElement? _buildContent;
public StandardUIControlWpf(StandardUIControl standardUIControl)
protected void InitImplementation(StandardControlImplementation<TControl> implementation)
{
_standardUIControl = standardUIControl;
_implementation = implementation;
_buildContent = (StandardUIFrameworkElement?)implementation.Build();
Width = standardUIControl.Width;
MinWidth = standardUIControl.MinWidth;
MaxWidth = standardUIControl.MaxWidth;
Height = standardUIControl.Height;
MinHeight = standardUIControl.MinHeight;
MaxHeight = standardUIControl.MaxHeight;
if (_buildContent != null)
{
AddVisualChild(_buildContent);
AddLogicalChild(_buildContent);
}
}
void IUIElement.Measure(Size availableSize)
{
Measure(availableSize.ToWpfSize());
}
void IUIElement.Arrange(Rect finalRect)
{
Arrange(finalRect.ToWpfRect());
}
Size IUIElement.DesiredSize => SizeExtensions.FromWpfSize(DesiredSize);
IUIPropertyObject? IControl.GetTemplateChild(string childName)
{
throw new System.NotImplementedException();
}
protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint)
{
_standardUIControl.Measure(new Size(constraint.Width, constraint.Height));
return _standardUIControl.DesiredSize.ToWpfSize();
_implementation.Measure(new Size(constraint.Width, constraint.Height));
return _implementation.DesiredSize.ToWpfSize();
}
protected override System.Windows.Size ArrangeOverride(System.Windows.Size arrangeSize)
{
_standardUIControl.Arrange(new Rect(0, 0, arrangeSize.Width, arrangeSize.Height));
_implementation.Arrange(new Rect(0, 0, arrangeSize.Width, arrangeSize.Height));
return arrangeSize;
}
/*
protected override int VisualChildrenCount => _standardUIControl.Content != null ? 1 : 0;
double IUIElement.ActualX => throw new System.NotImplementedException();
protected override Visual GetVisualChild(int index)
{
IUIElement? content = _standardUIControl.Content;
if (content == null)
throw new ArgumentOutOfRangeException("index", index, "Control has no content");
if (index != 0)
throw new ArgumentOutOfRangeException("index", index, "Index out of range; control only has a single visual child.");
return (Visual)content;
}
*/
double IUIElement.ActualY => throw new System.NotImplementedException();
public object GetValue(IUIProperty dp)
{
@ -66,7 +74,22 @@ namespace Microsoft.StandardUI.Wpf
SetValue(wpfDependencyProperty, value);
}
IControlTemplate? IStandardUIControlEnvironmentPeer.Template
protected override int VisualChildrenCount => _buildContent != null ? 1 : 0;
IUIElement? IStandardControlEnvironmentPeer.BuildContent => _buildContent;
protected override Visual GetVisualChild(int index)
{
if (_buildContent == null)
throw new ArgumentOutOfRangeException("index", index, "Control returned null from build");
if (index != 0)
throw new ArgumentOutOfRangeException("index", index, "Index out of range; control only has a single visual child.");
return _buildContent;
}
#if false
IControlTemplate? IControl.Template
{
get
{
@ -90,7 +113,9 @@ namespace Microsoft.StandardUI.Wpf
_controlTemplateWpf = controlTemplateWpf;
}
}
#endif
#if false
IUIPropertyObject? IStandardUIControlEnvironmentPeer.GetTemplateChild(string childName)
{
System.Windows.DependencyObject? child = this.GetTemplateChild(childName);
@ -100,5 +125,6 @@ namespace Microsoft.StandardUI.Wpf
// TODO:Finish this
return null;
}
#endif
}
}

Просмотреть файл

@ -43,10 +43,6 @@ namespace Microsoft.StandardUI.Wpf
public IPolyQuadraticBezierSegment CreatePolyQuadraticBezierSegment(Points points) => throw new NotImplementedException();
public IQuadraticBezierSegment CreateQuadraticBezierSegment(in Point point1, in Point point2) => throw new NotImplementedException();
/*** Environment peers ***/
public IStandardUIControlEnvironmentPeer CreateStandardUIControlEnvironmentPeer(StandardUIControl standardUIControl) => new StandardUIControlWpf(standardUIControl);
/*** Infrastructure objects ***/
public IUIPropertyMetadata CreatePropertyMetadata(object defaultValue) => throw new NotImplementedException();

Просмотреть файл

@ -11,12 +11,12 @@ namespace Microsoft.StandardUI.Wpf
{
StandardUIFrameworkElementHelper _helper = new StandardUIFrameworkElementHelper();
public void Measure(Size availableSize)
void IUIElement.Measure(Size availableSize)
{
Measure(availableSize.ToWpfSize());
}
public void Arrange(Rect finalRect)
void IUIElement.Arrange(Rect finalRect)
{
Arrange(finalRect.ToWpfRect());
}
@ -39,7 +39,7 @@ namespace Microsoft.StandardUI.Wpf
Rect cullingRect = new Rect(0, 0, 200, 200);
IVisual visual;
using (IVisualizer visualizer = visualEnvironment.CreateVisualizer(cullingRect)) {
using (IDrawingContext visualizer = visualEnvironment.CreateDrawingContext(cullingRect)) {
OnVisualize(visualizer);
visual = visualizer.End();
}
@ -53,7 +53,7 @@ namespace Microsoft.StandardUI.Wpf
InvalidateVisual();
}
public virtual void OnVisualize(IVisualizer visualizer)
public virtual void OnVisualize(IDrawingContext visualizer)
{
}

Просмотреть файл

@ -1,41 +0,0 @@
using Microsoft.StandardUI.Controls;
using System;
using System.Windows.Media;
namespace Microsoft.StandardUI.Wpf
{
public class StandardUIUserControlWpf : StandardUIControlWpf
{
private StandardUIUserControl _userControl;
public StandardUIUserControlWpf(StandardUIUserControl userControl) : base(userControl)
{
_userControl = userControl;
Width = userControl.Width;
MinWidth = userControl.MinWidth;
MaxWidth = userControl.MaxWidth;
Height = userControl.Height;
MinHeight = userControl.MinHeight;
MaxHeight = userControl.MaxHeight;
var content = (System.Windows.UIElement?) userControl.Content;
if (content != null)
AddLogicalChild(content);
}
protected override int VisualChildrenCount => _userControl.Content != null ? 1 : 0;
protected override Visual GetVisualChild(int index)
{
IUIElement? content = _userControl.Content;
if (content == null)
throw new ArgumentOutOfRangeException("index", index, "Control has no content");
if (index != 0)
throw new ArgumentOutOfRangeException("index", index, "Index out of range; control only has a single visual child.");
return (Visual)content;
}
}
}

Просмотреть файл

@ -0,0 +1,7 @@
namespace Microsoft.StandardUI.Controls
{
public interface IStandardControlEnvironmentPeer : IDependencyObjectEnvironmentPeer
{
public IUIElement? BuildContent { get; }
}
}

Просмотреть файл

@ -1,17 +0,0 @@
namespace Microsoft.StandardUI.Controls
{
public interface IStandardUIControlEnvironmentPeer : IDependencyObjectEnvironmentPeer
{
double Width { get; set; }
public double MinWidth { get; set; }
public double MaxWidth { get; set; }
double Height { get; set; }
public double MinHeight { get; set; }
public double MaxHeight { get; set; }
public IControlTemplate? Template { get; set; }
public IUIPropertyObject? GetTemplateChild(string childName);
}
}

Просмотреть файл

@ -0,0 +1,100 @@
using System;
namespace Microsoft.StandardUI.Controls
{
public abstract class StandardControlImplementation<TControl> where TControl : IControl
{
public TControl Control { get; }
public StandardControlImplementation(TControl control)
{
Control = control;
}
/// <summary>
/// Create the contents of the control.
/// </summary>
/// <returns>control contents, or null if all content is drawn via Render</returns>
public virtual IUIElement? Build() => null;
/// <summary>
/// This method can be overridden to add further graphical elements (not previously defined in a logical tree) to a control.
/// The drawing instructions here aren't displayed immediately; instead they captured in an IVisual, shown later as part
/// of rendering the control.
///
/// There are two basic ways to create output for a control - create children for it (including shape primitives)
/// or create an IVisual by drawing to the IDrawingContext here. You can also combine approaches. In general, creating
/// children is more flexible, as those children can get input events and be replaced via templates. Each child will
/// also show up in UI hierarchy inspector tooling (like the Live Visual Tree in Visual Studio) as a separate element.
/// On the other hand, drawing to the IDrawingContext is lighter weight - all drawing instructions are combined into a
/// single IVisual, which in some cases is even stored on the GPU.
/// </summary>
/// <param name="drawingContext">drawing context that should draw to</param>
public virtual void Render(IDrawingContext drawingContext) { }
/// <summary>
/// Retrieves the named element in the instantiated ControlTemplate visual tree.
/// </summary>
/// <param name="childName">The name of the element to find.</param>
/// <returns>The named element from the template, if the element is found. Can
/// return null if no element with name childName was found in the template.</returns>
protected IUIPropertyObject GetTemplateChild(string childName)
{
// TODO: Finish this
return null;
}
public Size DesiredSize { get; private set; }
public void Measure(Size availableSize)
{
var desiredSize = MeasureOverride(availableSize);
//enforce that MeasureCore can not return PositiveInfinity size even if given Infinte availabel size.
//Note: NegativeInfinity can not be returned by definition of Size structure.
if (double.IsPositiveInfinity(desiredSize.Width) || double.IsPositiveInfinity(desiredSize.Height))
throw new InvalidOperationException($"Layout measurement override of element '{GetType().FullName}' should not return PositiveInfinity as its DesiredSize, even if Infinity is passed in as available size.");
//enforce that MeasureCore cannot return NaN size.
if (double.IsNaN(desiredSize.Width) || double.IsNaN(desiredSize.Height))
throw new InvalidOperationException($"Layout measurement override of element '{GetType().FullName}' should not return NaN values as its DesiredSize.");
DesiredSize = desiredSize;
}
public void Arrange(Rect finalRect)
{
ArrangeOverride(new Size(finalRect.Width, finalRect.Height));
}
protected virtual Size MeasureOverride(Size availableSize)
{
IUIElement? buildContent = EnvironmentPeer.BuildContent;
// By default, return the size of the content
if (buildContent != null)
{
buildContent.Measure(availableSize);
return buildContent.DesiredSize;
}
return new Size(0.0, 0.0);
}
protected virtual Size ArrangeOverride(Size finalSize)
{
IUIElement? buildContent = EnvironmentPeer.BuildContent;
// By default, give all the space to the content
if (buildContent != null)
{
Rect finalRect = new Rect(0, 0, finalSize.Width, finalSize.Height);
buildContent.Arrange(finalRect);
}
return finalSize;
}
private IStandardControlEnvironmentPeer EnvironmentPeer => (IStandardControlEnvironmentPeer)Control;
}
}

Просмотреть файл

@ -1,116 +0,0 @@
using System;
using static Microsoft.StandardUI.FactoryStatics;
namespace Microsoft.StandardUI.Controls
{
public abstract class StandardUIControl : IUIElement
{
IStandardUIControlEnvironmentPeer _peer;
public StandardUIControl(IStandardUIControlEnvironmentPeer? peer = null)
{
if (peer == null)
peer = StandardUIControlEnvironmentPeer(this);
_peer = peer;
}
public double Width
{
get => _peer.Width;
set => _peer.Height = value;
}
public double MinWidth
{
get => _peer.MinWidth;
set => _peer.MinWidth = value;
}
public double MaxWidth
{
get => _peer.MaxWidth;
set => _peer.MaxWidth = value;
}
public double Height
{
get => _peer.Height;
set => _peer.Height = value;
}
public double MinHeight
{
get => _peer.MinHeight;
set => _peer.MinHeight = value;
}
public double MaxHeight
{
get => _peer.MaxHeight;
set => _peer.MaxHeight = value;
}
public IControlTemplate Template
{
get => _peer.Template;
set => _peer.Template = value;
}
/// <summary>
/// Retrieves the named element in the instantiated ControlTemplate visual tree.
/// </summary>
/// <param name="childName">The name of the element to find.</param>
/// <returns>The named element from the template, if the element is found. Can
/// return null if no element with name childName was found in the template.</returns>
protected IUIPropertyObject GetTemplateChild(string childName)
{
// TODO: Finish this
return null;
}
public Size DesiredSize { get; private set; }
public double ActualX => throw new NotImplementedException();
public double ActualY => throw new NotImplementedException();
public double ActualWidth => throw new NotImplementedException();
public double ActualHeight => throw new NotImplementedException();
public void Measure(Size availableSize)
{
var desiredSize = MeasureOverride(availableSize);
//enforce that MeasureCore can not return PositiveInfinity size even if given Infinte availabel size.
//Note: NegativeInfinity can not be returned by definition of Size structure.
if (double.IsPositiveInfinity(desiredSize.Width) || double.IsPositiveInfinity(desiredSize.Height))
throw new InvalidOperationException($"Layout measurement override of element '{GetType().FullName}' should not return PositiveInfinity as its DesiredSize, even if Infinity is passed in as available size.");
//enforce that MeasureCore cannot return NaN size.
if (double.IsNaN(desiredSize.Width) || double.IsNaN(desiredSize.Height))
throw new InvalidOperationException($"Layout measurement override of element '{GetType().FullName}' should not return NaN values as its DesiredSize.");
DesiredSize = desiredSize;
}
public void Arrange(Rect finalRect)
{
ArrangeOverride(new Size(finalRect.Width, finalRect.Height));
}
protected abstract Size MeasureOverride(Size availableSize);
protected abstract Size ArrangeOverride(Size finalSize);
public object GetValue(IUIProperty dp) => _peer.GetValue(dp);
public object ReadLocalValue(IUIProperty dp) => _peer.ReadLocalValue(dp);
public void SetValue(IUIProperty dp, object value) => _peer.SetValue(dp, value);
/// <summary>
/// This method can be overridden to add further graphical elements (not previously defined in a logical tree) to a drawn element.
/// It's similar to the OnRender method in WPF.
/// </summary>
/// <param name="visualizer">visualizer that should draw to</param>
public virtual void OnVisualize(IVisualizer visualizer) { }
}
}

Просмотреть файл

@ -1,7 +1,11 @@
namespace Microsoft.StandardUI.Controls
{
public class StandardUIUserControl : StandardUIControl
public class StandardUserControlImplementation<TControl> : StandardControlImplementation<TControl> where TControl : IControl
{
public StandardUserControlImplementation(TControl control) : base(control)
{
}
public IUIElement? Content { get; set; }
protected override Size MeasureOverride(Size availableSize)

Просмотреть файл

@ -30,9 +30,6 @@ namespace Microsoft.StandardUI
/*** Environment peers ***/
public static IStandardUIControlEnvironmentPeer StandardUIControlEnvironmentPeer(StandardUIControl standardUIControl) =>
Factory.CreateStandardUIControlEnvironmentPeer(standardUIControl);
/*** Infrastructure objects ***/
public static IUIPropertyMetadata UIPropertyMetdata(object defaultValue) => Factory.CreatePropertyMetadata(defaultValue);

Просмотреть файл

@ -42,10 +42,6 @@ namespace Microsoft.StandardUI
IPathGeometry CreatePathGeometry(ITransform? transform, IEnumerable<IPathFigure> figures, FillRule fillRule);
IPathFigure CreatePathFigure(IEnumerable<IPathSegment> segments, Point startPoint, bool isClosed, bool isFilled);
/*** Environment peers ***/
IStandardUIControlEnvironmentPeer CreateStandardUIControlEnvironmentPeer(StandardUIControl standardUIControl);
/*** Infrastructure objects ***/
IUIPropertyMetadata CreatePropertyMetadata(object defaultValue);

Просмотреть файл

@ -44,11 +44,6 @@ namespace Microsoft.StandardUI
public IPathGeometry CreatePathGeometry(ITransform? transform, IEnumerable<IPathFigure> figures, FillRule fillRule) => throw CreateInitNotCalledException();
public IPathFigure CreatePathFigure(IEnumerable<IPathSegment> segments, Point startPoint, bool isClosed, bool isFilled) => throw CreateInitNotCalledException();
/*** Environment peers ***/
public IStandardUIControlEnvironmentPeer CreateStandardUIControlEnvironmentPeer(StandardUIControl standardUIControl) =>
throw CreateInitNotCalledException();
/*** Infrastructure objects ***/
public IUIPropertyMetadata CreatePropertyMetadata(object defaultValue) => throw CreateInitNotCalledException();