1/*
2 * Copyright (C) 2010 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
17package android.app;
18
19import com.android.ide.common.rendering.api.IProjectCallback;
20import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
21
22import android.content.Context;
23import android.os.Bundle;
24
25/**
26 * Delegate used to provide new implementation of a select few methods of {@link Fragment}
27 *
28 * Through the layoutlib_create tool, the original  methods of Fragment have been replaced
29 * by calls to methods of the same name in this delegate class.
30 *
31 * The methods being re-implemented are the ones responsible for instantiating Fragment objects.
32 * Because the classes of these objects are found in the project, these methods need access to
33 * {@link IProjectCallback} object. They are however static methods, so the callback is set
34 * before the inflation through {@link #setProjectCallback(IProjectCallback)}.
35 */
36public class Fragment_Delegate {
37
38    private static IProjectCallback sProjectCallback;
39
40    /**
41     * Sets the current {@link IProjectCallback} to be used to instantiate classes coming
42     * from the project being rendered.
43     */
44    public static void setProjectCallback(IProjectCallback projectCallback) {
45        sProjectCallback = projectCallback;
46    }
47
48    /**
49     * Like {@link #instantiate(Context, String, Bundle)} but with a null
50     * argument Bundle.
51     */
52    @LayoutlibDelegate
53    /*package*/ static Fragment instantiate(Context context, String fname) {
54        return instantiate(context, fname, null);
55    }
56
57    /**
58     * Create a new instance of a Fragment with the given class name.  This is
59     * the same as calling its empty constructor.
60     *
61     * @param context The calling context being used to instantiate the fragment.
62     * This is currently just used to get its ClassLoader.
63     * @param fname The class name of the fragment to instantiate.
64     * @param args Bundle of arguments to supply to the fragment, which it
65     * can retrieve with {@link #getArguments()}.  May be null.
66     * @return Returns a new fragment instance.
67     * @throws InstantiationException If there is a failure in instantiating
68     * the given fragment class.  This is a runtime exception; it is not
69     * normally expected to happen.
70     */
71    @LayoutlibDelegate
72    /*package*/ static Fragment instantiate(Context context, String fname, Bundle args) {
73        try {
74            if (sProjectCallback != null) {
75                Fragment f = (Fragment) sProjectCallback.loadView(fname,
76                        new Class[0], new Object[0]);
77
78                if (args != null) {
79                    args.setClassLoader(f.getClass().getClassLoader());
80                    f.mArguments = args;
81                }
82                return f;
83            }
84
85            return null;
86        } catch (ClassNotFoundException e) {
87            throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
88                    + ": make sure class name exists, is public, and has an"
89                    + " empty constructor that is public", e);
90        } catch (java.lang.InstantiationException e) {
91            throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
92                    + ": make sure class name exists, is public, and has an"
93                    + " empty constructor that is public", e);
94        } catch (IllegalAccessException e) {
95            throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
96                    + ": make sure class name exists, is public, and has an"
97                    + " empty constructor that is public", e);
98        } catch (Exception e) {
99            throw new Fragment.InstantiationException("Unable to instantiate fragment " + fname
100                    + ": make sure class name exists, is public, and has an"
101                    + " empty constructor that is public", e);
102        }
103    }
104}
105