blob: 0fa0eab0d4fbd60b0b57726d98091fdf26134a76 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.deskclock;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.content.DialogInterface;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.AppCompatEditText;
import android.text.Editable;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.Window;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import com.android.deskclock.data.DataModel;
import com.android.deskclock.data.Timer;
import com.android.deskclock.provider.Alarm;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE;
/**
* DialogFragment to edit label.
*/
public class LabelDialogFragment extends DialogFragment {
/**
* The tag that identifies instances of LabelDialogFragment in the fragment manager.
*/
private static final String TAG = "label_dialog";
private static final String ARG_LABEL = "arg_label";
private static final String ARG_ALARM = "arg_alarm";
private static final String ARG_TIMER_ID = "arg_timer_id";
private static final String ARG_TAG = "arg_tag";
private AppCompatEditText mLabelBox;
private Alarm mAlarm;
private int mTimerId;
private String mTag;
public static LabelDialogFragment newInstance(Alarm alarm, String label, String tag) {
final Bundle args = new Bundle();
args.putString(ARG_LABEL, label);
args.putParcelable(ARG_ALARM, alarm);
args.putString(ARG_TAG, tag);
final LabelDialogFragment frag = new LabelDialogFragment();
frag.setArguments(args);
return frag;
}
public static LabelDialogFragment newInstance(Timer timer) {
final Bundle args = new Bundle();
args.putString(ARG_LABEL, timer.getLabel());
args.putInt(ARG_TIMER_ID, timer.getId());
final LabelDialogFragment frag = new LabelDialogFragment();
frag.setArguments(args);
return frag;
}
/**
* Replaces any existing LabelDialogFragment with the given {@code fragment}.
*/
public static void show(FragmentManager manager, LabelDialogFragment fragment) {
if (manager == null || manager.isDestroyed()) {
return;
}
// Finish any outstanding fragment work.
manager.executePendingTransactions();
final FragmentTransaction tx = manager.beginTransaction();
// Remove existing instance of LabelDialogFragment if necessary.
final Fragment existing = manager.findFragmentByTag(TAG);
if (existing != null) {
tx.remove(existing);
}
tx.addToBackStack(null);
fragment.show(tx, TAG);
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
// As long as the label box exists, save its state.
if (mLabelBox != null) {
outState.putString(ARG_LABEL, mLabelBox.getText().toString());
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle args = getArguments() == null ? Bundle.EMPTY : getArguments();
mAlarm = args.getParcelable(ARG_ALARM);
mTimerId = args.getInt(ARG_TIMER_ID, -1);
mTag = args.getString(ARG_TAG);
String label = args.getString(ARG_LABEL);
if (savedInstanceState != null) {
label = savedInstanceState.getString(ARG_LABEL, label);
}
final AlertDialog dialog = new AlertDialog.Builder(getActivity())
.setPositiveButton(android.R.string.ok, new OkListener())
.setNegativeButton(android.R.string.cancel, null /* listener */)
.setMessage(R.string.label)
.create();
final Context context = dialog.getContext();
final int colorControlActivated =
ThemeUtils.resolveColor(context, R.attr.colorControlActivated);
final int colorControlNormal =
ThemeUtils.resolveColor(context, R.attr.colorControlNormal);
mLabelBox = new AppCompatEditText(context);
mLabelBox.setSupportBackgroundTintList(new ColorStateList(
new int[][] { { android.R.attr.state_activated }, {} },
new int[] { colorControlActivated, colorControlNormal }));
mLabelBox.setOnEditorActionListener(new ImeDoneListener());
mLabelBox.addTextChangedListener(new TextChangeListener());
mLabelBox.setSingleLine();
mLabelBox.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES);
mLabelBox.setText(label);
mLabelBox.selectAll();
// The line at the bottom of EditText is part of its background therefore the padding
// must be added to its container.
final int padding = context.getResources()
.getDimensionPixelSize(R.dimen.label_edittext_padding);
dialog.setView(mLabelBox, padding, 0, padding, 0);
final Window alertDialogWindow = dialog.getWindow();
if (alertDialogWindow != null) {
alertDialogWindow.setSoftInputMode(SOFT_INPUT_STATE_VISIBLE);
}
return dialog;
}
@Override
public void onDestroyView() {
super.onDestroyView();
// Stop callbacks from the IME since there is no view to process them.
mLabelBox.setOnEditorActionListener(null);
}
/**
* Sets the new label into the timer or alarm.
*/
private void setLabel() {
String label = mLabelBox.getText().toString();
if (label.trim().isEmpty()) {
// Don't allow user to input label with only whitespace.
label = "";
}
if (mAlarm != null) {
((AlarmLabelDialogHandler) getActivity()).onDialogLabelSet(mAlarm, label, mTag);
} else if (mTimerId >= 0) {
final Timer timer = DataModel.getDataModel().getTimer(mTimerId);
if (timer != null) {
DataModel.getDataModel().setTimerLabel(timer, label);
}
}
}
public interface AlarmLabelDialogHandler {
void onDialogLabelSet(Alarm alarm, String label, String tag);
}
/**
* Alters the UI to indicate when input is valid or invalid.
*/
private class TextChangeListener implements TextWatcher {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
mLabelBox.setActivated(!TextUtils.isEmpty(s));
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable editable) {
}
}
/**
* Handles completing the label edit from the IME keyboard.
*/
private class ImeDoneListener implements TextView.OnEditorActionListener {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
setLabel();
dismissAllowingStateLoss();
return true;
}
return false;
}
}
/**
* Handles completing the label edit from the Ok button of the dialog.
*/
private class OkListener implements DialogInterface.OnClickListener {
@Override
public void onClick(DialogInterface dialog, int which) {
setLabel();
dismiss();
}
}
}