您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

434 行
16 KiB

using System;
using System.Collections.Generic;
using Unity.UIWidgets.async;
using Unity.UIWidgets.foundation;
using Unity.UIWidgets.gestures;
using Unity.UIWidgets.rendering;
using Unity.UIWidgets.scheduler;
using Unity.UIWidgets.ui;
namespace Unity.UIWidgets.widgets {
public delegate UiWidgetAction ActionFactory();
public delegate void OnInvokeCallback(FocusNode node, Intent tag);
public class Intent : Diagnosticable {
public Intent(LocalKey key) : base() {
D.assert(key != null);
this.key = key;
}
public static readonly Intent doNothing = new Intent(DoNothingAction.key);
public readonly LocalKey key;
public bool isEnabled(BuildContext context) => true;
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<LocalKey>("key", key));
}
}
public abstract class UiWidgetAction : Diagnosticable {
public UiWidgetAction(LocalKey intentKey) {
D.assert(intentKey != null);
this.intentKey = intentKey;
}
public readonly LocalKey intentKey;
public abstract void invoke(FocusNode node, Intent intent);
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<LocalKey>("intentKey", intentKey));
}
}
class CallbackAction : UiWidgetAction {
public CallbackAction(LocalKey intentKey, OnInvokeCallback onInvoke) : base(intentKey: intentKey) {
D.assert(onInvoke != null);
this.onInvoke = onInvoke;
}
protected readonly OnInvokeCallback onInvoke;
public override void invoke(FocusNode node, Intent intent) {
onInvoke.Invoke(node, intent);
}
}
class ActionDispatcher : Diagnosticable {
public ActionDispatcher() {
}
public bool invokeAction(UiWidgetAction action, Intent intent, FocusNode focusNode = null) {
D.assert(action != null);
D.assert(intent != null);
focusNode = focusNode ?? FocusManagerUtils.primaryFocus;
if (action != null && intent.isEnabled(focusNode.context)) {
action.invoke(focusNode, intent);
return true;
}
return false;
}
}
class Actions : InheritedWidget {
public Actions(
Key key = null,
ActionDispatcher dispatcher = null,
Dictionary<LocalKey, ActionFactory> actions = null,
Widget child = null
) : base(key: key, child: child) {
D.assert(actions != null);
this.dispatcher = dispatcher;
this.actions = actions;
}
public readonly ActionDispatcher dispatcher;
public readonly Dictionary<LocalKey, ActionFactory> actions;
public static ActionDispatcher _findDispatcher(Element element) {
D.assert(element.widget is Actions);
Actions actions = element.widget as Actions;
ActionDispatcher dispatcher = actions.dispatcher;
if (dispatcher == null) {
bool visitAncestorElement(Element visitedElement) {
if (!(visitedElement.widget is Actions)) {
return true;
}
Actions actions1 = visitedElement.widget as Actions;
if (actions1.dispatcher == null) {
return true;
}
dispatcher = actions1.dispatcher;
return false;
}
element.visitAncestorElements(visitAncestorElement);
}
return dispatcher ?? new ActionDispatcher();
}
public static ActionDispatcher of(BuildContext context, bool nullOk = false) {
D.assert(context != null);
InheritedElement inheritedElement = context.getElementForInheritedWidgetOfExactType<Actions>();
Actions inherited = context.dependOnInheritedElement(inheritedElement) as Actions;
D.assert(() => {
if (nullOk) {
return true;
}
if (inherited == null) {
throw new UIWidgetsError("Unable to find an $Actions widget in the context.\n" +
"Actions.of() was called with a context that does not contain an " +
$"{typeof(Actions)} widget.\n" +
$"No {typeof(Actions)} ancestor could be found starting from the context that " +
"was passed to {Actions.of()}. This can happen if the context comes " +
"from a widget above those widgets.\n" +
"The context used was:\n" +
$"{context}");
}
return true;
});
return inherited?.dispatcher ?? _findDispatcher(inheritedElement);
}
public static bool invoke(
BuildContext context,
Intent intent,
FocusNode focusNode = null,
bool nullOk = false
) {
D.assert(context != null);
D.assert(intent != null);
Element actionsElement = null;
UiWidgetAction action = null;
bool visitAncestorElement(Element element) {
if (!(element.widget is Actions)) {
return true;
}
actionsElement = element;
Actions actions = element.widget as Actions;
action = actions.actions[intent.key]?.Invoke();
return action == null;
}
context.visitAncestorElements(visitAncestorElement);
D.assert(() => {
if (nullOk) {
return true;
}
if (actionsElement == null) {
throw new UIWidgetsError($"Unable to find a {typeof(Actions)} widget in the context.\n" +
"Actions.invoke() was called with a context that does not contain an " +
$"{typeof(Actions)} widget.\n" +
$"No {typeof(Actions)} ancestor could be found starting from the context that " +
"was passed to Actions.invoke(). This can happen if the context comes " +
"from a widget above those widgets.\n" +
"The context used was:\n" +
$" {context}");
}
if (action == null) {
throw new UIWidgetsError(
$"Unable to find an action for an intent in the {typeof(Actions)} widget in the context.\n" +
"Actions.invoke() was called on an {typeof(Actions)} widget that doesn't " +
"contain a mapping for the given intent.\n" +
"The context used was:\n" +
$" {context}\n" +
"The intent requested was:\n" +
$" {intent}");
}
return true;
});
if (action == null) {
return false;
}
return _findDispatcher(actionsElement).invokeAction(action, intent, focusNode: focusNode);
}
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);
properties.add(new DiagnosticsProperty<ActionDispatcher>("dispatcher", dispatcher));
properties.add(new DiagnosticsProperty<Dictionary<LocalKey, ActionFactory>>("actions", actions));
}
public override bool updateShouldNotify(InheritedWidget oldWidget) {
oldWidget = (Actions) oldWidget;
var dispatcherBool = ((Actions) oldWidget).dispatcher != dispatcher;
bool actionBool = ((Actions) oldWidget).actions == actions;
foreach (var actionsKey in ((Actions) oldWidget).actions.Keys) {
if (!actions.ContainsKey(actionsKey) ||
actions[actionsKey] != ((Actions) oldWidget).actions[actionsKey]) {
actionBool = false;
}
}
return dispatcherBool || actionBool;
}
}
class FocusableActionDetector : StatefulWidget {
public FocusableActionDetector(
Key key = null,
bool enabled = true,
FocusNode focusNode = null,
bool autofocus = false,
Dictionary<LogicalKeySet, Intent> shortcuts = null,
Dictionary<LocalKey, ActionFactory> actions = null,
ValueChanged<bool> onShowFocusHighlight = null,
ValueChanged<bool> onShowHoverHighlight = null,
ValueChanged<bool> onFocusChange = null,
Widget child = null
) : base(key: key) {
D.assert(enabled != null);
D.assert(autofocus != null);
D.assert(child != null);
this.enabled = enabled;
this.focusNode = focusNode;
this.autofocus = autofocus;
this.shortcuts = shortcuts;
this.actions = actions;
this.onShowFocusHighlight = onShowFocusHighlight;
this.onShowHoverHighlight = onShowHoverHighlight;
this.onFocusChange = onFocusChange;
this.child = child;
}
public readonly bool enabled;
public readonly FocusNode focusNode;
public readonly bool autofocus;
public readonly Dictionary<LocalKey, ActionFactory> actions;
public readonly Dictionary<LogicalKeySet, Intent> shortcuts;
public readonly ValueChanged<bool> onShowFocusHighlight;
public readonly ValueChanged<bool> onShowHoverHighlight;
public readonly ValueChanged<bool> onFocusChange;
public readonly Widget child;
public override State createState() {
return new _FocusableActionDetectorState();
}
}
class _FocusableActionDetectorState : State<FocusableActionDetector> {
public override void initState() {
base.initState();
SchedulerBinding.instance.addPostFrameCallback(((TimeSpan timespan) => {
_updateHighlightMode(FocusManager.instance.highlightMode);
}));
FocusManager.instance.addHighlightModeListener(_handleFocusHighlightModeChange);
}
public override void dispose() {
FocusManager.instance.removeHighlightModeListener(_handleFocusHighlightModeChange);
base.dispose();
}
bool _canShowHighlight = false;
void _updateHighlightMode(FocusHighlightMode mode) {
_mayTriggerCallback(task: () =>{
switch (FocusManager.instance.highlightMode) {
case FocusHighlightMode.touch:
_canShowHighlight = false;
break;
case FocusHighlightMode.traditional:
_canShowHighlight = true;
break;
}
});
}
void _handleFocusHighlightModeChange(FocusHighlightMode mode) {
if (!mounted) {
return;
}
_updateHighlightMode(mode);
}
bool _hovering = false;
void _handleMouseEnter(PointerEnterEvent Event) {
D.assert(widget.onShowHoverHighlight != null);
if (!_hovering) {
_mayTriggerCallback(task: ()=> {
_hovering = true;
});
}
}
void _handleMouseExit(PointerExitEvent Event) {
D.assert(widget.onShowHoverHighlight != null);
if (_hovering) {
_mayTriggerCallback(task: ()=>{
_hovering = false;
});
}
}
bool _focused = false;
void _handleFocusChange(bool focused) {
if (_focused != focused) {
_mayTriggerCallback(task: () =>{
_focused = focused;
});
widget.onFocusChange?.Invoke(_focused);
}
}
void _mayTriggerCallback(VoidCallback task = null, FocusableActionDetector oldWidget = null) {
bool shouldShowHoverHighlight(FocusableActionDetector target) {
return _hovering && target.enabled && _canShowHighlight;
}
bool shouldShowFocusHighlight(FocusableActionDetector target) {
return _focused && target.enabled && _canShowHighlight;
}
D.assert(SchedulerBinding.instance.schedulerPhase != SchedulerPhase.persistentCallbacks);
FocusableActionDetector oldTarget = oldWidget ?? widget;
bool didShowHoverHighlight = shouldShowHoverHighlight(oldTarget);
bool didShowFocusHighlight = shouldShowFocusHighlight(oldTarget);
if (task != null)
task();
bool doShowHoverHighlight = shouldShowHoverHighlight(widget);
bool doShowFocusHighlight = shouldShowFocusHighlight(widget);
if (didShowFocusHighlight != doShowFocusHighlight)
widget.onShowFocusHighlight?.Invoke(doShowFocusHighlight);
if (didShowHoverHighlight != doShowHoverHighlight)
widget.onShowHoverHighlight?.Invoke(doShowHoverHighlight);
}
public override void didUpdateWidget(StatefulWidget oldWidget) {
oldWidget =(FocusableActionDetector) oldWidget;
base.didUpdateWidget(oldWidget);
if (widget.enabled != ((FocusableActionDetector)oldWidget).enabled) {
SchedulerBinding.instance.addPostFrameCallback((TimeSpan timespan)=> {
_mayTriggerCallback(oldWidget: (FocusableActionDetector)oldWidget);
});
}
}
public override Widget build(BuildContext context) {
Widget child = new MouseRegion(
onEnter: _handleMouseEnter,
onExit: _handleMouseExit,
child: new Focus(
focusNode: widget.focusNode,
autofocus: widget.autofocus,
canRequestFocus: widget.enabled,
onFocusChange: _handleFocusChange,
child: widget.child
)
);
if (widget.enabled && widget.actions != null && widget.actions.isNotEmpty()) {
child = new Actions(actions: widget.actions, child: child);
}
if (widget.enabled && widget.shortcuts != null && widget.shortcuts.isNotEmpty()) {
child = new Shortcuts(shortcuts: widget.shortcuts, child: child);
}
return child;
}
}
public class DoNothingAction : UiWidgetAction {
public DoNothingAction() : base(key) {
}
public readonly static LocalKey key = new ValueKey<Type>(typeof(DoNothingAction));
public override void invoke(FocusNode node, Intent intent) { }
}
public abstract class ActivateAction : UiWidgetAction {
public ActivateAction() : base(key) {
}
public readonly static LocalKey key = new ValueKey<Type>(typeof(ActivateAction));
}
public abstract class SelectAction : UiWidgetAction {
public SelectAction() : base(key) {
}
public readonly static LocalKey key = new ValueKey<Type>(typeof(SelectAction));
}
}