/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.talkback.contextmenu;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.view.ActionProvider;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
public abstract class ContextMenuItem implements MenuItem {
private Context mContext;
private int mItemId;
private int mGroupId;
private char mAlphaShortcut;
private char mNumericShortcut;
private Drawable mIcon;
private int mOrder;
private Intent mIntent;
private boolean mEnabled = true;
private CharSequence mTitle;
private CharSequence mTitleCondensed;
private boolean mVisible = true;
private boolean mCheckable = false;
private boolean mChecked = false;
private OnMenuItemClickListener mListener;
private ContextMenuInfo mMenuInfo;
// Used for EditText cursor control.
// When the user performs cursor control(Move cursor to end, etc, from Local Context Menu)
// in an EditText, the accessibility focus will be saved (when navigating in the context menu)
// and reset back(when the context menu dismisses). A TYPE_ACCESSIBILITY_VIEW_FOCUS and a
// TYPE_WINDOWS_CHANGED event will be fired. To avoid EditText description re-read after
// the cursor control, we need to skip these two events.
private boolean mSkipRefocusEvents = false;
protected ContextMenuItem(Context context, int groupId, int itemId, int order,
CharSequence title) {
mItemId = itemId;
mGroupId = groupId;
mContext = context;
mOrder = order;
mTitle = title;
mMenuInfo = new ContextMenuInfo();
}
@Override
public char getAlphabeticShortcut() {
return mAlphaShortcut;
}
@Override
public char getNumericShortcut() {
return mNumericShortcut;
}
@Override
public ContextMenuItem setAlphabeticShortcut(char alphaChar) {
mAlphaShortcut = alphaChar;
return this;
}
@Override
public ContextMenuItem setNumericShortcut(char numericChar) {
mNumericShortcut = numericChar;
return this;
}
@Override
public ContextMenuItem setShortcut(char numericChar, char alphaChar) {
mNumericShortcut = numericChar;
mAlphaShortcut = alphaChar;
return this;
}
@Override
public int getGroupId() {
return mGroupId;
}
@Override
public Drawable getIcon() {
return mIcon;
}
@Override
public MenuItem setIcon(Drawable icon) {
mIcon = icon;
return this;
}
@Override
public MenuItem setIcon(int iconRes) {
if (iconRes == 0) {
mIcon = null;
} else {
mIcon = mContext.getResources().getDrawable(iconRes);
}
return this;
}
@Override
public int getOrder() {
return mOrder;
}
@Override
public Intent getIntent() {
return mIntent;
}
@Override
public MenuItem setIntent(Intent intent) {
mIntent = intent;
return this;
}
@Override
public boolean isEnabled() {
return mEnabled;
}
@Override
public MenuItem setEnabled(boolean enabled) {
mEnabled = enabled;
return this;
}
@Override
public CharSequence getTitle() {
return mTitle;
}
@Override
public MenuItem setTitle(CharSequence title) {
mTitle = title;
return this;
}
@Override
public CharSequence getTitleCondensed() {
return mTitleCondensed;
}
@Override
public MenuItem setTitleCondensed(CharSequence titleCondensed) {
mTitleCondensed = titleCondensed;
return this;
}
@Override
public MenuItem setTitle(int titleRes) {
mTitle = mContext.getText(titleRes);
return this;
}
@Override
public int getItemId() {
return mItemId;
}
@Override
public boolean isCheckable() {
return mCheckable;
}
@Override
public boolean isChecked() {
return mCheckable && mChecked;
}
@Override
public boolean isVisible() {
return mVisible;
}
@Override
public MenuItem setCheckable(boolean checkable) {
mCheckable = checkable;
return this;
}
@Override
public MenuItem setChecked(boolean checked) {
mChecked = checked;
return this;
}
@Override
public MenuItem setVisible(boolean visible) {
mVisible = visible;
return this;
}
@Override
public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) {
mListener = menuItemClickListener;
return this;
}
@Override
public boolean collapseActionView() {
return false;
}
@Override
public boolean expandActionView() {
return false;
}
@TargetApi(14)
@Override
public ActionProvider getActionProvider() {
return null;
}
@Override
public View getActionView() {
return null;
}
@Override
public boolean isActionViewExpanded() {
return false;
}
@TargetApi(14)
@Override
public MenuItem setActionProvider(ActionProvider actionProvider) {
throw new UnsupportedOperationException();
}
@Override
public MenuItem setActionView(View view) {
throw new UnsupportedOperationException();
}
@Override
public MenuItem setActionView(int resId) {
throw new UnsupportedOperationException();
}
@Override
public MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
throw new UnsupportedOperationException();
}
@Override
public void setShowAsAction(int actionEnum) {
throw new UnsupportedOperationException();
}
@Override
public MenuItem setShowAsActionFlags(int actionEnum) {
throw new UnsupportedOperationException();
}
@Override
public ContextMenu.ContextMenuInfo getMenuInfo() {
return mMenuInfo;
}
//TODO internal sdk has no setIconTintList abstract method but public sdk does.
// Check it after M release
public MenuItem setIconTintList(ColorStateList tint) {
return this;
}
//TODO internal sdk has no setIconTintMode abstract method but public sdk does.
// Check it after M release
public MenuItem setIconTintMode(PorterDuff.Mode tintMode) {
return this;
}
public void setSkipRefocusEvents(boolean skip) {
mSkipRefocusEvents = skip;
}
public boolean getSkipRefocusEvents() {
return mSkipRefocusEvents;
}
/**
* Attempts to perform this item's click action.
*
* @return {@code true} if this item performs an action
*/
public boolean onClickPerformed() {
if (mCheckable) {
mChecked = !mChecked;
}
return mListener != null && mListener.onMenuItemClick(this);
}
/**
* This class doesn't actually do anything.
*/
private static class ContextMenuInfo implements ContextMenu.ContextMenuInfo {
// Empty class.
}
}