1/*
2 * Copyright (C) 2014 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 androidx.appcompat.widget;
18
19import android.content.Context;
20import android.os.Build;
21import android.util.AttributeSet;
22import android.view.View;
23import android.widget.PopupWindow;
24
25import androidx.annotation.AttrRes;
26import androidx.annotation.NonNull;
27import androidx.annotation.Nullable;
28import androidx.annotation.StyleRes;
29import androidx.appcompat.R;
30import androidx.core.widget.PopupWindowCompat;
31
32class AppCompatPopupWindow extends PopupWindow {
33
34    private static final boolean COMPAT_OVERLAP_ANCHOR = Build.VERSION.SDK_INT < 21;
35
36    private boolean mOverlapAnchor;
37
38    public AppCompatPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
39            @AttrRes int defStyleAttr) {
40        super(context, attrs, defStyleAttr);
41        init(context, attrs, defStyleAttr, 0);
42    }
43
44    public AppCompatPopupWindow(@NonNull Context context, @Nullable AttributeSet attrs,
45            @AttrRes int defStyleAttr, @StyleRes int defStyleRes) {
46        super(context, attrs, defStyleAttr, defStyleRes);
47        init(context, attrs, defStyleAttr, defStyleRes);
48    }
49
50    private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
51        TintTypedArray a = TintTypedArray.obtainStyledAttributes(context, attrs,
52                R.styleable.PopupWindow, defStyleAttr, defStyleRes);
53        if (a.hasValue(R.styleable.PopupWindow_overlapAnchor)) {
54            setSupportOverlapAnchor(a.getBoolean(R.styleable.PopupWindow_overlapAnchor, false));
55        }
56        // We re-set this for tinting purposes
57        setBackgroundDrawable(a.getDrawable(R.styleable.PopupWindow_android_popupBackground));
58
59        a.recycle();
60    }
61
62    @Override
63    public void showAsDropDown(View anchor, int xoff, int yoff) {
64        if (COMPAT_OVERLAP_ANCHOR && mOverlapAnchor) {
65            // If we're pre-L, emulate overlapAnchor by modifying the yOff
66            yoff -= anchor.getHeight();
67        }
68        super.showAsDropDown(anchor, xoff, yoff);
69    }
70
71    @Override
72    public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
73        if (COMPAT_OVERLAP_ANCHOR && mOverlapAnchor) {
74            // If we're pre-L, emulate overlapAnchor by modifying the yOff
75            yoff -= anchor.getHeight();
76        }
77        super.showAsDropDown(anchor, xoff, yoff, gravity);
78    }
79
80    @Override
81    public void update(View anchor, int xoff, int yoff, int width, int height) {
82        if (COMPAT_OVERLAP_ANCHOR && mOverlapAnchor) {
83            // If we're pre-L, emulate overlapAnchor by modifying the yOff
84            yoff -= anchor.getHeight();
85        }
86        super.update(anchor, xoff, yoff, width, height);
87    }
88
89    private void setSupportOverlapAnchor(boolean overlapAnchor) {
90        if (COMPAT_OVERLAP_ANCHOR) {
91            mOverlapAnchor = overlapAnchor;
92        } else {
93            PopupWindowCompat.setOverlapAnchor(this, overlapAnchor);
94        }
95    }
96}
97