1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.ui; 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ClipData; 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.ClipboardManager; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.AttributeSet; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.EditText; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * We want the EditText used in Conversations to convert text to plain text on paste. This 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * conversion would happen anyway on send, so without this class it could appear to the user 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * that we would send e.g. bold or italic formatting, but in the sent message it would just be 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * plain text. 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class PlainTextEditText extends EditText { 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static final char OBJECT_UNICODE = '\uFFFC'; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public PlainTextEditText(final Context context, final AttributeSet attrs) { 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super(context, attrs); 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Intercept and modify the paste event. Let everything else through unchanged. 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean onTextContextMenuItem(final int id) { 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (id == android.R.id.paste) { 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We can use this to know where the text position was originally before we pasted 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int selectionStartPrePaste = getSelectionStart(); 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Let the EditText's normal paste routine fire, then modify the content after. 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // This is simpler than re-implementing the paste logic, which we'd have to do 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // if we want to get the text from the clipboard ourselves and then modify it. 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean result = super.onTextContextMenuItem(id); 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd CharSequence text = getText(); 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int selectionStart = getSelectionStart(); 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int selectionEnd = getSelectionEnd(); 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // There is an option in the Chrome mobile app to copy image; however, instead of the 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // image in the form of the uri, Chrome gives us the html source for the image, which 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the platform paste code turns into the unicode object character. The below section 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // of code looks for that edge case and replaces it with the url for the image. 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int startIndex = selectionStart - 1; 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int pasteStringLength = selectionStart - selectionStartPrePaste; 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Only going to handle the case where the pasted object is the image 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (pasteStringLength == 1 && text.charAt(startIndex) == OBJECT_UNICODE) { 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ClipboardManager clipboard = 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE); 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ClipData clip = clipboard.getPrimaryClip(); 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (clip != null) { 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ClipData.Item item = clip.getItemAt(0); 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StringBuilder sb = new StringBuilder(text); 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String url = item.getText().toString(); 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd sb.replace(selectionStartPrePaste, selectionStart, url); 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd text = sb.toString(); 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selectionStart = selectionStartPrePaste + url.length(); 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd selectionEnd = selectionStart; 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // This removes the formatting due to the conversion to string. 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setText(text.toString(), BufferType.EDITABLE); 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Restore the cursor selection state. 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setSelection(selectionStart, selectionEnd); 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return result; 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return super.onTextContextMenuItem(id); 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 86