1224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta/*
2224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * Copyright (C) 2015 The Android Open Source Project
3224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta *
4224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * Licensed under the Apache License, Version 2.0 (the "License");
5224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * you may not use this file except in compliance with the License.
6224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * You may obtain a copy of the License at
7224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta *
8224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta *      http://www.apache.org/licenses/LICENSE-2.0
9224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta *
10224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * Unless required by applicable law or agreed to in writing, software
11224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * distributed under the License is distributed on an "AS IS" BASIS,
12224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * See the License for the specific language governing permissions and
14224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * limitations under the License.
15224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta */
16224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
17224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptapackage com.android.layoutlib.bridge.bars;
18224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
19224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.annotations.NonNull;
20224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.ide.common.rendering.api.ActionBarCallback;
21224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
22224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.ide.common.rendering.api.RenderResources;
23224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.ide.common.rendering.api.ResourceValue;
24224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.ide.common.rendering.api.SessionParams;
25224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport com.android.layoutlib.bridge.android.BridgeContext;
26224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
27224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport android.view.LayoutInflater;
28224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport android.view.View;
29224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport android.view.ViewGroup;
30224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport android.view.ViewGroup.LayoutParams;
31224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport android.widget.FrameLayout;
32224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptaimport android.widget.RelativeLayout;
33224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
34224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta/**
35224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta * An abstraction over two implementations of the ActionBar - framework and appcompat.
36224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta */
37224e931fed1220f175805fdec71a882649270aa7Deepanshu Guptapublic abstract class BridgeActionBar {
38224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    // Store a reference to the context so that we don't have to cast it repeatedly.
39224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    @NonNull protected final BridgeContext mBridgeContext;
40224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    @NonNull protected final SessionParams mParams;
41224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    // A Layout that contains the inflated action bar. The menu popup is added to this layout.
42224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    @NonNull protected final ViewGroup mEnclosingLayout;
43224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
44224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    private final View mDecorContent;
45224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    private final ActionBarCallback mCallback;
46224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
47224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    @NonNull private FrameLayout mContentRoot;
48224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
49224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    public BridgeActionBar(@NonNull BridgeContext context, @NonNull SessionParams params,
50224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            @NonNull ViewGroup parentView) {
51224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        mBridgeContext = context;
52224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        mParams = params;
53224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        mCallback = params.getProjectCallback().getActionBarCallback();
54224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        ResourceValue layoutName = getLayoutResource(context);
55224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        if (layoutName == null) {
56224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            throw new RuntimeException("Unable to find the layout for Action Bar.");
57224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        }
58224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        int layoutId;
59224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        if (layoutName.isFramework()) {
60224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            layoutId = context.getFrameworkResourceValue(layoutName.getResourceType(),
61224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                    layoutName.getName(), 0);
62224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        } else {
63224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            layoutId = context.getProjectResourceValue(layoutName.getResourceType(),
64224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                    layoutName.getName(), 0);
65224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
66224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        }
67224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        if (layoutId == 0) {
68224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            throw new RuntimeException(
69224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                    String.format("Unable to resolve attribute \"%1$s\" of type \"%2$s\"",
70224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                            layoutName.getName(), layoutName.getResourceType()));
71224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        }
72224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        if (mCallback.isOverflowPopupNeeded()) {
73224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            // Create a RelativeLayout around the action bar, to which the overflow popup may be
74224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            // added.
75224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            mEnclosingLayout = new RelativeLayout(mBridgeContext);
76224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            setMatchParent(mEnclosingLayout);
77224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            parentView.addView(mEnclosingLayout);
78224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        } else {
79224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            mEnclosingLayout = parentView;
80224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        }
81224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
82224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        // Inflate action bar layout.
83224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        mDecorContent = LayoutInflater.from(context).inflate(layoutId, mEnclosingLayout, true);
84224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
85224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
86224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
87224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    /**
88224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta     * Returns the Layout Resource that should be used to inflate the action bar. This layout
89224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta     * should cover the complete screen, and have a FrameLayout included, where the content will
90224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta     * be inflated.
91224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta     */
92224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected abstract ResourceValue getLayoutResource(BridgeContext context);
93224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
94224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected void setContentRoot(FrameLayout contentRoot) {
95224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        mContentRoot = contentRoot;
96224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
97224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
98224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    @NonNull
99224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    public FrameLayout getContentRoot() {
100224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        return mContentRoot;
101224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
102224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
103224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    /**
104224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta     * Returns the view inflated. This should contain both the ActionBar and the app content in it.
105224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta     */
106224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected View getDecorContent() {
107224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        return mDecorContent;
108224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
109224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
110224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    /** Setup things like the title, subtitle, icon etc. */
111224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected void setupActionBar() {
112224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        setTitle();
113224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        setSutTitle();
114224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        setIcon();
115224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        setHomeAsUp(mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP);
116224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
117224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
118224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected abstract void setTitle(CharSequence title);
119224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected abstract void setSubtitle(CharSequence subtitle);
120224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected abstract void setIcon(String icon);
121224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected abstract void setHomeAsUp(boolean homeAsUp);
122224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
123224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    private void setTitle() {
124224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        RenderResources res = mBridgeContext.getRenderResources();
125224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
126224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        String title = mParams.getAppLabel();
127224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        ResourceValue titleValue = res.findResValue(title, false);
128224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        if (titleValue != null && titleValue.getValue() != null) {
129224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            setTitle(titleValue.getValue());
130224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        } else {
131224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            setTitle(title);
132224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        }
133224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
134224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
135224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    private void setSutTitle() {
136224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        String subTitle = mCallback.getSubTitle();
137224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        if (subTitle != null) {
138224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            setSubtitle(subTitle);
139224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        }
140224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
141224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
142224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    private void setIcon() {
143224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        String appIcon = mParams.getAppIcon();
144224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        if (appIcon != null) {
145224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta            setIcon(appIcon);
146224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        }
147224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
148224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
149224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    public abstract void createMenuPopup();
150224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
151224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    public ActionBarCallback getCallBack() {
152224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        return mCallback;
153224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
154224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta
155224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    protected static void setMatchParent(View view) {
156224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta        view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
157224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta                LayoutParams.MATCH_PARENT));
158224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta    }
159224e931fed1220f175805fdec71a882649270aa7Deepanshu Gupta}
160