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 void setCustomView(View view) { 128 // Custom view is not supported here. 129 } 130 131 @Override 132 public void invalidate() { 133 mMenu.stopDispatchingItemsChanged(); 134 try { 135 mCallback.onPrepareActionMode(this, mMenu); 136 } finally { 137 mMenu.startDispatchingItemsChanged(); 138 } 139 } 140 141 public boolean dispatchOnCreate() { 142 mMenu.stopDispatchingItemsChanged(); 143 try { 144 return mCallback.onCreateActionMode(this, mMenu); 145 } finally { 146 mMenu.startDispatchingItemsChanged(); 147 } 148 } 149 150 @Override 151 public void finish() { 152 if (mActionMode != this) { 153 // Not the active action mode - no-op 154 return; 155 } 156 157 mCallback.onDestroyActionMode(this); 158 mCallback = null; 159 160 mExtractActionButton.setVisibility(VISIBLE); 161 mEditButton.setVisibility(INVISIBLE); 162 163 sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); 164 165 mActionMode = null; 166 } 167 168 @Override 169 public Menu getMenu() { 170 return mMenu; 171 } 172 173 @Override 174 public CharSequence getTitle() { 175 return null; 176 } 177 178 @Override 179 public CharSequence getSubtitle() { 180 return null; 181 } 182 183 @Override 184 public View getCustomView() { 185 return null; 186 } 187 188 @Override 189 public MenuInflater getMenuInflater() { 190 return new MenuInflater(getContext()); 191 } 192 193 @Override 194 public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) { 195 if (mCallback != null) { 196 return mCallback.onActionItemClicked(this, item); 197 } 198 return false; 199 } 200 201 @Override 202 public void onMenuModeChange(MenuBuilder menu) { 203 } 204 205 } 206 } 207