Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4329ad3b authored by Alan Viverette's avatar Alan Viverette Committed by android-build-merger
Browse files

Merge "Add support for Explore by Touch to RadialTimePickerView" into lmp-mr1-dev

automerge: 1ac52667

* commit '1ac52667':
  Add support for Explore by Touch to RadialTimePickerView
parents fb7c62c1 1ac52667
Loading
Loading
Loading
Loading
+162 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 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 android.util;

import com.android.internal.util.ArrayUtils;

import libcore.util.EmptyArray;

/**
 * Implements a growing array of int primitives.
 *
 * @hide
 */
public class IntArray implements Cloneable {
    private static final int MIN_CAPACITY_INCREMENT = 12;

    private int[] mValues;
    private int mSize;

    /**
     * Creates an empty IntArray with the default initial capacity.
     */
    public IntArray() {
        this(10);
    }

    /**
     * Creates an empty IntArray with the specified initial capacity.
     */
    public IntArray(int initialCapacity) {
        if (initialCapacity == 0) {
            mValues = EmptyArray.INT;
        } else {
            mValues = ArrayUtils.newUnpaddedIntArray(initialCapacity);
        }
        mSize = 0;
    }

    /**
     * Appends the specified value to the end of this array.
     */
    public void add(int value) {
        add(mSize, value);
    }

    /**
     * Inserts a value at the specified position in this array.
     *
     * @throws IndexOutOfBoundsException when index < 0 || index > size()
     */
    public void add(int index, int value) {
        if (index < 0 || index > mSize) {
            throw new IndexOutOfBoundsException();
        }

        ensureCapacity(1);

        if (mSize - index != 0) {
            System.arraycopy(mValues, index, mValues, index + 1, mSize - index);
        }

        mValues[index] = value;
        mSize++;
    }

    /**
     * Adds the values in the specified array to this array.
     */
    public void addAll(IntArray values) {
        final int count = values.mSize;
        ensureCapacity(count);

        System.arraycopy(values.mValues, 0, mValues, mSize, count);
        mSize += count;
    }

    /**
     * Ensures capacity to append at least <code>count</code> values.
     */
    private void ensureCapacity(int count) {
        final int currentSize = mSize;
        final int minCapacity = currentSize + count;
        if (minCapacity >= mValues.length) {
            final int targetCap = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2) ?
                    MIN_CAPACITY_INCREMENT : currentSize >> 1);
            final int newCapacity = targetCap > minCapacity ? targetCap : minCapacity;
            final int[] newValues = ArrayUtils.newUnpaddedIntArray(newCapacity);
            System.arraycopy(mValues, 0, newValues, 0, currentSize);
            mValues = newValues;
        }
    }

    /**
     * Removes all values from this array.
     */
    public void clear() {
        mSize = 0;
    }

    @Override
    public IntArray clone() throws CloneNotSupportedException {
        final IntArray clone = (IntArray) super.clone();
        clone.mValues = mValues.clone();
        return clone;
    }

    /**
     * Returns the value at the specified position in this array.
     */
    public int get(int index) {
        if (index >= mSize) {
            throw new ArrayIndexOutOfBoundsException(mSize, index);
        }
        return mValues[index];
    }

    /**
     * Returns the index of the first occurrence of the specified value in this
     * array, or -1 if this array does not contain the value.
     */
    public int indexOf(int value) {
        final int n = mSize;
        for (int i = 0; i < n; i++) {
            if (mValues[i] == value) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Removes the value at the specified index from this array.
     */
    public void remove(int index) {
        if (index >= mSize) {
            throw new ArrayIndexOutOfBoundsException(mSize, index);
        }
        System.arraycopy(mValues, index + 1, mValues, index, mSize - index - 1);
        mSize--;
    }

    /**
     * Returns the number of values in this array.
     */
    public int size() {
        return mSize;
    }
}
+396 −142

File changed.

Preview size limit exceeded, changes collapsed.

+2 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.IntArray;
import android.util.MathUtils;
import android.view.MotionEvent;
import android.view.View;
@@ -610,7 +611,7 @@ class SimpleMonthView extends View {
        }

        @Override
        protected void getVisibleVirtualViews(List<Integer> virtualViewIds) {
        protected void getVisibleVirtualViews(IntArray virtualViewIds) {
            for (int day = 1; day <= mNumCells; day++) {
                virtualViewIds.add(day);
            }
+5 −15
Original line number Diff line number Diff line
@@ -611,15 +611,12 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
            if (mAllowAutoAdvance && autoAdvance) {
                updateHeaderHour(newValue, false);
                setCurrentItemShowing(MINUTE_INDEX, true, false);
                mRadialTimePickerView.announceForAccessibility(newValue + ". " + mSelectMinutes);
                mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes);
            } else {
                updateHeaderHour(newValue, true);
                mRadialTimePickerView.setContentDescription(
                        mHourPickerDescription + ": " + newValue);
            }
        } else if (pickerIndex == MINUTE_INDEX){
            updateHeaderMinute(newValue, true);
            mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + newValue);
        } else if (pickerIndex == AMPM_INDEX) {
            updateAmPmLabelStates(newValue);
        } else if (pickerIndex == ENABLE_PICKER_INDEX) {
@@ -744,19 +741,12 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
        mRadialTimePickerView.setCurrentItemShowing(index, animateCircle);

        if (index == HOUR_INDEX) {
            int hours = mRadialTimePickerView.getCurrentHour();
            if (!mIs24HourView) {
                hours = hours % 12;
            }
            mRadialTimePickerView.setContentDescription(mHourPickerDescription + ": " + hours);
            if (announce) {
                mRadialTimePickerView.announceForAccessibility(mSelectHours);
                mDelegator.announceForAccessibility(mSelectHours);
            }
        } else {
            int minutes = mRadialTimePickerView.getCurrentMinute();
            mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + minutes);
            if (announce) {
                mRadialTimePickerView.announceForAccessibility(mSelectMinutes);
                mDelegator.announceForAccessibility(mSelectMinutes);
            }
        }

@@ -789,7 +779,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
                    } else {
                        deletedKeyStr = String.format("%d", getValFromKeyCode(deleted));
                    }
                    mRadialTimePickerView.announceForAccessibility(
                    mDelegator.announceForAccessibility(
                            String.format(mDeletedKeyFormat, deletedKeyStr));
                    updateDisplay(true);
                }
@@ -851,7 +841,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl
        }

        int val = getValFromKeyCode(keyCode);
        mRadialTimePickerView.announceForAccessibility(String.format("%d", val));
        mDelegator.announceForAccessibility(String.format("%d", val));
        // Automatically fill in 0's if AM or PM was legally entered.
        if (isTypedTimeFullyLegal()) {
            if (!mIs24HourView && mTypedTimes.size() <= 3) {
+55 −30
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.internal.widget;
import android.content.Context;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.IntArray;
import android.view.accessibility.*;
import android.view.MotionEvent;
import android.view.View;
@@ -26,11 +27,9 @@ import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.view.accessibility.AccessibilityNodeProvider;

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

/**
 * ExploreByTouchHelper is a utility class for implementing accessibility
 * support in custom {@link android.view.View}s that represent a collection of View-like
@@ -58,14 +57,16 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
    private static final Rect INVALID_PARENT_BOUNDS = new Rect(
            Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);

    // Temporary, reusable data structures.
    private final Rect mTempScreenRect = new Rect();
    private final Rect mTempParentRect = new Rect();
    private final Rect mTempVisibleRect = new Rect();
    private final int[] mTempGlobalRect = new int[2];
    // Lazily-created temporary data structures used when creating nodes.
    private Rect mTempScreenRect;
    private Rect mTempParentRect;
    private int[] mTempGlobalRect;

    /** Lazily-created temporary data structure used to compute visibility. */
    private Rect mTempVisibleRect;

    /** View's context **/
    private Context mContext;
    /** Lazily-created temporary data structure used to obtain child IDs. */
    private IntArray mTempArray;

    /** System accessibility manager, used to check state and send events. */
    private final AccessibilityManager mManager;
@@ -73,6 +74,9 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
    /** View whose internal structure is exposed through this helper. */
    private final View mView;

    /** Context of the host view. **/
    private final Context mContext;

    /** Node provider that handles creating nodes and performing actions. */
    private ExploreByTouchNodeProvider mNodeProvider;

@@ -332,11 +336,17 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
        onInitializeAccessibilityNodeInfo(mView, node);

        // Add the virtual descendants.
        final LinkedList<Integer> virtualViewIds = new LinkedList<Integer>();
        if (mTempArray == null) {
            mTempArray = new IntArray();
        } else {
            mTempArray.clear();
        }
        final IntArray virtualViewIds = mTempArray;
        getVisibleVirtualViews(virtualViewIds);

        for (Integer childVirtualViewId : virtualViewIds) {
            node.addChild(mView, childVirtualViewId);
        final int N = virtualViewIds.size();
        for (int i = 0; i < N; i++) {
            node.addChild(mView, virtualViewIds.get(i));
        }

        return node;
@@ -371,6 +381,11 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
     * @return An {@link AccessibilityNodeInfo} for the specified item.
     */
    private AccessibilityNodeInfo createNodeForChild(int virtualViewId) {
        ensureTempRects();
        final Rect tempParentRect = mTempParentRect;
        final int[] tempGlobalRect = mTempGlobalRect;
        final Rect tempScreenRect = mTempScreenRect;

        final AccessibilityNodeInfo node = AccessibilityNodeInfo.obtain();

        // Ensure the client has good defaults.
@@ -387,8 +402,8 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
                    + "populateNodeForVirtualViewId()");
        }

        node.getBoundsInParent(mTempParentRect);
        if (mTempParentRect.equals(INVALID_PARENT_BOUNDS)) {
        node.getBoundsInParent(tempParentRect);
        if (tempParentRect.equals(INVALID_PARENT_BOUNDS)) {
            throw new RuntimeException("Callbacks must set parent bounds in "
                    + "populateNodeForVirtualViewId()");
        }
@@ -411,29 +426,35 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
        // Manage internal accessibility focus state.
        if (mFocusedVirtualViewId == virtualViewId) {
            node.setAccessibilityFocused(true);
            node.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
            node.addAction(AccessibilityAction.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
        } else {
            node.setAccessibilityFocused(false);
            node.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
            node.addAction(AccessibilityAction.ACTION_ACCESSIBILITY_FOCUS);
        }

        // Set the visibility based on the parent bound.
        if (intersectVisibleToUser(mTempParentRect)) {
        if (intersectVisibleToUser(tempParentRect)) {
            node.setVisibleToUser(true);
            node.setBoundsInParent(mTempParentRect);
            node.setBoundsInParent(tempParentRect);
        }

        // Calculate screen-relative bound.
        mView.getLocationOnScreen(mTempGlobalRect);
        final int offsetX = mTempGlobalRect[0];
        final int offsetY = mTempGlobalRect[1];
        mTempScreenRect.set(mTempParentRect);
        mTempScreenRect.offset(offsetX, offsetY);
        node.setBoundsInScreen(mTempScreenRect);
        mView.getLocationOnScreen(tempGlobalRect);
        final int offsetX = tempGlobalRect[0];
        final int offsetY = tempGlobalRect[1];
        tempScreenRect.set(tempParentRect);
        tempScreenRect.offset(offsetX, offsetY);
        node.setBoundsInScreen(tempScreenRect);

        return node;
    }

    private void ensureTempRects() {
        mTempGlobalRect = new int[2];
        mTempParentRect = new Rect();
        mTempScreenRect = new Rect();
    }

    private boolean performAction(int virtualViewId, int action, Bundle arguments) {
        switch (virtualViewId) {
            case View.NO_ID:
@@ -451,13 +472,13 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
        switch (action) {
            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
                return manageFocusForChild(virtualViewId, action, arguments);
                return manageFocusForChild(virtualViewId, action);
            default:
                return onPerformActionForVirtualView(virtualViewId, action, arguments);
        }
    }

    private boolean manageFocusForChild(int virtualViewId, int action, Bundle arguments) {
    private boolean manageFocusForChild(int virtualViewId, int action) {
        switch (action) {
            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS:
                return requestAccessibilityFocus(virtualViewId);
@@ -503,12 +524,16 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
        }

        // If no portion of the parent is visible, this view is not visible.
        if (!mView.getLocalVisibleRect(mTempVisibleRect)) {
        if (mTempVisibleRect == null) {
            mTempVisibleRect = new Rect();
        }
        final Rect tempVisibleRect = mTempVisibleRect;
        if (!mView.getLocalVisibleRect(tempVisibleRect)) {
            return false;
        }

        // Check if the view intersects the visible portion of the parent.
        return localRect.intersect(mTempVisibleRect);
        return localRect.intersect(tempVisibleRect);
    }

    /**
@@ -588,7 +613,7 @@ public abstract class ExploreByTouchHelper extends View.AccessibilityDelegate {
     *
     * @param virtualViewIds The list to populate with visible items
     */
    protected abstract void getVisibleVirtualViews(List<Integer> virtualViewIds);
    protected abstract void getVisibleVirtualViews(IntArray virtualViewIds);

    /**
     * Populates an {@link AccessibilityEvent} with information about the
Loading