mirror of
https://github.com/ZuneDev/MicrosoftIris.git
synced 2026-07-27 13:13:29 -07:00
453 lines
17 KiB
C#
453 lines
17 KiB
C#
// Decompiled with JetBrains decompiler
|
|
// Type: Microsoft.Iris.ViewItems.Graphic
|
|
// Assembly: UIX, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
|
|
// MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11
|
|
// Assembly location: C:\Program Files\Zune\UIX.dll
|
|
|
|
using Microsoft.Iris.Drawing;
|
|
using Microsoft.Iris.Layout;
|
|
using Microsoft.Iris.Layouts;
|
|
using Microsoft.Iris.Library;
|
|
using Microsoft.Iris.Markup;
|
|
using Microsoft.Iris.Render;
|
|
using Microsoft.Iris.RenderAPI.Drawing;
|
|
using Microsoft.Iris.UI;
|
|
|
|
namespace Microsoft.Iris.ViewItems
|
|
{
|
|
internal class Graphic : ContentViewItem
|
|
{
|
|
private const string s_effectElementName = "BaseImage";
|
|
private const string s_effectPropertyName = "BaseImage.Image";
|
|
private static readonly DataCookie s_pendingLoadCompleteHandlerProperty = DataCookie.ReserveSlot();
|
|
private static readonly DataCookie s_acquiringImageProperty = DataCookie.ReserveSlot();
|
|
private static readonly DataCookie s_errorImageProperty = DataCookie.ReserveSlot();
|
|
private static string s_AcquiringDefaultImageUri = "res://UIX!AcquiringImage.png";
|
|
private static string s_ErrorDefaultImageUri = "res://UIX!ErrorImage.png";
|
|
private static UIImage s_AcquiringDefaultImage;
|
|
private static UIImage s_ErrorDefaultImage;
|
|
private static object s_NullImage = new object();
|
|
private UIImage _contentImage;
|
|
private UIImage _preloadImage;
|
|
private StripAlignment _horizontalAlignment;
|
|
private StripAlignment _verticalAlignment;
|
|
private StretchingPolicy _stretchMode;
|
|
|
|
public Graphic()
|
|
{
|
|
_horizontalAlignment = StripAlignment.Near;
|
|
_verticalAlignment = StripAlignment.Near;
|
|
_stretchMode = StretchingPolicy.Fill;
|
|
SizingPolicy = SizingPolicy.SizeToContent;
|
|
}
|
|
|
|
public static void EnsureFallbackImages()
|
|
{
|
|
if (s_AcquiringDefaultImage != null)
|
|
return;
|
|
s_AcquiringDefaultImage = new UriImage(s_AcquiringDefaultImageUri, new Inset(3, 3, 53, 53), Size.Zero, false);
|
|
s_AcquiringDefaultImage.Load();
|
|
s_ErrorDefaultImage = new UriImage(s_ErrorDefaultImageUri, new Inset(3, 3, 53, 53), Size.Zero, false);
|
|
s_ErrorDefaultImage.Load();
|
|
}
|
|
|
|
protected override void OnDispose()
|
|
{
|
|
ReleaseInUseImage(_contentImage, null);
|
|
ReleaseInUseImage(_preloadImage, null);
|
|
ReleaseInUseImage(AcquiringImage, s_AcquiringDefaultImage);
|
|
ReleaseInUseImage(ErrorImage, s_ErrorDefaultImage);
|
|
_preloadImage = null;
|
|
_contentImage = null;
|
|
AsyncLoadCompleteHandler = null;
|
|
base.OnDispose();
|
|
}
|
|
|
|
protected override void OnEffectChanged()
|
|
{
|
|
if (_contents == null)
|
|
return;
|
|
_contents.Effect = null;
|
|
}
|
|
|
|
public UIImage Content
|
|
{
|
|
get => _contentImage;
|
|
set
|
|
{
|
|
if (_contentImage == value)
|
|
return;
|
|
if (_contentImage != null)
|
|
{
|
|
RemoveAsyncLoadCompleteHandler(_contentImage);
|
|
_contentImage.RemoveUser(this);
|
|
}
|
|
_contentImage = value;
|
|
if (_contentImage != null)
|
|
{
|
|
_contentImage.AddUser(this);
|
|
_contentImage.Load();
|
|
if (_contentImage.Status == ImageStatus.Loading || _contentImage.Status == ImageStatus.PendingLoad)
|
|
AttachAsyncLoadCompleteHandler(_contentImage);
|
|
}
|
|
FireNotification(NotificationID.Content);
|
|
NotifyContentChange();
|
|
}
|
|
}
|
|
|
|
public UIImage AcquiringImage
|
|
{
|
|
get => GetStatusImage(s_acquiringImageProperty, s_AcquiringDefaultImage);
|
|
set => SetStatusImage(value, NotificationID.AcquiringImage, s_acquiringImageProperty, s_AcquiringDefaultImage);
|
|
}
|
|
|
|
public UIImage ErrorImage
|
|
{
|
|
get => GetStatusImage(s_errorImageProperty, s_ErrorDefaultImage);
|
|
set => SetStatusImage(value, NotificationID.ErrorImage, s_errorImageProperty, s_ErrorDefaultImage);
|
|
}
|
|
|
|
public UIImage PreloadContent
|
|
{
|
|
get => _preloadImage;
|
|
set
|
|
{
|
|
if (_preloadImage != null)
|
|
_preloadImage.RemoveUser(this);
|
|
_preloadImage = value;
|
|
if (_preloadImage == null)
|
|
return;
|
|
_preloadImage.AddUser(this);
|
|
_preloadImage.Load();
|
|
}
|
|
}
|
|
|
|
private UIImage GetStatusImage(DataCookie cookie, UIImage defaultImage)
|
|
{
|
|
object data = GetData(cookie);
|
|
return data != null ? (data != s_NullImage ? (UIImage)data : null) : defaultImage;
|
|
}
|
|
|
|
private void SetStatusImage(
|
|
UIImage value,
|
|
string name,
|
|
DataCookie cookie,
|
|
UIImage defaultImage)
|
|
{
|
|
UIImage statusImage = GetStatusImage(cookie, defaultImage);
|
|
if (value == statusImage)
|
|
return;
|
|
object obj;
|
|
if (value != null)
|
|
{
|
|
obj = value;
|
|
value.Load();
|
|
if (value.Status == ImageStatus.Loading || value.Status == ImageStatus.PendingLoad)
|
|
AttachAsyncLoadCompleteHandler(value);
|
|
value.AddUser(this);
|
|
}
|
|
else
|
|
obj = s_NullImage;
|
|
ReleaseInUseImage(statusImage, defaultImage);
|
|
SetData(cookie, obj);
|
|
MarkPaintInvalid();
|
|
FireNotification(name);
|
|
}
|
|
|
|
private void OnAsyncLoadComplete(object image, ImageStatus status)
|
|
{
|
|
RemoveAsyncLoadCompleteHandler((UIImage)image);
|
|
NotifyContentChange();
|
|
}
|
|
|
|
private void AttachAsyncLoadCompleteHandler(UIImage image)
|
|
{
|
|
ContentLoadCompleteHandler loadCompleteHandler = AsyncLoadCompleteHandler;
|
|
if (loadCompleteHandler == null)
|
|
{
|
|
loadCompleteHandler = new ContentLoadCompleteHandler(OnAsyncLoadComplete);
|
|
AsyncLoadCompleteHandler = loadCompleteHandler;
|
|
}
|
|
image.LoadComplete += loadCompleteHandler;
|
|
}
|
|
|
|
private void RemoveAsyncLoadCompleteHandler(UIImage image)
|
|
{
|
|
if (image == null)
|
|
return;
|
|
image.LoadComplete -= AsyncLoadCompleteHandler;
|
|
}
|
|
|
|
private void ReleaseInUseImage(UIImage image, UIImage defaultImage)
|
|
{
|
|
if (image != null && image != defaultImage && (image.Status == ImageStatus.Loading || image.Status == ImageStatus.PendingLoad))
|
|
RemoveAsyncLoadCompleteHandler(image);
|
|
if (image == null || image == defaultImage)
|
|
return;
|
|
image.RemoveUser(this);
|
|
}
|
|
|
|
private void NotifyContentChange()
|
|
{
|
|
ForceContentChange();
|
|
if (Layout is ImageLayout layout && UpdateSourceOnLayout(layout))
|
|
MarkLayoutInvalid();
|
|
MarkPaintInvalid();
|
|
}
|
|
|
|
protected override void OnMinimumSizeChanged()
|
|
{
|
|
if (!(Layout is ImageLayout layout))
|
|
return;
|
|
layout.MinimumSize = MinimumSize;
|
|
}
|
|
|
|
public SizingPolicy SizingPolicy
|
|
{
|
|
get
|
|
{
|
|
if (!(Layout is ImageLayout layout))
|
|
return SizingPolicy.SizeToChildren;
|
|
return layout.Fill ? SizingPolicy.SizeToConstraint : SizingPolicy.SizeToContent;
|
|
}
|
|
set
|
|
{
|
|
if (value == SizingPolicy)
|
|
return;
|
|
if (value == SizingPolicy.SizeToChildren)
|
|
{
|
|
Layout = DefaultLayout.Instance;
|
|
}
|
|
else
|
|
{
|
|
ImageLayout imageLayout = new ImageLayout();
|
|
UpdateSourceOnLayout(imageLayout);
|
|
UpdateMaintainAspectRatioOnLayout(imageLayout);
|
|
imageLayout.MinimumSize = MinimumSize;
|
|
imageLayout.Fill = value == SizingPolicy.SizeToConstraint;
|
|
Layout = imageLayout;
|
|
}
|
|
FireNotification(NotificationID.SizingPolicy);
|
|
}
|
|
}
|
|
|
|
public StretchingPolicy StretchingPolicy
|
|
{
|
|
get => _stretchMode;
|
|
set
|
|
{
|
|
if (_stretchMode == value)
|
|
return;
|
|
_stretchMode = value;
|
|
if (UpdateMaintainAspectRatioOnLayout(Layout as ImageLayout))
|
|
MarkLayoutInvalid();
|
|
MarkPaintInvalid();
|
|
FireNotification(NotificationID.StretchingPolicy);
|
|
}
|
|
}
|
|
|
|
private bool UpdateMaintainAspectRatioOnLayout(ImageLayout imageLayout)
|
|
{
|
|
bool flag1 = false;
|
|
if (imageLayout != null)
|
|
{
|
|
bool flag2 = _stretchMode == StretchingPolicy.Uniform;
|
|
if (imageLayout.MaintainAspectRatio != flag2)
|
|
{
|
|
imageLayout.MaintainAspectRatio = flag2;
|
|
flag1 = true;
|
|
}
|
|
}
|
|
return flag1;
|
|
}
|
|
|
|
private bool UpdateSourceOnLayout(ImageLayout layout)
|
|
{
|
|
bool flag = false;
|
|
Size size = Size.Zero;
|
|
if (_contentImage != null)
|
|
{
|
|
UIImage activeImage = GetActiveImage();
|
|
if (activeImage != null)
|
|
size = activeImage.Size;
|
|
}
|
|
if (layout.SourceSize != size)
|
|
{
|
|
layout.SourceSize = size;
|
|
flag = true;
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
public StripAlignment HorizontalAlignment
|
|
{
|
|
get => _horizontalAlignment;
|
|
set
|
|
{
|
|
if (_horizontalAlignment == value)
|
|
return;
|
|
_horizontalAlignment = value;
|
|
MarkPaintInvalid();
|
|
FireNotification(NotificationID.HorizontalAlignment);
|
|
}
|
|
}
|
|
|
|
public StripAlignment VerticalAlignment
|
|
{
|
|
get => _verticalAlignment;
|
|
set
|
|
{
|
|
if (_verticalAlignment == value)
|
|
return;
|
|
_verticalAlignment = value;
|
|
MarkPaintInvalid();
|
|
FireNotification(NotificationID.VerticalAlignment);
|
|
}
|
|
}
|
|
|
|
private ContentLoadCompleteHandler AsyncLoadCompleteHandler
|
|
{
|
|
get => (ContentLoadCompleteHandler)GetData(s_pendingLoadCompleteHandlerProperty);
|
|
set => SetData(s_pendingLoadCompleteHandlerProperty, value);
|
|
}
|
|
|
|
public void CommitPreload() => Content = PreloadContent;
|
|
|
|
protected override bool HasContent() => _contentImage != null;
|
|
|
|
protected override void OnPaint(bool visible)
|
|
{
|
|
base.OnPaint(visible);
|
|
if (_contents == null)
|
|
return;
|
|
if (_contents.Effect == null)
|
|
{
|
|
_contents.Effect = EffectClass.CreateImageRenderEffectWithFallback(Effect, this, null);
|
|
_contents.Effect.UnregisterUsage(this);
|
|
}
|
|
UpdateEffectContents();
|
|
UpdateCoordinateMaps();
|
|
}
|
|
|
|
private void UpdateEffectContents() => EffectClass.SetDefaultEffectProperty(Effect, _contents.Effect, GetActiveImage()?.RenderImage);
|
|
|
|
internal void UpdateCoordinateMaps()
|
|
{
|
|
UIImage activeImage = GetActiveImage();
|
|
if (activeImage == null)
|
|
return;
|
|
if (_stretchMode == StretchingPolicy.Fill && activeImage.NineGrid != Inset.Zero)
|
|
{
|
|
_contents.RelativeSize = true;
|
|
_contents.Size = Vector2.UnitVector;
|
|
_contents.SetNineGrid(activeImage.NineGrid.Left, activeImage.NineGrid.Top, activeImage.NineGrid.Right, activeImage.NineGrid.Bottom);
|
|
}
|
|
else
|
|
{
|
|
Vector2 visualSize = VisualSize;
|
|
Size layoutSize = new Size((int)visualSize.X, (int)visualSize.Y);
|
|
Size size = activeImage.Size;
|
|
RectangleF source;
|
|
RectangleF destination;
|
|
CalculatePaintRectangles(size, layoutSize, out source, out destination);
|
|
switch (size.IsEmpty ? 1 : (int)_stretchMode)
|
|
{
|
|
case 0:
|
|
case 2:
|
|
case 3:
|
|
RectangleF rectangleF = new RectangleF(Point.Zero, size);
|
|
CoordMap coordMap = null;
|
|
if (source != rectangleF)
|
|
{
|
|
float flValue1 = source.Left / size.Width;
|
|
float flValue2 = source.Right / size.Width;
|
|
float flValue3 = source.Top / size.Height;
|
|
float flValue4 = source.Bottom / size.Height;
|
|
coordMap = new CoordMap();
|
|
coordMap.AddValue(0.0f, flValue1, Orientation.Horizontal);
|
|
coordMap.AddValue(0.0f, flValue3, Orientation.Vertical);
|
|
coordMap.AddValue(1f, flValue2, Orientation.Horizontal);
|
|
coordMap.AddValue(1f, flValue4, Orientation.Vertical);
|
|
}
|
|
_contents.RelativeSize = false;
|
|
_contents.Position = new Vector3(destination.Left, destination.Top, 0.0f);
|
|
_contents.Size = new Vector2(destination.Width, destination.Height);
|
|
_contents.SetCoordMap(0, coordMap);
|
|
break;
|
|
case 1:
|
|
_contents.RelativeSize = true;
|
|
_contents.Size = Vector2.UnitVector;
|
|
_contents.SetCoordMap(0, null);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private UIImage GetActiveImage() => _contentImage.Status != ImageStatus.Complete ? (_contentImage.Status == ImageStatus.Loading || _contentImage.Status == ImageStatus.PendingLoad ? AcquiringImage : ErrorImage) : _contentImage;
|
|
|
|
private void CalculatePaintRectangles(
|
|
Size originalSourceSize,
|
|
Size layoutSize,
|
|
out RectangleF source,
|
|
out RectangleF destination)
|
|
{
|
|
if (_stretchMode == StretchingPolicy.Fill)
|
|
{
|
|
source = RectangleF.Zero;
|
|
destination = RectangleF.Zero;
|
|
}
|
|
else
|
|
{
|
|
Size size1 = originalSourceSize;
|
|
Size size2 = layoutSize;
|
|
if (size1.IsZero || size2.IsZero)
|
|
{
|
|
source = RectangleF.Zero;
|
|
destination = RectangleF.Zero;
|
|
}
|
|
else
|
|
{
|
|
switch (_stretchMode)
|
|
{
|
|
case StretchingPolicy.None:
|
|
size1 = Size.Min(size1, size2);
|
|
size2 = size1;
|
|
break;
|
|
case StretchingPolicy.Uniform:
|
|
size2 = Size.LargestFit(size1, size2);
|
|
break;
|
|
case StretchingPolicy.UniformToFill:
|
|
size1 = Size.LargestFit(size2, size1);
|
|
break;
|
|
}
|
|
float dimensionOffset1 = CalculateDimensionOffset(size1.Width, originalSourceSize.Width, _horizontalAlignment);
|
|
float dimensionOffset2 = CalculateDimensionOffset(size2.Width, layoutSize.Width, _horizontalAlignment);
|
|
float dimensionOffset3 = CalculateDimensionOffset(size1.Height, originalSourceSize.Height, _verticalAlignment);
|
|
float dimensionOffset4 = CalculateDimensionOffset(size2.Height, layoutSize.Height, _verticalAlignment);
|
|
source = new RectangleF(dimensionOffset1, dimensionOffset3, size1.Width, size1.Height);
|
|
destination = new RectangleF(dimensionOffset2, dimensionOffset4, size2.Width, size2.Height);
|
|
}
|
|
}
|
|
}
|
|
|
|
private float CalculateDimensionOffset(
|
|
float actualSize,
|
|
float availableSize,
|
|
StripAlignment alignment)
|
|
{
|
|
float num = availableSize - actualSize;
|
|
switch (alignment)
|
|
{
|
|
case StripAlignment.Near:
|
|
return 0.0f;
|
|
case StripAlignment.Center:
|
|
return num / 2f;
|
|
case StripAlignment.Far:
|
|
return num;
|
|
default:
|
|
return 0.0f;
|
|
}
|
|
}
|
|
}
|
|
}
|