1/*
2 * Copyright (C) 2012 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;
18
19import android.app.Dialog;
20import android.app.DialogFragment;
21import android.content.Context;
22import android.content.DialogInterface;
23import android.content.res.ColorStateList;
24import android.os.Bundle;
25import android.support.annotation.NonNull;
26import android.support.v7.app.AlertDialog;
27import android.support.v7.widget.AppCompatEditText;
28import android.text.Editable;
29import android.text.InputType;
30import android.text.TextUtils;
31import android.text.TextWatcher;
32import android.view.KeyEvent;
33import android.view.inputmethod.EditorInfo;
34import android.widget.TextView;
35
36import com.android.deskclock.data.DataModel;
37import com.android.deskclock.data.Timer;
38import com.android.deskclock.provider.Alarm;
39
40import static android.graphics.Color.RED;
41import static android.graphics.Color.WHITE;
42import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE;
43
44/**
45 * DialogFragment to edit label.
46 */
47public class LabelDialogFragment extends DialogFragment {
48
49    private static final String KEY_LABEL = "label";
50    private static final String KEY_ALARM = "alarm";
51    private static final String KEY_TIMER_ID = "timer_id";
52    private static final String KEY_TAG = "tag";
53
54    private AppCompatEditText mLabelBox;
55    private Alarm mAlarm;
56    private int mTimerId;
57    private String mTag;
58
59    public static LabelDialogFragment newInstance(Alarm alarm, String label, String tag) {
60        final Bundle args = new Bundle();
61        args.putString(KEY_LABEL, label);
62        args.putParcelable(KEY_ALARM, alarm);
63        args.putString(KEY_TAG, tag);
64
65        final LabelDialogFragment frag = new LabelDialogFragment();
66        frag.setArguments(args);
67        return frag;
68    }
69
70    public static LabelDialogFragment newInstance(Timer timer) {
71        final Bundle args = new Bundle();
72        args.putString(KEY_LABEL, timer.getLabel());
73        args.putInt(KEY_TIMER_ID, timer.getId());
74
75        final LabelDialogFragment frag = new LabelDialogFragment();
76        frag.setArguments(args);
77        return frag;
78    }
79
80    @Override
81    public void onSaveInstanceState(@NonNull Bundle outState) {
82        super.onSaveInstanceState(outState);
83        outState.putString(KEY_LABEL, mLabelBox.getText().toString());
84    }
85
86    @Override
87    public Dialog onCreateDialog(Bundle savedInstanceState) {
88        final Bundle bundle = getArguments();
89        mAlarm = bundle.getParcelable(KEY_ALARM);
90        mTimerId = bundle.getInt(KEY_TIMER_ID, -1);
91        mTag = bundle.getString(KEY_TAG);
92
93        final String label = savedInstanceState != null ?
94                savedInstanceState.getString(KEY_LABEL) : bundle.getString(KEY_LABEL);
95
96        final Context context = getActivity();
97
98        mLabelBox = new AppCompatEditText(context);
99        mLabelBox.setOnEditorActionListener(new ImeDoneListener());
100        mLabelBox.addTextChangedListener(new TextChangeListener(context));
101        mLabelBox.setSingleLine();
102        mLabelBox.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
103        mLabelBox.setText(label);
104        mLabelBox.selectAll();
105
106        final int padding = getResources().getDimensionPixelSize(R.dimen.label_edittext_padding);
107        final AlertDialog alertDialog = new AlertDialog.Builder(context)
108                .setView(mLabelBox, padding, 0, padding, 0)
109                .setPositiveButton(R.string.time_picker_set, new OkListener())
110                .setNegativeButton(R.string.time_picker_cancel, new CancelListener())
111                .setMessage(R.string.label)
112                .create();
113
114        alertDialog.getWindow().setSoftInputMode(SOFT_INPUT_STATE_VISIBLE);
115        return alertDialog;
116    }
117
118    /**
119     * Sets the new label into the timer or alarm.
120     */
121    private void setLabel() {
122        String label = mLabelBox.getText().toString();
123        if (label.trim().isEmpty()) {
124            // Don't allow user to input label with only whitespace.
125            label = "";
126        }
127
128        if (mAlarm != null) {
129            ((AlarmLabelDialogHandler) getActivity()).onDialogLabelSet(mAlarm, label, mTag);
130        } else if (mTimerId >= 0) {
131            final Timer timer = DataModel.getDataModel().getTimer(mTimerId);
132            if (timer != null) {
133                DataModel.getDataModel().setTimerLabel(timer, label);
134            }
135        }
136    }
137
138    interface AlarmLabelDialogHandler {
139        void onDialogLabelSet(Alarm alarm, String label, String tag);
140    }
141
142    /**
143     * Alters the UI to indicate when input is valid or invalid.
144     */
145    private class TextChangeListener implements TextWatcher {
146
147        private final int colorAccent;
148        private final int colorControlNormal;
149
150        public TextChangeListener(Context context) {
151            colorAccent = Utils.obtainStyledColor(context, R.attr.colorAccent, RED);
152            colorControlNormal = Utils.obtainStyledColor(context, R.attr.colorControlNormal, WHITE);
153        }
154
155        @Override
156        public void onTextChanged(CharSequence s, int start, int before, int count) {
157            final int color = TextUtils.isEmpty(s) ? colorControlNormal : colorAccent;
158            mLabelBox.setSupportBackgroundTintList(ColorStateList.valueOf(color));
159        }
160
161        @Override
162        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
163
164        @Override
165        public void afterTextChanged(Editable editable) {}
166    }
167
168    /**
169     * Handles completing the label edit from the IME keyboard.
170     */
171    private class ImeDoneListener implements TextView.OnEditorActionListener {
172        @Override
173        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
174            if (actionId == EditorInfo.IME_ACTION_DONE) {
175                setLabel();
176                dismiss();
177                return true;
178            }
179            return false;
180        }
181    }
182
183    /**
184     * Handles completing the label edit from the Ok button of the dialog.
185     */
186    private class OkListener implements DialogInterface.OnClickListener {
187        @Override
188        public void onClick(DialogInterface dialog, int which) {
189            setLabel();
190            dismiss();
191        }
192    }
193
194    /**
195     * Handles discarding the label edit from the Cancel button of the dialog.
196     */
197    private class CancelListener implements DialogInterface.OnClickListener {
198        @Override
199        public void onClick(DialogInterface dialog, int which) {
200            dismiss();
201        }
202    }
203}