Home | History | Annotate | Download | only in bitmap
      1 package com.android.mail.bitmap;
      2 
      3 import android.graphics.Canvas;
      4 import android.graphics.ColorFilter;
      5 import android.graphics.PixelFormat;
      6 import android.graphics.Rect;
      7 import android.graphics.drawable.Drawable;
      8 
      9 import com.android.bitmap.Trace;
     10 
     11 import java.util.ArrayList;
     12 import java.util.List;
     13 
     14 /**
     15  * A drawable that contains up to 4 other smaller drawables in a regular grid. This class attempts
     16  * to reuse inner drawables when feasible to promote object reuse. This design goal makes the API
     17  * to reuse an instance a little awkward: you must first zero out the count, then set it to a new
     18  * value, then populate the entries with {@link #getOrCreateDrawable(int)} and a drawable subclass
     19  * bind() method of your design.
     20  */
     21 public abstract class CompositeDrawable<T extends Drawable> extends Drawable
     22         implements Drawable.Callback {
     23 
     24     protected final List<T> mDrawables;
     25     protected int mCount;
     26 
     27     public CompositeDrawable(int maxDivisions) {
     28         if (maxDivisions >= 4) {
     29             throw new IllegalArgumentException("CompositeDrawable only supports 4 divisions");
     30         }
     31         mDrawables = new ArrayList<T>(maxDivisions);
     32         for (int i = 0; i < maxDivisions; i++) {
     33             mDrawables.add(i, null);
     34         }
     35         mCount = 0;
     36     }
     37 
     38     protected abstract T createDivisionDrawable();
     39 
     40     public void setCount(int count) {
     41         // zero out the composite bounds, which will propagate to the division drawables
     42         // this invalidates any old division bounds, which may change with the count
     43         setBounds(0, 0, 0, 0);
     44         mCount = count;
     45     }
     46 
     47     public int getCount() {
     48         return mCount;
     49     }
     50 
     51     public T getOrCreateDrawable(int i) {
     52         if (i >= mCount) {
     53             throw new IllegalArgumentException("bad index: " + i);
     54         }
     55 
     56         T result = mDrawables.get(i);
     57         if (result == null) {
     58             Trace.beginSection("create division drawable");
     59             result = createDivisionDrawable();
     60             mDrawables.set(i, result);
     61             result.setCallback(this);
     62             // Make sure drawables created after the bounds were already set have their bounds
     63             // set initially (the other unaffected drawables basically de-bounce this).
     64             onBoundsChange(getBounds());
     65             Trace.endSection();
     66         }
     67         return result;
     68     }
     69 
     70     @Override
     71     protected void onBoundsChange(Rect bounds) {
     72         final int w = bounds.width();
     73         final int h = bounds.height();
     74         final int mw = w / 2;
     75         final int mh = h / 2;
     76         switch (mCount) {
     77             case 1:
     78                 // 1 bitmap: passthrough
     79                 applyBounds(0, 0, 0, w, h);
     80                 break;
     81             case 2:
     82                 // 2 bitmaps split vertically
     83                 applyBounds(0, 0, 0, mw, h);
     84                 applyBounds(1, mw, 0, w, h);
     85                 break;
     86             case 3:
     87                 // 1st is tall on the left, 2nd/3rd stacked vertically on the right
     88                 applyBounds(0, 0, 0, mw, h);
     89                 applyBounds(1, mw, 0, w, mh);
     90                 applyBounds(2, mw, mh, w, h);
     91                 break;
     92             case 4:
     93                 // 4 bitmaps in a 2x2 grid
     94                 applyBounds(0, 0, 0, mw, mh);
     95                 applyBounds(1, mw, 0, w, mh);
     96                 applyBounds(2, 0, mh, mw, h);
     97                 applyBounds(3, mw, mh, w, h);
     98                 break;
     99         }
    100     }
    101 
    102     private void applyBounds(int index, int left, int top, int right, int bottom) {
    103         final T d = mDrawables.get(index);
    104         if (d == null) {
    105             return;
    106         }
    107         d.setBounds(left, top, right, bottom);
    108     }
    109 
    110     @Override
    111     public void draw(Canvas canvas) {
    112         for (int i = 0; i < mCount; i++) {
    113             mDrawables.get(i).draw(canvas);
    114         }
    115     }
    116 
    117     @Override
    118     public void setAlpha(int alpha) {
    119         for (int i = 0; i < mCount; i++) {
    120             mDrawables.get(i).setAlpha(alpha);
    121         }
    122     }
    123 
    124     @Override
    125     public void setColorFilter(ColorFilter cf) {
    126         for (int i = 0; i < mCount; i++) {
    127             mDrawables.get(i).setColorFilter(cf);
    128         }
    129     }
    130 
    131     @Override
    132     public int getOpacity() {
    133         int opacity = PixelFormat.OPAQUE;
    134         for (int i = 0; i < mCount; i++) {
    135             if (mDrawables.get(i).getOpacity() != PixelFormat.OPAQUE) {
    136                 opacity = PixelFormat.TRANSLUCENT;
    137                 break;
    138             }
    139         }
    140         return opacity;
    141     }
    142 
    143     @Override
    144     public void invalidateDrawable(Drawable who) {
    145         invalidateSelf();
    146     }
    147 
    148     @Override
    149     public void scheduleDrawable(Drawable who, Runnable what, long when) {
    150         scheduleSelf(what, when);
    151     }
    152 
    153     @Override
    154     public void unscheduleDrawable(Drawable who, Runnable what) {
    155         unscheduleSelf(what);
    156     }
    157 
    158 }
    159