1 /* 2 * Copyright (C) 2011 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.content.res; 18 19 import com.android.ide.common.rendering.api.ResourceReference; 20 import com.android.ide.common.rendering.api.StyleResourceValue; 21 import com.android.layoutlib.bridge.android.BridgeContext; 22 import com.android.layoutlib.bridge.impl.DelegateManager; 23 import com.android.layoutlib.bridge.impl.RenderSessionImpl; 24 import com.android.resources.ResourceType; 25 import com.android.tools.layoutlib.annotations.LayoutlibDelegate; 26 27 import android.annotation.Nullable; 28 import android.content.res.Resources.NotFoundException; 29 import android.content.res.Resources.Theme; 30 import android.content.res.Resources.ThemeKey; 31 import android.util.AttributeSet; 32 import android.util.TypedValue; 33 34 /** 35 * Delegate used to provide new implementation of a select few methods of {@link Resources.Theme} 36 * 37 * Through the layoutlib_create tool, the original methods of Theme have been replaced 38 * by calls to methods of the same name in this delegate class. 39 * 40 */ 41 public class Resources_Theme_Delegate { 42 43 // ---- delegate manager ---- 44 45 private static final DelegateManager<Resources_Theme_Delegate> sManager = 46 new DelegateManager<Resources_Theme_Delegate>(Resources_Theme_Delegate.class); 47 getDelegateManager()48 public static DelegateManager<Resources_Theme_Delegate> getDelegateManager() { 49 return sManager; 50 } 51 52 // ---- delegate methods. ---- 53 54 @LayoutlibDelegate obtainStyledAttributes( Resources thisResources, Theme thisTheme, int[] attrs)55 /*package*/ static TypedArray obtainStyledAttributes( 56 Resources thisResources, Theme thisTheme, 57 int[] attrs) { 58 boolean changed = setupResources(thisTheme); 59 BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs); 60 ta.setTheme(thisTheme); 61 restoreResources(changed); 62 return ta; 63 } 64 65 @LayoutlibDelegate obtainStyledAttributes( Resources thisResources, Theme thisTheme, int resid, int[] attrs)66 /*package*/ static TypedArray obtainStyledAttributes( 67 Resources thisResources, Theme thisTheme, 68 int resid, int[] attrs) 69 throws NotFoundException { 70 boolean changed = setupResources(thisTheme); 71 BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid, 72 attrs); 73 ta.setTheme(thisTheme); 74 restoreResources(changed); 75 return ta; 76 } 77 78 @LayoutlibDelegate obtainStyledAttributes( Resources thisResources, Theme thisTheme, AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)79 /*package*/ static TypedArray obtainStyledAttributes( 80 Resources thisResources, Theme thisTheme, 81 AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) { 82 boolean changed = setupResources(thisTheme); 83 BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set, 84 attrs, defStyleAttr, defStyleRes); 85 ta.setTheme(thisTheme); 86 restoreResources(changed); 87 return ta; 88 } 89 90 @LayoutlibDelegate resolveAttribute( Resources thisResources, Theme thisTheme, int resid, TypedValue outValue, boolean resolveRefs)91 /*package*/ static boolean resolveAttribute( 92 Resources thisResources, Theme thisTheme, 93 int resid, TypedValue outValue, 94 boolean resolveRefs) { 95 boolean changed = setupResources(thisTheme); 96 boolean found = RenderSessionImpl.getCurrentContext().resolveThemeAttribute(resid, 97 outValue, resolveRefs); 98 restoreResources(changed); 99 return found; 100 } 101 102 @LayoutlibDelegate resolveAttributes(Resources thisResources, Theme thisTheme, int[] values, int[] attrs)103 /*package*/ static TypedArray resolveAttributes(Resources thisResources, Theme thisTheme, 104 int[] values, int[] attrs) { 105 // FIXME 106 return null; 107 } 108 109 // ---- private helper methods ---- 110 setupResources(Theme thisTheme)111 private static boolean setupResources(Theme thisTheme) { 112 // Key is a space-separated list of theme ids applied that have been merged into the 113 // BridgeContext's theme to make thisTheme. 114 final ThemeKey key = thisTheme.getKey(); 115 final int[] resId = key.mResId; 116 final boolean[] force = key.mForce; 117 118 boolean changed = false; 119 for (int i = 0, N = key.mCount; i < N; i++) { 120 StyleResourceValue style = resolveStyle(resId[i]); 121 if (style != null) { 122 RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle( 123 style, force[i]); 124 changed = true; 125 } 126 127 } 128 return changed; 129 } 130 restoreResources(boolean changed)131 private static void restoreResources(boolean changed) { 132 if (changed) { 133 RenderSessionImpl.getCurrentContext().getRenderResources().clearStyles(); 134 } 135 } 136 137 @Nullable resolveStyle(int nativeResid)138 private static StyleResourceValue resolveStyle(int nativeResid) { 139 if (nativeResid == 0) { 140 return null; 141 } 142 BridgeContext context = RenderSessionImpl.getCurrentContext(); 143 ResourceReference theme = context.resolveId(nativeResid); 144 if (theme.isFramework()) { 145 return (StyleResourceValue) context.getRenderResources() 146 .getFrameworkResource(ResourceType.STYLE, theme.getName()); 147 } else { 148 return (StyleResourceValue) context.getRenderResources() 149 .getProjectResource(ResourceType.STYLE, theme.getName()); 150 } 151 } 152 } 153