com.forrestguice.suntimeswidget.settings.ColorChooser.java Source code

Java tutorial

Introduction

Here is the source code for com.forrestguice.suntimeswidget.settings.ColorChooser.java

Source

/**
Copyright (C) 2017-2018 Forrest Guice
This file is part of SuntimesWidget.
    
SuntimesWidget is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
SuntimesWidget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with SuntimesWidget.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.forrestguice.suntimeswidget.settings;

import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Locale;

@SuppressWarnings("Convert2Diamond")
public class ColorChooser implements TextWatcher, View.OnFocusChangeListener {
    private static final String DIALOGTAG_COLOR = "colorchooser";

    private String chooserID = "0";
    final protected ImageButton button;
    final protected EditText edit;
    final protected TextView label;

    private int color;
    private boolean isRunning = false, isRemoving = false;
    private boolean isCollapsed = false;

    public static final char[] alphabet = { '#', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'A', 'b',
            'B', 'c', 'C', 'd', 'D', 'e', 'E', 'f', 'F' };
    protected final HashSet<Character> inputSet;

    public ColorChooser(final Context context, TextView txtLabel, EditText editField, ImageButton imgButton,
            String id) {
        chooserID = id;

        label = txtLabel;
        if (label != null) {
            label.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onFocusGained(v);
                }
            });
        }

        edit = editField;
        if (edit != null) {
            edit.addTextChangedListener(this);
            edit.setOnFocusChangeListener(this);

            edit.setOnEditorActionListener(new EditText.OnEditorActionListener() {
                @Override
                public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                    if (actionId == EditorInfo.IME_ACTION_DONE) {
                        changeColor();
                        return true;
                    }
                    return false;
                }
            });

        }

        inputSet = new HashSet<>();
        for (char c : alphabet) {
            inputSet.add(c);
        }

        button = imgButton;
        if (button != null) {
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (label != null) {
                        label.requestFocus();
                    }
                    showColorPicker(context);
                }
            });
        }
    }

    private final ArrayList<ColorChooser> linked = new ArrayList<ColorChooser>();

    public ArrayList<ColorChooser> getLinked() {
        return linked;
    }

    public void link(ColorChooser chooser) {
        if (!linked.contains(chooser)) {
            linked.add(chooser);
        }
    }

    public void unlink(ColorChooser chooser) {
        if (linked.contains(chooser)) {
            linked.remove(chooser);
        }
    }

    /**
     * @return a key that identifies this chooser's value
     */
    public String getID() {
        return chooserID;
    }

    /**
     * @return EditText wrapped by chooser
     */
    public EditText getField() {
        return edit;
    }

    /**
     * @return Button wrapped by chooser
     */
    public ImageButton getButton() {
        return button;
    }

    /**
     * @return TextView wrapped by chooser
     */
    public TextView getLabel() {
        return label;
    }

    /**
     * Set the color.
     * @param color color as integer
     */
    public void setColor(int color) {
        this.color = color;
        updateViews();
    }

    /**
     * Set the color.
     * @param hexCode hex color code #aarrggbb
     */
    public void setColor(String hexCode) {
        this.color = Color.parseColor(hexCode);
        updateViews();
    }

    /**
     * Set the color from provided bundle (using chooserID as a key).
     * @param savedState Bundle
     */
    public void setColor(Bundle savedState) {
        setColor(savedState.getInt(chooserID, getColor()));
    }

    /**
     * @return color value
     */
    public int getColor() {
        return color;
    }

    /**
     * @param value true expand edit field, false collapse edit field
     */
    public void setCollapsed(boolean value) {
        isCollapsed = value;
        updateViews();
    }

    public void setEnabled(boolean value) {
        if (label != null) {
            label.setEnabled(value);
        }
        if (edit != null) {
            edit.setEnabled(value);
        }
        if (button != null) {
            button.setEnabled(value);
        }
        if (!value) {
            setCollapsed(true);
        }
    }

    private void updateViews() {
        if (edit != null) {
            edit.setText(String.format("#%08X", color));
            edit.setVisibility((isCollapsed ? View.GONE : View.VISIBLE));
        }

        if (button != null) {
            Drawable d = button.getDrawable();
            if (d != null) {
                GradientDrawable g = (GradientDrawable) d.mutate();
                g.setColor(color);
                g.invalidateSelf();
            }
        }
    }

    @Override
    public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
        isRemoving = count > after;
    }

    @Override
    public void onTextChanged(CharSequence charSequence, int start, int before, int after) {
    }

    @Override
    public void afterTextChanged(Editable editable) {
        if (isRunning || isRemoving)
            return;
        isRunning = true;

        String text = editable.toString(); // should consist of [#][0-9][a-f]
        for (int j = text.length() - 1; j >= 0; j--) {
            if (!inputSet.contains(text.charAt(j))) {
                editable.delete(j, j + 1);
            }
        }

        text = editable.toString(); // should start with a #
        int i = text.indexOf('#');
        if (i != -1) {
            editable.delete(i, i + 1);
        }
        editable.insert(0, "#");

        if (editable.length() > 8) // should be no longer than 8
        {
            editable.delete(9, editable.length());
        }

        text = editable.toString();
        String toCaps = text.toUpperCase(Locale.US);
        editable.clear();
        editable.append(toCaps);

        isRunning = false;
    }

    protected void onColorChanged(int newColor) {
        for (ColorChooser chooser : getLinked()) {
            chooser.setColor(newColor);
        }
    }

    protected void onFocusGained(View view) {
        setCollapsed(false);
        if (edit != null) {
            edit.requestFocus();
        }
    }

    protected void onFocusLost(View view) {
        setCollapsed(true);
    }

    @Override
    public void onFocusChange(View view, boolean hasFocus) {
        if (!hasFocus) {
            if (edit != null) {
                changeColor();
                onFocusLost(view);
            }
        }
    }

    private void changeColor() {
        Editable editable = edit.getText();
        int i = editable.toString().indexOf('#');
        if (i != -1) // should start with a #
        {
            editable.delete(i, i + 1);
        }
        editable.insert(0, "#");

        while (editable.length() < 3) // supply an alpha value (FF)
        {
            editable.insert(1, "F");
        }
        if (editable.length() == 7) {
            editable.insert(1, "FF");
        }

        while (editable.length() < 9) // fill rest with "0"
        {
            editable.append("0");
        }

        //Log.d("DEBUG", "color is " + editable.toString());
        edit.setText(editable);
        setColor(editable.toString());
        onColorChanged(getColor());
    }

    private FragmentManager fragmentManager = null;

    public void setFragmentManager(FragmentManager manager) {
        fragmentManager = manager;
    }

    private void showColorPicker(Context context) {
        ColorDialog colorDialog = new ColorDialog();
        colorDialog.setColor(getColor());
        colorDialog.setColorChangeListener(colorDialogChangeListener);
        if (fragmentManager != null) {
            colorDialog.show(fragmentManager, DIALOGTAG_COLOR + "_" + chooserID);
        } else {
            Log.w("showColorPicker", "fragmentManager is null; showing fallback ...");
            Dialog dialog = colorDialog.getDialog();
            dialog.show();
        }
    }

    private final ColorDialog.ColorChangeListener colorDialogChangeListener = new ColorDialog.ColorChangeListener() {
        @Override
        public void onColorChanged(int color) {
            setColor(color);
            ColorChooser.this.onColorChanged(getColor());
        }
    };

    public void onResume() {
        if (fragmentManager != null) {
            ColorDialog colorDialog = (ColorDialog) fragmentManager
                    .findFragmentByTag(DIALOGTAG_COLOR + "_" + chooserID);
            if (colorDialog != null) {
                colorDialog.setColorChangeListener(colorDialogChangeListener);
            }
        }
    }

}