15ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell/*
25ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * Copyright (C) 2011 The Android Open Source Project
35ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell *
45ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * Licensed under the Apache License, Version 2.0 (the "License");
55ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * you may not use this file except in compliance with the License.
65ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * You may obtain a copy of the License at
75ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell *
85ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell *      http://www.apache.org/licenses/LICENSE-2.0
95ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell *
105ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * Unless required by applicable law or agreed to in writing, software
115ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * distributed under the License is distributed on an "AS IS" BASIS,
125ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * See the License for the specific language governing permissions and
145ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * limitations under the License.
155ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell */
165ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
175ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellpackage android.inputmethodservice;
185ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1986ed436b83d6b71ff00d1c3db910f2952018489eAdam Powellimport com.android.internal.view.menu.MenuBuilder;
2086ed436b83d6b71ff00d1c3db910f2952018489eAdam Powellimport com.android.internal.view.menu.MenuPopupHelper;
2186ed436b83d6b71ff00d1c3db910f2952018489eAdam Powell
225ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.content.Context;
235ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.util.AttributeSet;
245ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.view.ActionMode;
255ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.view.Menu;
265ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.view.MenuInflater;
275ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.view.MenuItem;
285ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.view.View;
2986ed436b83d6b71ff00d1c3db910f2952018489eAdam Powellimport android.view.accessibility.AccessibilityEvent;
305ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.widget.Button;
315ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellimport android.widget.LinearLayout;
325ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
335ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell/**
345ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * ExtractEditLayout provides an ActionMode presentation for the
355ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * limited screen real estate in extract mode.
365ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell *
375ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell * @hide
385ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell */
395ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powellpublic class ExtractEditLayout extends LinearLayout {
405ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    ExtractActionMode mActionMode;
415ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    Button mExtractActionButton;
425ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    Button mEditButton;
435ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
445ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    public ExtractEditLayout(Context context) {
455ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        super(context);
465ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    }
475ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
485ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    public ExtractEditLayout(Context context, AttributeSet attrs) {
495ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        super(context, attrs);
505ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    }
515ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
525ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    @Override
535ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    public ActionMode startActionModeForChild(View sourceView, ActionMode.Callback cb) {
545ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        final ExtractActionMode mode = new ExtractActionMode(cb);
555ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        if (mode.dispatchOnCreate()) {
565ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mode.invalidate();
575ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mExtractActionButton.setVisibility(INVISIBLE);
585ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mEditButton.setVisibility(VISIBLE);
595ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mActionMode = mode;
6086ed436b83d6b71ff00d1c3db910f2952018489eAdam Powell            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
615ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            return mode;
625ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
635ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        return null;
645ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    }
655ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
6634703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne    /**
6734703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne     * @return true if an action mode is currently active.
6834703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne     */
6934703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne    public boolean isActionModeStarted() {
7034703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        return mActionMode != null;
7134703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne    }
7234703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne
7334703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne    /**
7434703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne     * Finishes a possibly started action mode.
7534703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne     */
7634703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne    public void finishActionMode() {
7734703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        if (mActionMode != null) {
7834703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne            mActionMode.finish();
7934703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne        }
8034703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne    }
8134703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne
825ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    @Override
835ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    public void onFinishInflate() {
845ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        super.onFinishInflate();
855ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        mExtractActionButton = (Button) findViewById(com.android.internal.R.id.inputExtractAction);
865ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        mEditButton = (Button) findViewById(com.android.internal.R.id.inputExtractEditButton);
875ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        mEditButton.setOnClickListener(new OnClickListener() {
885ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            public void onClick(View clicked) {
895ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                if (mActionMode != null) {
905ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                    new MenuPopupHelper(getContext(), mActionMode.mMenu, clicked).show();
915ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                }
925ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            }
935ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        });
945ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    }
955ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
965ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    private class ExtractActionMode extends ActionMode implements MenuBuilder.Callback {
975ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        private ActionMode.Callback mCallback;
985ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        MenuBuilder mMenu;
995ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1005ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public ExtractActionMode(Callback cb) {
1015ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mMenu = new MenuBuilder(getContext());
1025ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mMenu.setCallback(this);
1035ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mCallback = cb;
1045ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1055ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1065ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1075ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public void setTitle(CharSequence title) {
1085ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            // Title will not be shown.
1095ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1105ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1115ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1125ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public void setTitle(int resId) {
11334703b6d304c2bc6f4a39583931c7582d0455b0cGilles Debunne            // Title will not be shown.
1145ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1155ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1165ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1175ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public void setSubtitle(CharSequence subtitle) {
1185ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            // Subtitle will not be shown.
1195ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1205ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1215ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1225ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public void setSubtitle(int resId) {
1235ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            // Subtitle will not be shown.
1245ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1255ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1265ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
127b98a81f86ab87f1d718f329f03256111fdabd8d1Adam Powell        public boolean isTitleOptional() {
128b98a81f86ab87f1d718f329f03256111fdabd8d1Adam Powell            // Not only is it optional, it will *never* be shown.
129b98a81f86ab87f1d718f329f03256111fdabd8d1Adam Powell            return true;
130b98a81f86ab87f1d718f329f03256111fdabd8d1Adam Powell        }
131b98a81f86ab87f1d718f329f03256111fdabd8d1Adam Powell
132b98a81f86ab87f1d718f329f03256111fdabd8d1Adam Powell        @Override
1335ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public void setCustomView(View view) {
1345ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            // Custom view is not supported here.
1355ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1365ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1375ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1385ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public void invalidate() {
1395ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mMenu.stopDispatchingItemsChanged();
1405ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            try {
1415ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                mCallback.onPrepareActionMode(this, mMenu);
1425ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            } finally {
1435ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                mMenu.startDispatchingItemsChanged();
1445ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            }
1455ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1465ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1475ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public boolean dispatchOnCreate() {
1485ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mMenu.stopDispatchingItemsChanged();
1495ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            try {
1505ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                return mCallback.onCreateActionMode(this, mMenu);
1515ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            } finally {
1525ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                mMenu.startDispatchingItemsChanged();
1535ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            }
1545ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1555ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1565ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1575ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public void finish() {
1585ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            if (mActionMode != this) {
1595ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                // Not the active action mode - no-op
1605ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell                return;
1615ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            }
1625ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1635ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mCallback.onDestroyActionMode(this);
1645ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mCallback = null;
1655ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1665ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mExtractActionButton.setVisibility(VISIBLE);
1675ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mEditButton.setVisibility(INVISIBLE);
1685ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
16986ed436b83d6b71ff00d1c3db910f2952018489eAdam Powell            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
17086ed436b83d6b71ff00d1c3db910f2952018489eAdam Powell
1715ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            mActionMode = null;
1725ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1735ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1745ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1755ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public Menu getMenu() {
1765ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            return mMenu;
1775ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1785ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1795ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1805ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public CharSequence getTitle() {
1815ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            return null;
1825ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1835ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1845ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1855ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public CharSequence getSubtitle() {
1865ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            return null;
1875ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1885ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1895ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1905ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public View getCustomView() {
1915ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            return null;
1925ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1935ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1945ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
1955ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public MenuInflater getMenuInflater() {
1965ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell            return new MenuInflater(getContext());
1975ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
1985ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
1995ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
2005ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public boolean onMenuItemSelected(MenuBuilder menu, MenuItem item) {
201d06caed8d6a53294fe5a0fa2c7e9e394d541ed64Adam Powell            if (mCallback != null) {
202d06caed8d6a53294fe5a0fa2c7e9e394d541ed64Adam Powell                return mCallback.onActionItemClicked(this, item);
203d06caed8d6a53294fe5a0fa2c7e9e394d541ed64Adam Powell            }
204d06caed8d6a53294fe5a0fa2c7e9e394d541ed64Adam Powell            return false;
2055ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
2065ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
2075ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        @Override
2085ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        public void onMenuModeChange(MenuBuilder menu) {
2095ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell        }
2105ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell
2115ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell    }
2125ee36c48be8d36c5f4025202e8ede561c9ad3abaAdam Powell}
213