1 /* 2 * Copyright (C) 2014 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 androidx.appcompat.graphics.drawable; 18 19 import android.content.res.ColorStateList; 20 import android.graphics.Canvas; 21 import android.graphics.ColorFilter; 22 import android.graphics.PorterDuff; 23 import android.graphics.Rect; 24 import android.graphics.Region; 25 import android.graphics.drawable.Drawable; 26 import android.view.View; 27 28 import androidx.core.graphics.drawable.DrawableCompat; 29 30 import org.jspecify.annotations.NonNull; 31 import org.jspecify.annotations.Nullable; 32 33 /** 34 * Drawable which delegates all calls to its wrapped {@link Drawable}. 35 * <p> 36 * The wrapped {@link Drawable} <em>must</em> be fully released from any {@link View} 37 * before wrapping, otherwise internal {@link Callback} may be dropped. 38 * <p> 39 * Adapted from platform class, altered with API level checks as necessary. 40 */ 41 public class DrawableWrapperCompat extends Drawable implements Drawable.Callback { 42 43 private Drawable mDrawable; 44 45 /** 46 * Creates a new wrapper around the specified drawable. 47 */ DrawableWrapperCompat(Drawable drawable)48 public DrawableWrapperCompat(Drawable drawable) { 49 setDrawable(drawable); 50 } 51 52 @Override draw(@onNull Canvas canvas)53 public void draw(@NonNull Canvas canvas) { 54 mDrawable.draw(canvas); 55 } 56 57 @Override onBoundsChange(Rect bounds)58 protected void onBoundsChange(Rect bounds) { 59 mDrawable.setBounds(bounds); 60 } 61 62 @Override setChangingConfigurations(int configs)63 public void setChangingConfigurations(int configs) { 64 mDrawable.setChangingConfigurations(configs); 65 } 66 67 @Override getChangingConfigurations()68 public int getChangingConfigurations() { 69 return mDrawable.getChangingConfigurations(); 70 } 71 72 @SuppressWarnings("deprecation") 73 @Override setDither(boolean dither)74 public void setDither(boolean dither) { 75 mDrawable.setDither(dither); 76 } 77 78 @Override setFilterBitmap(boolean filter)79 public void setFilterBitmap(boolean filter) { 80 mDrawable.setFilterBitmap(filter); 81 } 82 83 @Override setAlpha(int alpha)84 public void setAlpha(int alpha) { 85 mDrawable.setAlpha(alpha); 86 } 87 88 @Override setColorFilter(ColorFilter cf)89 public void setColorFilter(ColorFilter cf) { 90 mDrawable.setColorFilter(cf); 91 } 92 93 @Override isStateful()94 public boolean isStateful() { 95 return mDrawable.isStateful(); 96 } 97 98 @Override setState(final int[] stateSet)99 public boolean setState(final int[] stateSet) { 100 return mDrawable.setState(stateSet); 101 } 102 103 @Override getState()104 public int[] getState() { 105 return mDrawable.getState(); 106 } 107 108 @Override jumpToCurrentState()109 public void jumpToCurrentState() { 110 mDrawable.jumpToCurrentState(); 111 } 112 113 @Override getCurrent()114 public Drawable getCurrent() { 115 return mDrawable.getCurrent(); 116 } 117 118 @Override setVisible(boolean visible, boolean restart)119 public boolean setVisible(boolean visible, boolean restart) { 120 return super.setVisible(visible, restart) || mDrawable.setVisible(visible, restart); 121 } 122 123 @SuppressWarnings("deprecation") 124 @Override getOpacity()125 public int getOpacity() { 126 return mDrawable.getOpacity(); 127 } 128 129 @Override getTransparentRegion()130 public Region getTransparentRegion() { 131 return mDrawable.getTransparentRegion(); 132 } 133 134 @Override getIntrinsicWidth()135 public int getIntrinsicWidth() { 136 return mDrawable.getIntrinsicWidth(); 137 } 138 139 @Override getIntrinsicHeight()140 public int getIntrinsicHeight() { 141 return mDrawable.getIntrinsicHeight(); 142 } 143 144 @Override getMinimumWidth()145 public int getMinimumWidth() { 146 return mDrawable.getMinimumWidth(); 147 } 148 149 @Override getMinimumHeight()150 public int getMinimumHeight() { 151 return mDrawable.getMinimumHeight(); 152 } 153 154 @Override getPadding(Rect padding)155 public boolean getPadding(Rect padding) { 156 return mDrawable.getPadding(padding); 157 } 158 159 /** 160 * {@inheritDoc} 161 */ 162 @Override invalidateDrawable(Drawable who)163 public void invalidateDrawable(Drawable who) { 164 invalidateSelf(); 165 } 166 167 /** 168 * {@inheritDoc} 169 */ 170 @Override scheduleDrawable(Drawable who, Runnable what, long when)171 public void scheduleDrawable(Drawable who, Runnable what, long when) { 172 scheduleSelf(what, when); 173 } 174 175 /** 176 * {@inheritDoc} 177 */ 178 @Override unscheduleDrawable(Drawable who, Runnable what)179 public void unscheduleDrawable(Drawable who, Runnable what) { 180 unscheduleSelf(what); 181 } 182 183 @Override onLevelChange(int level)184 protected boolean onLevelChange(int level) { 185 return mDrawable.setLevel(level); 186 } 187 188 @Override setAutoMirrored(boolean mirrored)189 public void setAutoMirrored(boolean mirrored) { 190 DrawableCompat.setAutoMirrored(mDrawable, mirrored); 191 } 192 193 @Override isAutoMirrored()194 public boolean isAutoMirrored() { 195 return DrawableCompat.isAutoMirrored(mDrawable); 196 } 197 198 @Override setTint(int tint)199 public void setTint(int tint) { 200 DrawableCompat.setTint(mDrawable, tint); 201 } 202 203 @Override setTintList(ColorStateList tint)204 public void setTintList(ColorStateList tint) { 205 DrawableCompat.setTintList(mDrawable, tint); 206 } 207 208 @Override setTintMode(PorterDuff.Mode tintMode)209 public void setTintMode(PorterDuff.Mode tintMode) { 210 DrawableCompat.setTintMode(mDrawable, tintMode); 211 } 212 213 @Override setHotspot(float x, float y)214 public void setHotspot(float x, float y) { 215 DrawableCompat.setHotspot(mDrawable, x, y); 216 } 217 218 @Override setHotspotBounds(int left, int top, int right, int bottom)219 public void setHotspotBounds(int left, int top, int right, int bottom) { 220 DrawableCompat.setHotspotBounds(mDrawable, left, top, right, bottom); 221 } 222 223 /** 224 * @return the wrapped drawable 225 */ getDrawable()226 public @Nullable Drawable getDrawable() { 227 return mDrawable; 228 } 229 230 /** 231 * Sets the wrapped drawable. 232 * 233 * @param drawable the wrapped drawable 234 */ setDrawable(@ullable Drawable drawable)235 public void setDrawable(@Nullable Drawable drawable) { 236 if (mDrawable != null) { 237 mDrawable.setCallback(null); 238 } 239 240 mDrawable = drawable; 241 242 if (drawable != null) { 243 drawable.setCallback(this); 244 } 245 } 246 } 247