13bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy/*
23bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * Copyright (C) 2013 The Android Open Source Project
33bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy *
43bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * Licensed under the Apache License, Version 2.0 (the "License");
53bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * you may not use this file except in compliance with the License.
63bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * You may obtain a copy of the License at
73bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy *
83bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy *      http://www.apache.org/licenses/LICENSE-2.0
93bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy *
103bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * Unless required by applicable law or agreed to in writing, software
113bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * distributed under the License is distributed on an "AS IS" BASIS,
123bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * See the License for the specific language governing permissions and
143bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * limitations under the License.
153bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy */
163bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
173bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guypackage com.android.printspooler.util;
183bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
193bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport android.annotation.NonNull;
203bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport android.content.Context;
213bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport android.content.pm.ActivityInfo;
223bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport android.content.res.Configuration;
233bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport android.print.PrintAttributes.MediaSize;
243bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
253bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport com.android.printspooler.R;
263bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
273bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport java.util.Comparator;
283bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport java.util.HashMap;
293bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guyimport java.util.Map;
303bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
313bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy/**
323bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy * Utility functions and classes for dealing with media sizes.
333bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy */
343bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guypublic final class MediaSizeUtils {
353bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
363bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    private static Map<MediaSize, Integer> sMediaSizeToStandardMap;
373bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
383bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    /** The media size standard for all media sizes no standard is defined for */
393bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    private static int sMediaSizeStandardIso;
403bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
413bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    private MediaSizeUtils() {
428d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        /* do nothing - hide constructor */
433bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    }
443bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
453bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    /**
463bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * Gets the default media size for the current locale.
473bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     *
483bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * @param context Context for accessing resources.
493bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * @return The default media size.
503bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     */
513bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    public static MediaSize getDefault(Context context) {
523bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        String mediaSizeId = context.getString(R.string.mediasize_default);
533bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        return MediaSize.getStandardMediaSizeById(mediaSizeId);
543bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    }
553bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
563bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    /**
573bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * Get the standard the {@link MediaSize} belongs to.
583bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     *
593bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * @param context   The context of the caller
603bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * @param mediaSize The {@link MediaSize} to be resolved
613bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     *
623bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * @return The standard the {@link MediaSize} belongs to
633bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     */
643bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    private static int getStandardForMediaSize(Context context, MediaSize mediaSize) {
653bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        if (sMediaSizeToStandardMap == null) {
663bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            sMediaSizeStandardIso = Integer.parseInt(context.getString(
673bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                    R.string.mediasize_standard_iso));
683bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
693bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            sMediaSizeToStandardMap = new HashMap<>();
703bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            String[] mediaSizeToStandardMapValues = context.getResources()
713bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                    .getStringArray(R.array.mediasize_to_standard_map);
723bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            final int mediaSizeToStandardCount = mediaSizeToStandardMapValues.length;
733bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            for (int i = 0; i < mediaSizeToStandardCount; i += 2) {
743bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                String mediaSizeId = mediaSizeToStandardMapValues[i];
753bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                MediaSize key = MediaSize.getStandardMediaSizeById(mediaSizeId);
763bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                int value = Integer.parseInt(mediaSizeToStandardMapValues[i + 1]);
773bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                sMediaSizeToStandardMap.put(key, value);
783bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            }
793bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        }
803bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        Integer standard = sMediaSizeToStandardMap.get(mediaSize);
813bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        return (standard != null) ? standard : sMediaSizeStandardIso;
823bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    }
833bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
843bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    /**
853bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * Comparator for ordering standard media sizes. The ones for the current
863bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * standard go to the top and the ones for the other standards follow grouped
873bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     * by standard. Media sizes of the same standard are ordered alphabetically.
883bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy     */
893bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy    public static final class MediaSizeComparator implements Comparator<MediaSize> {
903bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        private final Context mContext;
913bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
923bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        /** Current configuration */
933bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        private Configuration mCurrentConfig;
943bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
953bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        /** The standard to use for the current locale */
963bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        private int mCurrentStandard;
973bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
983bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        /** Mapping from media size to label */
993bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        private final @NonNull Map<MediaSize, String> mMediaSizeToLabel;
1003bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1013bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        public MediaSizeComparator(Context context) {
1023bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            mContext = context;
1033bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            mMediaSizeToLabel = new HashMap<>();
1043bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            mCurrentStandard = Integer.parseInt(mContext.getString(R.string.mediasize_standard));
1053bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        }
1063bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1073bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        /**
1083bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         * Handle a configuration change by reloading all resources.
1093bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         *
1103bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         * @param newConfig The new configuration that will be applied.
1113bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         */
1123bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        public void onConfigurationChanged(@NonNull Configuration newConfig) {
1133bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            if (mCurrentConfig == null ||
1143bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                    (newConfig.diff(mCurrentConfig) & ActivityInfo.CONFIG_LOCALE) != 0) {
1153bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                mCurrentStandard = Integer
1163bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                        .parseInt(mContext.getString(R.string.mediasize_standard));
1173bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                mMediaSizeToLabel.clear();
1183bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1193bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                mCurrentConfig = newConfig;
1203bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            }
1213bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        }
1223bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1233bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        /**
1243bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         * Get the label for a {@link MediaSize}.
1253bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         *
1263bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         * @param context   The context the label should be loaded for
1273bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         * @param mediaSize The {@link MediaSize} to resolve
1283bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         *
1293bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         * @return The label for the media size
1303bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy         */
1313bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        public @NonNull String getLabel(@NonNull Context context, @NonNull MediaSize mediaSize) {
1323bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            String label = mMediaSizeToLabel.get(mediaSize);
1333bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1343bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            if (label == null) {
1353bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                label = mediaSize.getLabel(context.getPackageManager());
1363bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                mMediaSizeToLabel.put(mediaSize, label);
1373bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            }
1383bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1393bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            return label;
1403bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        }
1413bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1423bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        @Override
1433bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy        public int compare(MediaSize lhs, MediaSize rhs) {
1443bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            int lhsStandard = getStandardForMediaSize(mContext, lhs);
1453bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            int rhsStandard = getStandardForMediaSize(mContext, rhs);
1463bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1473bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            // The current standard always wins.
1483bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            if (lhsStandard == mCurrentStandard) {
1493bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                if (rhsStandard != mCurrentStandard) {
1503bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                    return -1;
1513bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                }
1523bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            } else if (rhsStandard == mCurrentStandard) {
1533bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy                return 1;
1543bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            }
1553bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy
1563bbacf27c0be1bae4e4483577fc89ae3113abe5dRomain Guy            if (lhsStandard != rhsStandard) {
1578d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy                // Different standards - use the standard ordering.
1588d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy                return Integer.valueOf(lhsStandard).compareTo(rhsStandard);
1598d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy            } else {
1608d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy                // Same standard - sort alphabetically by label.
1618d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy                return getLabel(mContext, lhs).compareTo(getLabel(mContext, rhs));
1628d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy            }
1638d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy        }
1648d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy    }
1658d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy}
1668d4aeb7111afac0c3c7e56d4ad5d92f9cfce2ffdRomain Guy