// 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; } } } }