blob: fcddf844d88914189026a8609569c446df6ba0c2 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of dart.ui;
/// The possible actions that can be conveyed from the operating system
/// accessibility APIs to a semantics node.
class SemanticsAction {
const SemanticsAction._(this.index);
static const int _kTapIndex = 1 << 0;
static const int _kLongPressIndex = 1 << 1;
static const int _kScrollLeftIndex = 1 << 2;
static const int _kScrollRightIndex = 1 << 3;
static const int _kScrollUpIndex = 1 << 4;
static const int _kScrollDownIndex = 1 << 5;
static const int _kIncreaseIndex = 1 << 6;
static const int _kDecreaseIndex = 1 << 7;
static const int _kShowOnScreen = 1 << 8;
static const int _kMoveCursorForwardByCharacter = 1 << 9;
static const int _kMoveCursorBackwardByCharacter = 1 << 10;
/// The numerical value for this action.
///
/// Each action has one bit set in this bit field.
final int index;
/// The equivalent of a user briefly tapping the screen with the finger
/// without moving it.
static const SemanticsAction tap = const SemanticsAction._(_kTapIndex);
/// The equivalent of a user pressing and holding the screen with the finger
/// for a few seconds without moving it.
static const SemanticsAction longPress = const SemanticsAction._(_kLongPressIndex);
/// The equivalent of a user moving their finger across the screen from right
/// to left.
///
/// This action should be recognized by controls that are horizontally
/// scrollable.
static const SemanticsAction scrollLeft = const SemanticsAction._(_kScrollLeftIndex);
/// The equivalent of a user moving their finger across the screen from left
/// to right.
///
/// This action should be recognized by controls that are horizontally
/// scrollable.
static const SemanticsAction scrollRight = const SemanticsAction._(_kScrollRightIndex);
/// The equivalent of a user moving their finger across the screen from
/// bottom to top.
///
/// This action should be recognized by controls that are vertically
/// scrollable.
static const SemanticsAction scrollUp = const SemanticsAction._(_kScrollUpIndex);
/// The equivalent of a user moving their finger across the screen from top
/// to bottom.
///
/// This action should be recognized by controls that are vertically
/// scrollable.
static const SemanticsAction scrollDown = const SemanticsAction._(_kScrollDownIndex);
/// A request to increase the value represented by the semantics node.
///
/// For example, this action might be recognized by a slider control.
static const SemanticsAction increase = const SemanticsAction._(_kIncreaseIndex);
/// A request to decrease the value represented by the semantics node.
///
/// For example, this action might be recognized by a slider control.
static const SemanticsAction decrease = const SemanticsAction._(_kDecreaseIndex);
/// A request to fully show the semantics node on screen.
///
/// For example, this action might be send to a node in a scrollable list that
/// is partially off screen to bring it on screen.
static const SemanticsAction showOnScreen = const SemanticsAction._(_kShowOnScreen);
/// Move the cursor forward by one character.
///
/// This is for example used by the cursor control in text fields.
static const SemanticsAction moveCursorForwardByCharacter = const SemanticsAction._(_kMoveCursorForwardByCharacter);
/// Move the cursor backward by one character.
///
/// This is for example used by the cursor control in text fields.
static const SemanticsAction moveCursorBackwardByCharacter = const SemanticsAction._(_kMoveCursorBackwardByCharacter);
/// The possible semantics actions.
///
/// The map's key is the [index] of the action and the value is the action
/// itself.
static final Map<int, SemanticsAction> values = const <int, SemanticsAction>{
_kTapIndex: tap,
_kLongPressIndex: longPress,
_kScrollLeftIndex: scrollLeft,
_kScrollRightIndex: scrollRight,
_kScrollUpIndex: scrollUp,
_kScrollDownIndex: scrollDown,
_kIncreaseIndex: increase,
_kDecreaseIndex: decrease,
_kShowOnScreen: showOnScreen,
_kMoveCursorForwardByCharacter: moveCursorForwardByCharacter,
_kMoveCursorBackwardByCharacter: moveCursorBackwardByCharacter,
};
@override
String toString() {
switch (index) {
case _kTapIndex:
return 'SemanticsAction.tap';
case _kLongPressIndex:
return 'SemanticsAction.longPress';
case _kScrollLeftIndex:
return 'SemanticsAction.scrollLeft';
case _kScrollRightIndex:
return 'SemanticsAction.scrollRight';
case _kScrollUpIndex:
return 'SemanticsAction.scrollUp';
case _kScrollDownIndex:
return 'SemanticsAction.scrollDown';
case _kIncreaseIndex:
return 'SemanticsAction.increase';
case _kDecreaseIndex:
return 'SemanticsAction.decrease';
case _kShowOnScreen:
return 'SemanticsAction.showOnScreen';
case _kMoveCursorForwardByCharacter:
return 'SemanticsAction.moveCursorForwardByCharacter';
case _kMoveCursorBackwardByCharacter:
return 'SemanticsAction.moveCursorBackwardByCharacter';
}
return null;
}
}
/// A Boolean value that can be associated with a semantics node.
class SemanticsFlags {
static const int _kHasCheckedStateIndex = 1 << 0;
static const int _kIsCheckedIndex = 1 << 1;
static const int _kIsSelectedIndex = 1 << 2;
static const int _kIsButtonIndex = 1 << 3;
static const int _kIsTextFieldIndex = 1 << 4;
static const int _kIsFocusedIndex = 1 << 5;
static const int _kIsDisabledIndex = 1 << 6;
const SemanticsFlags._(this.index);
/// The numerical value for this flag.
///
/// Each flag has one bit set in this bit field.
final int index;
/// The semantics node has the quality of either being "checked" or "unchecked".
///
/// For example, a checkbox or a radio button widget has checked state.
static const SemanticsFlags hasCheckedState = const SemanticsFlags._(_kHasCheckedStateIndex);
/// Whether a semantics node that [hasCheckedState] is checked.
///
/// If true, the semantics node is "checked". If false, the semantics node is
/// "unchecked".
///
/// For example, if a checkbox has a visible checkmark, [isChecked] is true.
static const SemanticsFlags isChecked = const SemanticsFlags._(_kIsCheckedIndex);
/// Whether a semantics node is selected.
///
/// If true, the semantics node is "selected". If false, the semantics node is
/// "unselected".
///
/// For example, the active tab in a tab bar has [isSelected] set to true.
static const SemanticsFlags isSelected = const SemanticsFlags._(_kIsSelectedIndex);
/// Whether the semantic node represents a button.
///
/// Platforms has special handling for buttons, for example Android's TalkBack
/// and iOS's VoiceOver provides an additional hint when the focused object is
/// a button.
static const SemanticsFlags isButton = const SemanticsFlags._(_kIsButtonIndex);
/// Whether the semantic node represents a text field.
///
/// Text fields are announced as such and allow text input via accessibility
/// affordances.
static const SemanticsFlags isTextField = const SemanticsFlags._(_kIsTextFieldIndex);
/// Whether the semantic node currently holds the user's focus.
///
/// The focused element is usually the current receiver of keyboard inputs.
static const SemanticsFlags isFocused = const SemanticsFlags._(_kIsFocusedIndex);
/// Whether the semantic node is currently disabled.
///
/// A disabled element does not respond to user interaction. For example, a
/// button that currently does not respond to user interaction should be
/// marked as disabled.
///
/// Elements, that never respond to user interactions (e.g. static text)
/// should not be marked as disabled.
static const SemanticsFlags isDisabled = const SemanticsFlags._(_kIsDisabledIndex);
/// The possible semantics flags.
///
/// The map's key is the [index] of the flag and the value is the flag itself.
static final Map<int, SemanticsFlags> values = const <int, SemanticsFlags>{
_kHasCheckedStateIndex: hasCheckedState,
_kIsCheckedIndex: isChecked,
_kIsSelectedIndex: isSelected,
_kIsButtonIndex: isButton,
_kIsTextFieldIndex: isTextField,
_kIsFocusedIndex: isFocused,
_kIsDisabledIndex: isDisabled,
};
@override
String toString() {
switch (index) {
case _kHasCheckedStateIndex:
return 'SemanticsFlags.hasCheckedState';
case _kIsCheckedIndex:
return 'SemanticsFlags.isChecked';
case _kIsSelectedIndex:
return 'SemanticsFlags.isSelected';
case _kIsButtonIndex:
return 'SemanticsFlags.isButton';
case _kIsTextFieldIndex:
return 'SemanticsFlags.isTextField';
case _kIsFocusedIndex:
return 'SemanticsFlags.isFocused';
case _kIsDisabledIndex:
return 'SemanticsFlags.isDisabled';
}
return null;
}
}
/// An object that creates [SemanticsUpdate] objects.
///
/// Once created, the [SemanticsUpdate] objects can be passed to
/// [Window.updateSemantics] to update the semantics conveyed to the user.
class SemanticsUpdateBuilder extends NativeFieldWrapperClass2 {
/// Creates an empty [SemanticsUpdateBuilder] object.
SemanticsUpdateBuilder() { _constructor(); }
void _constructor() native "SemanticsUpdateBuilder_constructor";
/// Update the information associated with the node with the given `id`.
///
/// The semantics nodes form a tree, with the root of the tree always having
/// an id of zero. The `children` are the ids of the nodes that are immediate
/// children of this node. The system retains the nodes that are currently
/// reachable from the root. A given update need not contain information for
/// nodes that do not change in the update. If a node is not reachable from
/// the root after an update, the node will be discarded from the tree.
///
/// The `flags` are a bit field of [SemanticsFlags] that apply to this node.
///
/// The `actions` are a bit field of [SemanticsAction]s that can be undertaken
/// by this node. If the user wishes to undertake one of these actions on this
/// node, the [Window.onSemanticsAction] will be called with `id` and one of
/// the possible [SemanticsAction]s. Because the semantics tree is maintained
/// asynchronously, the [Window.onSemanticsAction] callback might be called
/// with an action that is no longer possible.
///
/// The `label` is a string that describes this node. The `value` property
/// describes the current value of the node as a string. The `increasedValue`
/// string will become the `value` string after a [SemanticsAction.increase]
/// action is performed. The `decreasedValue` string will become the `value`
/// string after a [SemanticsAction.decrease] action is performed. The `hint`
/// string describes what result an action performed on this node has. The
/// reading direction of all these strings is given by `textDirection`.
///
/// The `rect` is the region occupied by this node in its own coordinate
/// system.
///
/// The `transform` is a matrix that maps this node's coodinate system into
/// its parent's coordinate system.
void updateNode({
int id,
int flags,
int actions,
Rect rect,
String label,
String hint,
String value,
String increasedValue,
String decreasedValue,
TextDirection textDirection,
Float64List transform,
Int32List children
}) {
if (transform.length != 16)
throw new ArgumentError('transform argument must have 16 entries.');
_updateNode(id,
flags,
actions,
rect.left,
rect.top,
rect.right,
rect.bottom,
label,
hint,
value,
increasedValue,
decreasedValue,
textDirection != null ? textDirection.index + 1 : 0,
transform,
children);
}
void _updateNode(
int id,
int flags,
int actions,
double left,
double top,
double right,
double bottom,
String label,
String hint,
String value,
String increasedValue,
String decreasedValue,
int textDirection,
Float64List transform,
Int32List children
) native "SemanticsUpdateBuilder_updateNode";
/// Creates a [SemanticsUpdate] object that encapsulates the updates recorded
/// by this object.
///
/// The returned object can be passed to [Window.updateSemantics] to actually
/// update the semantics retained by the system.
SemanticsUpdate build() native "SemanticsUpdateBuilder_build";
}
/// An opaque object representing a batch of semantics updates.
///
/// To create a SemanticsUpdate object, use a [SemanticsUpdateBuilder].
///
/// Semantics updates can be applied to the system's retained semantics tree
/// using the [Window.updateSemantics] method.
class SemanticsUpdate extends NativeFieldWrapperClass2 {
/// Creates an uninitialized SemanticsUpdate object.
///
/// Calling the SemanticsUpdate constructor directly will not create a useable
/// object. To create a SemanticsUpdate object, use a [SemanticsUpdateBuilder].
SemanticsUpdate(); // (this constructor is here just so we can document it)
/// Releases the resources used by this semantics update.
///
/// After calling this function, the semantics update is cannot be used
/// further.
void dispose() native "SemanticsUpdateBuilder_dispose";
}