/* * Copyright (C) 2011 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.speechrules; import android.content.Context; import android.os.Build; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.view.accessibility.AccessibilityEvent; import com.android.talkback.R; import com.android.utils.Role; import com.google.android.marvin.talkback.TalkBackService; import com.android.utils.AccessibilityNodeInfoUtils; import com.android.utils.StringBuilderUtils; import com.android.utils.labeling.CustomLabelManager; import com.android.utils.labeling.Label; /** * Processes image widgets. */ public class RuleNonTextViews extends RuleDefault { /** * Lazily initialized manager for handling custom label substitutions in the * rule processor */ private CustomLabelManager mLabelManager = null; @Override public boolean accept(AccessibilityNodeInfoCompat node, AccessibilityEvent event) { initLabelManagerIfNeeded(); int role = Role.getRole(node); return role == Role.ROLE_IMAGE || role == Role.ROLE_IMAGE_BUTTON; } @Override public CharSequence format(Context context, AccessibilityNodeInfoCompat node, AccessibilityEvent event) { final CharSequence text = AccessibilityNodeInfoUtils.getNodeText(node); CharSequence labelText = null; if (!TextUtils.isEmpty(text)) { labelText = text; } else { if (mLabelManager != null) { // Check to see if a custom label exists for the unlabeled control. Label label = mLabelManager.getLabelForViewIdFromCache( node.getViewIdResourceName()); if (label != null) { labelText = label.getText(); } } } // If the node's role is ROLE_IMAGE and the node is selectable, there's a non-trivial chance // that the node acts like a button (but we can't be sure). In this case, it is safest to // not append any role text to avoid confusing the user. CharSequence roleText; if (Role.getRole(node) == Role.ROLE_IMAGE && AccessibilityNodeInfoUtils.supportsAction( node, AccessibilityNodeInfoCompat.ACTION_SELECT)) { roleText = node.getRoleDescription(); // But don't fall back to default text. } else { roleText = Role.getRoleDescriptionOrDefault(context, node); } CharSequence unlabelledState; if (labelText == null) { unlabelledState = context.getString(R.string.value_unlabelled); } else { unlabelledState = null; } SpannableStringBuilder output = new SpannableStringBuilder(); StringBuilderUtils.append(output, labelText, roleText); StringBuilderUtils.append(output, unlabelledState); return output; } /** * Retrieves a handle to the correct {@link CustomLabelManager} if the rule * requires it. */ private void initLabelManagerIfNeeded() { if (Build.VERSION.SDK_INT >= CustomLabelManager.MIN_API_LEVEL) { final TalkBackService service = TalkBackService.getInstance(); if (service != null) { mLabelManager = service.getLabelManager(); } } } }