Home | History | Annotate | Download | only in inputmethodservice
      1 /*
      2  * Copyright (C) 2008 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 
     17 package android.inputmethodservice;
     18 
     19 import android.content.Context;
     20 import android.util.AttributeSet;
     21 import android.view.inputmethod.ExtractedText;
     22 import android.view.inputmethod.InputMethodManager;
     23 import android.widget.EditText;
     24 
     25 /***
     26  * Specialization of {@link EditText} for showing and interacting with the
     27  * extracted text in a full-screen input method.
     28  */
     29 public class ExtractEditText extends EditText {
     30     private InputMethodService mIME;
     31     private int mSettingExtractedText;
     32 
     33     public ExtractEditText(Context context) {
     34         super(context, null);
     35     }
     36 
     37     public ExtractEditText(Context context, AttributeSet attrs) {
     38         super(context, attrs, com.android.internal.R.attr.editTextStyle);
     39     }
     40 
     41     public ExtractEditText(Context context, AttributeSet attrs, int defStyle) {
     42         super(context, attrs, defStyle);
     43     }
     44 
     45     void setIME(InputMethodService ime) {
     46         mIME = ime;
     47     }
     48 
     49     /**
     50      * Start making changes that will not be reported to the client.  That
     51      * is, {@link #onSelectionChanged(int, int)} will not result in sending
     52      * the new selection to the client
     53      */
     54     public void startInternalChanges() {
     55         mSettingExtractedText += 1;
     56     }
     57 
     58     /**
     59      * Finish making changes that will not be reported to the client.  That
     60      * is, {@link #onSelectionChanged(int, int)} will not result in sending
     61      * the new selection to the client
     62      */
     63     public void finishInternalChanges() {
     64         mSettingExtractedText -= 1;
     65     }
     66 
     67     /**
     68      * Implement just to keep track of when we are setting text from the
     69      * client (vs. seeing changes in ourself from the user).
     70      */
     71     @Override public void setExtractedText(ExtractedText text) {
     72         try {
     73             mSettingExtractedText++;
     74             super.setExtractedText(text);
     75         } finally {
     76             mSettingExtractedText--;
     77         }
     78     }
     79 
     80     /**
     81      * Report to the underlying text editor about selection changes.
     82      */
     83     @Override protected void onSelectionChanged(int selStart, int selEnd) {
     84         if (mSettingExtractedText == 0 && mIME != null && selStart >= 0 && selEnd >= 0) {
     85             mIME.onExtractedSelectionChanged(selStart, selEnd);
     86         }
     87     }
     88 
     89     /**
     90      * Redirect clicks to the IME for handling there.  First allows any
     91      * on click handler to run, though.
     92      */
     93     @Override public boolean performClick() {
     94         if (!super.performClick() && mIME != null) {
     95             mIME.onExtractedTextClicked();
     96             return true;
     97         }
     98         return false;
     99     }
    100 
    101     @Override public boolean onTextContextMenuItem(int id) {
    102         if (mIME != null && mIME.onExtractTextContextMenuItem(id)) {
    103             // Mode was started on Extracted, needs to be stopped here.
    104             // Cut and paste will change the text, which stops selection mode.
    105             if (id == android.R.id.copy) stopSelectionActionMode();
    106             return true;
    107         }
    108         return super.onTextContextMenuItem(id);
    109     }
    110 
    111     /**
    112      * We are always considered to be an input method target.
    113      */
    114     @Override
    115     public boolean isInputMethodTarget() {
    116         return true;
    117     }
    118 
    119     /**
    120      * Return true if the edit text is currently showing a scroll bar.
    121      */
    122     public boolean hasVerticalScrollBar() {
    123         return computeVerticalScrollRange() > computeVerticalScrollExtent();
    124     }
    125 
    126     /**
    127      * Pretend like the window this view is in always has focus, so its
    128      * highlight and cursor will be displayed.
    129      */
    130     @Override public boolean hasWindowFocus() {
    131         return this.isEnabled();
    132     }
    133 
    134     /**
    135      * Pretend like this view always has focus, so its
    136      * highlight and cursor will be displayed.
    137      */
    138     @Override public boolean isFocused() {
    139         return this.isEnabled();
    140     }
    141 
    142     /**
    143      * Pretend like this view always has focus, so its
    144      * highlight and cursor will be displayed.
    145      */
    146     @Override public boolean hasFocus() {
    147         return this.isEnabled();
    148     }
    149 
    150     /**
    151      * @hide
    152      */
    153     @Override protected void viewClicked(InputMethodManager imm) {
    154         // As an instance of this class is supposed to be owned by IMS,
    155         // and it has a reference to the IMS (the current IME),
    156         // we just need to call back its onViewClicked() here.
    157         // It should be good to avoid unnecessary IPCs by doing this as well.
    158         if (mIME != null) {
    159             mIME.onViewClicked(false);
    160         }
    161     }
    162 
    163     /**
    164      * {@inheritDoc}
    165      * @hide
    166      */
    167     @Override
    168     protected void deleteText_internal(int start, int end) {
    169         // Do not call the super method.
    170         // This will change the source TextView instead, which will update the ExtractTextView.
    171         mIME.onExtractedDeleteText(start, end);
    172     }
    173 
    174     /**
    175      * {@inheritDoc}
    176      * @hide
    177      */
    178     @Override
    179     protected void replaceText_internal(int start, int end, CharSequence text) {
    180         // Do not call the super method.
    181         // This will change the source TextView instead, which will update the ExtractTextView.
    182         mIME.onExtractedReplaceText(start, end, text);
    183     }
    184 
    185     /**
    186      * {@inheritDoc}
    187      * @hide
    188      */
    189     @Override
    190     protected void setSpan_internal(Object span, int start, int end, int flags) {
    191         // Do not call the super method.
    192         // This will change the source TextView instead, which will update the ExtractTextView.
    193         mIME.onExtractedSetSpan(span, start, end, flags);
    194     }
    195 
    196     /**
    197      * {@inheritDoc}
    198      * @hide
    199      */
    200     @Override
    201     protected void setCursorPosition_internal(int start, int end) {
    202         // Do not call the super method.
    203         // This will change the source TextView instead, which will update the ExtractTextView.
    204         mIME.onExtractedSelectionChanged(start, end);
    205     }
    206 }
    207