mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 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.mail.ui; |
| 18 | |
| 19 | import android.content.Context; |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 20 | import android.content.res.Resources; |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 21 | import android.graphics.Bitmap; |
| 22 | import android.graphics.Canvas; |
| 23 | import android.graphics.Paint; |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 24 | import android.graphics.PorterDuff.Mode; |
| 25 | import android.graphics.PorterDuffXfermode; |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 26 | import android.graphics.Rect; |
| 27 | |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 28 | import com.android.mail.R; |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 29 | import com.android.mail.utils.Utils; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 30 | import com.google.common.collect.Lists; |
| 31 | import com.google.common.collect.Maps; |
mindyp | 9009e59 | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 32 | |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 33 | import java.util.ArrayList; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 34 | import java.util.List; |
| 35 | import java.util.Map; |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 36 | |
| 37 | /** |
| 38 | * DividedImageCanvas creates a canvas that can display into a minimum of 1 |
| 39 | * and maximum of 4 images. As images are added, they |
| 40 | * are laid out according to the following algorithm: |
| 41 | * 1 Image: Draw the bitmap filling the entire canvas. |
| 42 | * 2 Images: Draw 2 bitmaps split vertically down the middle. |
| 43 | * 3 Images: Draw 3 bitmaps: the first takes up all vertical space; the 2nd and 3rd are stacked in |
| 44 | * the second vertical position. |
| 45 | * 4 Images: Divide the Canvas into 4 equal quadrants and draws 1 bitmap in each. |
| 46 | */ |
Mark Wei | 47cb510 | 2013-03-19 04:27:06 -0700 | [diff] [blame] | 47 | public class DividedImageCanvas implements ImageCanvas { |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 48 | public static final int MAX_DIVISIONS = 4; |
| 49 | |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 50 | private final Map<String, Integer> mDivisionMap = Maps |
| 51 | .newHashMapWithExpectedSize(MAX_DIVISIONS); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 52 | private Bitmap mDividedBitmap; |
| 53 | private Canvas mCanvas; |
| 54 | private int mWidth; |
| 55 | private int mHeight; |
| 56 | |
| 57 | private final Context mContext; |
| 58 | private final InvalidateCallback mCallback; |
mindyp | 379ff59 | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 59 | private final ArrayList<Bitmap> mDivisionImages = new ArrayList<Bitmap>(MAX_DIVISIONS); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 60 | |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 61 | /** |
| 62 | * Ignore any request to draw final output when not yet ready. This prevents partially drawn |
| 63 | * canvases from appearing. |
| 64 | */ |
| 65 | private boolean mBitmapValid = false; |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 66 | |
Andy Huang | b53fe05 | 2013-04-20 23:37:37 -0700 | [diff] [blame] | 67 | private int mGeneration; |
| 68 | |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 69 | private static final Paint sPaint = new Paint(); |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 70 | private static final Paint sClearPaint = new Paint(); |
| 71 | private static final Rect sSrc = new Rect(); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 72 | private static final Rect sDest = new Rect(); |
| 73 | |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 74 | private static int sDividerLineWidth = -1; |
| 75 | private static int sDividerColor; |
| 76 | |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 77 | static { |
| 78 | sClearPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR)); |
| 79 | } |
| 80 | |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 81 | public DividedImageCanvas(Context context, InvalidateCallback callback) { |
| 82 | mContext = context; |
| 83 | mCallback = callback; |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 84 | setupDividerLines(); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 85 | } |
| 86 | |
| 87 | /** |
| 88 | * Get application context for this object. |
| 89 | */ |
| 90 | public Context getContext() { |
| 91 | return mContext; |
| 92 | } |
| 93 | |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 94 | @Override |
| 95 | public String toString() { |
| 96 | final StringBuilder sb = new StringBuilder("{"); |
| 97 | sb.append(super.toString()); |
| 98 | sb.append(" mDivisionMap="); |
| 99 | sb.append(mDivisionMap); |
| 100 | sb.append(" mDivisionImages="); |
| 101 | sb.append(mDivisionImages); |
| 102 | sb.append(" mWidth="); |
| 103 | sb.append(mWidth); |
| 104 | sb.append(" mHeight="); |
| 105 | sb.append(mHeight); |
| 106 | sb.append("}"); |
| 107 | return sb.toString(); |
| 108 | } |
| 109 | |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 110 | /** |
| 111 | * Set the id associated with each quadrant. The quadrants are laid out: |
| 112 | * TopLeft, TopRight, Bottom Left, Bottom Right |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 113 | * @param keys |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 114 | */ |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 115 | public void setDivisionIds(List<Object> keys) { |
| 116 | if (keys.size() > MAX_DIVISIONS) { |
| 117 | throw new IllegalArgumentException("too many divisionIds: " + keys); |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 118 | } |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 119 | |
| 120 | boolean needClear = getDivisionCount() != keys.size(); |
| 121 | if (!needClear) { |
| 122 | for (int i = 0; i < keys.size(); i++) { |
| 123 | String divisionId = transformKeyToDivisionId(keys.get(i)); |
| 124 | // different item or different place |
| 125 | if (!mDivisionMap.containsKey(divisionId) || mDivisionMap.get(divisionId) != i) { |
| 126 | needClear = true; |
| 127 | break; |
| 128 | } |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | if (needClear) { |
| 133 | mDivisionMap.clear(); |
| 134 | mDivisionImages.clear(); |
| 135 | int i = 0; |
| 136 | for (Object key : keys) { |
| 137 | String divisionId = transformKeyToDivisionId(key); |
| 138 | mDivisionMap.put(divisionId, i); |
| 139 | mDivisionImages.add(null); |
| 140 | i++; |
| 141 | } |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 142 | } |
| 143 | } |
| 144 | |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 145 | private void draw(Bitmap b, int left, int top, int right, int bottom) { |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 146 | if (b != null) { |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 147 | // Some times we load taller images compared to the destination rect on the canvas |
| 148 | int srcTop = 0; |
| 149 | int srcBottom = b.getHeight(); |
| 150 | int destHeight = bottom - top; |
| 151 | if (b.getHeight() > bottom - top) { |
| 152 | srcTop = b.getHeight() / 2 - destHeight/2; |
| 153 | srcBottom = b.getHeight() / 2 + destHeight/2; |
| 154 | } |
| 155 | |
| 156 | // todo:markwei do not scale very small bitmaps |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 157 | // l t r b |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 158 | sSrc.set(0, srcTop, b.getWidth(), srcBottom); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 159 | sDest.set(left, top, right, bottom); |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 160 | mCanvas.drawBitmap(b, sSrc, sDest, sPaint); |
| 161 | } else { |
| 162 | // clear |
| 163 | mCanvas.drawRect(left, top, right, bottom, sClearPaint); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 164 | } |
| 165 | } |
| 166 | |
| 167 | /** |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 168 | * Get the desired dimensions and scale for the bitmap to be placed in the |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 169 | * location corresponding to id. Caller must allocate the Dimensions object. |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 170 | * @param key |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 171 | * @param outDim a {@link ImageCanvas.Dimensions} object to write results into |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 172 | */ |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 173 | @Override |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 174 | public void getDesiredDimensions(Object key, Dimensions outDim) { |
| 175 | Utils.traceBeginSection("get desired dimensions"); |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 176 | int w = 0, h = 0; |
| 177 | float scale = 0; |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 178 | final Integer pos = mDivisionMap.get(transformKeyToDivisionId(key)); |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 179 | if (pos != null && pos >= 0) { |
| 180 | final int size = mDivisionMap.size(); |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 181 | switch (size) { |
| 182 | case 0: |
| 183 | break; |
| 184 | case 1: |
| 185 | w = mWidth; |
| 186 | h = mHeight; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 187 | scale = Dimensions.SCALE_ONE; |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 188 | break; |
| 189 | case 2: |
| 190 | w = mWidth / 2; |
| 191 | h = mHeight; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 192 | scale = Dimensions.SCALE_HALF; |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 193 | break; |
| 194 | case 3: |
| 195 | switch (pos) { |
| 196 | case 0: |
| 197 | w = mWidth / 2; |
| 198 | h = mHeight; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 199 | scale = Dimensions.SCALE_HALF; |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 200 | break; |
| 201 | default: |
| 202 | w = mWidth / 2; |
| 203 | h = mHeight / 2; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 204 | scale = Dimensions.SCALE_QUARTER; |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 205 | } |
| 206 | break; |
| 207 | case 4: |
| 208 | w = mWidth / 2; |
| 209 | h = mHeight / 2; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 210 | scale = Dimensions.SCALE_QUARTER; |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 211 | break; |
| 212 | } |
| 213 | } |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 214 | outDim.width = w; |
| 215 | outDim.height = h; |
| 216 | outDim.scale = scale; |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 217 | Utils.traceEndSection(); |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 218 | } |
| 219 | |
| 220 | @Override |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 221 | public void drawImage(Bitmap b, Object key) { |
| 222 | addDivisionImage(b, key); |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 223 | } |
| 224 | |
mindyp | 379ff59 | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 225 | /** |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 226 | * Add a bitmap to this view in the quadrant matching its id. |
| 227 | * @param b Bitmap |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 228 | * @param key Id to look for that was previously set in setDivisionIds. |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 229 | */ |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 230 | public void addDivisionImage(Bitmap b, Object key) { |
| 231 | if (b != null) { |
| 232 | addOrClearDivisionImage(b, key); |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | public void clearDivisionImage(Object key) { |
| 237 | addOrClearDivisionImage(null, key); |
| 238 | } |
| 239 | private void addOrClearDivisionImage(Bitmap b, Object key) { |
| 240 | Utils.traceBeginSection("add or clear division image"); |
| 241 | final Integer pos = mDivisionMap.get(transformKeyToDivisionId(key)); |
| 242 | if (pos != null && pos >= 0) { |
mindyp | 379ff59 | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 243 | mDivisionImages.set(pos, b); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 244 | boolean complete = false; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 245 | final int width = mWidth; |
| 246 | final int height = mHeight; |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 247 | // Different layouts depending on count. |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 248 | final int size = mDivisionMap.size(); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 249 | switch (size) { |
| 250 | case 0: |
| 251 | // Do nothing. |
| 252 | break; |
| 253 | case 1: |
| 254 | // Draw the bitmap filling the entire canvas. |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 255 | draw(mDivisionImages.get(0), 0, 0, width, height); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 256 | complete = true; |
| 257 | break; |
| 258 | case 2: |
| 259 | // Draw 2 bitmaps split vertically down the middle |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 260 | switch (pos) { |
| 261 | case 0: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 262 | draw(mDivisionImages.get(0), 0, 0, width / 2, height); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 263 | break; |
| 264 | case 1: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 265 | draw(mDivisionImages.get(1), width / 2, 0, width, height); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 266 | break; |
| 267 | } |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 268 | complete = mDivisionImages.get(0) != null && mDivisionImages.get(1) != null |
| 269 | || isPartialBitmapComplete(); |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 270 | if (complete) { |
| 271 | // Draw dividers |
| 272 | drawVerticalDivider(width, height); |
| 273 | } |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 274 | break; |
| 275 | case 3: |
| 276 | // Draw 3 bitmaps: the first takes up all vertical |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 277 | // space, the 2nd and 3rd are stacked in the second vertical |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 278 | // position. |
| 279 | switch (pos) { |
| 280 | case 0: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 281 | draw(mDivisionImages.get(0), 0, 0, width / 2, height); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 282 | break; |
| 283 | case 1: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 284 | draw(mDivisionImages.get(1), width / 2, 0, width, height / 2); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 285 | break; |
| 286 | case 2: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 287 | draw(mDivisionImages.get(2), width / 2, height / 2, width, height); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 288 | break; |
| 289 | } |
| 290 | complete = mDivisionImages.get(0) != null && mDivisionImages.get(1) != null |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 291 | && mDivisionImages.get(2) != null || isPartialBitmapComplete(); |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 292 | if (complete) { |
| 293 | // Draw dividers |
| 294 | drawVerticalDivider(width, height); |
mindyp | 3f22573 | 2013-01-17 14:45:26 -0800 | [diff] [blame] | 295 | drawHorizontalDivider(width / 2, height / 2, width, height / 2); |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 296 | } |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 297 | break; |
| 298 | default: |
| 299 | // Draw all 4 bitmaps in a grid |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 300 | switch (pos) { |
| 301 | case 0: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 302 | draw(mDivisionImages.get(0), 0, 0, width / 2, height / 2); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 303 | break; |
| 304 | case 1: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 305 | draw(mDivisionImages.get(1), width / 2, 0, width, height / 2); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 306 | break; |
| 307 | case 2: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 308 | draw(mDivisionImages.get(2), 0, height / 2, width / 2, height); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 309 | break; |
| 310 | case 3: |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 311 | draw(mDivisionImages.get(3), width / 2, height / 2, width, height); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 312 | break; |
| 313 | } |
| 314 | complete = mDivisionImages.get(0) != null && mDivisionImages.get(1) != null |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 315 | && mDivisionImages.get(2) != null && mDivisionImages.get(3) != null |
| 316 | || isPartialBitmapComplete(); |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 317 | if (complete) { |
| 318 | // Draw dividers |
| 319 | drawVerticalDivider(width, height); |
mindyp | 3f22573 | 2013-01-17 14:45:26 -0800 | [diff] [blame] | 320 | drawHorizontalDivider(0, height / 2, width, height / 2); |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 321 | } |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 322 | break; |
| 323 | } |
| 324 | // Create the new image bitmap. |
| 325 | if (complete) { |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 326 | mBitmapValid = true; |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 327 | mCallback.invalidate(); |
| 328 | } |
| 329 | } |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 330 | Utils.traceEndSection(); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 331 | } |
| 332 | |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 333 | public boolean hasImageFor(Object key) { |
| 334 | final Integer pos = mDivisionMap.get(transformKeyToDivisionId(key)); |
Andy Huang | bbe7f92 | 2013-04-22 14:35:28 -0700 | [diff] [blame] | 335 | return pos != null && mDivisionImages.get(pos) != null; |
| 336 | } |
| 337 | |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 338 | private void setupDividerLines() { |
| 339 | if (sDividerLineWidth == -1) { |
| 340 | Resources res = getContext().getResources(); |
| 341 | sDividerLineWidth = res |
| 342 | .getDimensionPixelSize(R.dimen.tile_divider_width); |
| 343 | sDividerColor = res.getColor(R.color.tile_divider_color); |
| 344 | } |
| 345 | } |
| 346 | |
Scott Kennedy | ff8553f | 2013-04-05 20:57:44 -0700 | [diff] [blame] | 347 | private static void setupPaint() { |
mindyp | 3f22573 | 2013-01-17 14:45:26 -0800 | [diff] [blame] | 348 | sPaint.setStrokeWidth(sDividerLineWidth); |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 349 | sPaint.setColor(sDividerColor); |
mindyp | 3f22573 | 2013-01-17 14:45:26 -0800 | [diff] [blame] | 350 | } |
| 351 | |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 352 | protected void drawVerticalDivider(int width, int height) { |
mindyp | 3f22573 | 2013-01-17 14:45:26 -0800 | [diff] [blame] | 353 | int x1 = width / 2, y1 = 0, x2 = width/2, y2 = height; |
| 354 | setupPaint(); |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 355 | mCanvas.drawLine(x1, y1, x2, y2, sPaint); |
| 356 | } |
| 357 | |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 358 | protected void drawHorizontalDivider(int x1, int y1, int x2, int y2) { |
mindyp | 3f22573 | 2013-01-17 14:45:26 -0800 | [diff] [blame] | 359 | setupPaint(); |
mindyp | b47828f | 2013-01-17 13:55:44 -0800 | [diff] [blame] | 360 | mCanvas.drawLine(x1, y1, x2, y2, sPaint); |
| 361 | } |
| 362 | |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 363 | protected boolean isPartialBitmapComplete() { |
| 364 | return false; |
| 365 | } |
| 366 | |
| 367 | protected String transformKeyToDivisionId(Object key) { |
| 368 | return key.toString(); |
| 369 | } |
| 370 | |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 371 | /** |
| 372 | * Draw the contents of the DividedImageCanvas to the supplied canvas. |
| 373 | */ |
| 374 | public void draw(Canvas canvas) { |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 375 | // todo:markwei we can see the old image behind transparency regions. Should we also |
| 376 | // "clear" the canvas? ath |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 377 | if (mDividedBitmap != null && mBitmapValid) { |
| 378 | canvas.drawBitmap(mDividedBitmap, 0, 0, null); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 379 | } |
| 380 | } |
| 381 | |
Mark Wei | 47cb510 | 2013-03-19 04:27:06 -0700 | [diff] [blame] | 382 | @Override |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 383 | public void reset() { |
mindyp | 379ff59 | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 384 | if (mCanvas != null && mDividedBitmap != null) { |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 385 | mBitmapValid = false; |
mindyp | 379ff59 | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 386 | } |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 387 | mDivisionMap.clear(); |
mindyp | 379ff59 | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 388 | mDivisionImages.clear(); |
Andy Huang | b53fe05 | 2013-04-20 23:37:37 -0700 | [diff] [blame] | 389 | mGeneration++; |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 390 | } |
| 391 | |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 392 | @Override |
Andy Huang | b53fe05 | 2013-04-20 23:37:37 -0700 | [diff] [blame] | 393 | public int getGeneration() { |
| 394 | return mGeneration; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 395 | } |
| 396 | |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 397 | /** |
| 398 | * Set the width and height of the canvas. |
| 399 | * @param width |
| 400 | * @param height |
| 401 | */ |
| 402 | public void setDimensions(int width, int height) { |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 403 | Utils.traceBeginSection("set dimensions"); |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 404 | if (mWidth == width && mHeight == height) { |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 405 | Utils.traceEndSection(); |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 406 | return; |
| 407 | } |
| 408 | |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 409 | mWidth = width; |
| 410 | mHeight = height; |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 411 | |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 412 | // todo:ath this bitmap is creating a GC which is killing CIV.loadAttachmentPreviews() |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 413 | mDividedBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); |
| 414 | mCanvas = new Canvas(mDividedBitmap); |
| 415 | mBitmapValid = true; |
Mark Wei | 479505d | 2013-03-21 06:04:46 -0700 | [diff] [blame] | 416 | Utils.traceEndSection(); |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 417 | } |
| 418 | |
| 419 | /** |
| 420 | * Get the resulting canvas width. |
| 421 | */ |
| 422 | public int getWidth() { |
| 423 | return mWidth; |
| 424 | } |
| 425 | |
| 426 | /** |
| 427 | * Get the resulting canvas height. |
| 428 | */ |
| 429 | public int getHeight() { |
| 430 | return mHeight; |
| 431 | } |
| 432 | |
| 433 | /** |
| 434 | * The class that will provided the canvas to which the DividedImageCanvas |
| 435 | * should render its contents must implement this interface. |
| 436 | */ |
| 437 | public interface InvalidateCallback { |
| 438 | public void invalidate(); |
| 439 | } |
mindyp | 5395555 | 2013-01-10 15:42:39 -0800 | [diff] [blame] | 440 | |
mindyp | 646d4fc | 2013-01-15 17:17:10 -0800 | [diff] [blame] | 441 | public int getDivisionCount() { |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 442 | return mDivisionMap.size(); |
mindyp | 646d4fc | 2013-01-15 17:17:10 -0800 | [diff] [blame] | 443 | } |
| 444 | |
| 445 | /** |
mindyp | 6fbad63 | 2013-01-17 09:59:25 -0800 | [diff] [blame] | 446 | * Get the division ids currently associated with this DivisionImageCanvas. |
| 447 | */ |
| 448 | public ArrayList<String> getDivisionIds() { |
Andy Huang | 8b7fab5 | 2013-04-15 11:34:10 -0700 | [diff] [blame] | 449 | return Lists.newArrayList(mDivisionMap.keySet()); |
mindyp | 6fbad63 | 2013-01-17 09:59:25 -0800 | [diff] [blame] | 450 | } |
mindyp | 6d11c8f | 2013-01-03 13:19:15 -0800 | [diff] [blame] | 451 | } |