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