Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2006 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 android.widget;
     18 
     19 import android.graphics.Canvas;
     20 import android.graphics.ColorFilter;
     21 import android.graphics.PixelFormat;
     22 import android.graphics.Rect;
     23 import android.graphics.drawable.Drawable;
     24 
     25 /**
     26  * This is only used by View for displaying its scroll bars.  It should probably
     27  * be moved in to the view package since it is used in that lower-level layer.
     28  * For now, we'll hide it so it can be cleaned up later.
     29  * {@hide}
     30  */
     31 public class ScrollBarDrawable extends Drawable {
     32     private Drawable mVerticalTrack;
     33     private Drawable mHorizontalTrack;
     34     private Drawable mVerticalThumb;
     35     private Drawable mHorizontalThumb;
     36     private int mRange;
     37     private int mOffset;
     38     private int mExtent;
     39     private boolean mVertical;
     40     private boolean mChanged;
     41     private boolean mRangeChanged;
     42     private final Rect mTempBounds = new Rect();
     43     private boolean mAlwaysDrawHorizontalTrack;
     44     private boolean mAlwaysDrawVerticalTrack;
     45 
     46     public ScrollBarDrawable() {
     47     }
     48 
     49     /**
     50      * Indicate whether the horizontal scrollbar track should always be drawn regardless of the
     51      * extent. Defaults to false.
     52      *
     53      * @param alwaysDrawTrack Set to true if the track should always be drawn
     54      */
     55     public void setAlwaysDrawHorizontalTrack(boolean alwaysDrawTrack) {
     56         mAlwaysDrawHorizontalTrack = alwaysDrawTrack;
     57     }
     58 
     59     /**
     60      * Indicate whether the vertical scrollbar track should always be drawn regardless of the
     61      * extent. Defaults to false.
     62      *
     63      * @param alwaysDrawTrack Set to true if the track should always be drawn
     64      */
     65     public void setAlwaysDrawVerticalTrack(boolean alwaysDrawTrack) {
     66         mAlwaysDrawVerticalTrack = alwaysDrawTrack;
     67     }
     68 
     69     /**
     70      * Indicates whether the vertical scrollbar track should always be drawn regardless of the
     71      * extent.
     72      */
     73     public boolean getAlwaysDrawVerticalTrack() {
     74         return mAlwaysDrawVerticalTrack;
     75     }
     76 
     77     /**
     78      * Indicates whether the horizontal scrollbar track should always be drawn regardless of the
     79      * extent.
     80      */
     81     public boolean getAlwaysDrawHorizontalTrack() {
     82         return mAlwaysDrawHorizontalTrack;
     83     }
     84 
     85     public void setParameters(int range, int offset, int extent, boolean vertical) {
     86         if (mVertical != vertical) {
     87             mChanged = true;
     88         }
     89 
     90         if (mRange != range || mOffset != offset || mExtent != extent) {
     91             mRangeChanged = true;
     92         }
     93 
     94         mRange = range;
     95         mOffset = offset;
     96         mExtent = extent;
     97         mVertical = vertical;
     98     }
     99 
    100     @Override
    101     public void draw(Canvas canvas) {
    102         final boolean vertical = mVertical;
    103         final int extent = mExtent;
    104         final int range = mRange;
    105 
    106         boolean drawTrack = true;
    107         boolean drawThumb = true;
    108         if (extent <= 0 || range <= extent) {
    109             drawTrack = vertical ? mAlwaysDrawVerticalTrack : mAlwaysDrawHorizontalTrack;
    110             drawThumb = false;
    111         }
    112 
    113         Rect r = getBounds();
    114         if (canvas.quickReject(r.left, r.top, r.right, r.bottom, Canvas.EdgeType.AA)) {
    115             return;
    116         }
    117         if (drawTrack) {
    118             drawTrack(canvas, r, vertical);
    119         }
    120 
    121         if (drawThumb) {
    122             int size = vertical ? r.height() : r.width();
    123             int thickness = vertical ? r.width() : r.height();
    124             int length = Math.round((float) size * extent / range);
    125             int offset = Math.round((float) (size - length) * mOffset / (range - extent));
    126 
    127             // avoid the tiny thumb
    128             int minLength = thickness * 2;
    129             if (length < minLength) {
    130                 length = minLength;
    131             }
    132             // avoid the too-big thumb
    133             if (offset + length > size) {
    134                 offset = size - length;
    135             }
    136 
    137             drawThumb(canvas, r, offset, length, vertical);
    138         }
    139     }
    140 
    141     @Override
    142     protected void onBoundsChange(Rect bounds) {
    143         super.onBoundsChange(bounds);
    144         mChanged = true;
    145     }
    146 
    147     protected void drawTrack(Canvas canvas, Rect bounds, boolean vertical) {
    148         Drawable track;
    149         if (vertical) {
    150             track = mVerticalTrack;
    151         } else {
    152             track = mHorizontalTrack;
    153         }
    154         if (track != null) {
    155             if (mChanged) {
    156                 track.setBounds(bounds);
    157             }
    158             track.draw(canvas);
    159         }
    160     }
    161 
    162     protected void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) {
    163         final Rect thumbRect = mTempBounds;
    164         final boolean changed = mRangeChanged || mChanged;
    165         if (changed) {
    166             if (vertical) {
    167                 thumbRect.set(bounds.left,  bounds.top + offset,
    168                         bounds.right, bounds.top + offset + length);
    169             } else {
    170                 thumbRect.set(bounds.left + offset, bounds.top,
    171                         bounds.left + offset + length, bounds.bottom);
    172             }
    173         }
    174 
    175         if (vertical) {
    176             if (mVerticalThumb != null) {
    177                 final Drawable thumb = mVerticalThumb;
    178                 if (changed) thumb.setBounds(thumbRect);
    179                 thumb.draw(canvas);
    180             }
    181         } else {
    182             if (mHorizontalThumb != null) {
    183                 final Drawable thumb = mHorizontalThumb;
    184                 if (changed) thumb.setBounds(thumbRect);
    185                 thumb.draw(canvas);
    186             }
    187         }
    188     }
    189 
    190     public void setVerticalThumbDrawable(Drawable thumb) {
    191         if (thumb != null) {
    192             mVerticalThumb = thumb;
    193         }
    194     }
    195 
    196     public void setVerticalTrackDrawable(Drawable track) {
    197         mVerticalTrack = track;
    198     }
    199 
    200     public void setHorizontalThumbDrawable(Drawable thumb) {
    201         if (thumb != null) {
    202             mHorizontalThumb = thumb;
    203         }
    204     }
    205 
    206     public void setHorizontalTrackDrawable(Drawable track) {
    207         mHorizontalTrack = track;
    208     }
    209 
    210     public int getSize(boolean vertical) {
    211         if (vertical) {
    212             return mVerticalTrack != null ? mVerticalTrack.getIntrinsicWidth() :
    213                     mVerticalThumb != null ? mVerticalThumb.getIntrinsicWidth() : 0;
    214         } else {
    215             return mHorizontalTrack != null ? mHorizontalTrack.getIntrinsicHeight() :
    216                     mHorizontalThumb != null ? mHorizontalThumb.getIntrinsicHeight() : 0;
    217         }
    218     }
    219 
    220     @Override
    221     public void setAlpha(int alpha) {
    222         if (mVerticalTrack != null) {
    223             mVerticalTrack.setAlpha(alpha);
    224         }
    225         if (mVerticalThumb != null) {
    226             mVerticalThumb.setAlpha(alpha);
    227         }
    228         if (mHorizontalTrack != null) {
    229             mHorizontalTrack.setAlpha(alpha);
    230         }
    231         if (mHorizontalThumb != null) {
    232             mHorizontalThumb.setAlpha(alpha);
    233         }
    234     }
    235 
    236     @Override
    237     public int getAlpha() {
    238         // All elements should have same alpha, just return one of them
    239         return mVerticalThumb.getAlpha();
    240     }
    241 
    242     @Override
    243     public void setColorFilter(ColorFilter cf) {
    244         if (mVerticalTrack != null) {
    245             mVerticalTrack.setColorFilter(cf);
    246         }
    247         if (mVerticalThumb != null) {
    248             mVerticalThumb.setColorFilter(cf);
    249         }
    250         if (mHorizontalTrack != null) {
    251             mHorizontalTrack.setColorFilter(cf);
    252         }
    253         if (mHorizontalThumb != null) {
    254             mHorizontalThumb.setColorFilter(cf);
    255         }
    256     }
    257 
    258     @Override
    259     public int getOpacity() {
    260         return PixelFormat.TRANSLUCENT;
    261     }
    262 
    263     @Override
    264     public String toString() {
    265         return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset +
    266                " extent=" + mExtent + (mVertical ? " V" : " H");
    267     }
    268 }
    269 
    270 
    271