com.google.android.marvin.talkback.menurules.RuleUnlabeledImage.java Source code

Java tutorial

Introduction

Here is the source code for com.google.android.marvin.talkback.menurules.RuleUnlabeledImage.java

Source

/*
 * Copyright (C) 2013 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.google.android.marvin.talkback.menurules;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.text.TextUtils;
import android.util.Pair;
import android.view.MenuItem;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;

import com.google.android.marvin.talkback.R;
import com.google.android.marvin.talkback.TalkBackService;
import com.googlecode.eyesfree.labeling.CustomLabelManager;
import com.googlecode.eyesfree.labeling.Label;
import com.googlecode.eyesfree.labeling.LabelOperationUtils;
import com.googlecode.eyesfree.utils.AccessibilityNodeInfoUtils;
import com.googlecode.eyesfree.widget.RadialMenu;
import com.googlecode.eyesfree.widget.RadialMenuItem;

import java.util.LinkedList;
import java.util.List;

/**
 * Processes {@link ImageView} nodes without text.
 *
 * @author caseyburkhardt@google.com (Casey Burkhardt)
 */
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
class RuleUnlabeledImage implements NodeMenuRule {

    @Override
    public boolean accept(Context context, AccessibilityNodeInfoCompat node) {
        final AccessibilityNodeInfo unwrapped = (AccessibilityNodeInfo) node.getInfo();
        final boolean isImage = AccessibilityNodeInfoUtils.nodeMatchesClassByType(context, node,
                android.widget.ImageView.class);
        final boolean hasDescription = !TextUtils.isEmpty(AccessibilityNodeInfoUtils.getNodeText(node));
        final Pair<String, String> parsedId = CustomLabelManager
                .splitResourceName(unwrapped.getViewIdResourceName());
        final boolean hasParseableId = (parsedId != null);

        // TODO(caseyburkhardt): There are a number of views that have a
        // different resource namespace than their parent application. It's
        // likely we'll need to refine the database structure to accommodate
        // these while also allowing the user to modify them through TalkBack
        // settings. For now, we'll simply not allow labeling of such views.
        boolean isFromKnownApp = false;
        if (hasParseableId) {
            try {
                context.getPackageManager().getPackageInfo(parsedId.first, 0);
                isFromKnownApp = true;
            } catch (NameNotFoundException e) {
                // Do nothing.
            }
        }

        return (isImage && !hasDescription && hasParseableId && isFromKnownApp);
    }

    @Override
    public List<RadialMenuItem> getMenuItemsForNode(TalkBackService service, AccessibilityNodeInfoCompat node) {
        final AccessibilityNodeInfoCompat nodeCopy = AccessibilityNodeInfoCompat.obtain(node);
        // TODO(caseyburkhardt): Undo when the support library is fixed.
        final AccessibilityNodeInfo unwrappedCopy = (AccessibilityNodeInfo) nodeCopy.getInfo();
        final CustomLabelManager labelManager = service.getLabelManager();
        final List<RadialMenuItem> items = new LinkedList<RadialMenuItem>();

        final Label viewLabel = labelManager.getLabelForViewIdFromCache(unwrappedCopy.getViewIdResourceName());
        if (viewLabel == null) {
            final RadialMenuItem addLabel = new RadialMenuItem(service, RadialMenu.NONE,
                    R.id.labeling_breakout_add_label, RadialMenu.NONE,
                    service.getString(R.string.label_dialog_title_add));
            items.add(addLabel);
        } else {
            final RadialMenuItem editLabel = new RadialMenuItem(service, RadialMenu.NONE,
                    R.id.labeling_breakout_edit_label, RadialMenu.NONE,
                    service.getString(R.string.label_dialog_title_edit));
            final RadialMenuItem removeLabel = new RadialMenuItem(service, RadialMenu.NONE,
                    R.id.labeling_breakout_remove_label, RadialMenu.NONE,
                    service.getString(R.string.label_dialog_title_remove));
            items.add(editLabel);
            items.add(removeLabel);
        }

        for (MenuItem item : items) {
            item.setOnMenuItemClickListener(
                    new UnlabeledImageMenuItemClickListener(service, unwrappedCopy, viewLabel));
        }

        return items;
    }

    @Override
    public CharSequence getUserFriendlyMenuName(Context context) {
        return context.getString(R.string.title_labeling_controls);
    }

    @Override
    public boolean canCollapseMenu() {
        return true;
    }

    private static class UnlabeledImageMenuItemClickListener implements MenuItem.OnMenuItemClickListener {
        private final Context mContext;
        private final AccessibilityNodeInfo mNode;
        private final Label mExistingLabel;

        public UnlabeledImageMenuItemClickListener(TalkBackService service, AccessibilityNodeInfo node,
                Label label) {
            mContext = service;
            mNode = node;
            mExistingLabel = label;
        }

        @Override
        public boolean onMenuItemClick(MenuItem item) {
            if (item == null) {
                mNode.recycle();
                return true;
            }

            final int itemId = item.getItemId();

            if (itemId == R.id.labeling_breakout_add_label) {
                return LabelOperationUtils.startActivityAddLabelForNode(mContext, mNode);
            } else if (itemId == R.id.labeling_breakout_edit_label) {
                return LabelOperationUtils.startActivityEditLabel(mContext, mExistingLabel);
            } else if (itemId == R.id.labeling_breakout_remove_label) {
                return LabelOperationUtils.startActivityRemoveLabel(mContext, mExistingLabel);
            }

            mNode.recycle();
            return true;
        }
    }
}