// Copyright 2016 Workiva Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
library over_react.handler_chain_util;
import 'package:over_react/over_react.dart' show ResizeSensorEvent;
import 'package:react/react.dart' show
SyntheticEvent,
SyntheticClipboardEvent,
SyntheticKeyboardEvent,
SyntheticFocusEvent,
SyntheticFormEvent,
SyntheticMouseEvent,
SyntheticTouchEvent,
SyntheticUIEvent,
SyntheticWheelEvent;
import '../component/callback_typedefs.dart';
/// Provides chaining utilities for [DomEventCallback].
final CallbackUtil1Arg<SyntheticEvent> domEventCallbacks = const CallbackUtil1Arg<SyntheticEvent>();
/// Provides chaining utilities for [ClipboardEventCallback].
final CallbackUtil1Arg<SyntheticClipboardEvent> clipboardEventCallbacks = const CallbackUtil1Arg<SyntheticClipboardEvent>();
/// Provides chaining utilities for [KeyboardEventCallback].
final CallbackUtil1Arg<SyntheticKeyboardEvent> keyboardEventCallbacks = const CallbackUtil1Arg<SyntheticKeyboardEvent>();
/// Provides chaining utilities for [FocusEventCallback].
final CallbackUtil1Arg<SyntheticFocusEvent> focusEventCallbacks = const CallbackUtil1Arg<SyntheticFocusEvent>();
/// Provides chaining utilities for [FormEventCallback].
final CallbackUtil1Arg<SyntheticFormEvent> formEventCallbacks = const CallbackUtil1Arg<SyntheticFormEvent>();
/// Provides chaining utilities for [MouseEventCallback].
final CallbackUtil1Arg<SyntheticMouseEvent> mouseEventCallbacks = const CallbackUtil1Arg<SyntheticMouseEvent>();
/// Provides chaining utilities for [TouchEventCallback].
final CallbackUtil1Arg<SyntheticTouchEvent> touchEventCallbacks = const CallbackUtil1Arg<SyntheticTouchEvent>();
/// Provides chaining utilities for [UIEventCallback].
final CallbackUtil1Arg<SyntheticUIEvent> uiEventCallbacks = const CallbackUtil1Arg<SyntheticUIEvent>();
/// Provides chaining utilities for [WheelEventCallback].
final CallbackUtil1Arg<SyntheticWheelEvent> wheelEventCallbacks = const CallbackUtil1Arg<SyntheticWheelEvent>();
/// Provides chaining utilities for [Callback].
final CallbackUtil0Arg callbacks = const CallbackUtil0Arg();
/// Provides chaining utilities for [ResizeSensorHandler].
final CallbackUtil1Arg<ResizeSensorEvent> resizeEventCallbacks = const CallbackUtil1Arg<ResizeSensorEvent>();
typedef Callback0Arg();
typedef Callback1Arg<T1>(T1 arg1);
typedef Callback2Arg<T1, T2>(T1 arg1, T2 arg2);
typedef Callback3Arg<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
/// Generic callback chaining utilities for callbacks with no arguments.
class CallbackUtil0Arg extends CallbackUtil<Callback0Arg> {
const CallbackUtil0Arg();
_noop() {}
/// A function of type [Callback0Arg] that does nothing.
@override
Callback0Arg get noop => _noop;
/// Returns a strongly-typed chained callback that calls through to the two provided callbacks, [a] and [b], in order.
/// Useful for executing multiple callbacks where only a single callback is accepted.
///
/// Returns `false` if one or more of the provided callbacks returns `false`.
///
/// Gracefully handles when [a] and/or [b] are null, always returning a callable function.
@override
Callback0Arg chain(Callback0Arg a, Callback0Arg b) {
if (a == null && b == null) return noop;
if (a == null) return b;
if (b == null) return a;
return () {
var aDidReturnFalse = a() == false;
var bDidReturnFalse = b() == false;
if (aDidReturnFalse || bDidReturnFalse) return false;
};
}
}
/// Generic strongly-typed callback chaining utilities for callbacks with one argument.
class CallbackUtil1Arg<T> extends CallbackUtil<Callback1Arg<T>> {
const CallbackUtil1Arg();
_noop(T arg1) {}
/// A function of type [Callback1Arg<T>] that does nothing.
@override
Callback1Arg<T> get noop => _noop;
/// Returns a strongly-typed chained callback that calls through to the two provided callbacks, [a] and [b], in order.
/// Useful for executing multiple callbacks where only a single callback is accepted.
///
/// Returns `false` if one or more of the provided callbacks returns `false`.
///
/// Gracefully handles when [a] and/or [b] are null, always returning a callable function.
@override
Callback1Arg<T> chain(Callback1Arg<T> a, Callback1Arg<T> b) {
if (a == null && b == null) return noop;
if (a == null) return b;
if (b == null) return a;
return (T arg1) {
var aDidReturnFalse = a(arg1) == false;
var bDidReturnFalse = b(arg1) == false;
if (aDidReturnFalse || bDidReturnFalse) return false;
};
}
}
/// Generic strongly-typed callback chaining utilities for callbacks with two arguments.
class CallbackUtil2Arg<T1, T2> extends CallbackUtil<Callback2Arg<T1, T2>> {
const CallbackUtil2Arg();
_noop(T1 arg1, T2 arg2) {}
/// A function of type [Callback2Arg<T1, T2>] that does nothing.
@override
Callback2Arg<T1, T2> get noop => _noop;
/// Returns a strongly-typed chained callback that calls through to the two provided callbacks, [a] and [b], in order.
/// Useful for executing multiple callbacks where only a single callback is accepted.
///
/// Returns `false` if one or more of the provided callbacks returns `false`.
///
/// Gracefully handles when [a] and/or [b] are null, always returning a callable function.
@override
Callback2Arg<T1, T2> chain(Callback2Arg<T1, T2> a, Callback2Arg<T1, T2> b) {
if (a == null && b == null) return noop;
if (a == null) return b;
if (b == null) return a;
return (T1 arg1, T2 arg2) {
var aDidReturnFalse = a(arg1, arg2) == false;
var bDidReturnFalse = b(arg1, arg2) == false;
if (aDidReturnFalse || bDidReturnFalse) return false;
};
}
}
/// Generic strongly-typed callback chaining utilities for callbacks with three arguments.
class CallbackUtil3Arg<T1, T2, T3> extends CallbackUtil<Callback3Arg<T1, T2, T3>> {
const CallbackUtil3Arg();
_noop(T1 arg1, T2 arg2, T3 arg3) {}
/// A function of type [Callback3Arg<T1, T2, T3>] that does nothing.
@override
Callback3Arg<T1, T2, T3> get noop => _noop;
/// Returns a strongly-typed chained callback that calls through to the two provided callbacks, [a] and [b], in order.
/// Useful for executing multiple callbacks where only a single callback is accepted.
///
/// Returns `false` if one or more of the provided callbacks returns `false`.
///
/// Gracefully handles when [a] and/or [b] are null, always returning a callable function.
@override
Callback3Arg<T1, T2, T3> chain(Callback3Arg<T1, T2, T3> a, Callback3Arg<T1, T2, T3> b) {
if (a == null && b == null) return noop;
if (a == null) return b;
if (b == null) return a;
return (T1 arg1, T2 arg2, T3 arg3) {
var aDidReturnFalse = a(arg1, arg2, arg3) == false;
var bDidReturnFalse = b(arg1, arg2, arg3) == false;
if (aDidReturnFalse || bDidReturnFalse) return false;
};
}
}
/// Base class for generic strongly-typed callback chaining utilities.
abstract class CallbackUtil<TTypedef extends Function> {
const CallbackUtil();
/// Returns a strongly-typed chained callback that calls through to the two provided callbacks, [a] and [b], in order.
/// Useful for executing multiple callbacks where only a single callback is accepted.
///
/// Returns `false` if one or more of the provided callbacks returns `false`.
///
/// Gracefully handles when [a] and/or [b] are null, always returning a callable function.
TTypedef chain(TTypedef a, TTypedef b);
/// Returns a strongly-typed chained callback that calls through to the list of provided [callbacks] in order.
/// Useful for executing multiple callbacks where only a single callback is accepted.
///
/// Returns `false` if one or more of the provided callbacks returns `false`.
///
/// Gracefully handles when [callbacks] is empty or its items are null, always returning a callable function.
TTypedef chainFromList(List<TTypedef> callbacks) =>
callbacks.fold(null, chain) ?? noop;
/// A function of type [TTypedef] that does nothing.
TTypedef get noop;
}