[go: nahoru, domu]

blob: 5ef1b55accd78832c3620991acfeb8b4be43e66c [file] [log] [blame]
Qingqing Dengb745a942019-06-05 18:26:52 -07001/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Louis Pullen-Freilichca6eca22020-07-20 00:31:45 +010017package androidx.compose.foundation.text.selection
Qingqing Dengb745a942019-06-05 18:26:52 -070018
Nader Jawad22f59782020-05-14 17:07:11 -070019import androidx.ui.geometry.Rect
Nader Jawad6df06122020-06-03 15:27:08 -070020import androidx.ui.geometry.Offset
Qingqing Dengb745a942019-06-05 18:26:52 -070021
22/**
23 * The enum class allows user to decide the selection mode.
24 */
Qingqing Deng608b8e72019-11-18 11:45:41 -080025internal enum class SelectionMode {
Qingqing Dengb745a942019-06-05 18:26:52 -070026 /**
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010027 * When selection handles are dragged across composables, selection extends by row, for example,
Qingqing Dengb745a942019-06-05 18:26:52 -070028 * when the end selection handle is dragged down, upper rows will be selected first, and the
29 * lower rows.
30 */
31 Vertical {
32 override fun isSelected(
Nader Jawad22f59782020-05-14 17:07:11 -070033 bounds: Rect,
Nader Jawad6df06122020-06-03 15:27:08 -070034 start: Offset,
35 end: Offset
Qingqing Dengb745a942019-06-05 18:26:52 -070036 ): Boolean {
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010037 // When the end of the selection is above the top of the composable, the composable is outside
Qingqing Dengb745a942019-06-05 18:26:52 -070038 // of the selection range.
Nader Jawade6a9b332020-05-21 13:49:20 -070039 if (end.y < bounds.top) return false
Qingqing Dengb745a942019-06-05 18:26:52 -070040
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010041 // When the end of the selection is on the left of the composable, and not below the bottom
42 // of composable, the composable is outside of the selection range.
Nader Jawade6a9b332020-05-21 13:49:20 -070043 if (end.x < bounds.left && end.y < bounds.bottom) return false
Qingqing Dengb745a942019-06-05 18:26:52 -070044
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010045 // When the start of the selection is below the bottom of the composable, the composable is
Qingqing Dengb745a942019-06-05 18:26:52 -070046 // outside of the selection range.
Nader Jawade6a9b332020-05-21 13:49:20 -070047 if (start.y >= bounds.bottom) return false
Qingqing Dengb745a942019-06-05 18:26:52 -070048
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010049 // When the start of the selection is on the right of the composable, and not above the top
50 // of the composable, the composable is outside of the selection range.
Nader Jawade6a9b332020-05-21 13:49:20 -070051 if (start.x >= bounds.right && start.y >= bounds.top) return false
Qingqing Dengb745a942019-06-05 18:26:52 -070052
53 return true
54 }
Qingqing Denga5d80952019-10-11 16:46:52 -070055
56 override fun areHandlesCrossed(
Nader Jawad22f59782020-05-14 17:07:11 -070057 bounds: Rect,
Nader Jawad6df06122020-06-03 15:27:08 -070058 start: Offset,
59 end: Offset
Qingqing Denga5d80952019-10-11 16:46:52 -070060 ): Boolean {
Nader Jawade6a9b332020-05-21 13:49:20 -070061 if (start.y >= bounds.top && start.y < bounds.bottom &&
62 end.y >= bounds.top && end.y < bounds.bottom
Qingqing Denga5d80952019-10-11 16:46:52 -070063 ) {
64 // When the start and end of the selection are in the same row of widgets, check if
65 // x coordinates of the start and end are crossed each other.
66 return start.x > end.x
67 } else {
68 // When the start and end of the selection are not in the same row of widgets, check
69 // if y coordinates of the start and end are crossed each other.
70 return start.y > end.y
71 }
72 }
Qingqing Dengb745a942019-06-05 18:26:52 -070073 },
74
75 /**
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010076 * When selection handles are dragged across composables, selection extends by column, for example,
Qingqing Dengb745a942019-06-05 18:26:52 -070077 * when the end selection handle is dragged to the right, left columns will be selected first,
78 * and the right rows.
79 */
80 Horizontal {
81 override fun isSelected(
Nader Jawad22f59782020-05-14 17:07:11 -070082 bounds: Rect,
Nader Jawad6df06122020-06-03 15:27:08 -070083 start: Offset,
84 end: Offset
Qingqing Dengb745a942019-06-05 18:26:52 -070085 ): Boolean {
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010086 // When the end of the selection is on the left of the composable, the composable is outside of
Qingqing Dengb745a942019-06-05 18:26:52 -070087 // the selection range.
Nader Jawade6a9b332020-05-21 13:49:20 -070088 if (end.x < bounds.left) return false
Qingqing Dengb745a942019-06-05 18:26:52 -070089
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010090 // When the end of the selection is on the top of the composable, and the not on the right
91 // of the composable, the composable is outside of the selection range.
Nader Jawade6a9b332020-05-21 13:49:20 -070092 if (end.y < bounds.top && end.x < bounds.right) return false
Qingqing Dengb745a942019-06-05 18:26:52 -070093
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010094 // When the start of the selection is on the right of the composable, the composable is outside
Qingqing Dengb745a942019-06-05 18:26:52 -070095 // of the selection range.
Nader Jawade6a9b332020-05-21 13:49:20 -070096 if (start.x >= bounds.right) return false
Qingqing Dengb745a942019-06-05 18:26:52 -070097
Louis Pullen-Freilich5da28bd2019-10-15 17:05:07 +010098 // When the start of the selection is below the composable, and not on the left of the
99 // composable, the composable is outside of the selection range.
Nader Jawade6a9b332020-05-21 13:49:20 -0700100 if (start.y >= bounds.bottom && start.x >= bounds.left) return false
Qingqing Dengb745a942019-06-05 18:26:52 -0700101
102 return true
103 }
Qingqing Denga5d80952019-10-11 16:46:52 -0700104
105 override fun areHandlesCrossed(
Nader Jawad22f59782020-05-14 17:07:11 -0700106 bounds: Rect,
Nader Jawad6df06122020-06-03 15:27:08 -0700107 start: Offset,
108 end: Offset
Qingqing Denga5d80952019-10-11 16:46:52 -0700109 ): Boolean {
Nader Jawade6a9b332020-05-21 13:49:20 -0700110 if (start.x >= bounds.left && start.x < bounds.right &&
111 end.x >= bounds.left && end.x < bounds.right
Qingqing Denga5d80952019-10-11 16:46:52 -0700112 ) {
113 // When the start and end of the selection are in the same column of widgets,
114 // check if y coordinates of the start and end are crossed each other.
115 return start.y > end.y
116 } else {
117 // When the start and end of the selection are not in the same column of widgets,
118 // check if x coordinates of the start and end are crossed each other.
119 return start.x > end.x
120 }
121 }
Qingqing Dengb745a942019-06-05 18:26:52 -0700122 };
123
Siyamed Sinir62282752019-10-20 22:34:30 -0700124 /**
125 * Decides if Composable which has [bounds], should be accepted by the selection and
126 * change its selected state for a selection that starts at [start] and ends at [end].
127 *
Qingqing Denga5d80952019-10-11 16:46:52 -0700128 * @param bounds Composable bounds of the widget to be checked.
129 * @param start The start coordinates of the selection, in SelectionContainer range.
130 * @param end The end coordinates of the selection, in SelectionContainer range.
Siyamed Sinir62282752019-10-20 22:34:30 -0700131 */
Qingqing Dengb745a942019-06-05 18:26:52 -0700132 internal abstract fun isSelected(
Nader Jawad22f59782020-05-14 17:07:11 -0700133 bounds: Rect,
Nader Jawad6df06122020-06-03 15:27:08 -0700134 start: Offset,
135 end: Offset
Qingqing Dengb745a942019-06-05 18:26:52 -0700136 ): Boolean
Qingqing Denga5d80952019-10-11 16:46:52 -0700137
138 /**
139 * Decides if the [start] and [end] handles of the selection are crossed around a Composable
140 * which has [bounds].
141 * When the end handle is visually crossed the start handle, return true.
142 *
143 * @param bounds Composable bounds of the widget to be checked.
144 * @param start The start coordinates of the selection, in SelectionContainer range.
145 * @param end The end coordinates of the selection, in SelectionContainer range.
146 */
147 internal abstract fun areHandlesCrossed(
Nader Jawad22f59782020-05-14 17:07:11 -0700148 bounds: Rect,
Nader Jawad6df06122020-06-03 15:27:08 -0700149 start: Offset,
150 end: Offset
Qingqing Denga5d80952019-10-11 16:46:52 -0700151 ): Boolean
Qingqing Dengb745a942019-06-05 18:26:52 -0700152}