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 44 public ExtractEditLayout(Context context) { 45 super(context); 46 } 47 48 public ExtractEditLayout(Context context, AttributeSet attrs) { 49 super(context, attrs); 50 } 51 52 @Override 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 */ 69 public boolean isActionModeStarted() { 70 return mActionMode != null; 71 } 72 73 /** 74 * Finishes a possibly started action mode. 75 */ 76 public void finishActionMode() { 77 if (mActionMode != null) { 78 mActionMode.finish(); 79 } 80 } 81 82 @Override 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 100 public ExtractActionMode(Callback cb) { 101 mMenu = new MenuBuilder(getContext()); 102 mMenu.setCallback(this); 103 mCallback = cb; 104 } 105 106 @Override 107 public void setTitle(CharSequence title) { 108 // Title will not be shown. 109 } 110 111 @Override 112 public void setTitle(int resId) { 113 // Title will not be shown. 114 } 115 116 @Override 117 public void setSubtitle(CharSequence subtitle) { 118 // Subtitle will not be shown. 119 } 120 121 @Override 122 public void setSubtitle(int resId) { 123 // Subtitle will not be shown. 124 } 125 126 @Override 127 public boolean isTitleOptional() { 128 // Not only is it optional, it will *never* be shown. 129 return true; 130 } 131 132 @Override 133 public void setCustomView(View view) { 134 // Custom view is not supported here. 135 } 136 137 @Override 138 public void invalidate() { 139 mMenu.stopDispatchingItemsChanged(); 140 try { 141 mCallback.onPrepareActionMode(this, mMenu); 142 } finally { 143 mMenu.startDispatchingItemsChanged(); 144 } 145 } 146 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 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 175 public Menu getMenu() { 176 return mMenu; 177 } 178 179 @Override 180 public CharSequence getTitle() { 181 return null; 182 } 183 184 @Override 185 public CharSequence getSubtitle() { 186 return null; 187 } 188 189 @Override 190 public View getCustomView() { 191 return null; 192 } 193 194 @Override 195 public MenuInflater getMenuInflater() { 196 return new MenuInflater(getContext()); 197 } 198 199 @Override 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 208 public void onMenuModeChange(MenuBuilder menu) { 209 } 210 211 } 212 } 213