12cfe25aefb32ed215f1c661d9670baf276fb7776James Kung/*
22cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * Copyright (C) 2013 The Android Open Source Project
32cfe25aefb32ed215f1c661d9670baf276fb7776James Kung *
42cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * Licensed under the Apache License, Version 2.0 (the "License");
52cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * you may not use this file except in compliance with the License.
62cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * You may obtain a copy of the License at
72cfe25aefb32ed215f1c661d9670baf276fb7776James Kung *
82cfe25aefb32ed215f1c661d9670baf276fb7776James Kung *      http://www.apache.org/licenses/LICENSE-2.0
92cfe25aefb32ed215f1c661d9670baf276fb7776James Kung *
102cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * Unless required by applicable law or agreed to in writing, software
112cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * distributed under the License is distributed on an "AS IS" BASIS,
122cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * See the License for the specific language governing permissions and
142cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * limitations under the License.
152cfe25aefb32ed215f1c661d9670baf276fb7776James Kung */
162cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
172cfe25aefb32ed215f1c661d9670baf276fb7776James Kungpackage com.android.colorpicker;
182cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
192cfe25aefb32ed215f1c661d9670baf276fb7776James Kungimport android.content.Context;
203f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzsteinimport android.content.res.Resources;
212cfe25aefb32ed215f1c661d9670baf276fb7776James Kungimport android.util.AttributeSet;
222cfe25aefb32ed215f1c661d9670baf276fb7776James Kungimport android.view.View;
232cfe25aefb32ed215f1c661d9670baf276fb7776James Kungimport android.view.ViewGroup;
242cfe25aefb32ed215f1c661d9670baf276fb7776James Kungimport android.widget.ImageView;
252cfe25aefb32ed215f1c661d9670baf276fb7776James Kungimport android.widget.TableLayout;
262cfe25aefb32ed215f1c661d9670baf276fb7776James Kungimport android.widget.TableRow;
272cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
282cfe25aefb32ed215f1c661d9670baf276fb7776James Kungimport com.android.colorpicker.ColorPickerSwatch.OnColorSelectedListener;
292cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
302cfe25aefb32ed215f1c661d9670baf276fb7776James Kung/**
312cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * A color picker custom view which creates an grid of color squares.  The number of squares per
322cfe25aefb32ed215f1c661d9670baf276fb7776James Kung * row (and the padding between the squares) is determined by the user.
332cfe25aefb32ed215f1c661d9670baf276fb7776James Kung */
342cfe25aefb32ed215f1c661d9670baf276fb7776James Kungpublic class ColorPickerPalette extends TableLayout {
352cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
362cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    public OnColorSelectedListener mOnColorSelectedListener;
372cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
383f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein    private String mDescription;
393f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein    private String mDescriptionSelected;
403f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein
412cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    private int mSwatchLength;
422cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    private int mMarginSize;
432cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    private int mNumColumns;
442cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
452cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    public ColorPickerPalette(Context context, AttributeSet attrs) {
462cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        super(context, attrs);
472cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    }
482cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
492cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    public ColorPickerPalette(Context context) {
502cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        super(context);
512cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    }
522cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
532cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    /**
542cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     * Initialize the size, columns, and listener.  Size should be a pre-defined size (SIZE_LARGE
552cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     * or SIZE_SMALL) from ColorPickerDialogFragment.
562cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     */
572cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    public void init(int size, int columns, OnColorSelectedListener listener) {
582cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        mNumColumns = columns;
593f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        Resources res = getResources();
602cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        if (size == ColorPickerDialog.SIZE_LARGE) {
613f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein            mSwatchLength = res.getDimensionPixelSize(R.dimen.color_swatch_large);
623f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein            mMarginSize = res.getDimensionPixelSize(R.dimen.color_swatch_margins_large);
632cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        } else {
643f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein            mSwatchLength = res.getDimensionPixelSize(R.dimen.color_swatch_small);
653f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein            mMarginSize = res.getDimensionPixelSize(R.dimen.color_swatch_margins_small);
662cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        }
672cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        mOnColorSelectedListener = listener;
683f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein
693f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        mDescription = res.getString(R.string.color_swatch_description);
703f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        mDescriptionSelected = res.getString(R.string.color_swatch_description_selected);
712cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    }
722cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
732cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    private TableRow createTableRow() {
742cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        TableRow row = new TableRow(getContext());
752cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.WRAP_CONTENT,
762cfe25aefb32ed215f1c661d9670baf276fb7776James Kung                LayoutParams.WRAP_CONTENT);
772cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        row.setLayoutParams(params);
782cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        return row;
792cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    }
802cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
812cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    /**
822cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     * Adds swatches to table in a serpentine format.
832cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     */
842cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    public void drawPalette(int[] colors, int selectedColor) {
851f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang        drawPalette(colors, selectedColor, null);
861f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang    }
871f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang
881f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang    /**
891f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang     * Adds swatches to table in a serpentine format.
901f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang     */
911f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang    public void drawPalette(int[] colors, int selectedColor, String[] colorContentDescriptions) {
922cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        if (colors == null) {
932cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            return;
942cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        }
952cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
962cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        this.removeAllViews();
973f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        int tableElements = 0;
982cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        int rowElements = 0;
992cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        int rowNumber = 0;
1002cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
1012cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        // Fills the table with swatches based on the array of colors.
1022cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        TableRow row = createTableRow();
1033f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        for (int color : colors) {
1043f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein            View colorSwatch = createColorSwatch(color, selectedColor);
1053f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein            setSwatchDescription(rowNumber, tableElements, rowElements, color == selectedColor,
1061f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang                    colorSwatch, colorContentDescriptions);
1073f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein            addSwatchToRow(row, colorSwatch, rowNumber);
1083f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein
1096563b3d6f6bdee33c258a0f3139ebb97f2d23f1eKaikai Wang            tableElements++;
1102cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            rowElements++;
1112cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            if (rowElements == mNumColumns) {
1122cfe25aefb32ed215f1c661d9670baf276fb7776James Kung                addView(row);
1132cfe25aefb32ed215f1c661d9670baf276fb7776James Kung                row = createTableRow();
1142cfe25aefb32ed215f1c661d9670baf276fb7776James Kung                rowElements = 0;
1152cfe25aefb32ed215f1c661d9670baf276fb7776James Kung                rowNumber++;
1162cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            }
1172cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        }
1182cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
1192cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        // Create blank views to fill the row if the last row has not been filled.
1202cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        if (rowElements > 0) {
1212cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            while (rowElements != mNumColumns) {
1222cfe25aefb32ed215f1c661d9670baf276fb7776James Kung                addSwatchToRow(row, createBlankSpace(), rowNumber);
1232cfe25aefb32ed215f1c661d9670baf276fb7776James Kung                rowElements++;
1242cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            }
1252cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            addView(row);
1262cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        }
1272cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    }
1282cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
1292cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    /**
1302cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     * Appends a swatch to the end of the row for even-numbered rows (starting with row 0),
1312cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     * to the beginning of a row for odd-numbered rows.
1322cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     */
13352f6c4fb384a3937b54c72fcddcc0ed77344f90cScott Kennedy    private static void addSwatchToRow(TableRow row, View swatch, int rowNumber) {
1342cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        if (rowNumber % 2 == 0) {
1352cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            row.addView(swatch);
1362cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        } else {
1372cfe25aefb32ed215f1c661d9670baf276fb7776James Kung            row.addView(swatch, 0);
1382cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        }
1392cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    }
1402cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
1412cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    /**
1423f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein     * Add a content description to the specified swatch view. Because the colors get added in a
1433f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein     * snaking form, every other row will need to compensate for the fact that the colors are added
1443f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein     * in an opposite direction from their left->right/top->bottom order, which is how the system
1453f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein     * will arrange them for accessibility purposes.
1463f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein     */
1473f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein    private void setSwatchDescription(int rowNumber, int index, int rowElements, boolean selected,
1481f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            View swatch, String[] contentDescriptions) {
1493f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        String description;
1501f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang        if (contentDescriptions != null && contentDescriptions.length > index) {
1511f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            description = contentDescriptions[index];
1523f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        } else {
1531f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            int accessibilityIndex;
1541f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            if (rowNumber % 2 == 0) {
1551f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang                // We're in a regular-ordered row
1566563b3d6f6bdee33c258a0f3139ebb97f2d23f1eKaikai Wang                accessibilityIndex = index + 1;
1571f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            } else {
1581f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang                // We're in a backwards-ordered row.
1591f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang                int rowMax = ((rowNumber + 1) * mNumColumns);
1601f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang                accessibilityIndex = rowMax - rowElements;
1611f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            }
1621f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang
1631f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            if (selected) {
1641f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang                description = String.format(mDescriptionSelected, accessibilityIndex);
1651f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            } else {
1661f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang                description = String.format(mDescription, accessibilityIndex);
1671f20a74925ab5ca73b451a437a718eb72f9a22b3Kaikai Wang            }
1683f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        }
1693f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein        swatch.setContentDescription(description);
1703f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein    }
1713f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein
1723f672cabe031e42b31eea2d5fd187bc4ad607f77Sam Blitzstein    /**
1732cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     * Creates a blank space to fill the row.
1742cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     */
1752cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    private ImageView createBlankSpace() {
1762cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        ImageView view = new ImageView(getContext());
1772cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        TableRow.LayoutParams params = new TableRow.LayoutParams(mSwatchLength, mSwatchLength);
1782cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        params.setMargins(mMarginSize, mMarginSize, mMarginSize, mMarginSize);
1792cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        view.setLayoutParams(params);
1802cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        return view;
1812cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    }
1822cfe25aefb32ed215f1c661d9670baf276fb7776James Kung
1832cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    /**
1842cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     * Creates a color swatch.
1852cfe25aefb32ed215f1c661d9670baf276fb7776James Kung     */
1862cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    private ColorPickerSwatch createColorSwatch(int color, int selectedColor) {
1872cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        ColorPickerSwatch view = new ColorPickerSwatch(getContext(), color,
1882cfe25aefb32ed215f1c661d9670baf276fb7776James Kung                color == selectedColor, mOnColorSelectedListener);
1892cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        TableRow.LayoutParams params = new TableRow.LayoutParams(mSwatchLength, mSwatchLength);
1902cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        params.setMargins(mMarginSize, mMarginSize, mMarginSize, mMarginSize);
1912cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        view.setLayoutParams(params);
1922cfe25aefb32ed215f1c661d9670baf276fb7776James Kung        return view;
1932cfe25aefb32ed215f1c661d9670baf276fb7776James Kung    }
1942cfe25aefb32ed215f1c661d9670baf276fb7776James Kung}
195