1 /*
2  * Copyright (C) 2011 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 com.android.internal.view.menu.MenuBuilder;
20 import com.android.internal.view.menu.MenuPopupHelper;
21 
22 import android.content.Context;
23 import android.util.AttributeSet;
24 import android.view.ActionMode;
25 import android.view.Menu;
26 import android.view.MenuInflater;
27 import android.view.MenuItem;
28 import android.view.View;
29 import android.view.accessibility.AccessibilityEvent;
30 import android.widget.Button;
31 import android.widget.LinearLayout;
32 
33 /**
34  * ExtractEditLayout provides an ActionMode presentation for the
35  * limited screen real estate in extract mode.
36  *
37  * @hide
38  */
39 public class ExtractEditLayout extends LinearLayout {
40     ExtractActionMode mActionMode;
41     Button mExtractActionButton;
42     Button mEditButton;
43 
ExtractEditLayout(Context context)44     public ExtractEditLayout(Context context) {
45         super(context);
46     }
47 
ExtractEditLayout(Context context, AttributeSet attrs)48     public ExtractEditLayout(Context context, AttributeSet attrs) {
49         super(context, attrs);
50     }
51 
52     @Override
startActionModeForChild(View sourceView, ActionMode.Callback cb)53     public ActionMode startActionModeForChild(View sourceView, ActionMode.Callback cb) {
54         final ExtractActionMode mode = new ExtractActionMode(cb);
55         if (mode.dispatchOnCreate()) {
56             mode.invalidate();
57             mExtractActionButton.setVisibility(INVISIBLE);
58             mEditButton.setVisibility(VISIBLE);
59             mActionMode = mode;
60             sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
61             return mode;
62         }
63         return null;
64     }
65 
66     /**
67      * @return true if an action mode is currently active.
68      */
isActionModeStarted()69     public boolean isActionModeStarted() {
70         return mActionMode != null;
71     }
72 
73     /**
74      * Finishes a possibly started action mode.
75      */
finishActionMode()76     public void finishActionMode() {
77         if (mActionMode != null) {
78             mActionMode.finish();
79         }
80     }
81 
82     @Override
onFinishInflate()83     public void onFinishInflate() {
84         super.onFinishInflate();
85         mExtractActionButton = (Button) findViewById(com.android.internal.R.id.inputExtractAction);
86         mEditButton = (Button) findViewById(com.android.internal.R.id.inputExtractEditButton);
87         mEditButton.setOnClickListener(new OnClickListener() {
88             public void onClick(View clicked) {
89                 if (mActionMode != null) {
90                     new MenuPopupHelper(getContext(), mActionMode.mMenu, clicked).show();
91                 }
92             }
93         });
94     }
95 
96     private class ExtractActionMode extends ActionMode implements MenuBuilder.Callback {
97         private ActionMode.Callback mCallback;
98         MenuBuilder mMenu;
99 
ExtractActionMode(Callback cb)100         public ExtractActionMode(Callback cb) {
101             mMenu = new MenuBuilder(getContext());
102             mMenu.setCallback(this);
103             mCallback = cb;
104         }
105 
106         @Override
setTitle(CharSequence title)107         public void setTitle(CharSequence title) {
108             // Title will not be shown.
109         }
110 
111         @Override
setTitle(int resId)112         public void setTitle(int resId) {
113             // Title will not be shown.
114         }
115 
116         @Override
setSubtitle(CharSequence subtitle)117         public void setSubtitle(CharSequence subtitle) {
118             // Subtitle will not be shown.
119         }
120 
121         @Override
setSubtitle(int resId)122         public void setSubtitle(int resId) {
123             // Subtitle will not be shown.
124         }
125 
126         @Override
isTitleOptional()127         public boolean isTitleOptional() {
128             // Not only is it optional, it will *never* be shown.
129             return true;
130         }
131 
132         @Override
setCustomView(View view)133         public void setCustomView(View view) {
134             // Custom view is not supported here.
135         }
136 
137         @Override
invalidate()138         public void invalidate() {
139             mMenu.stopDispatchingItemsChanged();
140             try {
141                 mCallback.onPrepareActionMode(this, mMenu);
142             } finally {
143                 mMenu.startDispatchingItemsChanged();
144             }
145         }
146 
dispatchOnCreate()147         public boolean dispatchOnCreate() {
148             mMenu.stopDispatchingItemsChanged();
149             try {
150                 return mCallback.onCreateActionMode(this, mMenu);
151             } finally {
152                 mMenu.startDispatchingItemsChanged();
153             }
154         }
155 
156         @Override
finish()157         public void finish() {
158             if (mActionMode != this) {
159                 // Not the active action mode - no-op
160                 return;
161             }
162 
163             mCallback.onDestroyActionMode(this);
164             mCallback = null;
165 
166             mExtractActionButton.setVisibility(VISIBLE);
167             mEditButton.setVisibility(INVISIBLE);
168 
169             sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
170 
171             mActionMode = null;
172         }
173 
174         @Override
getMenu()175         public Menu getMenu() {
176             return mMenu;
177         }
178 
179         @Override
getTitle()180         public CharSequence getTitle() {
181             return null;
182         }
183 
184         @Override
getSubtitle()185         public CharSequence getSubtitle() {
186             return null;
187         }
188 
189         @Override
getCustomView()190         public View getCustomView() {
191             return null;
192         }
193 
194         @Override
getMenuInflater()195         public MenuInflater getMenuInflater() {
196             return new MenuInflater(getContext());
197         }
198 
199         @Override
onMenuItemSelected(MenuBuilder menu, MenuItem item)200         public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
201             if (mCallback != null) {
202                 return mCallback.onActionItemClicked(this, item);
203             }
204             return false;
205         }
206 
207         @Override
onMenuModeChange(MenuBuilder menu)208         public void onMenuModeChange(MenuBuilder menu) {
209         }
210 
211     }
212 }
213