1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.printspooler.util; 18 19 import android.annotation.NonNull; 20 import android.content.Context; 21 import android.content.pm.ActivityInfo; 22 import android.content.res.Configuration; 23 import android.print.PrintAttributes.MediaSize; 24 25 import com.android.printspooler.R; 26 27 import java.util.Comparator; 28 import java.util.HashMap; 29 import java.util.Map; 30 31 /** 32 * Utility functions and classes for dealing with media sizes. 33 */ 34 public final class MediaSizeUtils { 35 36 private static Map<MediaSize, Integer> sMediaSizeToStandardMap; 37 38 /** The media size standard for all media sizes no standard is defined for */ 39 private static int sMediaSizeStandardIso; 40 41 private MediaSizeUtils() { 42 /* do nothing - hide constructor */ 43 } 44 45 /** 46 * Gets the default media size for the current locale. 47 * 48 * @param context Context for accessing resources. 49 * @return The default media size. 50 */ 51 public static MediaSize getDefault(Context context) { 52 String mediaSizeId = context.getString(R.string.mediasize_default); 53 return MediaSize.getStandardMediaSizeById(mediaSizeId); 54 } 55 56 /** 57 * Get the standard the {@link MediaSize} belongs to. 58 * 59 * @param context The context of the caller 60 * @param mediaSize The {@link MediaSize} to be resolved 61 * 62 * @return The standard the {@link MediaSize} belongs to 63 */ 64 private static int getStandardForMediaSize(Context context, MediaSize mediaSize) { 65 if (sMediaSizeToStandardMap == null) { 66 sMediaSizeStandardIso = Integer.parseInt(context.getString( 67 R.string.mediasize_standard_iso)); 68 69 sMediaSizeToStandardMap = new HashMap<>(); 70 String[] mediaSizeToStandardMapValues = context.getResources() 71 .getStringArray(R.array.mediasize_to_standard_map); 72 final int mediaSizeToStandardCount = mediaSizeToStandardMapValues.length; 73 for (int i = 0; i < mediaSizeToStandardCount; i += 2) { 74 String mediaSizeId = mediaSizeToStandardMapValues[i]; 75 MediaSize key = MediaSize.getStandardMediaSizeById(mediaSizeId); 76 int value = Integer.parseInt(mediaSizeToStandardMapValues[i + 1]); 77 sMediaSizeToStandardMap.put(key, value); 78 } 79 } 80 Integer standard = sMediaSizeToStandardMap.get(mediaSize); 81 return (standard != null) ? standard : sMediaSizeStandardIso; 82 } 83 84 /** 85 * Comparator for ordering standard media sizes. The ones for the current 86 * standard go to the top and the ones for the other standards follow grouped 87 * by standard. Media sizes of the same standard are ordered alphabetically. 88 */ 89 public static final class MediaSizeComparator implements Comparator<MediaSize> { 90 private final Context mContext; 91 92 /** Current configuration */ 93 private Configuration mCurrentConfig; 94 95 /** The standard to use for the current locale */ 96 private int mCurrentStandard; 97 98 /** Mapping from media size to label */ 99 private final @NonNull Map<MediaSize, String> mMediaSizeToLabel; 100 101 public MediaSizeComparator(Context context) { 102 mContext = context; 103 mMediaSizeToLabel = new HashMap<>(); 104 mCurrentStandard = Integer.parseInt(mContext.getString(R.string.mediasize_standard)); 105 } 106 107 /** 108 * Handle a configuration change by reloading all resources. 109 * 110 * @param newConfig The new configuration that will be applied. 111 */ 112 public void onConfigurationChanged(@NonNull Configuration newConfig) { 113 if (mCurrentConfig == null || 114 (newConfig.diff(mCurrentConfig) & ActivityInfo.CONFIG_LOCALE) != 0) { 115 mCurrentStandard = Integer 116 .parseInt(mContext.getString(R.string.mediasize_standard)); 117 mMediaSizeToLabel.clear(); 118 119 mCurrentConfig = newConfig; 120 } 121 } 122 123 /** 124 * Get the label for a {@link MediaSize}. 125 * 126 * @param context The context the label should be loaded for 127 * @param mediaSize The {@link MediaSize} to resolve 128 * 129 * @return The label for the media size 130 */ 131 public @NonNull String getLabel(@NonNull Context context, @NonNull MediaSize mediaSize) { 132 String label = mMediaSizeToLabel.get(mediaSize); 133 134 if (label == null) { 135 label = mediaSize.getLabel(context.getPackageManager()); 136 mMediaSizeToLabel.put(mediaSize, label); 137 } 138 139 return label; 140 } 141 142 @Override 143 public int compare(MediaSize lhs, MediaSize rhs) { 144 int lhsStandard = getStandardForMediaSize(mContext, lhs); 145 int rhsStandard = getStandardForMediaSize(mContext, rhs); 146 147 // The current standard always wins. 148 if (lhsStandard == mCurrentStandard) { 149 if (rhsStandard != mCurrentStandard) { 150 return -1; 151 } 152 } else if (rhsStandard == mCurrentStandard) { 153 return 1; 154 } 155 156 if (lhsStandard != rhsStandard) { 157 // Different standards - use the standard ordering. 158 return Integer.valueOf(lhsStandard).compareTo(rhsStandard); 159 } else { 160 // Same standard - sort alphabetically by label. 161 return getLabel(mContext, lhs).compareTo(getLabel(mContext, rhs)); 162 } 163 } 164 } 165 } 166