• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 com.android.calculator2;
18 
19 import android.content.ClipData;
20 import android.content.ClipboardManager;
21 import android.content.Context;
22 import android.content.res.Resources;
23 import android.text.Editable;
24 import android.text.InputType;
25 import android.text.TextUtils;
26 import android.util.AttributeSet;
27 import android.util.Log;
28 import android.view.ActionMode;
29 import android.view.ContextMenu;
30 import android.view.Menu;
31 import android.view.MenuItem;
32 import android.view.MotionEvent;
33 import android.widget.EditText;
34 import android.widget.Toast;
35 
36 public class CalculatorEditText extends EditText {
37 
38     private static final String LOG_TAG = "Calculator2";
39     private static final int CUT = 0;
40     private static final int COPY = 1;
41     private static final int PASTE = 2;
42     private String[] mMenuItemsStrings;
43 
CalculatorEditText(Context context, AttributeSet attrs)44     public CalculatorEditText(Context context, AttributeSet attrs) {
45         super(context, attrs);
46         setCustomSelectionActionModeCallback(new NoTextSelectionMode());
47         setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
48     }
49 
50     @Override
onTouchEvent(MotionEvent event)51     public boolean onTouchEvent(MotionEvent event) {
52        if (event.getActionMasked() == MotionEvent.ACTION_UP) {
53             // Hack to prevent keyboard and insertion handle from showing.
54            cancelLongPress();
55         }
56         return super.onTouchEvent(event);
57     }
58 
59     @Override
performLongClick()60     public boolean performLongClick() {
61         showContextMenu();
62         return true;
63     }
64 
65     private class MenuHandler implements MenuItem.OnMenuItemClickListener {
onMenuItemClick(MenuItem item)66         public boolean onMenuItemClick(MenuItem item) {
67             return onTextContextMenuItem(item.getTitle());
68         }
69     }
70 
onTextContextMenuItem(CharSequence title)71     public boolean onTextContextMenuItem(CharSequence title) {
72         boolean handled = false;
73         if (TextUtils.equals(title, mMenuItemsStrings[CUT])) {
74             cutContent();
75             handled = true;
76         } else if (TextUtils.equals(title,  mMenuItemsStrings[COPY])) {
77             copyContent();
78             handled = true;
79         } else if (TextUtils.equals(title,  mMenuItemsStrings[PASTE])) {
80             pasteContent();
81             handled = true;
82         }
83         return handled;
84     }
85 
86     @Override
onCreateContextMenu(ContextMenu menu)87     public void onCreateContextMenu(ContextMenu menu) {
88         MenuHandler handler = new MenuHandler();
89         if (mMenuItemsStrings == null) {
90             Resources resources = getResources();
91             mMenuItemsStrings = new String[3];
92             mMenuItemsStrings[CUT] = resources.getString(android.R.string.cut);
93             mMenuItemsStrings[COPY] = resources.getString(android.R.string.copy);
94             mMenuItemsStrings[PASTE] = resources.getString(android.R.string.paste);
95         }
96         for (int i = 0; i < mMenuItemsStrings.length; i++) {
97             menu.add(Menu.NONE, i, i, mMenuItemsStrings[i]).setOnMenuItemClickListener(handler);
98         }
99         if (getText().length() == 0) {
100             menu.getItem(CUT).setVisible(false);
101             menu.getItem(COPY).setVisible(false);
102         }
103         ClipData primaryClip = getPrimaryClip();
104         if (primaryClip == null || primaryClip.getItemCount() == 0
105                 || !canPaste(primaryClip.getItemAt(0).coerceToText(getContext()))) {
106             menu.getItem(PASTE).setVisible(false);
107         }
108     }
109 
setPrimaryClip(ClipData clip)110     private void setPrimaryClip(ClipData clip) {
111         ClipboardManager clipboard = (ClipboardManager) getContext().
112                 getSystemService(Context.CLIPBOARD_SERVICE);
113         clipboard.setPrimaryClip(clip);
114     }
115 
copyContent()116     private void copyContent() {
117         final Editable text = getText();
118         int textLength = text.length();
119         setSelection(0, textLength);
120         ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(
121                 Context.CLIPBOARD_SERVICE);
122         clipboard.setPrimaryClip(ClipData.newPlainText(null, text));
123         Toast.makeText(getContext(), R.string.text_copied_toast, Toast.LENGTH_SHORT).show();
124         setSelection(textLength);
125     }
126 
cutContent()127     private void cutContent() {
128         final Editable text = getText();
129         int textLength = text.length();
130         setSelection(0, textLength);
131         setPrimaryClip(ClipData.newPlainText(null, text));
132         ((Editable) getText()).delete(0, textLength);
133         setSelection(0);
134     }
135 
getPrimaryClip()136     private ClipData getPrimaryClip() {
137         ClipboardManager clipboard = (ClipboardManager) getContext().getSystemService(
138                 Context.CLIPBOARD_SERVICE);
139         return clipboard.getPrimaryClip();
140     }
141 
pasteContent()142     private void pasteContent() {
143         ClipData clip = getPrimaryClip();
144         if (clip != null) {
145             for (int i = 0; i < clip.getItemCount(); i++) {
146                 CharSequence paste = clip.getItemAt(i).coerceToText(getContext());
147                 if (canPaste(paste)) {
148                     ((Editable) getText()).insert(getSelectionEnd(), paste);
149                 }
150             }
151         }
152     }
153 
canPaste(CharSequence paste)154     private boolean canPaste(CharSequence paste) {
155         boolean canPaste = true;
156         try {
157             Float.parseFloat(paste.toString());
158         } catch (NumberFormatException e) {
159             Log.e(LOG_TAG, "Error turning string to integer. Ignoring paste.", e);
160             canPaste = false;
161         }
162         return canPaste;
163     }
164 
165     class NoTextSelectionMode implements ActionMode.Callback {
166         @Override
onActionItemClicked(ActionMode mode, MenuItem item)167         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
168             return false;
169         }
170 
171         @Override
onCreateActionMode(ActionMode mode, Menu menu)172         public boolean onCreateActionMode(ActionMode mode, Menu menu) {
173             copyContent();
174             // Prevents the selection action mode on double tap.
175             return false;
176         }
177 
178         @Override
onDestroyActionMode(ActionMode mode)179         public void onDestroyActionMode(ActionMode mode) {}
180 
181         @Override
onPrepareActionMode(ActionMode mode, Menu menu)182         public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
183             return false;
184         }
185     }
186 }
187