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             final Drawable thumb = mVerticalThumb;
    177             if (changed) thumb.setBounds(thumbRect);
    178             thumb.draw(canvas);
    179         } else {
    180             final Drawable thumb = mHorizontalThumb;
    181             if (changed) thumb.setBounds(thumbRect);
    182             thumb.draw(canvas);
    183         }
    184     }
    185 
    186     public void setVerticalThumbDrawable(Drawable thumb) {
    187         if (thumb != null) {
    188             mVerticalThumb = thumb;
    189         }
    190     }
    191 
    192     public void setVerticalTrackDrawable(Drawable track) {
    193         mVerticalTrack = track;
    194     }
    195 
    196     public void setHorizontalThumbDrawable(Drawable thumb) {
    197         if (thumb != null) {
    198             mHorizontalThumb = thumb;
    199         }
    200     }
    201 
    202     public void setHorizontalTrackDrawable(Drawable track) {
    203         mHorizontalTrack = track;
    204     }
    205 
    206     public int getSize(boolean vertical) {
    207         if (vertical) {
    208             return (mVerticalTrack != null ?
    209                     mVerticalTrack : mVerticalThumb).getIntrinsicWidth();
    210         } else {
    211             return (mHorizontalTrack != null ?
    212                     mHorizontalTrack : mHorizontalThumb).getIntrinsicHeight();
    213         }
    214     }
    215 
    216     @Override
    217     public void setAlpha(int alpha) {
    218         if (mVerticalTrack != null) {
    219             mVerticalTrack.setAlpha(alpha);
    220         }
    221         mVerticalThumb.setAlpha(alpha);
    222         if (mHorizontalTrack != null) {
    223             mHorizontalTrack.setAlpha(alpha);
    224         }
    225         mHorizontalThumb.setAlpha(alpha);
    226     }
    227 
    228     @Override
    229     public int getAlpha() {
    230         // All elements should have same alpha, just return one of them
    231         return mVerticalThumb.getAlpha();
    232     }
    233 
    234     @Override
    235     public void setColorFilter(ColorFilter cf) {
    236         if (mVerticalTrack != null) {
    237             mVerticalTrack.setColorFilter(cf);
    238         }
    239         mVerticalThumb.setColorFilter(cf);
    240         if (mHorizontalTrack != null) {
    241             mHorizontalTrack.setColorFilter(cf);
    242         }
    243         mHorizontalThumb.setColorFilter(cf);
    244     }
    245 
    246     @Override
    247     public int getOpacity() {
    248         return PixelFormat.TRANSLUCENT;
    249     }
    250 
    251     @Override
    252     public String toString() {
    253         return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset +
    254                " extent=" + mExtent + (mVertical ? " V" : " H");
    255     }
    256 }
    257 
    258 
    259