1/*
2 * Copyright (C) 2016 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 com.android.deskclock.settings;
18
19import android.content.Context;
20import android.support.annotation.NonNull;
21import android.support.v4.content.ContextCompat;
22import android.support.v7.preference.DropDownPreference;
23import android.util.AttributeSet;
24import android.view.View;
25import android.view.ViewGroup;
26import android.widget.ArrayAdapter;
27
28import com.android.deskclock.R;
29import com.android.deskclock.Utils;
30
31/**
32 * Bend {@link DropDownPreference} to support
33 * <a href="https://material.google.com/components/menus.html#menus-behavior">Simple Menus</a>.
34 */
35public class SimpleMenuPreference extends DropDownPreference {
36
37    private SimpleMenuAdapter mAdapter;
38
39    public SimpleMenuPreference(Context context) {
40        this(context, null);
41    }
42
43    public SimpleMenuPreference(Context context, AttributeSet attrs) {
44        this(context, attrs, R.attr.dropdownPreferenceStyle);
45    }
46
47    public SimpleMenuPreference(Context context, AttributeSet attrs, int defStyle) {
48        this(context, attrs, defStyle, 0);
49    }
50
51    public SimpleMenuPreference(Context context, AttributeSet attrs, int defStyleAttr,
52            int defStyleRes) {
53        super(context, attrs, defStyleAttr, defStyleRes);
54    }
55
56    @Override
57    protected ArrayAdapter createAdapter() {
58        mAdapter = new SimpleMenuAdapter(getContext(), R.layout.simple_menu_dropdown_item);
59        return mAdapter;
60    }
61
62    private static void restoreOriginalOrder(CharSequence[] array,
63            int lastSelectedOriginalPosition) {
64        final CharSequence item = array[0];
65        System.arraycopy(array, 1, array, 0, lastSelectedOriginalPosition);
66        array[lastSelectedOriginalPosition] = item;
67    }
68
69    private static void swapSelectedToFront(CharSequence[] array, int position) {
70        final CharSequence item = array[position];
71        System.arraycopy(array, 0, array, 1, position);
72        array[0] = item;
73    }
74
75    private static void setSelectedPosition(CharSequence[] array, int lastSelectedOriginalPosition,
76            int position) {
77        final CharSequence item = array[position];
78        restoreOriginalOrder(array, lastSelectedOriginalPosition);
79        final int originalPosition = Utils.indexOf(array, item);
80        swapSelectedToFront(array, originalPosition);
81    }
82
83    @Override
84    public void setSummary(CharSequence summary) {
85        final CharSequence[] entries = getEntries();
86        final int index = Utils.indexOf(entries, summary);
87        if (index == -1) {
88            throw new IllegalArgumentException("Illegal Summary");
89        }
90        final int lastSelectedOriginalPosition = mAdapter.getLastSelectedOriginalPosition();
91        mAdapter.setSelectedPosition(index);
92        setSelectedPosition(entries, lastSelectedOriginalPosition, index);
93        setSelectedPosition(getEntryValues(), lastSelectedOriginalPosition, index);
94        super.setSummary(summary);
95    }
96
97    private final static class SimpleMenuAdapter extends ArrayAdapter<CharSequence> {
98
99        /** The original position of the last selected element */
100        private int mLastSelectedOriginalPosition = 0;
101
102        SimpleMenuAdapter(Context context, int resource) {
103            super(context, resource);
104        }
105
106        private void restoreOriginalOrder() {
107            final CharSequence item = getItem(0);
108            remove(item);
109            insert(item, mLastSelectedOriginalPosition);
110        }
111
112        private void swapSelectedToFront(int position) {
113            final CharSequence item = getItem(position);
114            remove(item);
115            insert(item, 0);
116            mLastSelectedOriginalPosition = position;
117        }
118
119        int getLastSelectedOriginalPosition() {
120            return mLastSelectedOriginalPosition;
121        }
122
123        void setSelectedPosition(int position) {
124            setNotifyOnChange(false);
125            final CharSequence item = getItem(position);
126            restoreOriginalOrder();
127            final int originalPosition = getPosition(item);
128            swapSelectedToFront(originalPosition);
129            notifyDataSetChanged();
130        }
131
132        @Override
133        public View getDropDownView(int position, View convertView, @NonNull ViewGroup parent) {
134            final View view = super.getDropDownView(position, convertView, parent);
135            if (position == 0) {
136                view.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.white_08p));
137            } else {
138                view.setBackgroundColor(ContextCompat.getColor(getContext(), R.color.transparent));
139            }
140            return view;
141        }
142    }
143}
144