/*
* Copyright (C) 2014 Google Inc.
*
* 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.menurules;
import android.view.Menu;
import com.android.talkback.R;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat;
import android.text.TextUtils;
import android.view.MenuItem;
import com.google.android.marvin.talkback.TalkBackService;
import com.android.talkback.contextmenu.ContextMenuItem;
import com.android.talkback.contextmenu.ContextMenuItemBuilder;
import com.android.utils.AccessibilityNodeInfoUtils;
import com.android.utils.PerformActionUtils;
import java.util.LinkedList;
import java.util.List;
/**
* Adds custom actions to the local context menu.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class RuleCustomAction implements NodeMenuRule {
public static final int MIN_API_LEVEL = Build.VERSION_CODES.LOLLIPOP;
@Override
public boolean accept(TalkBackService service, AccessibilityNodeInfoCompat node) {
List<AccessibilityActionCompat> actions = node.getActionList();
return actions != null && !actions.isEmpty();
}
@Override
public List<ContextMenuItem> getMenuItemsForNode(TalkBackService service,
ContextMenuItemBuilder menuItemBuilder, AccessibilityNodeInfoCompat node) {
List<ContextMenuItem> menu = new LinkedList<>();
recursivelyPopulateMenuItemsForNode(service, menuItemBuilder, node, menu);
return menu;
}
/**
* Populates a menu with the context menu items for a node, searching up its ancestor
* hierarchy if the current node has no custom actions.
*/
private void recursivelyPopulateMenuItemsForNode(TalkBackService service,
ContextMenuItemBuilder menuItemBuilder, AccessibilityNodeInfoCompat node,
List<ContextMenuItem> menu) {
if (node == null) {
return;
}
for (AccessibilityActionCompat action : AccessibilityNodeInfoUtils.getCustomActions(node)) {
CharSequence label = action.getLabel();
int id = action.getId();
if (TextUtils.isEmpty(label)) {
continue;
}
ContextMenuItem item = menuItemBuilder.createMenuItem(service, Menu.NONE, id, Menu.NONE,
label);
item.setOnMenuItemClickListener(new CustomMenuItem(id,
AccessibilityNodeInfoCompat.obtain(node)));
item.setCheckable(false);
menu.add(item);
}
if (menu.isEmpty()) {
recursivelyPopulateMenuItemsForNode(service, menuItemBuilder, node.getParent(), menu);
}
}
@Override
public boolean canCollapseMenu() {
return true;
}
@Override
public CharSequence getUserFriendlyMenuName(Context context) {
return context.getString(R.string.title_custom_action);
}
private static class CustomMenuItem implements MenuItem.OnMenuItemClickListener {
final int mId;
final AccessibilityNodeInfoCompat mNode;
CustomMenuItem(int id, AccessibilityNodeInfoCompat node) {
mId = id;
mNode = node;
}
@Override
public boolean onMenuItemClick(MenuItem item) {
boolean ret = PerformActionUtils.performAction(mNode, mId);
mNode.recycle();
return ret;
}
}
}