19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.text.method; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Layout; 20cc3ec6cdb2b892eb29513e72d8b205acbe997b25Gilles Debunneimport android.text.Layout.Alignment; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.NoCopySpan; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.Spannable; 23c982f60e982c1d2df9f115ed9a5c3ef3643d0892Doug Feltimport android.view.KeyEvent; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.MotionEvent; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ViewConfiguration; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.TextView; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class Touch { 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Touch() { } 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Scrolls the specified widget to the specified coordinates, except 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * constrains the X scrolling position to the horizontal regions of 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the text that will be visible after scrolling to the specified 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Y position. 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static void scrollTo(TextView widget, Layout layout, int x, int y) { 38f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne final int horizontalPadding = widget.getTotalPaddingLeft() + widget.getTotalPaddingRight(); 39f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne final int availableWidth = widget.getWidth() - horizontalPadding; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne final int top = layout.getLineForVertical(y); 42b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne Alignment a = layout.getParagraphAlignment(top); 43b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne boolean ltr = layout.getParagraphDirection(top) > 0; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 45f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne int left, right; 46f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne if (widget.getHorizontallyScrolling()) { 47f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne final int verticalPadding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(); 48f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne final int bottom = layout.getLineForVertical(y + widget.getHeight() - verticalPadding); 49f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne 50f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne left = Integer.MAX_VALUE; 51f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne right = 0; 52f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne 53f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne for (int i = top; i <= bottom; i++) { 54f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne left = (int) Math.min(left, layout.getLineLeft(i)); 55f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne right = (int) Math.max(right, layout.getLineRight(i)); 56f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne } 57f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne } else { 58f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne left = 0; 59f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne right = availableWidth; 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 62b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne final int actualWidth = right - left; 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 64b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne if (actualWidth < availableWidth) { 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (a == Alignment.ALIGN_CENTER) { 66b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne x = left - ((availableWidth - actualWidth) / 2); 6701524651cb8f7b97a310bd262f4c792e860e140fRaph Levien } else if ((ltr && (a == Alignment.ALIGN_OPPOSITE)) || 6801524651cb8f7b97a310bd262f4c792e860e140fRaph Levien (!ltr && (a == Alignment.ALIGN_NORMAL)) || 6901524651cb8f7b97a310bd262f4c792e860e140fRaph Levien (a == Alignment.ALIGN_RIGHT)) { 70b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne // align_opposite does NOT mean align_right, we need the paragraph 71b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne // direction to resolve it to left or right 72b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne x = left - (availableWidth - actualWidth); 73b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne } else { 74b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne x = left; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 76b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne } else { 77b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne x = Math.min(x, right - availableWidth); 78b2beb92073cea6e472748e729ac8e265ca83a925Gilles Debunne x = Math.max(x, left); 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project widget.scrollTo(x, y); 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handles touch events for dragging. You may want to do other actions 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * like moving the cursor on touch as well. 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static boolean onTouchEvent(TextView widget, Spannable buffer, 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project MotionEvent event) { 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DragState[] ds; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 92cc3ec6cdb2b892eb29513e72d8b205acbe997b25Gilles Debunne switch (event.getActionMasked()) { 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_DOWN: 9458b971d733a2c700cabd3db02b6ea4d5faca6939Eric Fischer ds = buffer.getSpans(0, buffer.length(), DragState.class); 9558b971d733a2c700cabd3db02b6ea4d5faca6939Eric Fischer 9658b971d733a2c700cabd3db02b6ea4d5faca6939Eric Fischer for (int i = 0; i < ds.length; i++) { 9758b971d733a2c700cabd3db02b6ea4d5faca6939Eric Fischer buffer.removeSpan(ds[i]); 9858b971d733a2c700cabd3db02b6ea4d5faca6939Eric Fischer } 9958b971d733a2c700cabd3db02b6ea4d5faca6939Eric Fischer 10038e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn buffer.setSpan(new DragState(event.getX(), event.getY(), 10138e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn widget.getScrollX(), widget.getScrollY()), 10238e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn 0, 0, Spannable.SPAN_MARK_MARK); 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_UP: 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ds = buffer.getSpans(0, buffer.length(), DragState.class); 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < ds.length; i++) { 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buffer.removeSpan(ds[i]); 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ds.length > 0 && ds[0].mUsed) { 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case MotionEvent.ACTION_MOVE: 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ds = buffer.getSpans(0, buffer.length(), DragState.class); 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ds.length > 0) { 122cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan ds[0].mIsSelectionStarted = false; 123cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ds[0].mFarEnough == false) { 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int slop = ViewConfiguration.get(widget.getContext()).getScaledTouchSlop(); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Math.abs(event.getX() - ds[0].mX) >= slop || 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Math.abs(event.getY() - ds[0].mY) >= slop) { 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ds[0].mFarEnough = true; 130cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan if (event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { 131cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan ds[0].mIsActivelySelecting = true; 132cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan ds[0].mIsSelectionStarted = true; 133cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan } 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ds[0].mFarEnough) { 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ds[0].mUsed = true; 1396b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown boolean cap = (event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0 1406b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown || MetaKeyKeyListener.getMetaState(buffer, 1416b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown MetaKeyKeyListener.META_SHIFT_ON) == 1 1426b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown || MetaKeyKeyListener.getMetaState(buffer, 1436b53e8daa69cba1a2a5a7c95a01e37ce9c53226cJeff Brown MetaKeyKeyListener.META_SELECTING) != 0; 144cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan 145cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan if (!event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { 146cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan ds[0].mIsActivelySelecting = false; 147cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan } 148cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan 149ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett float dx; 150ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett float dy; 151cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan if (cap && event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { 152ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett // if we're selecting, we want the scroll to go in 153ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett // the direction of the drag 154ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett dx = event.getX() - ds[0].mX; 155ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett dy = event.getY() - ds[0].mY; 156ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett } else { 157ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett dx = ds[0].mX - event.getX(); 158ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett dy = ds[0].mY - event.getY(); 159ab9289320f598509cf358523ba173d69178a55eaMaryam Garrett } 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ds[0].mX = event.getX(); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ds[0].mY = event.getY(); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nx = widget.getScrollX() + (int) dx; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ny = widget.getScrollY() + (int) dy; 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16670a6312f09329bd0b19343bc7906f9ce665fe3adGilles Debunne int padding = widget.getTotalPaddingTop() + widget.getTotalPaddingBottom(); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Layout layout = widget.getLayout(); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 16970a6312f09329bd0b19343bc7906f9ce665fe3adGilles Debunne ny = Math.min(ny, layout.getHeight() - (widget.getHeight() - padding)); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ny = Math.max(ny, 0); 171cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan 17227d377221c7970a5205c83f8a9f62f755dc1fa5dDianne Hackborn int oldX = widget.getScrollX(); 17327d377221c7970a5205c83f8a9f62f755dc1fa5dDianne Hackborn int oldY = widget.getScrollY(); 17427d377221c7970a5205c83f8a9f62f755dc1fa5dDianne Hackborn 175cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan if (!event.isButtonPressed(MotionEvent.BUTTON_PRIMARY)) { 176cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan scrollTo(widget, layout, nx, ny); 177cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan } 17827d377221c7970a5205c83f8a9f62f755dc1fa5dDianne Hackborn 17927d377221c7970a5205c83f8a9f62f755dc1fa5dDianne Hackborn // If we actually scrolled, then cancel the up action. 18070a6312f09329bd0b19343bc7906f9ce665fe3adGilles Debunne if (oldX != widget.getScrollX() || oldY != widget.getScrollY()) { 18127d377221c7970a5205c83f8a9f62f755dc1fa5dDianne Hackborn widget.cancelLongPress(); 18227d377221c7970a5205c83f8a9f62f755dc1fa5dDianne Hackborn } 18327d377221c7970a5205c83f8a9f62f755dc1fa5dDianne Hackborn 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 192f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne /** 193f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne * @param widget The text view. 194f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne * @param buffer The text buffer. 195f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne */ 19638e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn public static int getInitialScrollX(TextView widget, Spannable buffer) { 19738e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class); 19838e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn return ds.length > 0 ? ds[0].mScrollX : -1; 19938e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn } 200f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne 201f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne /** 202f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne * @param widget The text view. 203f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne * @param buffer The text buffer. 204f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne */ 20538e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn public static int getInitialScrollY(TextView widget, Spannable buffer) { 20638e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn DragState[] ds = buffer.getSpans(0, buffer.length(), DragState.class); 20738e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn return ds.length > 0 ? ds[0].mScrollY : -1; 20838e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn } 209f2a02018e2fa3089f6d39fc838a04818ae6cf26bGilles Debunne 210cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan /** 211cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * Checks if selection is still active. 212cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * This is useful for extending Selection span on buffer. 213cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * @param buffer The text buffer. 214cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * @return true if buffer has been marked for selection. 215cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * 216cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * @hide 217cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan */ 218cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan static boolean isActivelySelecting(Spannable buffer) { 219cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan DragState[] ds; 220cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan ds = buffer.getSpans(0, buffer.length(), DragState.class); 221cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan 222cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan return ds.length > 0 && ds[0].mIsActivelySelecting; 223cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan } 224cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan 225cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan /** 226cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * Checks if selection has begun (are we out of slop?). 227cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * Note: DragState.mIsSelectionStarted goes back to false with the very next event. 228cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * This is useful for starting Selection span on buffer. 229cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * @param buffer The text buffer. 230cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * @return true if selection has started on the buffer. 231cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * 232cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan * @hide 233cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan */ 234cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan static boolean isSelectionStarted(Spannable buffer) { 235cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan DragState[] ds; 236cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan ds = buffer.getSpans(0, buffer.length(), DragState.class); 237cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan 238cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan return ds.length > 0 && ds[0].mIsSelectionStarted; 239cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan } 240cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static class DragState implements NoCopySpan { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float mX; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public float mY; 24438e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn public int mScrollX; 24538e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn public int mScrollY; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean mFarEnough; 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean mUsed; 248cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan public boolean mIsActivelySelecting; 249cc32bd83e4d420c1adaeb3ea40f8986471e54590Sujith Ramakrishnan public boolean mIsSelectionStarted; 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 25138e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn public DragState(float x, float y, int scrollX, int scrollY) { 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mX = x; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mY = y; 25438e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn mScrollX = scrollX; 25538e98fccfab9592f871f3066f8569c559f1ee226Dianne Hackborn mScrollY = scrollY; 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 259