1bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta/* 2bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * Copyright (C) 2015 The Android Open Source Project 3bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * 4bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License"); 5bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * you may not use this file except in compliance with the License. 6bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * You may obtain a copy of the License at 7bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * 8bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * http://www.apache.org/licenses/LICENSE-2.0 9bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * 10bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * Unless required by applicable law or agreed to in writing, software 11bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS, 12bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * See the License for the specific language governing permissions and 14bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * limitations under the License. 15bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta */ 16bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta 17bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Guptapackage android.graphics.drawable; 18bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta 19bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Guptaimport com.android.tools.layoutlib.annotations.LayoutlibDelegate; 20bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta 21bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Guptaimport android.graphics.Path; 22bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Guptaimport android.graphics.drawable.GradientDrawable.GradientState; 23bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta 24bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Guptaimport java.lang.reflect.Field; 25bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta 26bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta/** 27bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * Delegate implementing the native methods of {@link GradientDrawable} 28bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * 29bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * Through the layoutlib_create tool, the original native methods of GradientDrawable have been 30bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * replaced by calls to methods of the same name in this delegate class. 31bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta */ 32bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Guptapublic class GradientDrawable_Delegate { 33bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta 34bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta /** 35bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * The ring can be built either by drawing full circles, or by drawing arcs in case the 36bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * circle isn't complete. LayoutLib cannot handle drawing full circles (requires path 37bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta * subtraction). So, if we need to draw full circles, we switch to drawing 99% circle. 38bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta */ 39bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta @LayoutlibDelegate 40bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta /*package*/ static Path buildRing(GradientDrawable thisDrawable, GradientState st) { 41bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta boolean useLevel = st.mUseLevelForShape; 42bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta int level = thisDrawable.getLevel(); 43bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta // 10000 is the max level. See android.graphics.drawable.Drawable#getLevel() 44bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta float sweep = useLevel ? (360.0f * level / 10000.0f) : 360f; 45bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta Field mLevel = null; 46bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta if (sweep >= 360 || sweep <= -360) { 47bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta st.mUseLevelForShape = true; 48bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta // Use reflection to set the value of the field to prevent setting the drawable to 49bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta // dirty again. 50bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta try { 51bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta mLevel = Drawable.class.getDeclaredField("mLevel"); 52bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta mLevel.setAccessible(true); 53bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta mLevel.setInt(thisDrawable, 9999); // set to one less than max. 54bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta } catch (NoSuchFieldException e) { 55bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta // The field has been removed in a recent framework change. Fall back to old 56bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta // buggy behaviour. 57bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta } catch (IllegalAccessException e) { 58bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta // We've already set the field to be accessible. 59bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta assert false; 60bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta } 61bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta } 62bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta Path path = thisDrawable.buildRing_Original(st); 63bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta st.mUseLevelForShape = useLevel; 64bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta if (mLevel != null) { 65bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta try { 66bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta mLevel.setInt(thisDrawable, level); 67bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta } catch (IllegalAccessException e) { 68bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta assert false; 69bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta } 70bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta } 71bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta return path; 72bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta } 73bab3f779655416107aef2c77142a6775eec4aa67Deepanshu Gupta} 74