Home | History | Annotate | Download | only in method
      1 /*
      2  * Copyright (C) 2006 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.text.method;
     18 
     19 import android.view.KeyEvent;
     20 import android.view.View;
     21 import android.text.*;
     22 import android.text.method.TextKeyListener.Capitalize;
     23 import android.widget.TextView;
     24 
     25 public abstract class BaseKeyListener
     26 extends MetaKeyKeyListener
     27 implements KeyListener {
     28     /* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete();
     29 
     30     /**
     31      * Performs the action that happens when you press the DEL key in
     32      * a TextView.  If there is a selection, deletes the selection;
     33      * otherwise, DEL alone deletes the character before the cursor,
     34      * if any;
     35      * ALT+DEL deletes everything on the line the cursor is on.
     36      *
     37      * @return true if anything was deleted; false otherwise.
     38      */
     39     public boolean backspace(View view, Editable content, int keyCode,
     40                              KeyEvent event) {
     41         int selStart, selEnd;
     42         boolean result = true;
     43 
     44         {
     45             int a = Selection.getSelectionStart(content);
     46             int b = Selection.getSelectionEnd(content);
     47 
     48             selStart = Math.min(a, b);
     49             selEnd = Math.max(a, b);
     50         }
     51 
     52         if (selStart != selEnd) {
     53             content.delete(selStart, selEnd);
     54         } else if (altBackspace(view, content, keyCode, event)) {
     55             result = true;
     56         } else {
     57             int to = TextUtils.getOffsetBefore(content, selEnd);
     58 
     59             if (to != selEnd) {
     60                 content.delete(Math.min(to, selEnd), Math.max(to, selEnd));
     61             }
     62             else {
     63                 result = false;
     64             }
     65         }
     66 
     67         if (result)
     68             adjustMetaAfterKeypress(content);
     69 
     70         return result;
     71     }
     72 
     73     private boolean altBackspace(View view, Editable content, int keyCode,
     74                                  KeyEvent event) {
     75         if (getMetaState(content, META_ALT_ON) != 1) {
     76             return false;
     77         }
     78 
     79         if (!(view instanceof TextView)) {
     80             return false;
     81         }
     82 
     83         Layout layout = ((TextView) view).getLayout();
     84 
     85         if (layout == null) {
     86             return false;
     87         }
     88 
     89         int l = layout.getLineForOffset(Selection.getSelectionStart(content));
     90         int start = layout.getLineStart(l);
     91         int end = layout.getLineEnd(l);
     92 
     93         if (end == start) {
     94             return false;
     95         }
     96 
     97         content.delete(start, end);
     98         return true;
     99     }
    100 
    101     static int makeTextContentType(Capitalize caps, boolean autoText) {
    102         int contentType = InputType.TYPE_CLASS_TEXT;
    103         switch (caps) {
    104             case CHARACTERS:
    105                 contentType |= InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS;
    106                 break;
    107             case WORDS:
    108                 contentType |= InputType.TYPE_TEXT_FLAG_CAP_WORDS;
    109                 break;
    110             case SENTENCES:
    111                 contentType |= InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
    112                 break;
    113         }
    114         if (autoText) {
    115             contentType |= InputType.TYPE_TEXT_FLAG_AUTO_CORRECT;
    116         }
    117         return contentType;
    118     }
    119 
    120     public boolean onKeyDown(View view, Editable content,
    121                              int keyCode, KeyEvent event) {
    122         if (keyCode == KeyEvent.KEYCODE_DEL) {
    123             backspace(view, content, keyCode, event);
    124             return true;
    125         }
    126 
    127         return super.onKeyDown(view, content, keyCode, event);
    128     }
    129 
    130     /**
    131      * Base implementation handles ACTION_MULTIPLE KEYCODE_UNKNOWN by inserting
    132      * the event's text into the content.
    133      */
    134     public boolean onKeyOther(View view, Editable content, KeyEvent event) {
    135         if (event.getAction() != KeyEvent.ACTION_MULTIPLE
    136                 || event.getKeyCode() != KeyEvent.KEYCODE_UNKNOWN) {
    137             // Not something we are interested in.
    138             return false;
    139         }
    140 
    141         int selStart, selEnd;
    142 
    143         {
    144             int a = Selection.getSelectionStart(content);
    145             int b = Selection.getSelectionEnd(content);
    146 
    147             selStart = Math.min(a, b);
    148             selEnd = Math.max(a, b);
    149         }
    150 
    151         CharSequence text = event.getCharacters();
    152         if (text == null) {
    153             return false;
    154         }
    155 
    156         content.replace(selStart, selEnd, text);
    157         return true;
    158     }
    159 }
    160 
    161