Use case
When generalizing over gesture details, we have to be specific about which details class we are using. This is not a big problem, but we could use of some generalization to make more abstract code.
For example, I have code similar to this in a production app:
// Currently, I have not how to guarantee that `DetailsType` is going to be a gesture details object
class GestureDetailsWithAdditionalData<DetailsType, T extends Object> {
const LayerGestureDetails({
required this.details,
required this.data,
});
final DetailsType details;
final T data;
}
ValueChanged<DetailsType> gesturerFor<DetailsType>({
required ValueChanged<GestureDetailsWithAdditionalData<DetailsType, Object>>? Function(Layer) gestureFunction,
required Offset Function(T) getLocalPosition,
}) {
return (DetailsType details) {
final layer = getLayer(...);
final localPosition = getLocalPosition(details);
// Do something with localPosition
final gesture = gestureFunction(layer);
};
}
// Usage
gesturerFor<TapDownDetails>(
gestureFunction: (layer) => layer.onTapUp,
getLocalPosition: (details) => details.localPosition,
);
If they implemented a common abstraction, the code could be simplified and made safer:
// Now I guarantee that details is something expected
class GestureDetailsWithAdditionalData<DetailsType extends PositionRelatedGestureDetails, T extends Object> {
const LayerGestureDetails({
required this.details,
required this.data,
});
final DetailsType details;
final T data;
}
ValueChanged<DetailsType> gesturerFor<DetailsType>(ValueChanged<GestureDetailsWithAdditionalData<DetailsType, Object>>? Function(Layer) gestureFunction) {
return (DetailsType details) {
final layer = getLayer(...);
// I now can use details.localPosition directly
final gesture = gestureFunction(layer);
};
}
// Usage now guarantees that the returned function works on details
gesturerFor<TapDownDetails>(gestureFunction: (layer) => layer.onTapUp);
Proposal
Almost all gesture details related to cartesian positioning have in common a localPosition and globalPosition.
DragDownDetails
DragStartDetails
DragUpdateDetails
ForcePressDetails
LongPressDownDetails
LongPressEndDetails
LongPressMoveUpdateDetails
LongPressStartDetails
SerialTapDownDetails
SerialTapUpDetails
TapDownDetails
TapUpDetails
It would be nice and, as far as I can tell, a non-breaking change to make a common interface for them:
abstract class PositionRelatedGestureDetails {
/// Documentation...
Offset get localPosition;
/// Documentation...
Offset get globalPosition;
}
Scale gestures also have similar properties (focalPoint and localFocalPoint), but I am not sure if they should be included somehow in this generalization.
Use case
When generalizing over gesture details, we have to be specific about which details class we are using. This is not a big problem, but we could use of some generalization to make more abstract code.
For example, I have code similar to this in a production app:
If they implemented a common abstraction, the code could be simplified and made safer:
Proposal
Almost all gesture details related to cartesian positioning have in common a
localPositionandglobalPosition.DragDownDetailsDragStartDetailsDragUpdateDetailsForcePressDetailsLongPressDownDetailsLongPressEndDetailsLongPressMoveUpdateDetailsLongPressStartDetailsSerialTapDownDetailsSerialTapUpDetailsTapDownDetailsTapUpDetailsIt would be nice and, as far as I can tell, a non-breaking change to make a common interface for them:
Scale gestures also have similar properties (
focalPointandlocalFocalPoint), but I am not sure if they should be included somehow in this generalization.