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

Commit 14db9654 authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Print UI polish (a.k.a. just the next iteration))

1. Added a dialog to show a spinner while the app is writing the
   printed content.

2. Fixed print job config acitivity leaking.

3. Updated the notifications a bit.

Change-Id: I8314390135a49605ee11ab4ed14b210a29566745
parent 614b4c4c
Loading
Loading
Loading
Loading
+134 −89
Original line number Diff line number Diff line
@@ -288,6 +288,7 @@ public final class PrintManager {
        private void doFinish() {
            mDocumentAdapter = null;
            mHandler = null;
            mLayoutOrWriteCancellation = null;
        }

        private final class MyHandler extends Handler {
@@ -312,10 +313,10 @@ public final class PrintManager {

                    case MSG_LAYOUT: {
                        SomeArgs args = (SomeArgs) message.obj;
                        final PrintAttributes oldAttributes = (PrintAttributes) args.arg1;
                        final PrintAttributes newAttributes = (PrintAttributes) args.arg2;
                        final ILayoutResultCallback callback = (ILayoutResultCallback) args.arg3;
                        final Bundle metadata = (Bundle) args.arg4;
                        PrintAttributes oldAttributes = (PrintAttributes) args.arg1;
                        PrintAttributes newAttributes = (PrintAttributes) args.arg2;
                        ILayoutResultCallback callback = (ILayoutResultCallback) args.arg3;
                        Bundle metadata = (Bundle) args.arg4;
                        final int sequence = args.argi1;
                        args.recycle();

@@ -324,116 +325,160 @@ public final class PrintManager {
                            mLayoutOrWriteCancellation = cancellation;
                        }

                        mDocumentAdapter.onLayout(oldAttributes, newAttributes,
                                cancellation, new LayoutResultCallback() {
                        mDocumentAdapter.onLayout(oldAttributes, newAttributes, cancellation,
                                new MyLayoutResultCallback(callback, sequence), metadata);
                    } break;

                    case MSG_WRITE: {
                        SomeArgs args = (SomeArgs) message.obj;
                        PageRange[] pages = (PageRange[]) args.arg1;
                        FileDescriptor fd = (FileDescriptor) args.arg2;
                        IWriteResultCallback callback = (IWriteResultCallback) args.arg3;
                        final int sequence = args.argi1;
                        args.recycle();

                        CancellationSignal cancellation = new CancellationSignal();
                        synchronized (mLock) {
                            mLayoutOrWriteCancellation = cancellation;
                        }

                        mDocumentAdapter.onWrite(pages, fd, cancellation,
                                new MyWriteResultCallback(callback, fd, sequence));
                    } break;

                    case MSG_FINISH: {
                        mDocumentAdapter.onFinish();
                        doFinish();
                    } break;

                    default: {
                        throw new IllegalArgumentException("Unknown message: "
                                + message.what);
                    }
                }
            }
        }

        private final class MyLayoutResultCallback extends LayoutResultCallback {
            private ILayoutResultCallback mCallback;
            private final int mSequence;

            public MyLayoutResultCallback(ILayoutResultCallback callback,
                    int sequence) {
                mCallback = callback;
                mSequence = sequence;
            }

            @Override
            public void onLayoutFinished(PrintDocumentInfo info, boolean changed) {
                final ILayoutResultCallback callback;
                synchronized (mLock) {
                    callback = mCallback;
                    clearLocked();
                }
                if (info == null) {
                    throw new IllegalArgumentException("info cannot be null");
                }
                                synchronized (mLock) {
                                    mLayoutOrWriteCancellation = null;
                                }
                if (callback != null) {
                    try {
                                    callback.onLayoutFinished(info, changed, sequence);
                        callback.onLayoutFinished(info, changed, mSequence);
                    } catch (RemoteException re) {
                        Log.e(LOG_TAG, "Error calling onLayoutFinished", re);
                    }
                }
            }

            @Override
            public void onLayoutFailed(CharSequence error) {
                final ILayoutResultCallback callback;
                synchronized (mLock) {
                                    mLayoutOrWriteCancellation = null;
                    callback = mCallback;
                    clearLocked();
                }
                if (callback != null) {
                    try {
                                    callback.onLayoutFailed(error, sequence);
                        callback.onLayoutFailed(error, mSequence);
                    } catch (RemoteException re) {
                        Log.e(LOG_TAG, "Error calling onLayoutFailed", re);
                    }
                }
            }

            @Override
            public void onLayoutCancelled() {
                synchronized (mLock) {
                    clearLocked();
                }
            }

            private void clearLocked() {
                mLayoutOrWriteCancellation = null;
                mCallback = null;
            }
        }
                        }, metadata);
                    } break;

                    case MSG_WRITE: {
                        SomeArgs args = (SomeArgs) message.obj;
                        final PageRange[] pages = (PageRange[]) args.arg1;
                        final FileDescriptor fd = (FileDescriptor) args.arg2;
                        final IWriteResultCallback callback = (IWriteResultCallback) args.arg3;
                        final int sequence = args.argi1;
                        args.recycle();
        private final class MyWriteResultCallback extends WriteResultCallback {
            private FileDescriptor mFd;
            private int mSequence;
            private IWriteResultCallback mCallback;

                        CancellationSignal cancellation = new CancellationSignal();
                        synchronized (mLock) {
                            mLayoutOrWriteCancellation = cancellation;
            public MyWriteResultCallback(IWriteResultCallback callback,
                    FileDescriptor fd, int sequence) {
                mFd = fd;
                mSequence = sequence;
                mCallback = callback;
            }

                        mDocumentAdapter.onWrite(pages, fd, cancellation,
                                new WriteResultCallback() {
            @Override
            public void onWriteFinished(PageRange[] pages) {
                final IWriteResultCallback callback;
                synchronized (mLock) {
                    callback = mCallback;
                    clearLocked();
                }
                if (pages == null) {
                    throw new IllegalArgumentException("pages cannot be null");
                }
                if (pages.length == 0) {
                    throw new IllegalArgumentException("pages cannot be empty");
                }
                                synchronized (mLock) {
                                    mLayoutOrWriteCancellation = null;
                                }
                                // Close before notifying the other end. We want
                                // to be ready by the time we announce it.
                                IoUtils.closeQuietly(fd);
                if (callback != null) {
                    try {
                                    callback.onWriteFinished(pages, sequence);
                        callback.onWriteFinished(pages, mSequence);
                    } catch (RemoteException re) {
                        Log.e(LOG_TAG, "Error calling onWriteFinished", re);
                    }
                }
            }

            @Override
            public void onWriteFailed(CharSequence error) {
                final IWriteResultCallback callback;
                synchronized (mLock) {
                                    mLayoutOrWriteCancellation = null;
                    callback = mCallback;
                    clearLocked();
                }
                                // Close before notifying the other end. We want
                                // to be ready by the time we announce it.
                                IoUtils.closeQuietly(fd);
                if (callback != null) {
                    try {
                                    callback.onWriteFailed(error, sequence);
                        callback.onWriteFailed(error, mSequence);
                    } catch (RemoteException re) {
                        Log.e(LOG_TAG, "Error calling onWriteFailed", re);
                    }
                }
            }

            @Override
            public void onWriteCancelled() {
                synchronized (mLock) {
                                    mLayoutOrWriteCancellation = null;
                    clearLocked();
                }
                                // Just close the fd for now.
                                IoUtils.closeQuietly(fd);
            }
                        });
                    } break;

                    case MSG_FINISH: {
                        mDocumentAdapter.onFinish();
                        doFinish();
                    } break;

                    default: {
                        throw new IllegalArgumentException("Unknown message: "
                                + message.what);
                    }
                }
            private void clearLocked() {
                mLayoutOrWriteCancellation = null;
                IoUtils.closeQuietly(mFd);
                mCallback = null;
                mFd = null;
            }
        }
    }
+24 −0
Original line number Diff line number Diff line
<?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.
-->

<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/progress"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dip"
    android:layout_gravity="center_horizontal"
    style="?android:attr/progressBarStyleLarge">
</ProgressBar>
+265 −263
Original line number Diff line number Diff line
@@ -14,7 +14,12 @@
     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:orientation="vertical">

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
@@ -268,20 +273,17 @@
                android:contentDescription="@null">
            </ImageView>

        </GridLayout>

    </ScrollView>

    <Button
        android:id="@+id/print_button"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="fill_horizontal"
            android:layout_row="11"
            android:layout_column="0"
            android:layout_columnSpan="2"
            android:padding="0dip"
        android:text="@string/print_button"
            android:background="?android:attr/selectableItemBackground"
            android:minHeight="?android:attr/listPreferredItemHeight">
        style="?android:attr/buttonBarButtonStyle">
    </Button>

    </GridLayout>

</ScrollView>
</LinearLayout>
+6 −3
Original line number Diff line number Diff line
@@ -55,10 +55,10 @@
    <!-- Title if the number of pages in a printed document is unknown. [CHAR LIMIT=20] -->
    <string name="page_count_unknown">unknown</string>

    <!-- Notifications -->
    <!-- Title for the temporary dialog show while an app is generating a print job. [CHAR LIMIT=30] -->
    <string name="generating_print_job">Generating print job</string>

    <!-- Template for the notificaiton label for a queued print job. [CHAR LIMIT=25] -->
    <string name="queued_notification_title_template">Queued <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
    <!-- Notifications -->

    <!-- Template for the notificaiton label for a printing print job. [CHAR LIMIT=25] -->
    <string name="printing_notification_title_template">Printing <xliff:g id="print_job_name" example="foo.jpg">%1$s</xliff:g></string>
@@ -75,6 +75,9 @@
    <!-- Label for the notification button for restrating a filed print job. [CHAR LIMIT=25] -->
    <string name="restart">Restart</string>

    <!-- Message that there is no connection to a printer. [CHAR LIMIT=40] -->
    <string name="no_connection_to_printer">No connection to printer</string>

    <!-- Arrays -->

    <!-- Color mode labels. -->
+0 −20
Original line number Diff line number Diff line
@@ -65,10 +65,6 @@ public class NotificationController {
        }
        switch (printJob.getState()) {
            case PrintJobInfo.STATE_QUEUED: {
                createQueuingNotificaiton(printJob);
            } break;

            case PrintJobInfo.STATE_STARTED: {
                createPrintingNotificaiton(printJob);
            } break;

@@ -83,22 +79,6 @@ public class NotificationController {
        }
    }

    private void createQueuingNotificaiton(PrintJobInfo printJob) {
        Notification.Builder builder = new Notification.Builder(mContext)
                // TODO: Use appropriate icon when assets are ready
                .setSmallIcon(android.R.drawable.ic_secure)
                .setContentTitle(mContext.getString(R.string.queued_notification_title_template,
                        printJob.getLabel()))
                // TODO: Use appropriate icon when assets are ready
                .addAction(android.R.drawable.ic_secure, mContext.getString(R.string.cancel),
                        createCancelIntent(printJob))
                .setContentText(printJob.getPrinterId().getPrinterName())
                .setWhen(System.currentTimeMillis())
                .setOngoing(true)
                .setShowWhen(true);
        mNotificationManager.notify(printJob.getId(), builder.build());
    }

    private void createPrintingNotificaiton(PrintJobInfo printJob) {
        Notification.Builder builder = new Notification.Builder(mContext)
                // TODO: Use appropriate icon when assets are ready
Loading