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,
    115                 Canvas.EdgeType.AA)) {
    116             return;
    117         }
    118         if (drawTrack) {
    119             drawTrack(canvas, r, vertical);
    120         }
    121 
    122         if (drawThumb) {
    123             int size = vertical ? r.height() : r.width();
    124             int thickness = vertical ? r.width() : r.height();
    125             int length = Math.round((float) size * extent / range);
    126             int offset = Math.round((float) (size - length) * mOffset / (range - extent));
    127 
    128             // avoid the tiny thumb
    129             int minLength = thickness * 2;
    130             if (length < minLength) {
    131                 length = minLength;
    132             }
    133             // avoid the too-big thumb
    134             if (offset + length > size) {
    135                 offset = size - length;
    136             }
    137 
    138             drawThumb(canvas, r, offset, length, vertical);
    139         }
    140     }
    141 
    142     @Override
    143     protected void onBoundsChange(Rect bounds) {
    144         super.onBoundsChange(bounds);
    145         mChanged = true;
    146     }
    147 
    148     protected void drawTrack(Canvas canvas, Rect bounds, boolean vertical) {
    149         Drawable track;
    150         if (vertical) {
    151             track = mVerticalTrack;
    152         } else {
    153             track = mHorizontalTrack;
    154         }
    155         if (track != null) {
    156             if (mChanged) {
    157                 track.setBounds(bounds);
    158             }
    159             track.draw(canvas);
    160         }
    161     }
    162 
    163     protected void drawThumb(Canvas canvas, Rect bounds, int offset, int length, boolean vertical) {
    164         final Rect thumbRect = mTempBounds;
    165         final boolean changed = mRangeChanged || mChanged;
    166         if (changed) {
    167             if (vertical) {
    168                 thumbRect.set(bounds.left,  bounds.top + offset,
    169                         bounds.right, bounds.top + offset + length);
    170             } else {
    171                 thumbRect.set(bounds.left + offset, bounds.top,
    172                         bounds.left + offset + length, bounds.bottom);
    173             }
    174         }
    175 
    176         if (vertical) {
    177             final Drawable thumb = mVerticalThumb;
    178             if (changed) thumb.setBounds(thumbRect);
    179             thumb.draw(canvas);
    180         } else {
    181             final Drawable thumb = mHorizontalThumb;
    182             if (changed) thumb.setBounds(thumbRect);
    183             thumb.draw(canvas);
    184         }
    185     }
    186 
    187     public void setVerticalThumbDrawable(Drawable thumb) {
    188         if (thumb != null) {
    189             mVerticalThumb = thumb;
    190         }
    191     }
    192 
    193     public void setVerticalTrackDrawable(Drawable track) {
    194         mVerticalTrack = track;
    195     }
    196 
    197     public void setHorizontalThumbDrawable(Drawable thumb) {
    198         if (thumb != null) {
    199             mHorizontalThumb = thumb;
    200         }
    201     }
    202 
    203     public void setHorizontalTrackDrawable(Drawable track) {
    204         mHorizontalTrack = track;
    205     }
    206 
    207     public int getSize(boolean vertical) {
    208         if (vertical) {
    209             return (mVerticalTrack != null ?
    210                     mVerticalTrack : mVerticalThumb).getIntrinsicWidth();
    211         } else {
    212             return (mHorizontalTrack != null ?
    213                     mHorizontalTrack : mHorizontalThumb).getIntrinsicHeight();
    214         }
    215     }
    216 
    217     @Override
    218     public void setAlpha(int alpha) {
    219         if (mVerticalTrack != null) {
    220             mVerticalTrack.setAlpha(alpha);
    221         }
    222         mVerticalThumb.setAlpha(alpha);
    223         if (mHorizontalTrack != null) {
    224             mHorizontalTrack.setAlpha(alpha);
    225         }
    226         mHorizontalThumb.setAlpha(alpha);
    227     }
    228 
    229     @Override
    230     public void setColorFilter(ColorFilter cf) {
    231         if (mVerticalTrack != null) {
    232             mVerticalTrack.setColorFilter(cf);
    233         }
    234         mVerticalThumb.setColorFilter(cf);
    235         if (mHorizontalTrack != null) {
    236             mHorizontalTrack.setColorFilter(cf);
    237         }
    238         mHorizontalThumb.setColorFilter(cf);
    239     }
    240 
    241     @Override
    242     public int getOpacity() {
    243         return PixelFormat.TRANSLUCENT;
    244     }
    245 
    246     @Override
    247     public String toString() {
    248         return "ScrollBarDrawable: range=" + mRange + " offset=" + mOffset +
    249                " extent=" + mExtent + (mVertical ? " V" : " H");
    250     }
    251 }
    252 
    253 
    254