am 3a04f3cb: am 7e115924: am 930f4fe4: Merge "Accessibilty support for the print UI." into lmp-dev

* commit '3a04f3cbdf624eda7d4f8a91004c874022523cdd':
  Accessibilty support for the print UI.
diff --git a/packages/PrintSpooler/res/layout/preview_page.xml b/packages/PrintSpooler/res/layout/preview_page.xml
index df9848b..edce289 100644
--- a/packages/PrintSpooler/res/layout/preview_page.xml
+++ b/packages/PrintSpooler/res/layout/preview_page.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.printspooler.widget.PreviewPageFrame xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/preview_page"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
@@ -33,7 +33,8 @@
         android:layout_width="fill_parent"
         android:layout_height="@dimen/preview_page_footer_height"
         android:background="@color/material_grey_500"
-        android:orientation="horizontal">
+        android:orientation="horizontal"
+        android:duplicateParentState="true">
 
         <TextView
             android:id="@+id/page_number"
@@ -51,9 +52,10 @@
             android:layout_marginRight="8dip"
             android:layout_alignParentEnd="true"
             android:layout_centerVertical="true"
-            android:background="@drawable/page_selector_background">
+            android:background="@drawable/page_selector_background"
+            android:duplicateParentState="true">
         </ImageView>
 
     </RelativeLayout>
 
-</LinearLayout>
+</com.android.printspooler.widget.PreviewPageFrame>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 27e1d51..ab633ea 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -76,10 +76,36 @@
     <!-- Title for the print dialog announced to the user for accessibility. Not shown in the UI. [CHAR LIMIT=none] -->
     <string name="print_dialog">Print dialog</string>
 
-    <!-- Template for the message that shows the current page out of the total number of pages -->
+    <!-- Template for the message that shows the current page out of the total number of pages [CHAR LIMIT=none] -->
     <string name="current_page_template"><xliff:g id="current_page">%1$d</xliff:g>
         /<xliff:g id="page_count">%2$d</xliff:g></string>
 
+    <!-- Description of the current page - spoken to the user [CHAR LIMIT=none] -->
+    <string name="page_description_template">Page <xliff:g id="current_page" example="1">%1$d</xliff:g>
+        of <xliff:g id="page_count" example="100">%2$d</xliff:g></string>
+
+    <!-- Template for the message to announce the print options summary - spoken to the user. [CHAR LIMIT=none] -->
+    <string name="summary_template">Summary, copies <xliff:g id="copies" example="1">%1$s</xliff:g>,
+        paper size <xliff:g id="paper_size" example="A4">%2$s</xliff:g></string>
+
+    <!-- Description for the handle to expand all print options - spoken to the user. [CHAR LIMIT=none] -->
+    <string name="expand_handle">Expand handle</string>
+
+    <!-- Description for the handle to collapse all print options - spoken to the user. [CHAR LIMIT=none] -->
+    <string name="collapse_handle">Collapse handle</string>
+
+    <!-- Description for the print button - spoken to the user. [CHAR LIMIT=none] -->
+    <string name="print_button">Print</string>
+
+    <!-- Description for the save to PDF button - spoken to the user. [CHAR LIMIT=none] -->
+    <string name="savetopdf_button">Save to PDF</string>
+
+    <!-- Message to announce print options are expanded - spoken to the user. [CHAR LIMIT=none] -->
+    <string name="print_options_expanded">Print options expanded</string>
+
+    <!-- Message to announce print options are collapsed - spoken to the user. [CHAR LIMIT=none] -->
+    <string name="print_options_collapsed">Print options collapsed</string>
+
     <!-- Select printer activity -->
 
     <!-- Title for the share action bar menu item. [CHAR LIMIT=20] -->
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index b6c36c7..22a74d6 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -41,6 +41,7 @@
 import com.android.printspooler.model.PageContentRepository.PageContentProvider;
 import com.android.printspooler.util.PageRangeUtils;
 import com.android.printspooler.widget.PageContentView;
+import com.android.printspooler.widget.PreviewPageFrame;
 import dalvik.system.CloseGuard;
 
 import java.util.ArrayList;
@@ -94,12 +95,6 @@
     private int mDocumentPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
     private int mSelectedPageCount;
 
-    private float mSelectedPageElevation;
-    private float mSelectedPageAlpha;
-
-    private float mUnselectedPageElevation;
-    private float mUnselectedPageAlpha;
-
     private int mPreviewPageMargin;
     private int mPreviewPageMinWidth;
     private int mPreviewListPadding;
@@ -134,16 +129,6 @@
                 Context.LAYOUT_INFLATER_SERVICE);
         mPageContentRepository = new PageContentRepository(context, this);
 
-        mSelectedPageElevation = mContext.getResources().getDimension(
-                R.dimen.selected_page_elevation);
-        mSelectedPageAlpha = mContext.getResources().getFraction(
-                R.fraction.page_selected_alpha, 1, 1);
-
-        mUnselectedPageElevation = mContext.getResources().getDimension(
-                R.dimen.unselected_page_elevation);
-        mUnselectedPageAlpha = mContext.getResources().getFraction(
-                R.fraction.page_unselected_alpha, 1, 1);
-
         mPreviewPageMargin = mContext.getResources().getDimensionPixelSize(
                 R.dimen.preview_page_margin);
 
@@ -296,7 +281,7 @@
 
         MyViewHolder myHolder = (MyViewHolder) holder;
 
-        View page = holder.itemView;
+        PreviewPageFrame page = (PreviewPageFrame) holder.itemView;
         page.setOnClickListener(mPageClickListener);
 
         page.setTag(holder);
@@ -340,20 +325,15 @@
         }
         content.init(provider, mEmptyState, mMediaSize, mMinMargins);
 
-        View pageSelector = page.findViewById(R.id.page_selector);
-        pageSelector.setTag(myHolder);
-        pageSelector.setOnClickListener(mPageClickListener);
-
         if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) >= 0) {
-            pageSelector.setSelected(true);
-            page.setTranslationZ(mSelectedPageElevation);
-            page.setAlpha(mSelectedPageAlpha);
+            page.setSelected(true, false);
         } else {
-            pageSelector.setSelected(false);
-            page.setTranslationZ(mUnselectedPageElevation);
-            page.setAlpha(mUnselectedPageAlpha);
+            page.setSelected(false, false);
         }
 
+        page.setContentDescription(mContext.getString(R.string.page_description_template,
+                pageInDocument + 1, mDocumentPageCount));
+
         TextView pageNumberView = (TextView) page.findViewById(R.id.page_number);
         String text = mContext.getString(R.string.current_page_template,
                 pageInDocument + 1, mDocumentPageCount);
@@ -793,24 +773,20 @@
 
     private final class PageClickListener implements OnClickListener {
         @Override
-        public void onClick(View page) {
+        public void onClick(View view) {
+            PreviewPageFrame page = (PreviewPageFrame) view;
             MyViewHolder holder = (MyViewHolder) page.getTag();
             final int pageInAdapter = holder.mPageInAdapter;
             final int pageInDocument = computePageIndexInDocument(pageInAdapter);
-            View pageSelector = page.findViewById(R.id.page_selector);
             if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) < 0) {
                 mConfirmedPagesInDocument.put(pageInDocument, null);
-                pageSelector.setSelected(true);
-                page.animate().translationZ(mSelectedPageElevation)
-                        .alpha(mSelectedPageAlpha);
+                page.setSelected(true, true);
             } else {
                 if (mConfirmedPagesInDocument.size() <= 1) {
                     return;
                 }
                 mConfirmedPagesInDocument.remove(pageInDocument);
-                pageSelector.setSelected(false);
-                page.animate().translationZ(mUnselectedPageElevation)
-                        .alpha(mUnselectedPageAlpha);
+                page.setSelected(false, true);
             }
         }
     }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index c517f2d..4b58855 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -61,6 +61,7 @@
 import android.view.View.OnClickListener;
 import android.view.View.OnFocusChangeListener;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemSelectedListener;
@@ -191,6 +192,7 @@
 
     private PrintContentView mOptionsContent;
 
+    private View mSummaryContainer;
     private TextView mSummaryCopies;
     private TextView mSummaryPaperSize;
 
@@ -983,6 +985,7 @@
 
     private void bindUi() {
         // Summary
+        mSummaryContainer = findViewById(R.id.summary_content);
         mSummaryCopies = (TextView) findViewById(R.id.copies_count_summary);
         mSummaryPaperSize = (TextView) findViewById(R.id.paper_size_summary);
 
@@ -1081,15 +1084,7 @@
 
     void updateOptionsUi() {
         // Always update the summary.
-        if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
-            mSummaryCopies.setText(mCopiesEditText.getText());
-        }
-
-        final int selectedMediaIndex = mMediaSizeSpinner.getSelectedItemPosition();
-        if (selectedMediaIndex >= 0) {
-            SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(selectedMediaIndex);
-            mSummaryPaperSize.setText(mediaItem.label);
-        }
+        updateSummary();
 
         if (mState == STATE_PRINT_CONFIRMED
                 || mState == STATE_PRINT_COMPLETED
@@ -1330,8 +1325,10 @@
         // Print
         if (mDestinationSpinnerAdapter.getPdfPrinter() != mCurrentPrinter) {
             mPrintButton.setImageResource(com.android.internal.R.drawable.ic_print);
+            mPrintButton.setContentDescription(getString(R.string.print_button));
         } else {
             mPrintButton.setImageResource(R.drawable.ic_menu_savetopdf);
+            mPrintButton.setContentDescription(getString(R.string.savetopdf_button));
         }
         if ((mRangeOptionsSpinner.getSelectedItemPosition() == 1
                 && (TextUtils.isEmpty(mPageRangeEditText.getText()) || hasErrors()))
@@ -1357,6 +1354,28 @@
         }
     }
 
+    private void updateSummary() {
+        CharSequence copiesText = null;
+        CharSequence mediaSizeText = null;
+
+        if (!TextUtils.isEmpty(mCopiesEditText.getText())) {
+            copiesText = mCopiesEditText.getText();
+            mSummaryCopies.setText(copiesText);
+        }
+
+        final int selectedMediaIndex = mMediaSizeSpinner.getSelectedItemPosition();
+        if (selectedMediaIndex >= 0) {
+            SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(selectedMediaIndex);
+            mediaSizeText = mediaItem.label;
+            mSummaryPaperSize.setText(mediaSizeText);
+        }
+
+        if (!TextUtils.isEmpty(copiesText) && !TextUtils.isEmpty(mediaSizeText)) {
+            String summaryText = getString(R.string.summary_template, copiesText, mediaSizeText);
+            mSummaryContainer.setContentDescription(summaryText);
+        }
+    }
+
     private void updatePageRangeOptions(int pageCount) {
         ArrayAdapter<SpinnerItem<Integer>> rangeOptionsSpinnerAdapter =
                 (ArrayAdapter) mRangeOptionsSpinner.getAdapter();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
index e2ae758..c22c0e2 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
@@ -35,6 +35,7 @@
  */
 public class PageContentView extends View
         implements PageContentRepository.OnPageContentAvailableCallback {
+
     private PageContentProvider mProvider;
 
     private MediaSize mMediaSize;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java
new file mode 100644
index 0000000..feb0316
--- /dev/null
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PreviewPageFrame.java
@@ -0,0 +1,89 @@
+/*
+ * 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 com.android.printspooler.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+import com.android.printspooler.R;
+
+/**
+ * This class represents the frame of page in the print preview list
+ * that contains the page and a footer.
+ */
+public final class PreviewPageFrame extends LinearLayout {
+    private final float mSelectedElevation;
+    private final float mNotSelectedElevation;
+
+    private final float mSelectedPageAlpha;
+    private final float mNotSelectedAlpha;
+
+    public PreviewPageFrame(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mSelectedElevation = mContext.getResources().getDimension(
+                R.dimen.selected_page_elevation);
+        mNotSelectedElevation = mContext.getResources().getDimension(
+                R.dimen.unselected_page_elevation);
+        mSelectedPageAlpha = mContext.getResources().getFraction(
+                R.fraction.page_selected_alpha, 1, 1);
+        mNotSelectedAlpha = mContext.getResources().getFraction(
+                R.fraction.page_unselected_alpha, 1, 1);
+    }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        super.onInitializeAccessibilityEvent(event);
+        event.setClassName(CompoundButton.class.getName());
+        event.setChecked(isSelected());
+    }
+
+    @Override
+    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+        super.onInitializeAccessibilityNodeInfo(info);
+        info.setClassName(CompoundButton.class.getName());
+        info.setSelected(false);
+        info.setCheckable(true);
+        info.setChecked(isSelected());
+    }
+
+    public void setSelected(boolean selected, boolean animate) {
+        if (isSelected() == selected) {
+            return;
+        }
+        setSelected(selected);
+        if (selected) {
+            if (animate) {
+                animate().translationZ(mSelectedElevation)
+                        .alpha(mSelectedPageAlpha);
+            } else {
+                setTranslationZ(mSelectedElevation);
+                setAlpha(mSelectedPageAlpha);
+            }
+        } else {
+            if (animate) {
+                animate().translationZ(mNotSelectedElevation)
+                        .alpha(mNotSelectedAlpha);
+            } else {
+                setTranslationZ(mNotSelectedElevation);
+                setAlpha(mNotSelectedAlpha);
+            }
+        }
+    }
+}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
index 970e3c0..bfcd334 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PrintContentView.java
@@ -341,6 +341,9 @@
             if (mOptionsStateChangeListener != null) {
                 mOptionsStateChangeListener.onOptionsOpened();
             }
+            mExpandCollapseHandle.setContentDescription(
+                    mContext.getString(R.string.collapse_handle));
+            announceForAccessibility(mContext.getString(R.string.print_options_expanded));
             mSummaryContent.setVisibility(View.GONE);
             mEmbeddedContentScrim.setOnClickListener(this);
             mExpandCollapseIcon.setBackgroundResource(R.drawable.ic_expand_less);
@@ -352,6 +355,9 @@
             if (mOptionsStateChangeListener != null) {
                 mOptionsStateChangeListener.onOptionsClosed();
             }
+            mExpandCollapseHandle.setContentDescription(
+                    mContext.getString(R.string.expand_handle));
+            announceForAccessibility(mContext.getString(R.string.print_options_collapsed));
             if (mMoreOptionsButton.getVisibility() != View.GONE) {
                 mMoreOptionsButton.setVisibility(View.INVISIBLE);
             }