116e8d4dd91083260223c007c797e46bc8f631055Chris Banes/*
216e8d4dd91083260223c007c797e46bc8f631055Chris Banes * Copyright (C) 2015 The Android Open Source Project
316e8d4dd91083260223c007c797e46bc8f631055Chris Banes *
416e8d4dd91083260223c007c797e46bc8f631055Chris Banes * Licensed under the Apache License, Version 2.0 (the "License");
516e8d4dd91083260223c007c797e46bc8f631055Chris Banes * you may not use this file except in compliance with the License.
616e8d4dd91083260223c007c797e46bc8f631055Chris Banes * You may obtain a copy of the License at
716e8d4dd91083260223c007c797e46bc8f631055Chris Banes *
816e8d4dd91083260223c007c797e46bc8f631055Chris Banes *      http://www.apache.org/licenses/LICENSE-2.0
916e8d4dd91083260223c007c797e46bc8f631055Chris Banes *
1016e8d4dd91083260223c007c797e46bc8f631055Chris Banes * Unless required by applicable law or agreed to in writing, software
1116e8d4dd91083260223c007c797e46bc8f631055Chris Banes * distributed under the License is distributed on an "AS IS" BASIS,
1216e8d4dd91083260223c007c797e46bc8f631055Chris Banes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1316e8d4dd91083260223c007c797e46bc8f631055Chris Banes * See the License for the specific language governing permissions and
1416e8d4dd91083260223c007c797e46bc8f631055Chris Banes * limitations under the License.
1516e8d4dd91083260223c007c797e46bc8f631055Chris Banes */
1616e8d4dd91083260223c007c797e46bc8f631055Chris Banes
1716e8d4dd91083260223c007c797e46bc8f631055Chris Banespackage android.support.v7.app;
1816e8d4dd91083260223c007c797e46bc8f631055Chris Banes
1916e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.app.Dialog;
2016e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.content.Context;
2116e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.os.Bundle;
2216e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.support.annotation.LayoutRes;
23547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banesimport android.support.annotation.Nullable;
2416e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.support.v7.appcompat.R;
2516e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.support.v7.view.ActionMode;
2616e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.util.TypedValue;
2716e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.view.View;
2816e8d4dd91083260223c007c797e46bc8f631055Chris Banesimport android.view.ViewGroup;
2916e8d4dd91083260223c007c797e46bc8f631055Chris Banes
3016e8d4dd91083260223c007c797e46bc8f631055Chris Banes/**
3116e8d4dd91083260223c007c797e46bc8f631055Chris Banes * Base class for AppCompat themed {@link android.app.Dialog}s.
3216e8d4dd91083260223c007c797e46bc8f631055Chris Banes */
3316e8d4dd91083260223c007c797e46bc8f631055Chris Banespublic class AppCompatDialog extends Dialog implements AppCompatCallback {
3416e8d4dd91083260223c007c797e46bc8f631055Chris Banes
3516e8d4dd91083260223c007c797e46bc8f631055Chris Banes    private AppCompatDelegate mDelegate;
3616e8d4dd91083260223c007c797e46bc8f631055Chris Banes
3716e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public AppCompatDialog(Context context) {
3816e8d4dd91083260223c007c797e46bc8f631055Chris Banes        this(context, 0);
3916e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
4016e8d4dd91083260223c007c797e46bc8f631055Chris Banes
4116e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public AppCompatDialog(Context context, int theme) {
4216e8d4dd91083260223c007c797e46bc8f631055Chris Banes        super(context, getThemeResId(context, theme));
4316e8d4dd91083260223c007c797e46bc8f631055Chris Banes
4416e8d4dd91083260223c007c797e46bc8f631055Chris Banes        // This is a bit weird, but Dialog's are typically created and setup before being shown,
4516e8d4dd91083260223c007c797e46bc8f631055Chris Banes        // which means that we can't rely on onCreate() being called before a content view is set.
4616e8d4dd91083260223c007c797e46bc8f631055Chris Banes        // To workaround this, we call onCreate(null) in the ctor, and then again as usual in
4716e8d4dd91083260223c007c797e46bc8f631055Chris Banes        // onCreate().
4816e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().onCreate(null);
4916e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
5016e8d4dd91083260223c007c797e46bc8f631055Chris Banes
5116e8d4dd91083260223c007c797e46bc8f631055Chris Banes    protected AppCompatDialog(Context context, boolean cancelable,
5216e8d4dd91083260223c007c797e46bc8f631055Chris Banes            OnCancelListener cancelListener) {
5316e8d4dd91083260223c007c797e46bc8f631055Chris Banes        super(context, cancelable, cancelListener);
5416e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
5516e8d4dd91083260223c007c797e46bc8f631055Chris Banes
5616e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
5716e8d4dd91083260223c007c797e46bc8f631055Chris Banes    protected void onCreate(Bundle savedInstanceState) {
5816e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().installViewFactory();
5916e8d4dd91083260223c007c797e46bc8f631055Chris Banes        super.onCreate(savedInstanceState);
6016e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().onCreate(savedInstanceState);
6116e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
6216e8d4dd91083260223c007c797e46bc8f631055Chris Banes
6316e8d4dd91083260223c007c797e46bc8f631055Chris Banes    /**
6416e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * Support library version of {@link android.app.Dialog#getActionBar}.
6516e8d4dd91083260223c007c797e46bc8f631055Chris Banes     *
6616e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * <p>Retrieve a reference to this dialog's ActionBar.
6716e8d4dd91083260223c007c797e46bc8f631055Chris Banes     *
6816e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * @return The Dialog's ActionBar, or null if it does not have one.
6916e8d4dd91083260223c007c797e46bc8f631055Chris Banes     */
7016e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public ActionBar getSupportActionBar() {
7116e8d4dd91083260223c007c797e46bc8f631055Chris Banes        return getDelegate().getSupportActionBar();
7216e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
7316e8d4dd91083260223c007c797e46bc8f631055Chris Banes
7416e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
7516e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void setContentView(@LayoutRes int layoutResID) {
7616e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().setContentView(layoutResID);
7716e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
7816e8d4dd91083260223c007c797e46bc8f631055Chris Banes
7916e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
8016e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void setContentView(View view) {
8116e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().setContentView(view);
8216e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
8316e8d4dd91083260223c007c797e46bc8f631055Chris Banes
8416e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
8516e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void setContentView(View view, ViewGroup.LayoutParams params) {
8616e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().setContentView(view, params);
8716e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
8816e8d4dd91083260223c007c797e46bc8f631055Chris Banes
8916e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
9016e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void setTitle(CharSequence title) {
9116e8d4dd91083260223c007c797e46bc8f631055Chris Banes        super.setTitle(title);
9216e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().setTitle(title);
9316e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
9416e8d4dd91083260223c007c797e46bc8f631055Chris Banes
9516e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
9616e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void setTitle(int titleId) {
9716e8d4dd91083260223c007c797e46bc8f631055Chris Banes        super.setTitle(titleId);
9816e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().setTitle(getContext().getString(titleId));
9916e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
10016e8d4dd91083260223c007c797e46bc8f631055Chris Banes
10116e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
10216e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void addContentView(View view, ViewGroup.LayoutParams params) {
10316e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().addContentView(view, params);
10416e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
10516e8d4dd91083260223c007c797e46bc8f631055Chris Banes
10616e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
10716e8d4dd91083260223c007c797e46bc8f631055Chris Banes    protected void onStop() {
10816e8d4dd91083260223c007c797e46bc8f631055Chris Banes        super.onStop();
10916e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().onStop();
11016e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
11116e8d4dd91083260223c007c797e46bc8f631055Chris Banes
11216e8d4dd91083260223c007c797e46bc8f631055Chris Banes    /**
11316e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * Enable extended support library window features.
11416e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * <p>
11516e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * This is a convenience for calling
11616e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * {@link android.view.Window#requestFeature getWindow().requestFeature()}.
11716e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * </p>
11816e8d4dd91083260223c007c797e46bc8f631055Chris Banes     *
11916e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * @param featureId The desired feature as defined in {@link android.view.Window} or
12016e8d4dd91083260223c007c797e46bc8f631055Chris Banes     *                  {@link android.support.v4.view.WindowCompat}.
12116e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * @return Returns true if the requested feature is supported and now enabled.
12216e8d4dd91083260223c007c797e46bc8f631055Chris Banes     *
12316e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * @see android.app.Dialog#requestWindowFeature
12416e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * @see android.view.Window#requestFeature
12516e8d4dd91083260223c007c797e46bc8f631055Chris Banes     */
12616e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public boolean supportRequestWindowFeature(int featureId) {
12716e8d4dd91083260223c007c797e46bc8f631055Chris Banes        return getDelegate().requestWindowFeature(featureId);
12816e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
12916e8d4dd91083260223c007c797e46bc8f631055Chris Banes
13016e8d4dd91083260223c007c797e46bc8f631055Chris Banes    /**
13116e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * @hide
13216e8d4dd91083260223c007c797e46bc8f631055Chris Banes     */
13316e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void invalidateOptionsMenu() {
13416e8d4dd91083260223c007c797e46bc8f631055Chris Banes        getDelegate().invalidateOptionsMenu();
13516e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
13616e8d4dd91083260223c007c797e46bc8f631055Chris Banes
13716e8d4dd91083260223c007c797e46bc8f631055Chris Banes    /**
13816e8d4dd91083260223c007c797e46bc8f631055Chris Banes     * @return The {@link AppCompatDelegate} being used by this Dialog.
13916e8d4dd91083260223c007c797e46bc8f631055Chris Banes     */
14016e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public AppCompatDelegate getDelegate() {
14116e8d4dd91083260223c007c797e46bc8f631055Chris Banes        if (mDelegate == null) {
14216e8d4dd91083260223c007c797e46bc8f631055Chris Banes            mDelegate = AppCompatDelegate.create(this, this);
14316e8d4dd91083260223c007c797e46bc8f631055Chris Banes        }
14416e8d4dd91083260223c007c797e46bc8f631055Chris Banes        return mDelegate;
14516e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
14616e8d4dd91083260223c007c797e46bc8f631055Chris Banes
14716e8d4dd91083260223c007c797e46bc8f631055Chris Banes    private static int getThemeResId(Context context, int themeId) {
14816e8d4dd91083260223c007c797e46bc8f631055Chris Banes        if (themeId == 0) {
14916e8d4dd91083260223c007c797e46bc8f631055Chris Banes            // If the provided theme is 0, then retrieve the dialogTheme from our theme
15016e8d4dd91083260223c007c797e46bc8f631055Chris Banes            TypedValue outValue = new TypedValue();
15116e8d4dd91083260223c007c797e46bc8f631055Chris Banes            context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
15216e8d4dd91083260223c007c797e46bc8f631055Chris Banes            themeId = outValue.resourceId;
15316e8d4dd91083260223c007c797e46bc8f631055Chris Banes        }
15416e8d4dd91083260223c007c797e46bc8f631055Chris Banes        return themeId;
15516e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
15616e8d4dd91083260223c007c797e46bc8f631055Chris Banes
15716e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
15816e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void onSupportActionModeStarted(ActionMode mode) {
15916e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
16016e8d4dd91083260223c007c797e46bc8f631055Chris Banes
16116e8d4dd91083260223c007c797e46bc8f631055Chris Banes    @Override
16216e8d4dd91083260223c007c797e46bc8f631055Chris Banes    public void onSupportActionModeFinished(ActionMode mode) {
16316e8d4dd91083260223c007c797e46bc8f631055Chris Banes    }
164547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes
165547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    @Nullable
166547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    @Override
167547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    public ActionMode onWindowStartingSupportActionMode(ActionMode.Callback callback) {
168547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes        return null;
169547a80d347e0dc9751bbe3cf91f947477145bdbaChris Banes    }
17016e8d4dd91083260223c007c797e46bc8f631055Chris Banes}
171