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 17 package com.android.deskclock; 18 19 import android.app.Dialog; 20 import android.app.DialogFragment; 21 import android.content.Context; 22 import android.content.DialogInterface; 23 import android.content.res.ColorStateList; 24 import android.os.Bundle; 25 import android.support.annotation.NonNull; 26 import android.support.v7.app.AlertDialog; 27 import android.support.v7.widget.AppCompatEditText; 28 import android.text.Editable; 29 import android.text.InputType; 30 import android.text.TextUtils; 31 import android.text.TextWatcher; 32 import android.view.KeyEvent; 33 import android.view.inputmethod.EditorInfo; 34 import android.widget.TextView; 35 36 import com.android.deskclock.data.DataModel; 37 import com.android.deskclock.data.Timer; 38 import com.android.deskclock.provider.Alarm; 39 40 import static android.graphics.Color.RED; 41 import static android.graphics.Color.WHITE; 42 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE; 43 44 /** 45 * DialogFragment to edit label. 46 */ 47 public 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 }