1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2011 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License.
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License.
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage android.content.res;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
19bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Guptaimport com.android.ide.common.rendering.api.ResourceReference;
20bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Guptaimport com.android.ide.common.rendering.api.StyleResourceValue;
21bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Guptaimport com.android.layoutlib.bridge.android.BridgeContext;
22bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Guptaimport com.android.layoutlib.bridge.impl.DelegateManager;
23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.impl.RenderSessionImpl;
24bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Guptaimport com.android.resources.ResourceType;
25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
27476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.Nullable;
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.res.Resources.NotFoundException;
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.res.Resources.Theme;
3078f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viveretteimport android.content.res.Resources.ThemeKey;
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.util.AttributeSet;
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.util.TypedValue;
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
35bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta * Delegate used to provide new implementation of a select few methods of {@link Resources.Theme}
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Through the layoutlib_create tool, the original  methods of Theme have been replaced
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * by calls to methods of the same name in this delegate class.
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic class Resources_Theme_Delegate {
42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
43bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    // ---- delegate manager ----
44bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
45bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    private static final DelegateManager<Resources_Theme_Delegate> sManager =
46bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta            new DelegateManager<Resources_Theme_Delegate>(Resources_Theme_Delegate.class);
47bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
48bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    public static DelegateManager<Resources_Theme_Delegate> getDelegateManager() {
49bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        return sManager;
50bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    }
51bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
52bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    // ---- delegate methods. ----
53bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static TypedArray obtainStyledAttributes(
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Resources thisResources, Theme thisTheme,
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int[] attrs) {
58bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        boolean changed = setupResources(thisTheme);
594a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(attrs);
604a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        ta.setTheme(thisTheme);
61bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        restoreResources(changed);
62bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        return ta;
63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static TypedArray obtainStyledAttributes(
67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Resources thisResources, Theme thisTheme,
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int resid, int[] attrs)
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            throws NotFoundException {
70bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        boolean changed = setupResources(thisTheme);
714a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(resid,
724a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta                attrs);
734a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        ta.setTheme(thisTheme);
74bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        restoreResources(changed);
75bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        return ta;
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static TypedArray obtainStyledAttributes(
80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Resources thisResources, Theme thisTheme,
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes) {
82bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        boolean changed = setupResources(thisTheme);
834a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        BridgeTypedArray ta = RenderSessionImpl.getCurrentContext().obtainStyledAttributes(set,
844a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta                attrs, defStyleAttr, defStyleRes);
854a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        ta.setTheme(thisTheme);
86bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        restoreResources(changed);
87bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        return ta;
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static boolean resolveAttribute(
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Resources thisResources, Theme thisTheme,
93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int resid, TypedValue outValue,
94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            boolean resolveRefs) {
95bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        boolean changed = setupResources(thisTheme);
964a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta        boolean found =  RenderSessionImpl.getCurrentContext().resolveThemeAttribute(resid,
974a605c6fa0027ee116beb29fbc9625721f0441f0Deepanshu Gupta                outValue, resolveRefs);
98bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        restoreResources(changed);
99bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        return found;
100bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    }
101bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
102130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta    @LayoutlibDelegate
103130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta    /*package*/ static TypedArray resolveAttributes(Resources thisResources, Theme thisTheme,
104130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta            int[] values, int[] attrs) {
105130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        // FIXME
106130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta        return null;
107130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta    }
108130d2353edda445b8e36a6b5e4b176fd748035b0Deepanshu Gupta
109bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    // ---- private helper methods ----
110bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
111bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    private static boolean setupResources(Theme thisTheme) {
112b6444c43094353065f083d1ae6e4617f098a8b2bDeepanshu Gupta        // Key is a space-separated list of theme ids applied that have been merged into the
113b6444c43094353065f083d1ae6e4617f098a8b2bDeepanshu Gupta        // BridgeContext's theme to make thisTheme.
11478f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viverette        final ThemeKey key = thisTheme.getKey();
11578f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viverette        final int[] resId = key.mResId;
11678f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viverette        final boolean[] force = key.mForce;
11778f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viverette
118b6444c43094353065f083d1ae6e4617f098a8b2bDeepanshu Gupta        boolean changed = false;
11978f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viverette        for (int i = 0, N = key.mCount; i < N; i++) {
12078f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viverette            StyleResourceValue style = resolveStyle(resId[i]);
121b6444c43094353065f083d1ae6e4617f098a8b2bDeepanshu Gupta            if (style != null) {
12278f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viverette                RenderSessionImpl.getCurrentContext().getRenderResources().applyStyle(
12378f12e43f08a1b2acda7b565a310c48e507f5e47Alan Viverette                        style, force[i]);
124b6444c43094353065f083d1ae6e4617f098a8b2bDeepanshu Gupta                changed = true;
125b6444c43094353065f083d1ae6e4617f098a8b2bDeepanshu Gupta            }
126b6444c43094353065f083d1ae6e4617f098a8b2bDeepanshu Gupta
127bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        }
128b6444c43094353065f083d1ae6e4617f098a8b2bDeepanshu Gupta        return changed;
129bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    }
130bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
131bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    private static void restoreResources(boolean changed) {
132bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        if (changed) {
133bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta            RenderSessionImpl.getCurrentContext().getRenderResources().clearStyles();
134bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        }
135bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    }
136bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta
137bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    @Nullable
138bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta    private static StyleResourceValue resolveStyle(int nativeResid) {
139bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        if (nativeResid == 0) {
140bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta            return null;
141bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        }
142bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        BridgeContext context = RenderSessionImpl.getCurrentContext();
143bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        ResourceReference theme = context.resolveId(nativeResid);
144bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        if (theme.isFramework()) {
145bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta            return (StyleResourceValue) context.getRenderResources()
146bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta                    .getFrameworkResource(ResourceType.STYLE, theme.getName());
147bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        } else {
148bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta            return (StyleResourceValue) context.getRenderResources()
149bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta                    .getProjectResource(ResourceType.STYLE, theme.getName());
150bfec73c2db5a34ced248213edf5519c80727a65fDeepanshu Gupta        }
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
153