mirror of
https://github.com/ZuneDev/ZuneShell.dll.git
synced 2026-07-27 13:11:51 -07:00
1455 lines
56 KiB
C#
1455 lines
56 KiB
C#
// Decompiled with JetBrains decompiler
|
|
// Type: Microsoft.Iris.UI.UIClass
|
|
// 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.Accessibility;
|
|
using Microsoft.Iris.Animations;
|
|
using Microsoft.Iris.Debug;
|
|
using Microsoft.Iris.Drawing;
|
|
using Microsoft.Iris.Input;
|
|
using Microsoft.Iris.InputHandlers;
|
|
using Microsoft.Iris.Layout;
|
|
using Microsoft.Iris.Library;
|
|
using Microsoft.Iris.Markup;
|
|
using Microsoft.Iris.Navigation;
|
|
using Microsoft.Iris.Render;
|
|
using Microsoft.Iris.RenderAPI.Drawing;
|
|
using Microsoft.Iris.Session;
|
|
using Microsoft.Iris.ViewItems;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Specialized;
|
|
using System.Diagnostics;
|
|
|
|
namespace Microsoft.Iris.UI
|
|
{
|
|
internal class UIClass :
|
|
Microsoft.Iris.Library.TreeNode,
|
|
ICookedInputSite,
|
|
IMarkupTypeBase,
|
|
IDisposableOwner,
|
|
INotifyObject,
|
|
ISchemaInfo
|
|
{
|
|
public const string UIStateReservedSymbolName = "UI";
|
|
private BitVector32 _bits;
|
|
private Host _ownerHost;
|
|
private int _uiIDFactory;
|
|
private ViewItem _rootItem;
|
|
private InputHandlerList _inputHandlers;
|
|
private UIClassTypeSchema _typeSchema;
|
|
private Dictionary<object, object> _storage;
|
|
private Vector<IDisposableObject> _disposables;
|
|
private MarkupListeners _listeners;
|
|
private NotifyService _notifier = new NotifyService();
|
|
private ScriptRunScheduler _scriptRunScheduler = new ScriptRunScheduler();
|
|
private static DeferredHandler s_executePendingScriptsHandler = new DeferredHandler(UIClass.ExecutePendingScripts);
|
|
private static readonly FocusStateHandler s_updateMouseFocusStates = new FocusStateHandler(UIClass.UpdateMouseFocusStates);
|
|
private static readonly FocusStateHandler s_updateKeyFocusStates = new FocusStateHandler(UIClass.UpdateKeyFocusStates);
|
|
private static readonly DataCookie s_cursorProperty = DataCookie.ReserveSlot();
|
|
private static readonly DataCookie s_cursorOverrideProperty = DataCookie.ReserveSlot();
|
|
private static readonly DataCookie s_accProxyProperty = DataCookie.ReserveSlot();
|
|
private static readonly DataCookie s_pendingFocusRestoreProperty = DataCookie.ReserveSlot();
|
|
private static readonly DataCookie s_focusInterestTargetProperty = DataCookie.ReserveSlot();
|
|
private static readonly DataCookie s_focusInterestTargetMarginsProperty = DataCookie.ReserveSlot();
|
|
private static readonly EventCookie s_descendantKeyFocusChangedEvent = EventCookie.ReserveSlot();
|
|
private static readonly EventCookie s_descendantMouseFocusChangedEvent = EventCookie.ReserveSlot();
|
|
private EventContext _eventContext;
|
|
|
|
public UIClass(UIClassTypeSchema type)
|
|
{
|
|
this._typeSchema = type;
|
|
this._storage = new Dictionary<object, object>(type.TotalPropertiesAndLocalsCount);
|
|
this._bits = new BitVector32();
|
|
this.SetBit(UIClass.Bits.Flippable, true);
|
|
this.SetBit(UIClass.Bits.CreateInterestOnFocus, true);
|
|
this.SetBit(UIClass.Bits.KeyFocusOnMouseDown, true);
|
|
this.SetBit(UIClass.Bits.AllowDoubleClicks, true);
|
|
this.SetBit(UIClass.Bits.Enabled, true);
|
|
this.SetBit(UIClass.Bits.ScriptEnabled, true);
|
|
}
|
|
|
|
public bool Initialized => this.GetBit(UIClass.Bits.Initialized);
|
|
|
|
public void RegisterDisposable(IDisposableObject disposable)
|
|
{
|
|
if (disposable is ViewItem || disposable is InputHandler)
|
|
return;
|
|
if (this._disposables == null)
|
|
this._disposables = new Vector<IDisposableObject>();
|
|
this._disposables.Add(disposable);
|
|
}
|
|
|
|
public bool UnregisterDisposable(ref IDisposableObject disposable)
|
|
{
|
|
if (!(disposable is ViewItem) && !(disposable is InputHandler) && this._disposables != null)
|
|
{
|
|
int index = this._disposables.IndexOf(disposable);
|
|
if (index != -1)
|
|
{
|
|
disposable = this._disposables[index];
|
|
this._disposables.RemoveAt(index);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
protected override void OnDispose()
|
|
{
|
|
this._typeSchema.RunFinalEvaluates((IMarkupTypeBase)this);
|
|
base.OnDispose();
|
|
if (this.Initialized)
|
|
AccessibleProxy.NotifyDestroyed(this);
|
|
this.SetBit(UIClass.Bits.ScriptEnabled, false);
|
|
if (this._listeners != null)
|
|
{
|
|
this._listeners.Dispose((object)this);
|
|
this._listeners = (MarkupListeners)null;
|
|
}
|
|
this._notifier.ClearListeners();
|
|
if (this._rootItem != null)
|
|
{
|
|
this.DisposeViewItemTree(this._rootItem);
|
|
this._rootItem = (ViewItem)null;
|
|
}
|
|
this.DisposeInputHandlers();
|
|
this._storage.Clear();
|
|
if (this._disposables != null)
|
|
{
|
|
for (int index = 0; index < this._disposables.Count; ++index)
|
|
this._disposables[index].Dispose((object)this);
|
|
}
|
|
this.RemoveEventHandlers(UIClass.s_descendantMouseFocusChangedEvent);
|
|
this.RemoveEventHandlers(UIClass.s_descendantKeyFocusChangedEvent);
|
|
}
|
|
|
|
private void DisposeInputHandlers()
|
|
{
|
|
if (this._inputHandlers == null)
|
|
return;
|
|
foreach (DisposableObject inputHandler in this._inputHandlers)
|
|
inputHandler.Dispose((object)this);
|
|
}
|
|
|
|
internal void DisposeViewItemTree(ViewItem item)
|
|
{
|
|
if (item.UI != this)
|
|
return;
|
|
ViewItem nextSibling;
|
|
for (ViewItem viewItem = (ViewItem)item.FirstChild; viewItem != null; viewItem = nextSibling)
|
|
{
|
|
nextSibling = (ViewItem)viewItem.NextSibling;
|
|
this.DisposeViewItemTree(viewItem);
|
|
}
|
|
item.Dispose((object)this);
|
|
}
|
|
|
|
internal void DestroyVisualTree(ViewItem subjectItem) => this.DestroyVisualTree(subjectItem, false);
|
|
|
|
internal void DestroyVisualTree(ViewItem subjectItem, bool markLayoutOutputDirty) => this.DestroyVisualTree(subjectItem, true, markLayoutOutputDirty);
|
|
|
|
private void DestroyVisualTree(
|
|
ViewItem subjectItem,
|
|
bool allowAnimations,
|
|
bool markLayoutOutputDirty)
|
|
{
|
|
OrphanedVisualCollection orphans = new OrphanedVisualCollection(this.UISession.AnimationManager);
|
|
this.DestroyVisualTreeWorker(subjectItem, orphans, allowAnimations, markLayoutOutputDirty);
|
|
orphans.OnLayoutApplyComplete();
|
|
}
|
|
|
|
private void DestroyVisualTreeWorker(
|
|
ViewItem subjectItem,
|
|
OrphanedVisualCollection orphans,
|
|
bool allowAnimations,
|
|
bool markLayoutOutputDirty)
|
|
{
|
|
subjectItem.RendererVisual.MouseOptions = MouseOptions.None;
|
|
foreach (ViewItem child in subjectItem.Children)
|
|
{
|
|
if (child.HasVisual)
|
|
this.DestroyVisualTreeWorker(child, orphans, allowAnimations, markLayoutOutputDirty);
|
|
}
|
|
if (markLayoutOutputDirty)
|
|
subjectItem.MarkLayoutOutputDirty(false);
|
|
if (allowAnimations)
|
|
this.AnimateDestroyedVisual(subjectItem, orphans);
|
|
if (subjectItem == subjectItem.UI.RootItem && subjectItem.UI.RootItem.HasVisual)
|
|
subjectItem.UI.RevalidateUsage(true, true);
|
|
subjectItem.OrphanVisuals(orphans);
|
|
}
|
|
|
|
[Conditional("DEBUG")]
|
|
private static void DEBUG_VerifyVisualTreeDestroyed(ViewItem vi)
|
|
{
|
|
foreach (ViewItem child in vi.Children)
|
|
;
|
|
}
|
|
|
|
public int AllocateUIID(ViewItem item) => this._uiIDFactory++;
|
|
|
|
public override bool IsRoot => this.Zone.RootUI == this;
|
|
|
|
public UIClass Parent => (UIClass)base.Parent;
|
|
|
|
protected override void OnZoneAttached()
|
|
{
|
|
base.OnZoneAttached();
|
|
this.RevalidateUsage(true, false);
|
|
bool enabledFlag = true;
|
|
UIClass parent = this.Parent;
|
|
if (parent != null)
|
|
enabledFlag = parent.FullyEnabled;
|
|
this.DeliverFullyEnabled(enabledFlag);
|
|
if (this._inputHandlers != null)
|
|
{
|
|
foreach (InputHandler inputHandler in this._inputHandlers)
|
|
inputHandler.OnZoneAttached();
|
|
}
|
|
AccessibleProxy.NotifyTreeChanged(this);
|
|
}
|
|
|
|
protected override void OnZoneDetached()
|
|
{
|
|
base.OnZoneDetached();
|
|
this.ChangeBit(UIClass.Bits.AppFullyEnabled, false);
|
|
this.RevalidateUsage(true, true);
|
|
if (this._inputHandlers != null)
|
|
{
|
|
foreach (InputHandler inputHandler in this._inputHandlers)
|
|
inputHandler.OnZoneDetached();
|
|
}
|
|
if (this._rootItem == null || !this._rootItem.HasVisual)
|
|
return;
|
|
this.DestroyVisualTree(this._rootItem);
|
|
}
|
|
|
|
protected override void OnChildrenChanged()
|
|
{
|
|
base.OnChildrenChanged();
|
|
if (!this.IsZoned)
|
|
return;
|
|
AccessibleProxy.NotifyTreeChanged(this);
|
|
}
|
|
|
|
public bool HasAccessibleProxy => this.GetBit(UIClass.Bits.HasAccProxy);
|
|
|
|
protected virtual AccessibleProxy OnCreateAccessibleProxy(
|
|
UIClass ui,
|
|
Accessible data)
|
|
{
|
|
return new AccessibleProxy(ui, data);
|
|
}
|
|
|
|
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
|
public AccessibleProxy AccessibleProxy
|
|
{
|
|
get
|
|
{
|
|
AccessibleProxy accessibleProxy;
|
|
if (this.HasAccessibleProxy)
|
|
{
|
|
accessibleProxy = (AccessibleProxy)this.GetData(UIClass.s_accProxyProperty);
|
|
}
|
|
else
|
|
{
|
|
Accessible data = null;
|
|
foreach (KeyValuePair<object, object> keyValuePair in this._storage)
|
|
{
|
|
if (keyValuePair.Value is Accessible accessible)
|
|
{
|
|
data = accessible;
|
|
break;
|
|
}
|
|
}
|
|
if (data == null)
|
|
data = new Accessible();
|
|
accessibleProxy = this.OnCreateAccessibleProxy(this, data);
|
|
this.SetData(UIClass.s_accProxyProperty, (object)accessibleProxy);
|
|
this.SetBit(UIClass.Bits.HasAccProxy, true);
|
|
}
|
|
return accessibleProxy;
|
|
}
|
|
}
|
|
|
|
internal static bool ShouldPlayAnimation(IAnimationProvider provider)
|
|
{
|
|
if (provider == null)
|
|
return false;
|
|
bool flag = true;
|
|
if (provider is NonIntensiveAnimation)
|
|
flag = false;
|
|
return AnimationSystem.Enabled || !flag;
|
|
}
|
|
|
|
private void AnimateNewVisual(
|
|
ViewItem vi,
|
|
Vector3 startPosVector,
|
|
Vector2 startSizeVector,
|
|
Vector3 startScaleVector,
|
|
Rotation startRotation)
|
|
{
|
|
vi.VisualPosition = startPosVector;
|
|
vi.VisualSize = startSizeVector;
|
|
vi.VisualScale = startScaleVector;
|
|
vi.VisualRotation = startRotation;
|
|
this.AnimateNewVisual(vi);
|
|
}
|
|
|
|
private void AnimateNewVisual(ViewItem vi)
|
|
{
|
|
vi.PlayShowAnimation();
|
|
if (!this.DirectKeyFocus)
|
|
return;
|
|
vi.PlayAnimation(AnimationEventType.GainFocus);
|
|
}
|
|
|
|
private void AnimateDestroyedVisual(ViewItem vi, OrphanedVisualCollection orphans) => vi.PlayHideAnimation(orphans);
|
|
|
|
private void AnimateVisual(
|
|
ViewItem vi,
|
|
Vector3 newPosVector,
|
|
Vector2 newSizeVector,
|
|
Vector3 newScaleVector,
|
|
Rotation newRotation)
|
|
{
|
|
Vector3 visualPosition = vi.VisualPosition;
|
|
Vector2 visualSize = vi.VisualSize;
|
|
Vector3 visualScale = vi.VisualScale;
|
|
Rotation visualRotation = vi.VisualRotation;
|
|
float visualAlpha = vi.VisualAlpha;
|
|
AnimationArgs args = new AnimationArgs(vi, visualPosition, visualSize, visualScale, visualRotation, visualAlpha, newPosVector, newSizeVector, newScaleVector, newRotation, visualAlpha);
|
|
if (visualPosition != newPosVector)
|
|
vi.ApplyAnimatableValue(AnimationEventType.Move, ref args);
|
|
if (visualSize != newSizeVector)
|
|
vi.ApplyAnimatableValue(AnimationEventType.Size, ref args);
|
|
if (visualScale != newScaleVector)
|
|
vi.ApplyAnimatableValue(AnimationEventType.Scale, ref args);
|
|
if (!(visualRotation != newRotation))
|
|
return;
|
|
vi.ApplyAnimatableValue(AnimationEventType.Rotate, ref args);
|
|
}
|
|
|
|
private void TryToPlayAnimationOnTree(ViewItem vi, AnimationEventType type)
|
|
{
|
|
if (!vi.HasVisual)
|
|
return;
|
|
vi.PlayAnimation(type);
|
|
foreach (ViewItem child in vi.Children)
|
|
{
|
|
if (child.UI == this)
|
|
this.TryToPlayAnimationOnTree(child, type);
|
|
}
|
|
}
|
|
|
|
internal object SaveKeyFocus()
|
|
{
|
|
if (this.KeyFocus)
|
|
{
|
|
UIClass keyFocusDescendant = this.KeyFocusDescendant;
|
|
if (keyFocusDescendant != null && keyFocusDescendant.RootItem != null)
|
|
return (object)new UIClass.SavedFocusState(keyFocusDescendant.RootItem);
|
|
}
|
|
return (object)null;
|
|
}
|
|
|
|
internal void RestoreKeyFocus(object obj) => this.RestoreKeyFocus(obj, true);
|
|
|
|
internal void RestoreKeyFocus(object obj, bool allowDeferralFlag)
|
|
{
|
|
if (!(obj is UIClass.SavedFocusState focusState))
|
|
return;
|
|
ViewItem resultItem;
|
|
ViewItemID failedComponent;
|
|
switch (this.RootItem.FindChildFromPath(focusState.Path, out resultItem, out failedComponent))
|
|
{
|
|
case FindChildResult.Success:
|
|
if (resultItem == null)
|
|
break;
|
|
UIClass ui = resultItem.UI;
|
|
if (!this.HasDescendant((Microsoft.Iris.Library.TreeNode)ui) || !ui.IsKeyFocusable())
|
|
break;
|
|
resultItem.NavigateInto(focusState.FocusIsDefault);
|
|
break;
|
|
case FindChildResult.PotentiallyFaultIn:
|
|
if (!allowDeferralFlag)
|
|
break;
|
|
new UIClass.DeferredKeyFocusRestoreHelper(this, focusState).FaultInChild(resultItem, failedComponent);
|
|
break;
|
|
}
|
|
}
|
|
|
|
private UIClass.DeferredKeyFocusRestoreHelper PendingFocusRestore
|
|
{
|
|
get => this.GetData(UIClass.s_pendingFocusRestoreProperty) as UIClass.DeferredKeyFocusRestoreHelper;
|
|
set => this.SetData(UIClass.s_pendingFocusRestoreProperty, (object)value);
|
|
}
|
|
|
|
private static bool CheckHandled(InputInfo info, InputHandler inputHandler) => info.Handled;
|
|
|
|
public void SetAreaOfInterest(AreaOfInterestID id) => this.SetAreaOfInterest(id, this.RootItem, Inset.Zero);
|
|
|
|
public void SetAreaOfInterest(AreaOfInterestID id, ViewItem target, Inset margins) => target.SetAreaOfInterest(id, margins);
|
|
|
|
public void ClearAreaOfInterest(AreaOfInterestID id) => this.ClearAreaOfInterest(id, this.RootItem);
|
|
|
|
public void ClearAreaOfInterest(AreaOfInterestID id, ViewItem target) => target.ClearAreaOfInterest(id);
|
|
|
|
internal void UpdateMouseHandling(ViewItem childItem)
|
|
{
|
|
if (childItem == null)
|
|
{
|
|
childItem = this.RootItem;
|
|
if (childItem == null)
|
|
return;
|
|
}
|
|
if (!childItem.HasVisual)
|
|
return;
|
|
MouseOptions mouseOptions = MouseOptions.None;
|
|
if (!childItem.IsOffscreen && childItem.AllowMouseInput && (childItem != this.RootItem || this.IsInputBranchEnabled() && this.InputEnabled))
|
|
mouseOptions |= MouseOptions.Traversable;
|
|
if (childItem.MouseInteractive && this.MouseInteractive)
|
|
mouseOptions |= MouseOptions.Hittable;
|
|
if (childItem == this.RootItem)
|
|
mouseOptions |= MouseOptions.Returnable;
|
|
if (childItem.ClipMouse)
|
|
mouseOptions |= MouseOptions.ClipChildren;
|
|
childItem.RendererVisual.MouseOptions = mouseOptions;
|
|
}
|
|
|
|
internal void OnHostVisibilityChanged()
|
|
{
|
|
this.OnInputEnabledChanged();
|
|
AccessibleProxy.NotifyVisibilityChange(this, this.Visible);
|
|
}
|
|
|
|
public IList EnsureInputHandlerStorage()
|
|
{
|
|
if (this._inputHandlers == null)
|
|
this._inputHandlers = new InputHandlerList();
|
|
return (IList)this._inputHandlers;
|
|
}
|
|
|
|
internal bool Visible => this.IsRoot || this._ownerHost.HasVisual;
|
|
|
|
internal bool InputEnabled
|
|
{
|
|
get
|
|
{
|
|
if (this.IsRoot)
|
|
return true;
|
|
return this.Visible && this._ownerHost.InputEnabled;
|
|
}
|
|
}
|
|
|
|
public bool Enabled
|
|
{
|
|
get => this.GetBit(UIClass.Bits.Enabled);
|
|
set
|
|
{
|
|
if (!this.ChangeBit(UIClass.Bits.Enabled, value))
|
|
return;
|
|
this.UpdateMouseHandling((ViewItem)null);
|
|
this.RevalidateUsage(true, !value);
|
|
this.FireNotification(NotificationID.Enabled);
|
|
if (!this.IsZoned || this.Parent != null && !this.Parent.FullyEnabled)
|
|
return;
|
|
this.NotifyFullyEnabledChange();
|
|
}
|
|
}
|
|
|
|
private bool HostEnabled => this._ownerHost == null ? this.IsValid : this._ownerHost.InputEnabled;
|
|
|
|
public bool FullyEnabled => this.GetBit(UIClass.Bits.AppFullyEnabled);
|
|
|
|
public bool DirectMouseFocus => this.GetBit(UIClass.Bits.DirectMouseFocus);
|
|
|
|
public bool MouseFocus => this.GetBit(UIClass.Bits.MouseFocus);
|
|
|
|
public bool DirectKeyFocus => this.GetBit(UIClass.Bits.DirectKeyFocus);
|
|
|
|
public bool KeyFocus => this.GetBit(UIClass.Bits.KeyFocus);
|
|
|
|
public UIClass KeyFocusDescendant
|
|
{
|
|
get
|
|
{
|
|
//uiClass = (UIClass)null;
|
|
if (this.KeyFocus && this.UISession.InputManager.RawInstantaneousKeyFocus is UIClass uiClass)
|
|
{
|
|
if (uiClass.IsDisposed)
|
|
return null;
|
|
else
|
|
return uiClass;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public uint PaintOrder
|
|
{
|
|
get => this._ownerHost.Layer;
|
|
set => this._ownerHost.Layer = value;
|
|
}
|
|
|
|
public bool CreateInterestOnFocus
|
|
{
|
|
get => this.GetBit(UIClass.Bits.CreateInterestOnFocus);
|
|
set
|
|
{
|
|
if (!this.ChangeBit(UIClass.Bits.CreateInterestOnFocus, value))
|
|
return;
|
|
this.FireNotification(NotificationID.CreateInterestOnFocus);
|
|
}
|
|
}
|
|
|
|
public ViewItem FocusInterestTarget
|
|
{
|
|
get => (ViewItem)this.GetData(UIClass.s_focusInterestTargetProperty);
|
|
set
|
|
{
|
|
if (this.FocusInterestTarget == value)
|
|
return;
|
|
this.SetData(UIClass.s_focusInterestTargetProperty, (object)value);
|
|
this.FireNotification(NotificationID.FocusInterestTarget);
|
|
}
|
|
}
|
|
|
|
public Inset FocusInterestTargetMargins
|
|
{
|
|
get
|
|
{
|
|
object data = this.GetData(UIClass.s_focusInterestTargetMarginsProperty);
|
|
return data != null ? (Inset)data : Inset.Zero;
|
|
}
|
|
set
|
|
{
|
|
if (!(this.FocusInterestTargetMargins != value))
|
|
return;
|
|
this.SetData(UIClass.s_focusInterestTargetMarginsProperty, (object)value);
|
|
this.FireNotification(NotificationID.FocusInterestTargetMargins);
|
|
}
|
|
}
|
|
|
|
public CursorID Cursor
|
|
{
|
|
get
|
|
{
|
|
CursorID cursorId = CursorID.NotSpecified;
|
|
object data = this.GetData(UIClass.s_cursorProperty);
|
|
if (data != null)
|
|
cursorId = (CursorID)data;
|
|
return cursorId;
|
|
}
|
|
set
|
|
{
|
|
if (this.Cursor == value)
|
|
return;
|
|
this.SetData(UIClass.s_cursorProperty, (object)value);
|
|
this.FireNotification(NotificationID.Cursor);
|
|
if (!this.IsZoned || this.OverrideCursor != CursorID.NotSpecified)
|
|
return;
|
|
this.Zone.UpdateCursor(this);
|
|
}
|
|
}
|
|
|
|
private CursorID OverrideCursor
|
|
{
|
|
get
|
|
{
|
|
CursorID cursorId = CursorID.NotSpecified;
|
|
object data = this.GetData(UIClass.s_cursorOverrideProperty);
|
|
if (data != null)
|
|
cursorId = (CursorID)data;
|
|
return cursorId;
|
|
}
|
|
set
|
|
{
|
|
CursorID overrideCursor = this.OverrideCursor;
|
|
if (overrideCursor == value)
|
|
return;
|
|
this.SetData(UIClass.s_cursorOverrideProperty, (object)value);
|
|
if (!this.IsZoned || overrideCursor == CursorID.NotSpecified && value == this.Cursor)
|
|
return;
|
|
this.Zone.UpdateCursor(this);
|
|
}
|
|
}
|
|
|
|
public CursorID EffectiveCursor
|
|
{
|
|
get
|
|
{
|
|
CursorID cursorId = this.OverrideCursor;
|
|
if (cursorId == CursorID.NotSpecified)
|
|
cursorId = this.Cursor;
|
|
return cursorId;
|
|
}
|
|
}
|
|
|
|
public void UpdateCursor()
|
|
{
|
|
CursorID cursorId = CursorID.NotSpecified;
|
|
if (this._inputHandlers != null)
|
|
{
|
|
foreach (InputHandler inputHandler in this._inputHandlers)
|
|
{
|
|
if (inputHandler.Enabled)
|
|
{
|
|
cursorId = inputHandler.GetCursor();
|
|
if (cursorId != CursorID.NotSpecified)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
this.OverrideCursor = cursorId;
|
|
}
|
|
|
|
public bool KeyFocusOnMouseEnter
|
|
{
|
|
get => this.GetBit(UIClass.Bits.KeyFocusOnMouseEnter);
|
|
set => this.SetBit(UIClass.Bits.KeyFocusOnMouseEnter, value);
|
|
}
|
|
|
|
public bool KeyFocusOnMouseDown
|
|
{
|
|
get => this.GetBit(UIClass.Bits.KeyFocusOnMouseDown);
|
|
set => this.SetBit(UIClass.Bits.KeyFocusOnMouseDown, value);
|
|
}
|
|
|
|
public bool AllowDoubleClicks
|
|
{
|
|
get => this.GetBit(UIClass.Bits.AllowDoubleClicks);
|
|
set => this.SetBit(UIClass.Bits.AllowDoubleClicks, value);
|
|
}
|
|
|
|
internal void NotifyFullyEnabledChange() => this.Zone.ScheduleFullyEnabledChangeNotifications();
|
|
|
|
internal void DeliverFullyEnabled(bool enabledFlag)
|
|
{
|
|
if (!this.Enabled || !this.HostEnabled)
|
|
enabledFlag = false;
|
|
if (this.ChangeBit(UIClass.Bits.AppFullyEnabled, enabledFlag))
|
|
this.FireNotification(NotificationID.FullyEnabled);
|
|
foreach (UIClass child in this.Children)
|
|
child.DeliverFullyEnabled(enabledFlag);
|
|
}
|
|
|
|
public void EnableRawInput(bool enableFlag)
|
|
{
|
|
if (!this.ChangeBit(UIClass.Bits.RawInputDisabled, !enableFlag))
|
|
return;
|
|
this.UpdateMouseHandling((ViewItem)null);
|
|
this.RevalidateUsage(true, !enableFlag);
|
|
}
|
|
|
|
public bool IsInputBranchEnabled() => this.GetBit(UIClass.Bits.Enabled) && !this.GetBit(UIClass.Bits.RawInputDisabled);
|
|
|
|
public bool IsEligibleForInput() => this.IsEligibleForInput(out UIClass _);
|
|
|
|
public bool IsEligibleForInput(out UIClass failurePoint)
|
|
{
|
|
failurePoint = (UIClass)null;
|
|
UIClass uiClass = this;
|
|
while (true)
|
|
{
|
|
failurePoint = uiClass;
|
|
if (uiClass.IsInputBranchEnabled() && uiClass.InputEnabled)
|
|
{
|
|
UIClass parent = uiClass.Parent;
|
|
if (parent != null)
|
|
uiClass = parent;
|
|
else
|
|
goto label_5;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return false;
|
|
label_5:
|
|
failurePoint = (UIClass)null;
|
|
return this.IsZoned;
|
|
}
|
|
|
|
public bool MouseInteractive
|
|
{
|
|
get => this.GetBit(UIClass.Bits.MouseInteractive);
|
|
set => this.SetMouseInteractive(value, false);
|
|
}
|
|
|
|
public void SetMouseInteractive(bool value, bool fromScript)
|
|
{
|
|
if (fromScript)
|
|
this.SetBit(UIClass.Bits.MouseInteractiveSet, true);
|
|
if (!fromScript && this.GetBit(UIClass.Bits.MouseInteractiveSet) || !this.ChangeBit(UIClass.Bits.MouseInteractive, value))
|
|
return;
|
|
if (value && this._rootItem != null && !this.HasMouseInteractiveContent())
|
|
this._rootItem.MouseInteractive = true;
|
|
this.UpdateMouseHandling((ViewItem)null);
|
|
this.RevalidateUsage(false, !value);
|
|
this.FireNotification(NotificationID.MouseInteractive);
|
|
if (!DebugOutlines.Enabled)
|
|
return;
|
|
DebugOutlines.NotifyInteractivityChange((ViewItem)this.Host);
|
|
}
|
|
|
|
public bool IsMouseFocusable() => this.MouseInteractive && this.IsEligibleForInput();
|
|
|
|
public bool KeyInteractive
|
|
{
|
|
get => this.GetBit(UIClass.Bits.KeyInteractive);
|
|
set
|
|
{
|
|
if (!this.ChangeBit(UIClass.Bits.KeyInteractive, value))
|
|
return;
|
|
this.RevalidateUsage(false, !value);
|
|
this.FireNotification(NotificationID.KeyInteractive);
|
|
if (!DebugOutlines.Enabled)
|
|
return;
|
|
DebugOutlines.NotifyInteractivityChange((ViewItem)this.Host);
|
|
}
|
|
}
|
|
|
|
public event SessionInputHandler SessionInput
|
|
{
|
|
add => this.Zone.SessionInput += value;
|
|
remove => this.Zone.SessionInput -= value;
|
|
}
|
|
|
|
public bool HostActivated => this.Zone.Form.ActivationState;
|
|
|
|
public bool IsKeyFocusable() => this.KeyInteractive && this.IsEligibleForInput();
|
|
|
|
public UIClass FindKeyFocusableAncestor()
|
|
{
|
|
if (!this.IsValid)
|
|
return (UIClass)null;
|
|
UIClass uiClass;
|
|
for (uiClass = this; uiClass != null; uiClass = uiClass.Parent)
|
|
{
|
|
UIClass failurePoint = (UIClass)null;
|
|
if (uiClass.KeyInteractive && uiClass.IsEligibleForInput(out failurePoint))
|
|
return uiClass;
|
|
if (failurePoint != null)
|
|
uiClass = failurePoint;
|
|
}
|
|
return uiClass;
|
|
}
|
|
|
|
public void NavigateInto() => this.NavigateInto(false);
|
|
|
|
public void NavigateInto(bool isDefault) => this.RequestKeyFocus(isDefault ? KeyFocusReason.Default : KeyFocusReason.Other);
|
|
|
|
public void RequestKeyFocus() => this.RequestKeyFocus(KeyFocusReason.Other);
|
|
|
|
private void RequestKeyFocus(KeyFocusReason keyfocusReason)
|
|
{
|
|
if (!this.IsKeyFocusable())
|
|
return;
|
|
this.UISession.InputManager.Queue.RequestKeyFocus((ICookedInputSite)this, keyfocusReason);
|
|
}
|
|
|
|
public bool IsValid => !this.IsDisposed;
|
|
|
|
public static FocusStateHandler GetFocusUpdateProc(InputDeviceType focusType)
|
|
{
|
|
switch (focusType)
|
|
{
|
|
case InputDeviceType.Keyboard:
|
|
return UIClass.s_updateKeyFocusStates;
|
|
case InputDeviceType.Mouse:
|
|
return UIClass.s_updateMouseFocusStates;
|
|
default:
|
|
return (FocusStateHandler)null;
|
|
}
|
|
}
|
|
|
|
private void RevalidateUsage(bool recursiveFlag, bool knownDisabledFlag)
|
|
{
|
|
if (!this.IsZoned)
|
|
return;
|
|
this.UISession.InputManager.RevalidateInputSiteUsage((ICookedInputSite)this, recursiveFlag, knownDisabledFlag);
|
|
}
|
|
|
|
internal void OnInputEnabledChanged()
|
|
{
|
|
if (!this.IsZoned)
|
|
return;
|
|
this.RevalidateUsage(true, !this.InputEnabled);
|
|
this.UpdateMouseHandling((ViewItem)null);
|
|
if (!this.Enabled || this.Parent != null && !this.Parent.FullyEnabled)
|
|
return;
|
|
this.NotifyFullyEnabledChange();
|
|
}
|
|
|
|
IRawInputSite ICookedInputSite.RawInputSource
|
|
{
|
|
get
|
|
{
|
|
IRawInputSite rawInputSite = (IRawInputSite)null;
|
|
if (this._rootItem != null)
|
|
rawInputSite = (IRawInputSite)this._rootItem.RendererVisual;
|
|
return rawInputSite;
|
|
}
|
|
}
|
|
|
|
public void DeliverInput(InputInfo info, EventRouteStages stage)
|
|
{
|
|
if (stage != EventRouteStages.Unhandled)
|
|
{
|
|
switch (info.EventType)
|
|
{
|
|
case InputEventType.CommandDown:
|
|
case InputEventType.CommandUp:
|
|
case InputEventType.KeyDown:
|
|
case InputEventType.KeyUp:
|
|
case InputEventType.KeyCharacter:
|
|
case InputEventType.MouseMove:
|
|
case InputEventType.MousePrimaryUp:
|
|
case InputEventType.MouseSecondaryUp:
|
|
case InputEventType.MouseWheel:
|
|
case InputEventType.DragEnter:
|
|
case InputEventType.DragOver:
|
|
case InputEventType.DragLeave:
|
|
case InputEventType.DragDropped:
|
|
case InputEventType.DragComplete:
|
|
this.DeliverInputEvent(info, stage);
|
|
break;
|
|
case InputEventType.GainKeyFocus:
|
|
this.DeliverGainKeyFocus(info, stage);
|
|
break;
|
|
case InputEventType.LoseKeyFocus:
|
|
this.DeliverLoseKeyFocus(info, stage);
|
|
break;
|
|
case InputEventType.GainMouseFocus:
|
|
this.DeliverGainMouseFocus(info, stage);
|
|
break;
|
|
case InputEventType.LoseMouseFocus:
|
|
this.DeliverFocusChange(info, stage);
|
|
break;
|
|
case InputEventType.MousePrimaryDown:
|
|
case InputEventType.MouseSecondaryDown:
|
|
case InputEventType.MouseDoubleClick:
|
|
this.DeliverMouseButtonDown(info, stage);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(info is KeyStateInfo keyStateInfo) || keyStateInfo.Action != KeyAction.Down || (keyStateInfo.SystemKey || !this.KeyNavigate(keyStateInfo.Key, keyStateInfo.Modifiers)))
|
|
return;
|
|
keyStateInfo.MarkHandled();
|
|
}
|
|
}
|
|
|
|
private void DeliverInputEvent(InputInfo info, EventRouteStages stage)
|
|
{
|
|
if (info.Handled)
|
|
return;
|
|
this.ForwardEventToInputHandlers(info, stage);
|
|
}
|
|
|
|
private void ForwardEventToInputHandlers(InputInfo info, EventRouteStages stage)
|
|
{
|
|
if (this._inputHandlers == null)
|
|
return;
|
|
foreach (InputHandler inputHandler in this._inputHandlers)
|
|
{
|
|
inputHandler.DeliverInput(this, info, stage);
|
|
if (UIClass.CheckHandled(info, inputHandler))
|
|
break;
|
|
}
|
|
}
|
|
|
|
private void DeliverFocusChange(InputInfo info, EventRouteStages stage)
|
|
{
|
|
if (stage == EventRouteStages.Routed)
|
|
{
|
|
int num = info.Handled ? 1 : 0;
|
|
this.DeliverCodeNotifications(info);
|
|
}
|
|
this.ForwardEventToInputHandlers(info, stage);
|
|
}
|
|
|
|
private void DeliverGainKeyFocus(InputInfo info, EventRouteStages stage)
|
|
{
|
|
if (stage == EventRouteStages.Direct)
|
|
this.OnGainKeyFocus();
|
|
this.DeliverFocusChange(info, stage);
|
|
}
|
|
|
|
private void DeliverLoseKeyFocus(InputInfo info, EventRouteStages stage)
|
|
{
|
|
if (stage == EventRouteStages.Direct)
|
|
this.OnLoseKeyFocus();
|
|
this.DeliverFocusChange(info, stage);
|
|
}
|
|
|
|
private void DeliverGainMouseFocus(InputInfo info, EventRouteStages stage)
|
|
{
|
|
if (stage == EventRouteStages.Direct && this.GetBit(UIClass.Bits.KeyFocusOnMouseEnter))
|
|
this.RequestKeyFocus(KeyFocusReason.MouseEnter);
|
|
this.DeliverFocusChange(info, stage);
|
|
}
|
|
|
|
private void DeliverMouseButtonDown(InputInfo args, EventRouteStages stage)
|
|
{
|
|
if (stage == EventRouteStages.Direct && this.GetBit(UIClass.Bits.KeyFocusOnMouseDown))
|
|
this.RequestKeyFocus(KeyFocusReason.MouseDown);
|
|
this.DeliverInputEvent(args, stage);
|
|
}
|
|
|
|
private void OnGainKeyFocus()
|
|
{
|
|
NavigationServices.SeedDefaultFocus((INavigationSite)this.RootItem);
|
|
if (this.CreateInterestOnFocus)
|
|
{
|
|
this.SetAreaOfInterest(AreaOfInterestID.Focus);
|
|
ViewItem focusInterestTarget = this.FocusInterestTarget;
|
|
if (focusInterestTarget != null && focusInterestTarget != this.RootItem)
|
|
this.SetAreaOfInterest(AreaOfInterestID.FocusOverride, focusInterestTarget, this.FocusInterestTargetMargins);
|
|
}
|
|
this.TryToPlayAnimationOnTree(this.RootItem, AnimationEventType.GainFocus);
|
|
}
|
|
|
|
private void OnLoseKeyFocus()
|
|
{
|
|
if (this.RootItem == null)
|
|
return;
|
|
if (this.CreateInterestOnFocus)
|
|
{
|
|
this.ClearAreaOfInterest(AreaOfInterestID.Focus);
|
|
ViewItem focusInterestTarget = this.FocusInterestTarget;
|
|
if (focusInterestTarget != null && focusInterestTarget != this.RootItem)
|
|
this.ClearAreaOfInterest(AreaOfInterestID.FocusOverride, focusInterestTarget);
|
|
}
|
|
this.TryToPlayAnimationOnTree(this.RootItem, AnimationEventType.LoseFocus);
|
|
}
|
|
|
|
private void OnGainDeepKeyFocus()
|
|
{
|
|
if (this._inputHandlers == null)
|
|
return;
|
|
foreach (InputHandler inputHandler in this._inputHandlers)
|
|
inputHandler.NotifyGainDeepKeyFocus();
|
|
}
|
|
|
|
private void OnLoseDeepKeyFocus()
|
|
{
|
|
if (this._inputHandlers == null)
|
|
return;
|
|
foreach (InputHandler inputHandler in this._inputHandlers)
|
|
inputHandler.NotifyLoseDeepKeyFocus();
|
|
}
|
|
|
|
private static void UpdateKeyFocusStates(
|
|
UIClass recipient,
|
|
bool deepFocusFlag,
|
|
bool directFocusFlag)
|
|
{
|
|
if (recipient.ChangeBit(UIClass.Bits.KeyFocus, deepFocusFlag))
|
|
{
|
|
recipient.FireNotification(NotificationID.KeyFocus);
|
|
if (deepFocusFlag)
|
|
recipient.OnGainDeepKeyFocus();
|
|
else
|
|
recipient.OnLoseDeepKeyFocus();
|
|
}
|
|
if (!recipient.ChangeBit(UIClass.Bits.DirectKeyFocus, directFocusFlag))
|
|
return;
|
|
recipient.FireNotification(NotificationID.DirectKeyFocus);
|
|
if (DebugOutlines.Enabled)
|
|
DebugOutlines.NotifyInteractivityChange((ViewItem)recipient.Host);
|
|
if (!directFocusFlag)
|
|
return;
|
|
AccessibleProxy.NotifyFocus(recipient);
|
|
}
|
|
|
|
public event InputEventHandler DescendentKeyFocusChange
|
|
{
|
|
add => this.AddEventHandler(UIClass.s_descendantKeyFocusChangedEvent, (Delegate)value);
|
|
remove => this.RemoveEventHandler(UIClass.s_descendantKeyFocusChangedEvent, (Delegate)value);
|
|
}
|
|
|
|
private static void UpdateMouseFocusStates(
|
|
UIClass recipient,
|
|
bool deepFocusFlag,
|
|
bool directFocusFlag)
|
|
{
|
|
if (recipient.ChangeBit(UIClass.Bits.MouseFocus, deepFocusFlag))
|
|
recipient.FireNotification(NotificationID.MouseFocus);
|
|
if (!recipient.ChangeBit(UIClass.Bits.DirectMouseFocus, directFocusFlag))
|
|
return;
|
|
recipient.FireNotification(NotificationID.DirectMouseFocus);
|
|
if (!DebugOutlines.Enabled)
|
|
return;
|
|
DebugOutlines.NotifyInteractivityChange((ViewItem)recipient.Host);
|
|
}
|
|
|
|
public event InputEventHandler DescendentMouseFocusChange
|
|
{
|
|
add => this.AddEventHandler(UIClass.s_descendantMouseFocusChangedEvent, (Delegate)value);
|
|
remove => this.RemoveEventHandler(UIClass.s_descendantMouseFocusChangedEvent, (Delegate)value);
|
|
}
|
|
|
|
private void DeliverCodeNotifications(InputInfo info)
|
|
{
|
|
EventCookie focusChangedEvent = EventCookie.NULL;
|
|
switch (info.EventType)
|
|
{
|
|
case InputEventType.GainKeyFocus:
|
|
case InputEventType.LoseKeyFocus:
|
|
focusChangedEvent = UIClass.s_descendantKeyFocusChangedEvent;
|
|
break;
|
|
case InputEventType.GainMouseFocus:
|
|
case InputEventType.LoseMouseFocus:
|
|
focusChangedEvent = UIClass.s_descendantMouseFocusChangedEvent;
|
|
break;
|
|
}
|
|
if (!(focusChangedEvent != EventCookie.NULL) || !(this.GetEventHandler(focusChangedEvent) is InputEventHandler eventHandler))
|
|
return;
|
|
eventHandler(this, info);
|
|
}
|
|
|
|
public void ApplyLayoutOutput(
|
|
ViewItem subjectItem,
|
|
bool parentFullyVisible,
|
|
bool parentOffscreen,
|
|
bool allowAnimations,
|
|
out bool visibilityChange,
|
|
out bool offscreenChange)
|
|
{
|
|
bool flag1 = subjectItem.LayoutVisible && parentFullyVisible;
|
|
bool hasVisual = subjectItem.HasVisual;
|
|
if (!flag1 && !hasVisual)
|
|
{
|
|
visibilityChange = false;
|
|
offscreenChange = false;
|
|
}
|
|
else
|
|
{
|
|
visibilityChange = flag1 != hasVisual;
|
|
bool flag2 = visibilityChange && hasVisual;
|
|
bool flag3 = visibilityChange && !hasVisual;
|
|
if (flag3)
|
|
subjectItem.CreateVisual(this.Zone.Session.RenderSession);
|
|
Rectangle layoutBounds = subjectItem.LayoutBounds;
|
|
Vector2 vector2 = new Vector2((float)layoutBounds.Width, (float)layoutBounds.Height);
|
|
Vector3 vector3_1 = new Vector3((float)layoutBounds.X, (float)layoutBounds.Y, 0.0f);
|
|
Vector3 vector3_2 = subjectItem.LayoutScale * subjectItem.Scale;
|
|
Rotation layoutRotation = subjectItem.LayoutRotation;
|
|
Vector3 oldScaleVector;
|
|
if (!hasVisual)
|
|
{
|
|
this.AnimateNewVisual(subjectItem, vector3_1, vector2, vector3_2, layoutRotation);
|
|
oldScaleVector = vector3_2;
|
|
}
|
|
else
|
|
{
|
|
Vector2 visualSize = subjectItem.VisualSize;
|
|
oldScaleVector = subjectItem.VisualScale;
|
|
}
|
|
bool flag4 = subjectItem.LayoutOffscreen || parentOffscreen;
|
|
offscreenChange = flag4 != subjectItem.IsOffscreen;
|
|
if (offscreenChange)
|
|
subjectItem.IsOffscreen = flag4;
|
|
if (offscreenChange || flag3)
|
|
this.UpdateMouseHandling(subjectItem);
|
|
bool flag5 = hasVisual;
|
|
if (flag5 && flag2)
|
|
flag5 = false;
|
|
if (flag5)
|
|
this.AnimateVisual(subjectItem, vector3_1, vector2, vector3_2, layoutRotation);
|
|
if (flag2)
|
|
{
|
|
if (subjectItem.IsRoot)
|
|
return;
|
|
this.DestroyVisualTree(subjectItem, allowAnimations, false);
|
|
}
|
|
else
|
|
{
|
|
if (!(oldScaleVector != vector3_2) && hasVisual)
|
|
return;
|
|
subjectItem.OnScaleChange(oldScaleVector, vector3_2);
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool FindNextFocusablePeer(
|
|
Direction searchDirection,
|
|
RectangleF startRectangleF,
|
|
out UIClass resultUI)
|
|
{
|
|
if (this._rootItem != null)
|
|
return this.FindNextFocusablePeerWorker(this._rootItem, searchDirection, startRectangleF, out resultUI);
|
|
resultUI = (UIClass)null;
|
|
return false;
|
|
}
|
|
|
|
private bool FindNextFocusablePeerWorker(
|
|
ViewItem startItem,
|
|
Direction searchDirection,
|
|
RectangleF startRectangleF,
|
|
out UIClass resultUI)
|
|
{
|
|
INavigationSite resultSite;
|
|
bool nextPeer = NavigationServices.FindNextPeer((INavigationSite)startItem, searchDirection, startRectangleF, out resultSite);
|
|
resultUI = (UIClass)null;
|
|
if (resultSite != null && resultSite is ViewItem viewItem)
|
|
resultUI = viewItem.UI;
|
|
return nextPeer;
|
|
}
|
|
|
|
internal bool FindNextFocusableWithin(
|
|
Direction searchDirection,
|
|
RectangleF startRectangleF,
|
|
out UIClass resultUI)
|
|
{
|
|
INavigationSite resultSite;
|
|
bool nextWithin = NavigationServices.FindNextWithin((INavigationSite)this._rootItem, searchDirection, startRectangleF, out resultSite);
|
|
resultUI = (UIClass)null;
|
|
if (resultSite != null && resultSite is ViewItem viewItem)
|
|
resultUI = viewItem.UI;
|
|
return nextWithin;
|
|
}
|
|
|
|
internal NavigationClass GetNavigability(ViewItem subjectItem)
|
|
{
|
|
NavigationClass navigationClass = NavigationClass.None;
|
|
if (subjectItem == this._rootItem && this.IsKeyFocusable())
|
|
navigationClass = NavigationClass.Direct;
|
|
return navigationClass;
|
|
}
|
|
|
|
public void NotifyNavigationDestination(KeyFocusReason keyFocusReason) => this.RequestKeyFocus(keyFocusReason);
|
|
|
|
public bool InboundKeyNavigation(
|
|
Direction searchDirection,
|
|
RectangleF startRectangleF,
|
|
bool defaultFlag)
|
|
{
|
|
UIClass resultUI;
|
|
if (!this.FindNextFocusableWithin(searchDirection, startRectangleF, out resultUI) || resultUI == null)
|
|
return false;
|
|
resultUI.NotifyNavigationDestination(defaultFlag ? KeyFocusReason.Default : KeyFocusReason.Other);
|
|
return true;
|
|
}
|
|
|
|
public bool NavigateDirection(Direction direction, KeyFocusReason reason)
|
|
{
|
|
UIClass resultUI;
|
|
if (!this.FindNextFocusablePeer(direction, RectangleF.Zero, out resultUI) || resultUI == null)
|
|
return false;
|
|
UIClass uiClass = this;
|
|
resultUI.NotifyNavigationDestination(reason);
|
|
return true;
|
|
}
|
|
|
|
private bool KeyNavigate(Keys key, InputModifiers modifiers)
|
|
{
|
|
InputHandlerModifiers modifiers1 = InputHandler.GetModifiers(modifiers);
|
|
KeyHandler.TranslateKey(ref key, ref modifiers1);
|
|
KeyFocusReason reason = KeyFocusReason.Directional;
|
|
Direction direction;
|
|
switch (key)
|
|
{
|
|
case Keys.Tab:
|
|
direction = (modifiers1 & InputHandlerModifiers.Shift) != InputHandlerModifiers.Shift ? Direction.Next : Direction.Previous;
|
|
reason = KeyFocusReason.Tab;
|
|
break;
|
|
case Keys.Left:
|
|
direction = Direction.West;
|
|
break;
|
|
case Keys.Up:
|
|
direction = Direction.North;
|
|
break;
|
|
case Keys.Right:
|
|
direction = Direction.East;
|
|
break;
|
|
case Keys.Down:
|
|
direction = Direction.South;
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
return this.NavigateDirection(direction, reason);
|
|
}
|
|
|
|
public TypeSchema TypeSchema => (TypeSchema)this._typeSchema;
|
|
|
|
public void NotifyInitialized()
|
|
{
|
|
if (this._inputHandlers != null)
|
|
{
|
|
foreach (InputHandler inputHandler in this._inputHandlers)
|
|
inputHandler.NotifyUIInitialized();
|
|
}
|
|
if (this._rootItem != null)
|
|
{
|
|
if (this.MouseInteractive)
|
|
{
|
|
if (!this.HasMouseInteractiveContent())
|
|
this._rootItem.MouseInteractive = true;
|
|
}
|
|
else if (this.HasMouseInteractiveContent())
|
|
this.MouseInteractive = true;
|
|
}
|
|
this.SetBit(UIClass.Bits.Initialized, true);
|
|
AccessibleProxy.NotifyCreated(this);
|
|
}
|
|
|
|
public object ReadSymbol(SymbolReference symbolRef)
|
|
{
|
|
object obj = (object)null;
|
|
switch (symbolRef.Origin)
|
|
{
|
|
case SymbolOrigin.Properties:
|
|
case SymbolOrigin.Locals:
|
|
obj = this._storage[(object)symbolRef.Symbol];
|
|
break;
|
|
case SymbolOrigin.Input:
|
|
if (this._inputHandlers != null)
|
|
{
|
|
foreach (InputHandler inputHandler in this._inputHandlers)
|
|
{
|
|
if (inputHandler.Name != null && object.ReferenceEquals((object)inputHandler.Name, (object)symbolRef.Symbol))
|
|
{
|
|
obj = (object)inputHandler;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case SymbolOrigin.Content:
|
|
obj = (object)this.FindViewItemByName(this.RootItem, symbolRef.Symbol);
|
|
break;
|
|
case SymbolOrigin.Reserved:
|
|
if (symbolRef.Symbol == "UI")
|
|
{
|
|
obj = (object)this;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
public ViewItem FindViewItemByName(ViewItem item, string name)
|
|
{
|
|
if (object.ReferenceEquals((object)item.Name, (object)name))
|
|
return item;
|
|
if (item.HideNamedChildren)
|
|
return (ViewItem)null;
|
|
foreach (ViewItem child in item.Children)
|
|
{
|
|
if (child.UI == this)
|
|
{
|
|
ViewItem viewItemByName = this.FindViewItemByName(child, name);
|
|
if (viewItemByName != null)
|
|
return viewItemByName;
|
|
}
|
|
}
|
|
return (ViewItem)null;
|
|
}
|
|
|
|
public void WriteSymbol(SymbolReference symbolRef, object value)
|
|
{
|
|
string symbol = symbolRef.Symbol;
|
|
if (this._storage.ContainsKey((object)symbol) && Utility.IsEqual(this._storage[(object)symbol], value))
|
|
return;
|
|
this._storage[(object)symbol] = value;
|
|
if (symbolRef.Origin != SymbolOrigin.Properties && symbolRef.Origin != SymbolOrigin.Locals)
|
|
return;
|
|
bool surfaceViaHost = symbolRef.Origin == SymbolOrigin.Properties;
|
|
this.FireNotification(symbol, surfaceViaHost);
|
|
}
|
|
|
|
public object GetProperty(string name) => this._storage[(object)name];
|
|
|
|
public void SetProperty(string name, object value)
|
|
{
|
|
if (this._storage.ContainsKey((object)name) && Utility.IsEqual(this._storage[(object)name], value))
|
|
return;
|
|
this._storage[(object)name] = value;
|
|
this.FireNotification(name, true);
|
|
}
|
|
|
|
public Dictionary<object, object> Storage => this._storage;
|
|
|
|
public MarkupListeners Listeners
|
|
{
|
|
get => this._listeners;
|
|
set => this._listeners = value;
|
|
}
|
|
|
|
public void ScheduleScriptRun(uint scriptId, bool ignoreErrors)
|
|
{
|
|
if (!this._scriptRunScheduler.Pending)
|
|
DeferredCall.Post(DispatchPriority.Script, UIClass.s_executePendingScriptsHandler, (object)this);
|
|
this._scriptRunScheduler.ScheduleRun(scriptId, ignoreErrors);
|
|
}
|
|
|
|
private static void ExecutePendingScripts(object args)
|
|
{
|
|
UIClass uiClass = (UIClass)args;
|
|
uiClass._scriptRunScheduler.Execute((IMarkupTypeBase)uiClass);
|
|
}
|
|
|
|
public object RunScript(uint scriptId, bool ignoreErrors, ParameterContext parameterContext) => this._typeSchema.Run((IMarkupTypeBase)this, scriptId, ignoreErrors, parameterContext);
|
|
|
|
public void NotifyScriptErrors()
|
|
{
|
|
this.SetBit(UIClass.Bits.ScriptEnabled, false);
|
|
this._ownerHost.NotifyChildUIScriptErrors();
|
|
ErrorManager.ReportWarning("Script runtime failure: Scripting has been disabled for '{0}' due to runtime scripting errors", (object)this._typeSchema.Name);
|
|
}
|
|
|
|
public bool ScriptEnabled => this.GetBit(UIClass.Bits.ScriptEnabled);
|
|
|
|
protected void FireNotification(string id) => this.FireNotification(id, false);
|
|
|
|
private void FireNotification(string id, bool surfaceViaHost)
|
|
{
|
|
this._notifier.Fire(id);
|
|
if (!surfaceViaHost || this._ownerHost == null)
|
|
return;
|
|
this._ownerHost.FireChildUINotification(id);
|
|
}
|
|
|
|
void INotifyObject.AddListener(Listener listener) => this._notifier.AddListener(listener);
|
|
|
|
public ViewItem ConstructNamedContent(
|
|
string contentName,
|
|
ParameterContext parameterContext)
|
|
{
|
|
return this._typeSchema.ConstructNamedContent(contentName, (IMarkupTypeBase)this, parameterContext);
|
|
}
|
|
|
|
private bool GetBit(UIClass.Bits lookupBit) => this._bits[(int)lookupBit];
|
|
|
|
private void SetBit(UIClass.Bits changeBit, bool value) => this._bits[(int)changeBit] = value;
|
|
|
|
private bool ChangeBit(UIClass.Bits bit, bool value)
|
|
{
|
|
if (this._bits[(int)bit] == value)
|
|
return false;
|
|
this._bits[(int)bit] = value;
|
|
return true;
|
|
}
|
|
|
|
public ViewItem RootItem => this._rootItem;
|
|
|
|
public string ID => this._ownerHost.Name;
|
|
|
|
public Host Host => this._ownerHost;
|
|
|
|
public void DeclareHost(Host ownerHost) => this._ownerHost = ownerHost;
|
|
|
|
public bool Flippable
|
|
{
|
|
get => this.GetBit(UIClass.Bits.Flippable);
|
|
set => this.SetBit(UIClass.Bits.Flippable, value);
|
|
}
|
|
|
|
internal void SetRootItem(ViewItem newRootItem) => this._rootItem = newRootItem;
|
|
|
|
internal bool HasMouseInteractiveContent() => this._rootItem != null && this.HasMouseInteractiveContentWorker(this._rootItem);
|
|
|
|
private bool HasMouseInteractiveContentWorker(ViewItem checkItem)
|
|
{
|
|
if (checkItem.MouseInteractive)
|
|
return true;
|
|
foreach (ViewItem child in checkItem.Children)
|
|
{
|
|
if (child.UI == this && this.HasMouseInteractiveContentWorker(child))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public object GetEventContext() => this._eventContext != null ? this._eventContext.Value : (object)null;
|
|
|
|
internal void SetEventContext(EventContext eventContext) => this._eventContext = eventContext;
|
|
|
|
public override string ToString() => this._typeSchema.ToString();
|
|
|
|
private class SavedFocusState
|
|
{
|
|
private ViewItemID[] _path;
|
|
private bool _focusIsDefault;
|
|
|
|
public SavedFocusState(ViewItem item)
|
|
{
|
|
this._path = item.IDPath;
|
|
this._focusIsDefault = item.UISession.InputManager.RawKeyFocusIsDefault;
|
|
}
|
|
|
|
public ViewItemID[] Path => this._path;
|
|
|
|
public bool FocusIsDefault => this._focusIsDefault;
|
|
}
|
|
|
|
private class DeferredKeyFocusRestoreHelper
|
|
{
|
|
private UIClass _ui;
|
|
private UIClass.SavedFocusState _focusState;
|
|
private ICookedInputSite _lastFocus;
|
|
|
|
public DeferredKeyFocusRestoreHelper(UIClass ui, UIClass.SavedFocusState focusState)
|
|
{
|
|
this._ui = ui;
|
|
this._focusState = focusState;
|
|
this._lastFocus = ui.UISession.InputManager.RawKeyFocus;
|
|
}
|
|
|
|
public void FaultInChild(ViewItem bottleneck, ViewItemID item)
|
|
{
|
|
this._ui.PendingFocusRestore = this;
|
|
bottleneck.FaultInChild(item, new ChildFaultedInDelegate(this.ChildFaultedIn));
|
|
}
|
|
|
|
private void ChildFaultedIn(ViewItem bottleneckItem, ViewItem faultedInItem)
|
|
{
|
|
if (!this._ui.IsZoned || this._ui.PendingFocusRestore != this)
|
|
return;
|
|
this._ui.PendingFocusRestore = (UIClass.DeferredKeyFocusRestoreHelper)null;
|
|
InputManager inputManager = this._ui.UISession.InputManager;
|
|
if (!inputManager.RawKeyFocusIsDefault && inputManager.RawKeyFocus != this._lastFocus || (faultedInItem == null || faultedInItem.IsDisposed))
|
|
return;
|
|
this._ui.RestoreKeyFocus((object)this._focusState);
|
|
}
|
|
}
|
|
|
|
private enum Bits
|
|
{
|
|
Initialized = 1,
|
|
IsDisposed = 2,
|
|
CreateInterestOnFocus = 4,
|
|
Flippable = 8,
|
|
KeyInteractive = 16, // 0x00000010
|
|
MouseInteractive = 32, // 0x00000020
|
|
MouseInteractiveSet = 64, // 0x00000040
|
|
Enabled = 128, // 0x00000080
|
|
AppFullyEnabled = 256, // 0x00000100
|
|
RawInputDisabled = 512, // 0x00000200
|
|
DirectKeyFocus = 1024, // 0x00000400
|
|
DirectMouseFocus = 2048, // 0x00000800
|
|
KeyFocusOnMouseEnter = 4096, // 0x00001000
|
|
KeyFocusOnMouseDown = 8192, // 0x00002000
|
|
AllowDoubleClicks = 16384, // 0x00004000
|
|
KeyFocus = 32768, // 0x00008000
|
|
MouseFocus = 65536, // 0x00010000
|
|
HasAccProxy = 131072, // 0x00020000
|
|
ScriptEnabled = 262144, // 0x00040000
|
|
HasAutomationInstanceId = 524288, // 0x00080000
|
|
}
|
|
}
|
|
}
|