summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Svetoslav <svetoslavganov@google.com> 2013-07-17 18:37:36 -0700
committer Svetoslav Ganov <svetoslavganov@google.com> 2013-07-19 16:23:12 -0700
commit597945fd3a6b52ac70bb9afc5ec8c59039fffd77 (patch)
tree1e44c6e0c34deba26033b46878bbbfd010a3f8d9
parent7a5480d6d74eb64a360ed20062c66926c9eef9bc (diff)
First pass of the print dialog UX
Change-Id: I315a16d7f68c73ca180c76e722847b4b1bdea55b
-rw-r--r--core/java/android/printservice/PrintService.java15
-rw-r--r--packages/PrintSpooler/AndroidManifest.xml3
-rw-r--r--packages/PrintSpooler/res/layout/print_job_config_activity.xml425
-rw-r--r--packages/PrintSpooler/res/layout/spinner_dropdown_item.xml48
-rw-r--r--packages/PrintSpooler/res/values/constants.xml (renamed from packages/PrintSpooler/res/menu/print_job_config_activity.xml)18
-rw-r--r--packages/PrintSpooler/res/values/strings.xml76
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java426
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java18
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java4
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java59
-rw-r--r--services/java/com/android/server/print/RemotePrintSpooler.java3
11 files changed, 525 insertions, 570 deletions
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 820c2d8ff4ef..dde31d25678b 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -245,13 +245,10 @@ public abstract class PrintService extends Service {
* @see #removeDiscoveredPrinters(List)
* @see #onStartPrinterDiscovery()
* @see #onStopPrinterDiscovery()
- *
- * @throws IllegalStateException If this service is not connected.
*/
public final void addDiscoveredPrinters(List<PrinterInfo> printers) {
final IPrinterDiscoveryObserver observer;
synchronized (mLock) {
- throwIfNotConnectedLocked();
observer = mDiscoveryObserver;
}
if (observer != null) {
@@ -284,13 +281,10 @@ public abstract class PrintService extends Service {
* @see #addDiscoveredPrinters(List)
* @see #onStartPrinterDiscovery()
* @see #onStopPrinterDiscovery()
- *
- * @throws IllegalStateException If this service is not connected.
*/
public final void removeDiscoveredPrinters(List<PrinterId> printerIds) {
final IPrinterDiscoveryObserver observer;
synchronized (mLock) {
- throwIfNotConnectedLocked();
observer = mDiscoveryObserver;
}
if (observer != null) {
@@ -334,13 +328,10 @@ public abstract class PrintService extends Service {
* Gets the print jobs for the printers managed by this service.
*
* @return The print jobs.
- *
- * @throws IllegalStateException If this service is not connected.
*/
public final List<PrintJob> getPrintJobs() {
final IPrintServiceClient client;
synchronized (mLock) {
- throwIfNotConnectedLocked();
client = mClient;
}
if (client == null) {
@@ -410,12 +401,6 @@ public abstract class PrintService extends Service {
};
}
- private void throwIfNotConnectedLocked() {
- if (mClient == null) {
- throw new IllegalStateException("Print serivice not connected");
- }
- }
-
private final class MyHandler extends Handler {
public static final int MESSAGE_START_PRINTER_DISCOVERY = 1;
public static final int MESSAGE_STOP_PRINTER_DISCOVERY = 2;
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index fbb0060fa4a1..f0bbfa49fe06 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -46,7 +46,8 @@
<activity
android:name=".PrintJobConfigActivity"
- android:exported="true">
+ android:exported="true"
+ android:theme="@android:style/Theme.Holo.Light.Dialog.NoActionBar">
</activity>
</application>
diff --git a/packages/PrintSpooler/res/layout/print_job_config_activity.xml b/packages/PrintSpooler/res/layout/print_job_config_activity.xml
index 51e425d8c75b..8736bdd97f8c 100644
--- a/packages/PrintSpooler/res/layout/print_job_config_activity.xml
+++ b/packages/PrintSpooler/res/layout/print_job_config_activity.xml
@@ -14,248 +14,197 @@
limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
- <GridLayout
- android:layout_width="wrap_content"
+ <ScrollView
+ android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:orientation="vertical"
- android:columnCount="2">
+ android:background="@*android:color/bright_foreground_disabled_holo_light">
- <EditText
- android:id="@+id/copies_edittext"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="0"
- android:layout_column="1"
- android:minWidth="150dip"
- android:inputType="number"
- android:selectAllOnFocus="true">
- </EditText>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="0"
- android:layout_column="0"
- android:text="@string/label_copies"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:labelFor="@id/copies_edittext">
- </TextView>
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="1"
- android:layout_column="0"
- android:text="@string/label_destination"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/destination_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="1"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="2"
- android:layout_column="0"
- android:text="@string/label_media_size"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/media_size_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="2"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="3"
- android:layout_column="0"
- android:text="@string/label_resolution"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/resolution_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="3"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="4"
- android:layout_column="0"
- android:text="@string/label_input_tray"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/input_tray_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="4"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
-
- <TextView
+ <GridLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="5"
- android:layout_column="0"
- android:text="@string/label_output_tray"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/output_tray_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="5"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="6"
- android:layout_column="0"
- android:text="@string/label_duplex_mode"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/duplex_mode_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="6"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="7"
- android:layout_column="0"
- android:text="@string/label_color_mode"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/color_mode_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="7"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="8"
- android:layout_column="0"
- android:text="@string/label_fitting_mode"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/fitting_mode_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="8"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
-
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="9"
- android:layout_column="0"
- android:text="@string/label_orientation"
- android:textAppearance="?android:attr/textAppearanceMedium">
- </TextView>
-
- <Spinner
- android:id="@+id/orientation_spinner"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="12dip"
- android:layout_marginRight="12dip"
- android:layout_row="9"
- android:layout_column="1"
- android:minWidth="150dip">
- </Spinner>
-
- </GridLayout>
+ android:layout_margin="32dip"
+ android:orientation="vertical"
+ android:columnCount="2">
+
+ <!-- Destination -->
+
+ <Spinner
+ android:id="@+id/destination_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dip"
+ android:layout_row="0"
+ android:layout_column="0"
+ android:layout_columnSpan="2"
+ android:minWidth="324dip"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall">
+ </Spinner>
+
+ <!-- Copies -->
+
+ <view
+ class="com.android.printspooler.PrintJobConfigActivity$CustomEditText"
+ android:id="@+id/copies_edittext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="12dip"
+ android:layout_marginBottom="12dip"
+ android:layout_row="2"
+ android:layout_column="0"
+ android:layout_gravity="bottom"
+ android:inputType="numberDecimal"
+ android:selectAllOnFocus="true"
+ android:minWidth="150dip">
+ </view>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginRight="12dip"
+ android:layout_row="1"
+ android:layout_column="0"
+ android:layout_gravity="left|bottom"
+ android:text="@string/label_copies"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/copies_edittext">
+ </TextView>
+
+ <!-- Paper size -->
+
+ <Spinner
+ android:id="@+id/paper_size_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_marginBottom="12dip"
+ android:layout_row="2"
+ android:layout_column="1"
+ android:minWidth="150dip">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_marginTop="12dip"
+ android:layout_row="1"
+ android:layout_column="1"
+ android:text="@string/label_paper_size"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/paper_size_spinner">
+ </TextView>
+
+ <!-- Color -->
+
+ <Spinner
+ android:id="@+id/color_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="12dip"
+ android:layout_marginBottom="12dip"
+ android:layout_row="4"
+ android:layout_column="0"
+ android:minWidth="150dip">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginRight="12dip"
+ android:layout_row="3"
+ android:layout_column="0"
+ android:text="@string/label_color"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/color_spinner">
+ </TextView>
+
+ <!-- Orientation -->
+
+ <Spinner
+ android:id="@+id/orientation_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_marginBottom="12dip"
+ android:layout_row="4"
+ android:layout_column="1"
+ android:minWidth="150dip">
+ </Spinner>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_marginTop="12dip"
+ android:layout_row="3"
+ android:layout_column="1"
+ android:text="@string/label_orientation"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/orientation_spinner">
+ </TextView>
+
+ <!-- Pages -->
+
+ <Spinner
+ android:id="@+id/range_options_spinner"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="12dip"
+ android:layout_row="6"
+ android:layout_column="0"
+ android:minWidth="150dip">
+ </Spinner>
+
+ <EditText
+ android:id="@+id/page_range_edittext"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="12dip"
+ android:layout_row="6"
+ android:layout_column="1"
+ android:layout_gravity="bottom"
+ android:selectAllOnFocus="true"
+ android:minWidth="150dip"
+ android:hint="@string/pages_range_example"
+ android:inputType="textNoSuggestions"
+ android:visibility="gone">
+ </EditText>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="12dip"
+ android:layout_marginRight="12dip"
+ android:layout_row="5"
+ android:layout_column="0"
+ android:text="@string/label_pages"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ android:labelFor="@id/range_options_spinner">
+ </TextView>
+
+ </GridLayout>
+
+ </ScrollView>
+
+ <Button
+ android:id="@+id/print_button"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="0dip"
+ android:text="@string/print_button"
+ android:background="?android:attr/selectableItemBackground">
+ </Button>
-</ScrollView>
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
new file mode 100644
index 000000000000..66c67244b0ef
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/spinner_dropdown_item.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="8dip"
+ android:paddingRight="8dip"
+ android:minHeight="?android:attr/listPreferredItemHeightSmall"
+ android:orientation="vertical"
+ android:gravity="center_vertical">
+
+ <TextView
+ android:id="@+id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textIsSelectable="false">
+ </TextView>
+
+ <TextView
+ android:id="@+id/subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textIsSelectable="false"
+ android:visibility="gone">
+
+ </TextView>
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/menu/print_job_config_activity.xml b/packages/PrintSpooler/res/values/constants.xml
index 149c274dd1b9..7d2cdc37851f 100644
--- a/packages/PrintSpooler/res/menu/print_job_config_activity.xml
+++ b/packages/PrintSpooler/res/values/constants.xml
@@ -13,9 +13,15 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:id="@+id/print_button"
- android:title="@string/print_button"
- android:showAsAction="ifRoom">
- </item>
-</menu>
+
+<resources>
+
+ <integer name="page_option_value_all">1</integer>
+ <integer name="page_option_value_page_range">2</integer>
+
+ <integer-array name="page_options_values" translatable="false">
+ <item>@integer/page_option_value_all</item>
+ <item>@integer/page_option_value_page_range</item>
+ </integer-array>
+
+</resources> \ No newline at end of file
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 8b4b40aa2ec7..de6fb605d4ec 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -16,74 +16,44 @@
<resources>
- <!-- Title of the PrintSpooler application. [CHAR LIMIT=16] -->
+ <!-- Title of the PrintSpooler application. [CHAR LIMIT=50] -->
<string name="app_label">Print Spooler</string>
- <!-- Title of the print dialog. [CHAR LIMIT=10] -->
- <string name="print_job_config_dialog_title">Print</string>
-
<!-- Label of the print dialog's print button. [CHAR LIMIT=16] -->
- <string name="print_button">Print</string>
-
- <!-- Label of the print dialog's cancel button. [CHAR LIMIT=16] -->
- <string name="cancel_button">Cancel</string>
-
- <!-- Label of the destination spinner. [CHAR LIMIT=16] -->
- <string name="label_destination">Destination</string>
-
- <!-- Label of the copies count edit text. [CHAR LIMIT=16] -->
- <string name="label_copies">Copies</string>
-
- <!-- Label of the media size spinner. [CHAR LIMIT=16] -->
- <string name="label_media_size">Media size</string>
+ <string name="print_button">PRINT</string>
- <!-- Label of the resolution spinner. [CHAR LIMIT=16] -->
- <string name="label_resolution">Resolution</string>
+ <!-- Label of the destination widget. [CHAR LIMIT=20] -->
+ <string name="label_destination">DESTIINATION</string>
- <!-- Label of the input tray spinner. [CHAR LIMIT=16] -->
- <string name="label_input_tray">Input tray</string>
+ <!-- Label of the copies count widget. [CHAR LIMIT=20] -->
+ <string name="label_copies">COPIES</string>
- <!-- Label of the output tray spinner. [CHAR LIMIT=16] -->
- <string name="label_output_tray">Output tray</string>
+ <!-- Label of the paper size widget. [CHAR LIMIT=20] -->
+ <string name="label_paper_size">PAPER SIZE</string>
- <!-- Label of the duplex mode spinner. [CHAR LIMIT=16] -->
- <string name="label_duplex_mode">Duplex mode</string>
+ <!-- Label of the color mode widget. [CHAR LIMIT=20] -->
+ <string name="label_color">COLOR</string>
- <!-- Label of the color mode spinner. [CHAR LIMIT=16] -->
- <string name="label_color_mode">Color mode</string>
+ <!-- Label of the orientation widget. [CHAR LIMIT=20] -->
+ <string name="label_orientation">ORIENTATION</string>
- <!-- Label of the fitting mode spinner. [CHAR LIMIT=16] -->
- <string name="label_fitting_mode">Fitting mode</string>
+ <!-- Label of the page selection widget. [CHAR LIMIT=20] -->
+ <string name="label_pages">PAGES</string>
- <!-- Label of the orientation spinner. [CHAR LIMIT=16] -->
- <string name="label_orientation">Orientation</string>
+ <!-- Page range exmple used as a hint of how to specify such. [CHAR LIMIT=15] -->
+ <string name="pages_range_example">e.g. 1&#8211;5, 8</string>
- <!-- Duplex mode labels. -->
- <string-array name="duplex_mode_labels">
- <!-- Duplex mode label: No duplexing. [CHAR LIMIT=20] -->
- <item>None</item>
- <!-- Duplex mode label: Turn a page along its long edge, e.g. like a book. [CHAR LIMIT=20] -->
- <item>Long edge</item>
- <!-- Duplex mode label: Turn a page along its short edge, e.g. like a notepad. [CHAR LIMIT=20] -->
- <item>Short edge</item>
- </string-array>
+ <!-- Message to notify the user of entering invalid input. [CHAR LIMIT=25] -->
+ <string name="invalid_input">Invalid input</string>
<!-- Color mode labels. -->
<string-array name="color_mode_labels">
<!-- Color modelabel: Monochrome color scheme, e.g. one color is used. [CHAR LIMIT=20] -->
- <item>Monochrome</item>
+ <item>Black &amp; White</item>
<!-- Color mode label: Color color scheme, e.g. many colors are used. [CHAR LIMIT=20] -->
<item>Color</item>
</string-array>
- <!-- Fitting mode labels. -->
- <string-array name="fitting_mode_labels">
- <!-- Fitting mode label: No fitting. [CHAR LIMIT=30] -->
- <item>None</item>
- <!-- Fitting mode label: Fit the content to the page. [CHAR LIMIT=30] -->
- <item>Fit to page</item>
- </string-array>
-
<!-- Orientation labels. -->
<string-array name="orientation_labels">
<!-- Orientation label: Portrait page orientation. [CHAR LIMIT=30] -->
@@ -92,6 +62,14 @@
<item>Landscape</item>
</string-array>
+ <!-- Page options labels. -->
+ <string-array name="page_options_labels">
+ <!-- Page range option label: Print all pages [CHAR LIMIT=30] -->
+ <item>All</item>
+ <!-- Page range option label: Print a page range [CHAR LIMIT=30] -->
+ <item>Range</item>
+ </string-array>
+
<!-- Title of an application permission, listed so the user can choose
whether they want to allow the application to do this. -->
<string name="permlab_bindPrintSpoolerService">bind to a print spooler service</string>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index c0faed8afbf6..19f545d06569 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -17,7 +17,12 @@
package com.android.printspooler;
import android.app.Activity;
+import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Rect;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Binder;
@@ -34,8 +39,6 @@ import android.print.IPrinterDiscoveryObserver;
import android.print.PageRange;
import android.print.PrintAttributes;
import android.print.PrintAttributes.MediaSize;
-import android.print.PrintAttributes.Resolution;
-import android.print.PrintAttributes.Tray;
import android.print.PrintDocumentAdapter.LayoutResultCallback;
import android.print.PrintDocumentAdapter.WriteResultCallback;
import android.print.PrintDocumentInfo;
@@ -43,25 +46,28 @@ import android.print.PrintJobInfo;
import android.print.PrinterId;
import android.print.PrinterInfo;
import android.text.Editable;
-import android.text.InputFilter;
-import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
+import android.util.AttributeSet;
import android.util.Log;
-import android.view.Choreographer;
-import android.view.Menu;
-import android.view.MenuItem;
import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
+import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
+import android.widget.TextView;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* Activity for configuring a print job.
@@ -79,6 +85,14 @@ public class PrintJobConfigActivity extends Activity {
private static final int MIN_COPIES = 1;
+ private static final Pattern PATTERN_DIGITS = Pattern.compile("\\d");
+
+ private static final Pattern PATTERN_ESCAPE_SPECIAL_CHARS = Pattern.compile(
+ "(?=[]\\[+&|!(){}^\"~*?:\\\\])");
+
+ private static final Pattern PATTERN_PAGE_RANGE = Pattern.compile(
+ "([0-9]+[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*[,]?[\\s]*)+");
+
private final PrintSpooler mPrintSpooler = PrintSpooler.getInstance(this);
private IPrinterDiscoveryObserver mPrinterDiscoveryObserver;
@@ -90,42 +104,36 @@ public class PrintJobConfigActivity extends Activity {
private RemotePrintDocumentAdapter mRemotePrintAdapter;
+ private boolean mPrintConfirmed;
+
+ private boolean mStarted;
+
+ private IBinder mIPrintDocumentAdapter;
+
+ private PrintDocumentInfo mPrintDocumentInfo;
+
// UI elements
private EditText mCopiesEditText;
+ private EditText mRangeEditText;
+
private Spinner mDestinationSpinner;
public ArrayAdapter<SpinnerItem<PrinterInfo>> mDestinationSpinnerAdapter;
private Spinner mMediaSizeSpinner;
public ArrayAdapter<SpinnerItem<MediaSize>> mMediaSizeSpinnerAdapter;
- private Spinner mResolutionSpinner;
- public ArrayAdapter<SpinnerItem<Resolution>> mResolutionSpinnerAdapter;
-
- private Spinner mInputTraySpinner;
- public ArrayAdapter<SpinnerItem<Tray>> mInputTraySpinnerAdapter;
-
- private Spinner mOutputTraySpinner;
- public ArrayAdapter<SpinnerItem<Tray>> mOutputTraySpinnerAdapter;
-
- private Spinner mDuplexModeSpinner;
- public ArrayAdapter<SpinnerItem<Integer>> mDuplexModeSpinnerAdapter;
-
private Spinner mColorModeSpinner;
public ArrayAdapter<SpinnerItem<Integer>> mColorModeSpinnerAdapter;
- private Spinner mFittingModeSpinner;
- public ArrayAdapter<SpinnerItem<Integer>> mFittingModeSpinnerAdapter;
-
private Spinner mOrientationSpinner;
public ArrayAdapter<SpinnerItem<Integer>> mOrientationSpinnerAdapter;
- private boolean mPrintConfirmed;
+ private Spinner mRangeOptionsSpinner;
+ public ArrayAdapter<SpinnerItem<Integer>> mRangeOptionsSpinnerAdapter;
- private boolean mStarted;
-
- private IBinder mIPrintDocumentAdapter;
+ private Button mPrintButton;
// TODO: Implement store/restore state.
@@ -140,35 +148,34 @@ public class PrintJobConfigActivity extends Activity {
SpinnerItem<MediaSize> mediaItem = mMediaSizeSpinnerAdapter.getItem(position);
mPrintAttributes.setMediaSize(mediaItem.value);
updatePrintableContentIfNeeded();
- } else if (spinner == mResolutionSpinner) {
- SpinnerItem<Resolution> resolutionItem =
- mResolutionSpinnerAdapter.getItem(position);
- mPrintAttributes.setResolution(resolutionItem.value);
- updatePrintableContentIfNeeded();
- } else if (spinner == mInputTraySpinner) {
- SpinnerItem<Tray> inputTrayItem =
- mInputTraySpinnerAdapter.getItem(position);
- mPrintAttributes.setInputTray(inputTrayItem.value);
- } else if (spinner == mOutputTraySpinner) {
- SpinnerItem<Tray> outputTrayItem =
- mOutputTraySpinnerAdapter.getItem(position);
- mPrintAttributes.setOutputTray(outputTrayItem.value);
- } else if (spinner == mDuplexModeSpinner) {
- SpinnerItem<Integer> duplexModeItem =
- mDuplexModeSpinnerAdapter.getItem(position);
- mPrintAttributes.setDuplexMode(duplexModeItem.value);
} else if (spinner == mColorModeSpinner) {
SpinnerItem<Integer> colorModeItem =
mColorModeSpinnerAdapter.getItem(position);
mPrintAttributes.setColorMode(colorModeItem.value);
- } else if (spinner == mFittingModeSpinner) {
- SpinnerItem<Integer> fittingModeItem =
- mFittingModeSpinnerAdapter.getItem(position);
- mPrintAttributes.setFittingMode(fittingModeItem.value);
} else if (spinner == mOrientationSpinner) {
SpinnerItem<Integer> orientationItem =
mOrientationSpinnerAdapter.getItem(position);
mPrintAttributes.setOrientation(orientationItem.value);
+ } else if (spinner == mRangeOptionsSpinner) {
+ SpinnerItem<Integer> rangeOptionItem =
+ mRangeOptionsSpinnerAdapter.getItem(position);
+ if (rangeOptionItem.value == getResources().getInteger(
+ R.integer.page_option_value_all)) {
+ mRangeEditText.setVisibility(View.INVISIBLE);
+ mRangeEditText.setEnabled(false);
+ mRangeEditText.setText(null);
+ mRangeEditText.setError(null);
+ mPrintButton.setEnabled(true);
+ } else if (rangeOptionItem.value == getResources().getInteger(
+ R.integer.page_option_value_page_range)) {
+ mRangeEditText.setVisibility(View.VISIBLE);
+ mRangeEditText.setEnabled(true);
+ mRangeEditText.requestFocus();
+ mRangeEditText.setError(getString(R.string.invalid_input));
+ InputMethodManager imm = (InputMethodManager)
+ getSystemService(INPUT_METHOD_SERVICE);
+ imm.showSoftInput(mRangeEditText, 0);
+ }
}
}
@@ -178,11 +185,10 @@ public class PrintJobConfigActivity extends Activity {
}
};
- private final TextWatcher mTextWatcher = new TextWatcher() {
+ private final TextWatcher mCopiesTextWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
- final int copies = Integer.parseInt(mCopiesEditText.getText().toString());
- mPrintAttributes.setCopies(copies);
+ /* do nothing */
}
@Override
@@ -191,25 +197,64 @@ public class PrintJobConfigActivity extends Activity {
}
@Override
- public void afterTextChanged(Editable s) {
- /* do nothing */
+ public void afterTextChanged(Editable editable) {
+ if (editable.length() == 0) {
+ mCopiesEditText.setError(getString(R.string.invalid_input));
+ mPrintButton.setEnabled(false);
+ return;
+ }
+ final int copies = Integer.parseInt(editable.toString());
+ if (copies < MIN_COPIES) {
+ mCopiesEditText.setError(getString(R.string.invalid_input));
+ mPrintButton.setEnabled(false);
+ return;
+ }
+ mPrintAttributes.setCopies(copies);
+ mPrintButton.setEnabled(true);
}
};
- private final InputFilter mInputFilter = new InputFilter() {
+ private final TextWatcher mRangeTextWatcher = new TextWatcher() {
@Override
- public CharSequence filter(CharSequence source, int start, int end,
- Spanned dest, int dstart, int dend) {
- StringBuffer text = new StringBuffer(dest.toString());
- text.replace(dstart, dend, source.subSequence(start, end).toString());
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ /* do nothing */
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ /* do nothing */
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ String text = editable.toString();
+
if (TextUtils.isEmpty(text)) {
- return dest;
+ mRangeEditText.setError(getString(R.string.invalid_input));
+ mPrintButton.setEnabled(false);
+ return;
}
- final int copies = Integer.parseInt(text.toString());
- if (copies < MIN_COPIES) {
- return dest;
+
+ String escapedText = PATTERN_ESCAPE_SPECIAL_CHARS.matcher(text).replaceAll("////");
+ if (!PATTERN_PAGE_RANGE.matcher(escapedText).matches()) {
+ mRangeEditText.setError(getString(R.string.invalid_input));
+ mPrintButton.setEnabled(false);
+ return;
}
- return null;
+
+ Matcher matcher = PATTERN_DIGITS.matcher(text);
+ while (matcher.find()) {
+ String numericString = text.substring(matcher.start(), matcher.end());
+ final int pageIndex = Integer.parseInt(numericString);
+ if (pageIndex < 1 || pageIndex > mPrintDocumentInfo.getPageCount()) {
+ mRangeEditText.setError(getString(R.string.invalid_input));
+ mPrintButton.setEnabled(false);
+ return;
+ }
+ }
+
+ mRangeEditText.setError(null);
+ mPrintButton.setEnabled(true);
}
};
@@ -274,70 +319,95 @@ public class PrintJobConfigActivity extends Activity {
// Copies
mCopiesEditText = (EditText) findViewById(R.id.copies_edittext);
mCopiesEditText.setText(String.valueOf(MIN_COPIES));
- mCopiesEditText.addTextChangedListener(mTextWatcher);
- mCopiesEditText.setFilters(new InputFilter[] {mInputFilter});
+ mCopiesEditText.addTextChangedListener(mCopiesTextWatcher);
// Destination.
mDestinationSpinner = (Spinner) findViewById(R.id.destination_spinner);
mDestinationSpinnerAdapter = new ArrayAdapter<SpinnerItem<PrinterInfo>>(this,
- android.R.layout.simple_spinner_dropdown_item);
+ R.layout.spinner_dropdown_item) {
+ @Override
+ public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ return getView(position, convertView, parent);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (convertView == null) {
+ convertView = getLayoutInflater().inflate(
+ R.layout.spinner_dropdown_item, parent, false);
+ }
+
+ PrinterInfo printerInfo = getItem(position).value;
+ TextView title = (TextView) convertView.findViewById(R.id.title);
+ title.setText(printerInfo.getLabel());
+
+ try {
+ TextView subtitle = (TextView) convertView.findViewById(R.id.subtitle);
+ PackageManager pm = getPackageManager();
+ PackageInfo packageInfo = pm.getPackageInfo(
+ printerInfo.getId().getService().getPackageName(), 0);
+ subtitle.setText(packageInfo.applicationInfo.loadLabel(pm));
+ subtitle.setVisibility(View.VISIBLE);
+ } catch (NameNotFoundException nnfe) {
+ /* ignore */
+ }
+
+ return convertView;
+ }
+ };
mDestinationSpinner.setAdapter(mDestinationSpinnerAdapter);
mDestinationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
// Media size.
- mMediaSizeSpinner = (Spinner) findViewById(R.id.media_size_spinner);
+ mMediaSizeSpinner = (Spinner) findViewById(R.id.paper_size_spinner);
mMediaSizeSpinnerAdapter = new ArrayAdapter<SpinnerItem<MediaSize>>(this,
- android.R.layout.simple_spinner_dropdown_item);
+ R.layout.spinner_dropdown_item, R.id.title);
mMediaSizeSpinner.setAdapter(mMediaSizeSpinnerAdapter);
mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
- // Resolution.
- mResolutionSpinner = (Spinner) findViewById(R.id.resolution_spinner);
- mResolutionSpinnerAdapter = new ArrayAdapter<SpinnerItem<Resolution>>(this,
- android.R.layout.simple_spinner_dropdown_item);
- mResolutionSpinner.setAdapter(mResolutionSpinnerAdapter);
- mResolutionSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
- // Input tray.
- mInputTraySpinner = (Spinner) findViewById(R.id.input_tray_spinner);
- mInputTraySpinnerAdapter = new ArrayAdapter<SpinnerItem<Tray>>(this,
- android.R.layout.simple_spinner_dropdown_item);
- mInputTraySpinner.setAdapter(mInputTraySpinnerAdapter);
-
- // Output tray.
- mOutputTraySpinner = (Spinner) findViewById(R.id.output_tray_spinner);
- mOutputTraySpinnerAdapter = new ArrayAdapter<SpinnerItem<Tray>>(this,
- android.R.layout.simple_spinner_dropdown_item);
- mOutputTraySpinner.setAdapter(mOutputTraySpinnerAdapter);
- mOutputTraySpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
- // Duplex mode.
- mDuplexModeSpinner = (Spinner) findViewById(R.id.duplex_mode_spinner);
- mDuplexModeSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(this,
- android.R.layout.simple_spinner_dropdown_item);
- mDuplexModeSpinner.setAdapter(mDuplexModeSpinnerAdapter);
- mDuplexModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
// Color mode.
- mColorModeSpinner = (Spinner) findViewById(R.id.color_mode_spinner);
+ mColorModeSpinner = (Spinner) findViewById(R.id.color_spinner);
mColorModeSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(this,
- android.R.layout.simple_spinner_dropdown_item);
+ R.layout.spinner_dropdown_item, R.id.title);
mColorModeSpinner.setAdapter(mColorModeSpinnerAdapter);
mColorModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
- // Color mode.
- mFittingModeSpinner = (Spinner) findViewById(R.id.fitting_mode_spinner);
- mFittingModeSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(this,
- android.R.layout.simple_spinner_dropdown_item);
- mFittingModeSpinner.setAdapter(mFittingModeSpinnerAdapter);
- mFittingModeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
-
// Orientation
mOrientationSpinner = (Spinner) findViewById(R.id.orientation_spinner);
mOrientationSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(this,
- android.R.layout.simple_spinner_dropdown_item);
+ R.layout.spinner_dropdown_item, R.id.title);
mOrientationSpinner.setAdapter(mOrientationSpinnerAdapter);
mOrientationSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+
+ // Range
+ mRangeEditText = (EditText) findViewById(R.id.page_range_edittext);
+ mRangeEditText.addTextChangedListener(mRangeTextWatcher);
+
+ // Range options
+ mRangeOptionsSpinner = (Spinner) findViewById(R.id.range_options_spinner);
+ mRangeOptionsSpinnerAdapter = new ArrayAdapter<SpinnerItem<Integer>>(this,
+ R.layout.spinner_dropdown_item, R.id.title);
+ mRangeOptionsSpinner.setAdapter(mRangeOptionsSpinnerAdapter);
+ mRangeOptionsSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
+ final int[] rangeOptionsValues = getResources().getIntArray(
+ R.array.page_options_values);
+ String[] rangeOptionsLabels = getResources().getStringArray(
+ R.array.page_options_labels);
+ final int rangeOptionsCount = rangeOptionsLabels.length;
+ for (int i = 0; i < rangeOptionsCount; i++) {
+ mRangeOptionsSpinnerAdapter.add(new SpinnerItem<Integer>(
+ rangeOptionsValues[i], rangeOptionsLabels[i]));
+ }
+ mRangeOptionsSpinner.setSelection(0);
+
+ mPrintButton = (Button) findViewById(R.id.print_button);
+ mPrintButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPrintConfirmed = true;
+ finish();
+ }
+ });
}
private void updateUi() {
@@ -348,6 +418,7 @@ public class PrintJobConfigActivity extends Activity {
// Copies.
mCopiesEditText.setText(String.valueOf(
Math.max(mPrintAttributes.getCopies(), MIN_COPIES)));
+ mCopiesEditText.selectAll();
// Media size.
mMediaSizeSpinnerAdapter.clear();
@@ -363,80 +434,6 @@ public class PrintJobConfigActivity extends Activity {
mMediaSizeSpinner.setOnItemSelectedListener(null);
mMediaSizeSpinner.setSelection(selectedMediaSizeIndex);
- // Resolution.
- mResolutionSpinnerAdapter.clear();
- List<Resolution> resolutions = printer.getResolutions();
- final int resolutionCount = resolutions.size();
- for (int i = 0; i < resolutionCount; i++) {
- Resolution resolution = resolutions.get(i);
- mResolutionSpinnerAdapter.add(new SpinnerItem<Resolution>(
- resolution, resolution.getLabel(getPackageManager())));
- }
- final int selectedResolutionIndex = resolutions.indexOf(
- mPrintAttributes.getResolution());
- mResolutionSpinner.setOnItemSelectedListener(null);
- mResolutionSpinner.setSelection(selectedResolutionIndex);
-
- // AdapterView has the weird behavior to notify the selection listener for a
- // selection event that occurred *before* the listener was registered because
- // it does the real selection change on the next layout pass. To avoid this
- // behavior we re-attach the listener in the next traversal window - fun!
- Choreographer.getInstance().postCallback(
- Choreographer.CALLBACK_TRAVERSAL, new Runnable() {
- @Override
- public void run() {
- mMediaSizeSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
- mResolutionSpinner.setOnItemSelectedListener(mOnItemSelectedListener);
- }
- }, null);
-
- // Input tray.
- mInputTraySpinnerAdapter.clear();
- List<Tray> inputTrays = printer.getInputTrays();
- if (inputTrays != null) {
- final int inputTrayCount = inputTrays.size();
- for (int i = 0; i < inputTrayCount; i++) {
- Tray inputTray = inputTrays.get(i);
- mInputTraySpinnerAdapter.add(new SpinnerItem<Tray>(
- inputTray, inputTray.getLabel(getPackageManager())));
- }
- final int selectedInputTrayIndex = inputTrays.indexOf(
- mPrintAttributes.getInputTray());
- mInputTraySpinner.setSelection(selectedInputTrayIndex);
- }
-
- // Output tray.
- mOutputTraySpinnerAdapter.clear();
- List<Tray> outputTrays = printer.getOutputTrays();
- if (outputTrays != null) {
- final int outputTrayCount = outputTrays.size();
- for (int i = 0; i < outputTrayCount; i++) {
- Tray outputTray = outputTrays.get(i);
- mOutputTraySpinnerAdapter.add(new SpinnerItem<Tray>(
- outputTray, outputTray.getLabel(getPackageManager())));
- }
- final int selectedOutputTrayIndex = outputTrays.indexOf(
- mPrintAttributes.getOutputTray());
- mOutputTraySpinner.setSelection(selectedOutputTrayIndex);
- }
-
- // Duplex mode.
- final int duplexModes = printer.getDuplexModes();
- mDuplexModeSpinnerAdapter.clear();
- String[] duplexModeLabels = getResources().getStringArray(
- R.array.duplex_mode_labels);
- int remainingDuplexModes = duplexModes;
- while (remainingDuplexModes != 0) {
- final int duplexBitOffset = Integer.numberOfTrailingZeros(remainingDuplexModes);
- final int duplexMode = 1 << duplexBitOffset;
- remainingDuplexModes &= ~duplexMode;
- mDuplexModeSpinnerAdapter.add(new SpinnerItem<Integer>(duplexMode,
- duplexModeLabels[duplexBitOffset]));
- }
- final int selectedDuplexModeIndex = Integer.numberOfTrailingZeros(
- (duplexModes & mPrintAttributes.getDuplexMode()));
- mDuplexModeSpinner.setSelection(selectedDuplexModeIndex);
-
// Color mode.
final int colorModes = printer.getColorModes();
mColorModeSpinnerAdapter.clear();
@@ -454,23 +451,6 @@ public class PrintJobConfigActivity extends Activity {
(colorModes & mPrintAttributes.getColorMode()));
mColorModeSpinner.setSelection(selectedColorModeIndex);
- // Fitting mode.
- final int fittingModes = printer.getFittingModes();
- mFittingModeSpinnerAdapter.clear();
- String[] fittingModeLabels = getResources().getStringArray(
- R.array.fitting_mode_labels);
- int remainingFittingModes = fittingModes;
- while (remainingFittingModes != 0) {
- final int fittingBitOffset = Integer.numberOfTrailingZeros(remainingFittingModes);
- final int fittingMode = 1 << fittingBitOffset;
- remainingFittingModes &= ~fittingMode;
- mFittingModeSpinnerAdapter.add(new SpinnerItem<Integer>(fittingMode,
- fittingModeLabels[fittingBitOffset]));
- }
- final int selectedFittingModeIndex = Integer.numberOfTrailingZeros(
- (fittingModes & mPrintAttributes.getFittingMode()));
- mFittingModeSpinner.setSelection(selectedFittingModeIndex);
-
// Orientation.
final int orientations = printer.getOrientations();
mOrientationSpinnerAdapter.clear();
@@ -503,21 +483,6 @@ public class PrintJobConfigActivity extends Activity {
notifyPrintableFinishIfNeeded();
}
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.print_job_config_activity, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (item.getItemId() == R.id.print_button) {
- mPrintConfirmed = true;
- finish();
- }
- return super.onOptionsItemSelected(item);
- }
-
private void notifyPrintableStartIfNeeded() {
if (mDestinationSpinner.getSelectedItemPosition() < 0
|| mStarted) {
@@ -541,6 +506,8 @@ public class PrintJobConfigActivity extends Activity {
mPrintAttributes, new LayoutResultCallback() {
@Override
public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
+ mPrintDocumentInfo = info;
+
// TODO: Handle the case of unchanged content
mPrintSpooler.setPrintJobPrintDocumentInfo(mPrintJobId, info);
@@ -575,10 +542,7 @@ public class PrintJobConfigActivity extends Activity {
return;
}
- if (!mPrintConfirmed) {
- mRemotePrintAdapter.cancel();
- }
- mRemotePrintAdapter.finish();
+ mRemotePrintAdapter.finish(!mPrintConfirmed);
// If canceled or no printer, nothing to do.
final int selectedIndex = mDestinationSpinner.getSelectedItemPosition();
@@ -735,4 +699,38 @@ public class PrintJobConfigActivity extends Activity {
return label.toString();
}
}
+
+ /**
+ * An instance of this class class is intended to be the first focusable
+ * in a layout to which the system automatically gives focus. It performs
+ * some voodoo to avoid the first tap on it to start an edit mode, rather
+ * to bring up the IME, i.e. to get the behavior as if the view was not
+ * focused.
+ */
+ public static final class CustomEditText extends EditText {
+ private boolean mClickedBeforeFocus;
+
+ public CustomEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public boolean performClick() {
+ super.performClick();
+ if (isFocused() && !mClickedBeforeFocus) {
+ clearFocus();
+ requestFocus();
+ }
+ mClickedBeforeFocus = true;
+ return true;
+ }
+
+ protected void onFocusChanged(boolean gainFocus, int direction,
+ Rect previouslyFocusedRect) {
+ if (!gainFocus) {
+ mClickedBeforeFocus = false;
+ }
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
+ }
+ }
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
index 0546a4316619..9a44f7792b18 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpooler.java
@@ -129,7 +129,7 @@ public class PrintSpooler {
}
}
- public List<PrintJobInfo> getPrintJobs(ComponentName componentName, int state, int appId) {
+ public List<PrintJobInfo> getPrintJobInfos(ComponentName componentName, int state, int appId) {
synchronized (mLock) {
List<PrintJobInfo> foundPrintJobs = null;
final int printJobCount = mPrintJobs.size();
@@ -154,7 +154,7 @@ public class PrintSpooler {
}
}
- public PrintJobInfo getPrintJob(int printJobId, int appId) {
+ public PrintJobInfo getPrintJobInfo(int printJobId, int appId) {
synchronized (mLock) {
final int printJobCount = mPrintJobs.size();
for (int i = 0; i < printJobCount; i++) {
@@ -170,7 +170,7 @@ public class PrintSpooler {
public boolean cancelPrintJob(int printJobId, int appId) {
synchronized (mLock) {
- PrintJobInfo printJob = getPrintJob(printJobId, appId);
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, appId);
if (printJob != null) {
switch (printJob.getState()) {
case PrintJobInfo.STATE_CREATED:
@@ -291,7 +291,7 @@ public class PrintSpooler {
FileInputStream in = null;
FileOutputStream out = null;
try {
- PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
File file = generateFileForPrintJob(printJobId);
in = new FileInputStream(file);
@@ -355,7 +355,7 @@ public class PrintSpooler {
}
client = mClient;
- PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null && printJob.getState() < state) {
success = true;
printJob.setState(state);
@@ -465,7 +465,7 @@ public class PrintSpooler {
public boolean setPrintJobTag(int printJobId, String tag) {
synchronized (mLock) {
- PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
printJob.setTag(tag);
mPersistanceManager.writeStateLocked();
@@ -477,7 +477,7 @@ public class PrintSpooler {
public final boolean setPrintJobPrintDocumentInfo(int printJobId, PrintDocumentInfo info) {
synchronized (mLock) {
- PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
printJob.setDocumentInfo(info);
mPersistanceManager.writeStateLocked();
@@ -489,7 +489,7 @@ public class PrintSpooler {
public void setPrintJobAttributes(int printJobId, PrintAttributes attributes) {
synchronized (mLock) {
- PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
printJob.setAttributes(attributes);
mPersistanceManager.writeStateLocked();
@@ -499,7 +499,7 @@ public class PrintSpooler {
public void setPrintJobPrinterId(int printJobId, PrinterId printerId) {
synchronized (mLock) {
- PrintJobInfo printJob = getPrintJob(printJobId, PrintManager.APP_ID_ANY);
+ PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
if (printJob != null) {
printJob.setPrinterId(printerId);
mPersistanceManager.writeStateLocked();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
index 050332cc0dc0..ad5e5b0a9dc0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintSpoolerService.java
@@ -72,7 +72,7 @@ public final class PrintSpoolerService extends Service {
throws RemoteException {
List<PrintJobInfo> printJobs = null;
try {
- printJobs = mSpooler.getPrintJobs(componentName, state, appId);
+ printJobs = mSpooler.getPrintJobInfos(componentName, state, appId);
} finally {
callback.onGetPrintJobInfosResult(printJobs, sequence);
}
@@ -83,7 +83,7 @@ public final class PrintSpoolerService extends Service {
int appId, int sequence) throws RemoteException {
PrintJobInfo printJob = null;
try {
- printJob = mSpooler.getPrintJob(printJobId, appId);
+ printJob = mSpooler.getPrintJobInfo(printJobId, appId);
} finally {
callback.onGetPrintJobInfoResult(printJob, sequence);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java
index 71869323fc08..2bf62eebe8bc 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/RemotePrintDocumentAdapter.java
@@ -56,6 +56,7 @@ final class RemotePrintDocumentAdapter {
public static final int STATE_LAYOUT_COMPLETED = 2;
public static final int STATE_WRITE_COMPLETED = 3;
public static final int STATE_FINISH_COMPLETED = 4;
+ public static final int STATE_FAILED = 6;
private final Object mLock = new Object();
@@ -77,22 +78,14 @@ final class RemotePrintDocumentAdapter {
Log.i(LOG_TAG, "getFile()");
}
synchronized (mLock) {
- if (mState < STATE_WRITE_COMPLETED) {
+ if (mState != STATE_WRITE_COMPLETED
+ && mState != STATE_FINISH_COMPLETED) {
throw new IllegalStateException("Write not completed");
}
return mFile;
}
}
- public void cancel() {
- synchronized (mLock) {
- final int taskCount = mTaskQueue.size();
- for (int i = 0; i < taskCount; i++) {
- mTaskQueue.remove(i).cancel();
- }
- }
- }
-
public void start() {
QueuedAsyncTask task = new QueuedAsyncTask() {
@Override
@@ -101,6 +94,7 @@ final class RemotePrintDocumentAdapter {
Log.i(LOG_TAG, "start()");
}
synchronized (mLock) {
+ mTaskQueue.add(this);
if (mState != STATE_INITIALIZED) {
throw new IllegalStateException("Invalid state: " + mState);
}
@@ -116,29 +110,22 @@ final class RemotePrintDocumentAdapter {
return null;
}
};
- synchronized (mLock) {
- mTaskQueue.add(task);
- task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
- }
+ task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
public void layout(PrintAttributes oldAttributes, PrintAttributes newAttributes,
LayoutResultCallback callback, Bundle metadata) {
LayoutAsyncTask task = new LayoutAsyncTask(oldAttributes, newAttributes, callback,
metadata);
- synchronized (mLock) {
- mTaskQueue.add(task);
- task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
- }
+ task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
public void write(List<PageRange> pages, WriteResultCallback callback) {
WriteAsyncTask task = new WriteAsyncTask(pages, callback);
- mTaskQueue.add(task);
task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
- public void finish() {
+ public void finish(final boolean abortPendingWork) {
QueuedAsyncTask task = new QueuedAsyncTask() {
@Override
protected Void doInBackground(Void... params) {
@@ -146,9 +133,15 @@ final class RemotePrintDocumentAdapter {
Log.i(LOG_TAG, "finish");
}
synchronized (mLock) {
- if (mState != STATE_LAYOUT_COMPLETED
- && mState != STATE_WRITE_COMPLETED) {
- throw new IllegalStateException("Invalid state: " + mState);
+ if (abortPendingWork) {
+ final int taskCount = mTaskQueue.size();
+ for (int i = taskCount - 1; i >= 0; i--) {
+ mTaskQueue.remove(i).cancel();
+ }
+ }
+ mTaskQueue.add(this);
+ if (mState < STATE_START_COMPLETED) {
+ return null;
}
}
try {
@@ -158,15 +151,12 @@ final class RemotePrintDocumentAdapter {
}
} catch (RemoteException re) {
Log.e(LOG_TAG, "Error reading file", re);
- mState = STATE_INITIALIZED;
+ mState = STATE_FAILED;
}
return null;
}
};
- synchronized (mLock) {
- mTaskQueue.add(task);
- task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
- }
+ task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, (Void[]) null);
}
private abstract class QueuedAsyncTask extends AsyncTask<Void, Void, Void> {
@@ -243,6 +233,7 @@ final class RemotePrintDocumentAdapter {
@Override
protected Void doInBackground(Void... params) {
synchronized (mLock) {
+ mTaskQueue.add(this);
if (mState != STATE_START_COMPLETED
&& mState != STATE_LAYOUT_COMPLETED
&& mState != STATE_WRITE_COMPLETED) {
@@ -255,7 +246,6 @@ final class RemotePrintDocumentAdapter {
synchronized (mLock) {
while (true) {
if (isCancelled()) {
- mState = STATE_INITIALIZED;
mTaskQueue.remove(this);
break;
}
@@ -273,7 +263,7 @@ final class RemotePrintDocumentAdapter {
}
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error calling layout", re);
- mState = STATE_INITIALIZED;
+ mState = STATE_FAILED;
}
return null;
}
@@ -362,7 +352,9 @@ final class RemotePrintDocumentAdapter {
Log.i(LOG_TAG, "print()");
}
synchronized (mLock) {
- if (mState != STATE_LAYOUT_COMPLETED) {
+ mTaskQueue.add(this);
+ if (mState != STATE_LAYOUT_COMPLETED
+ && mState != STATE_WRITE_COMPLETED) {
throw new IllegalStateException("Invalid state: " + mState);
}
}
@@ -403,7 +395,6 @@ final class RemotePrintDocumentAdapter {
synchronized (mLock) {
while (true) {
if (isCancelled()) {
- mState = STATE_INITIALIZED;
mTaskQueue.remove(this);
break;
}
@@ -421,10 +412,10 @@ final class RemotePrintDocumentAdapter {
}
} catch (RemoteException re) {
Slog.e(LOG_TAG, "Error writing print document", re);
- mState = STATE_INITIALIZED;
+ mState = STATE_FAILED;
} catch (IOException ioe) {
Slog.e(LOG_TAG, "Error writing print document", ioe);
- mState = STATE_INITIALIZED;
+ mState = STATE_FAILED;
} finally {
IoUtils.closeQuietly(in);
IoUtils.closeQuietly(out);
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index bf2c8e73af6c..6445c2ee9814 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -296,8 +296,7 @@ final class RemotePrintSpooler {
}
mContext.bindServiceAsUser(mIntent, mServiceConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_OOM_MANAGEMENT,
- mUserHandle);
+ Context.BIND_AUTO_CREATE, mUserHandle);
final long startMillis = SystemClock.uptimeMillis();
while (true) {