mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
135 lines
4.7 KiB
Dart
135 lines
4.7 KiB
Dart
// Copyright 2014 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'dart:ui' show hashValues, TextAffinity, TextPosition, TextRange;
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
export 'dart:ui' show TextAffinity, TextPosition, TextRange;
|
|
|
|
/// A range of text that represents a selection.
|
|
@immutable
|
|
class TextSelection extends TextRange {
|
|
/// Creates a text selection.
|
|
///
|
|
/// The [baseOffset] and [extentOffset] arguments must not be null.
|
|
const TextSelection({
|
|
@required this.baseOffset,
|
|
@required this.extentOffset,
|
|
this.affinity = TextAffinity.downstream,
|
|
this.isDirectional = false,
|
|
}) : super(
|
|
start: baseOffset < extentOffset ? baseOffset : extentOffset,
|
|
end: baseOffset < extentOffset ? extentOffset : baseOffset,
|
|
);
|
|
|
|
/// Creates a collapsed selection at the given offset.
|
|
///
|
|
/// A collapsed selection starts and ends at the same offset, which means it
|
|
/// contains zero characters but instead serves as an insertion point in the
|
|
/// text.
|
|
///
|
|
/// The [offset] argument must not be null.
|
|
const TextSelection.collapsed({
|
|
@required int offset,
|
|
this.affinity = TextAffinity.downstream,
|
|
}) : baseOffset = offset,
|
|
extentOffset = offset,
|
|
isDirectional = false,
|
|
super.collapsed(offset);
|
|
|
|
/// Creates a collapsed selection at the given text position.
|
|
///
|
|
/// A collapsed selection starts and ends at the same offset, which means it
|
|
/// contains zero characters but instead serves as an insertion point in the
|
|
/// text.
|
|
TextSelection.fromPosition(TextPosition position)
|
|
: baseOffset = position.offset,
|
|
extentOffset = position.offset,
|
|
affinity = position.affinity,
|
|
isDirectional = false,
|
|
super.collapsed(position.offset);
|
|
|
|
/// The offset at which the selection originates.
|
|
///
|
|
/// Might be larger than, smaller than, or equal to extent.
|
|
final int baseOffset;
|
|
|
|
/// The offset at which the selection terminates.
|
|
///
|
|
/// When the user uses the arrow keys to adjust the selection, this is the
|
|
/// value that changes. Similarly, if the current theme paints a caret on one
|
|
/// side of the selection, this is the location at which to paint the caret.
|
|
///
|
|
/// Might be larger than, smaller than, or equal to base.
|
|
final int extentOffset;
|
|
|
|
/// If the text range is collapsed and has more than one visual location
|
|
/// (e.g., occurs at a line break), which of the two locations to use when
|
|
/// painting the caret.
|
|
final TextAffinity affinity;
|
|
|
|
/// Whether this selection has disambiguated its base and extent.
|
|
///
|
|
/// On some platforms, the base and extent are not disambiguated until the
|
|
/// first time the user adjusts the selection. At that point, either the start
|
|
/// or the end of the selection becomes the base and the other one becomes the
|
|
/// extent and is adjusted.
|
|
final bool isDirectional;
|
|
|
|
/// The position at which the selection originates.
|
|
///
|
|
/// Might be larger than, smaller than, or equal to extent.
|
|
TextPosition get base => TextPosition(offset: baseOffset, affinity: affinity);
|
|
|
|
/// The position at which the selection terminates.
|
|
///
|
|
/// When the user uses the arrow keys to adjust the selection, this is the
|
|
/// value that changes. Similarly, if the current theme paints a caret on one
|
|
/// side of the selection, this is the location at which to paint the caret.
|
|
///
|
|
/// Might be larger than, smaller than, or equal to base.
|
|
TextPosition get extent => TextPosition(offset: extentOffset, affinity: affinity);
|
|
|
|
@override
|
|
String toString() {
|
|
return '${objectRuntimeType(this, 'TextSelection')}(baseOffset: $baseOffset, extentOffset: $extentOffset, affinity: $affinity, isDirectional: $isDirectional)';
|
|
}
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (identical(this, other))
|
|
return true;
|
|
return other is TextSelection
|
|
&& other.baseOffset == baseOffset
|
|
&& other.extentOffset == extentOffset
|
|
&& other.affinity == affinity
|
|
&& other.isDirectional == isDirectional;
|
|
}
|
|
|
|
@override
|
|
int get hashCode => hashValues(
|
|
baseOffset.hashCode,
|
|
extentOffset.hashCode,
|
|
affinity.hashCode,
|
|
isDirectional.hashCode,
|
|
);
|
|
|
|
/// Creates a new [TextSelection] based on the current selection, with the
|
|
/// provided parameters overridden.
|
|
TextSelection copyWith({
|
|
int baseOffset,
|
|
int extentOffset,
|
|
TextAffinity affinity,
|
|
bool isDirectional,
|
|
}) {
|
|
return TextSelection(
|
|
baseOffset: baseOffset ?? this.baseOffset,
|
|
extentOffset: extentOffset ?? this.extentOffset,
|
|
affinity: affinity ?? this.affinity,
|
|
isDirectional: isDirectional ?? this.isDirectional,
|
|
);
|
|
}
|
|
}
|