// Decompiled with JetBrains decompiler // Type: Microsoft.Iris.ViewItems.Host // 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.Library; using Microsoft.Iris.Markup; using Microsoft.Iris.Markup.UIX; using Microsoft.Iris.Render; using Microsoft.Iris.Session; using Microsoft.Iris.UI; namespace Microsoft.Iris.ViewItems { public class Host : ViewItem, ISchemaInfo { private const string DefaultUI = "Default"; private UIClassTypeSchema _typeRestriction; private UIClassTypeSchema _typeCurrent; private UIClass _childUI; private string _lastRequestedSource; private HostStatus _status; private bool _inputEnabled; private bool _dynamicHost; private bool _unloadable; private bool _newContentOnTop; private Vector _heldUIProperties; private Vector _heldInitialUIDisposables; private ChildFaultedInDelegate _loadNotify; private string _loadNotifyURI; private HostRequestPacket _pendingHostRequest; private uint _islandId; private static DeferredHandler s_startRequestHandler = new DeferredHandler(StartSourceRequest); public Host() : this(null, null) { } public Host(UIClassTypeSchema typeSchema) : this(typeSchema, typeSchema) { } public Host(UIClassTypeSchema typeRestriction, UIClassTypeSchema typeCurrent) { _status = HostStatus.Normal; _inputEnabled = true; _typeRestriction = typeRestriction; _typeCurrent = typeCurrent; if (_typeCurrent == null) return; SetChildUI(_typeCurrent.ConstructUI()); _lastRequestedSource = SourceFromType(_typeCurrent); } private string SourceFromType(TypeSchema type) => type.Owner.Uri + "#" + type.Name; public TypeSchema TypeSchema => _typeCurrent; protected override void OnDispose() { base.OnDispose(); Cancel(); if (_childUI != null) SetChildUI(null); if (_heldInitialUIDisposables != null) { foreach (DisposableObject initialUiDisposable in _heldInitialUIDisposables) initialUiDisposable.Dispose(this); } if (!Unloadable) return; UnloadAll(); MarkupSystem.FreeIslandId(_islandId); _islandId = 0U; } protected override void OnOwnerDeclared(object owner) { base.OnOwnerDeclared(owner); UIClass uiClass = (UIClass)owner; if (ChildUI == null) return; uiClass.Children.Add(ChildUI); } public void RequestSource(string source, Vector properties) => RequestSource(source, null, properties); public void RequestSource(TypeSchema type, Vector properties) => RequestSource(null, type, properties); public void RequestSource(string source, TypeSchema type, Vector properties) { if (type != null) { if (!HostSchema.Type.IsAssignableFrom(type)) { ErrorManager.ReportError("RequestSource failed: Referrenced type '{0}' is not a UI", type.Name); return; } source = SourceFromType(type); } Cancel(); HostRequestPacket hostRequestPacket = new HostRequestPacket(); hostRequestPacket.Host = this; hostRequestPacket.Source = source; hostRequestPacket.Type = (UIClassTypeSchema)type; hostRequestPacket.Properties = properties; _pendingHostRequest = hostRequestPacket; _lastRequestedSource = source; DeferredCall.Post(DispatchPriority.High, s_startRequestHandler, hostRequestPacket); } public void Cancel() { if (_pendingHostRequest != null) { _pendingHostRequest.Clear(); _pendingHostRequest = null; } RevokePendingLoadNotification(); } private static void StartSourceRequest(object args) { HostRequestPacket hostRequestPacket = (HostRequestPacket)args; if (hostRequestPacket.Host == null) return; Host host = hostRequestPacket.Host; string source = hostRequestPacket.Source; UIClassTypeSchema type = hostRequestPacket.Type; Vector properties = hostRequestPacket.Properties; host.Cancel(); ErrorManager.EnterContext(source); try { host.SetStatus(HostStatus.LoadingSource); LoadResult loadResult = null; string uiToCreate = null; if (type == null && source != null) loadResult = MarkupSystem.Load(CrackSourceUri(source, out uiToCreate), host.InheritedIslandId); host.CompleteSourceRequest(source, type, properties, loadResult, uiToCreate); } finally { ErrorManager.ExitContext(); } } private void CompleteSourceRequest( string requestedSource, UIClassTypeSchema requestedType, Vector properties, LoadResult loadResult, string uiToCreate) { ErrorManager.EnterContext(requestedSource); ErrorWatermark watermark = ErrorManager.Watermark; bool flag = true; ForceContentChange(); try { if (_childUI != null) { if (_typeRestriction != null) HoldChildUIPropertyValues(); SetChildUI(null); _typeCurrent = _typeRestriction; FireNotification(NotificationID.SourceType); } _dynamicHost = true; UIClassTypeSchema uiClassTypeSchema = null; Vector vector = null; if (requestedSource != null) { if (requestedType == null) { if (loadResult == null || loadResult.Status == LoadResultStatus.Error) { ErrorManager.ReportError("RequestSource failed: Unable to load '{0}'", requestedSource); } else { TypeSchema type = loadResult.FindType(uiToCreate); if (type == null) ErrorManager.ReportError("RequestSource failed: Unable to find '{0}' within '{1}'", uiToCreate, requestedSource); else if (!HostSchema.Type.IsAssignableFrom(type)) ErrorManager.ReportError("RequestSource failed: Referrenced type '{0}' is not a UI", uiToCreate); else requestedType = (UIClassTypeSchema)type; } } if (requestedType != null) { uiClassTypeSchema = requestedType; if (_typeRestriction != null && !_typeRestriction.IsAssignableFrom(uiClassTypeSchema)) ErrorManager.ReportError("RequestSource failed: Found '{0}' within '{1}', but, it is not a '{2}'", uiToCreate, requestedSource, _typeRestriction.Name); vector = NegotiateNewChildUIPropertyValues(uiClassTypeSchema, properties); } } if (watermark.ErrorsDetected) { SetStatus(HostStatus.FailureLoadingSource); } else { if (uiClassTypeSchema != null) { Host host = (Host)uiClassTypeSchema.ConstructDefault(); UIClass childUi = host.ChildUI; foreach (UIPropertyRecord uiPropertyRecord in vector) { object instance = host; uiPropertyRecord.Schema.SetValue(ref instance, uiPropertyRecord.Value); } _heldUIProperties = null; SetChildUI(childUi); object instance1 = this; uiClassTypeSchema.InitializeInstance(ref instance1); UI.Children.Add(childUi); _typeCurrent = uiClassTypeSchema; FireNotification(NotificationID.Source); FireNotification(NotificationID.SourceType); } SetStatus(HostStatus.Normal); if (!NotifyForLatestLoad()) return; DeferredCall.Post(DispatchPriority.LayoutSync, new SimpleCallback(DeliverLoadCompleteNotification)); flag = false; } } finally { if (flag) RevokePendingLoadNotification(); ErrorManager.ExitContext(); } } private bool NotifyForLatestLoad() => _loadNotify != null && InvariantString.Equals(_loadNotifyURI, Source); private void DeliverLoadCompleteNotification() { if (NotifyForLatestLoad() && ChildUI != null && ChildUI.RootItem != null) _loadNotify(this, ChildUI.RootItem); RevokePendingLoadNotification(); } private void RevokePendingLoadNotification() { _loadNotify = null; _loadNotifyURI = null; } private void HoldChildUIPropertyValues() { if (_typeRestriction == null) return; _heldUIProperties = new Vector(); for (TypeSchema typeRestriction = _typeRestriction; typeRestriction != HostSchema.Type; typeRestriction = typeRestriction.Base) { foreach (PropertySchema property1 in typeRestriction.Properties) { string name = property1.Name; if (_childUI.Storage.ContainsKey(name) && !UIPropertyRecord.IsInList(_heldUIProperties, name)) { object property2 = _childUI.GetProperty(name); UIPropertyRecord.AddToList(_heldUIProperties, name, property2); if (!_dynamicHost && property2 != null && property1.PropertyType.Disposable) { IDisposableObject disposable = (IDisposableObject)property2; if (_childUI.UnregisterDisposable(ref disposable)) { if (_heldInitialUIDisposables == null) _heldInitialUIDisposables = new Vector(); _heldInitialUIDisposables.Add(disposable); disposable.TransferOwnership(this); } } } } } } private Vector NegotiateNewChildUIPropertyValues( TypeSchema replacementType, Vector specifiedProperties) { Vector list = specifiedProperties ?? new Vector(); if (_typeRestriction != null) { foreach (UIPropertyRecord heldUiProperty in _heldUIProperties) { if (!UIPropertyRecord.IsInList(list, heldUiProperty.Name)) list.Add(heldUiProperty); } } foreach (UIPropertyRecord uiPropertyRecord in list) { uiPropertyRecord.Schema = replacementType.FindPropertyDeep(uiPropertyRecord.Name); if (uiPropertyRecord.Schema == null) ErrorManager.ReportError("Runtime UI replacement to '{0}' failed since a property named '{1}' was specified but doesn't exist on '{0}'", replacementType.Name, uiPropertyRecord.Name); else if (!uiPropertyRecord.Schema.PropertyType.IsAssignableFrom(uiPropertyRecord.Value)) ErrorManager.ReportError("Runtime UI replacement to '{0}' failed since the value specified ({1}) for the '{2}' property is incompatible (type expected is '{3}')", replacementType.Name, uiPropertyRecord.Value, uiPropertyRecord.Name, uiPropertyRecord.Schema.PropertyType.Name); } foreach (string name in replacementType.FindRequiredPropertyNamesDeep()) { if (!UIPropertyRecord.IsInList(list, name)) ErrorManager.ReportError("Runtime UI replacement to '{0}' failed since required property '{1}' was never provided a value", replacementType.Name, name); } return list; } protected override ViewItemID IDForChild(ViewItem childItem) => new ViewItemID(Source); protected override FindChildResult ChildForID( ViewItemID part, out ViewItem resultItem) { resultItem = null; FindChildResult findChildResult = FindChildResult.Failure; if (part.StringPartValid && !part.IDValid) { if (InvariantString.Equals(Source, part.StringPart) && ChildUI != null && ChildUI.RootItem != null) { resultItem = ChildUI.RootItem; findChildResult = FindChildResult.Success; } else if (_status == HostStatus.LoadingSource) findChildResult = FindChildResult.PotentiallyFaultIn; } return findChildResult; } internal override void FaultInChild(ViewItemID childID, ChildFaultedInDelegate handler) { _loadNotify = handler; _loadNotifyURI = childID.StringPart; } public string Source => _lastRequestedSource; public TypeSchema SourceType => _typeCurrent; public bool Unloadable { get => _unloadable; set { if (_unloadable == value) return; _unloadable = value; if (!_unloadable) return; _islandId = MarkupSystem.AllocateIslandId(); if (_islandId != 0U) return; ErrorManager.ReportError("Maximum number of Unloadable Hosts reached"); } } public bool UnloadAll() => UnloadAll(true); public bool UnloadAll(bool requestSourceToNull) { if (Unloadable) { MarkupSystem.UnloadIsland(_islandId); if (requestSourceToNull) RequestSource(null, null, null); return true; } ErrorManager.ReportError("UnloadAll may only be called on Unloadable hosts"); return false; } protected uint InheritedIslandId { get { if (_islandId == 0U) _islandId = UI == null || UI.Host == null ? MarkupSystem.RootIslandId : UI.Host.InheritedIslandId; return _islandId; } } public void ForceRefresh() => ForceRefresh(false); public void ForceRefresh(bool unloadMarkup) { if (unloadMarkup) { string lastRequestedSource = _lastRequestedSource; RequestSource(null, null, null); DeferredCall.Post(DispatchPriority.High, new SimpleCallback(DeferredUnloadAll)); DeferredCall.Post(DispatchPriority.High, new DeferredHandler(DeferredRequestSource), lastRequestedSource); } else RequestSource(_lastRequestedSource, null); } private void DeferredUnloadAll() => UnloadAll(false); private void DeferredRequestSource(object objLastRequestedSource) => RequestSource((string)objLastRequestedSource, null); public HostStatus Status => _status; private void SetStatus(HostStatus status) { if (_status == status) return; _status = status; FireNotification(NotificationID.Status); } public bool InputEnabled { get => _inputEnabled; set { if (_inputEnabled == value) return; _inputEnabled = value; if (_childUI != null) _childUI.OnInputEnabledChanged(); FireNotification(NotificationID.InputEnabled); } } public UIClass ChildUI => _childUI; private void SetChildUI(UIClass childUI) { LoadResult loadResult = null; if (_childUI != null) { loadResult = _childUI.TypeSchema.Owner; _childUI.Dispose(this); } if (_dynamicHost) { loadResult?.UnregisterUsage(this); childUI?.TypeSchema.Owner.RegisterUsage(this); } _childUI = childUI; } protected override void CreateVisualContainer(IRenderSession renderSession) { base.CreateVisualContainer(renderSession); if (_childUI == null) return; _childUI.OnHostVisibilityChanged(); } protected static string CrackSourceUri(string source, out string uiToCreate) { string str = source; uiToCreate = "Default"; int length = source.LastIndexOf('#'); if (length != -1) { str = source.Substring(0, length); uiToCreate = source.Substring(length + 1, source.Length - length - 1); } return str; } public void NotifyChildUIScriptErrors() => SetStatus(HostStatus.FailureRunningScript); public object GetChildUIProperty(string name) => _childUI == null ? UIPropertyRecord.FindInList(_heldUIProperties, name).Value : _childUI.GetProperty(name); public void SetChildUIProperty(string name, object value) { if (_childUI != null) { _childUI.SetProperty(name, value); } else { UIPropertyRecord inList = UIPropertyRecord.FindInList(_heldUIProperties, name); if (Utility.IsEqual(inList.Value, value)) return; inList.Value = value; FireNotification(name); } } public void FireChildUINotification(string id) => FireNotification(id); public bool NewContentOnTop { get => _newContentOnTop; set { if (_newContentOnTop == value) return; _newContentOnTop = value; FireNotification(NotificationID.NewContentOnTop); } } protected override VisualOrder GetVisualOrder() => !NewContentOnTop ? VisualOrder.Last : VisualOrder.First; public override string ToString() => base.ToString() + " ('" + _lastRequestedSource + "')"; } }