com.todoroo.astrid.timers.TimerControlSet.java Source code

Java tutorial

Introduction

Here is the source code for com.todoroo.astrid.timers.TimerControlSet.java

Source

/**
 * Copyright (c) 2012 Todoroo Inc
 * <p/>
 * See the file "LICENSE" for the full license governing this code.
 */
package com.todoroo.astrid.timers;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.TextView;

import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.ui.TimeDurationControlSet;

import org.tasks.R;
import org.tasks.dialogs.DialogBuilder;
import org.tasks.injection.ForActivity;
import org.tasks.injection.FragmentComponent;
import org.tasks.themes.Theme;
import org.tasks.ui.TaskEditControlFragment;

import javax.inject.Inject;

import butterknife.BindView;
import butterknife.OnClick;

import static android.support.v4.content.ContextCompat.getColor;

/**
 * Control Set for managing repeats
 *
 * @author Tim Su <tim@todoroo.com>
 *
 */
public class TimerControlSet extends TaskEditControlFragment {

    public static final int TAG = R.string.TEA_ctrl_timer_pref;

    public interface TimerControlSetCallback {
        Task stopTimer();

        Task startTimer();
    }

    private static final String EXTRA_STARTED = "extra_started";
    private static final String EXTRA_ESTIMATED = "extra_estimated";
    private static final String EXTRA_ELAPSED = "extra_elapsed";

    @Inject
    DialogBuilder dialogBuilder;
    @Inject
    @ForActivity
    Context context;
    @Inject
    Theme theme;

    @BindView(R.id.display_row_edit)
    TextView displayEdit;
    @BindView(R.id.timer)
    Chronometer chronometer;
    @BindView(R.id.timer_button)
    ImageView timerButton;

    private TimeDurationControlSet estimated;
    private TimeDurationControlSet elapsed;
    private long timerStarted;
    private AlertDialog dialog;
    private View dialogView;
    private int elapsedSeconds;
    private int estimatedSeconds;
    private TimerControlSetCallback callback;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        if (savedInstanceState != null) {
            timerStarted = savedInstanceState.getLong(EXTRA_STARTED);
            elapsedSeconds = savedInstanceState.getInt(EXTRA_ELAPSED);
            estimatedSeconds = savedInstanceState.getInt(EXTRA_ESTIMATED);
        }

        dialogView = inflater.inflate(R.layout.control_set_timers_dialog, null);
        estimated = new TimeDurationControlSet(context, dialogView, R.id.estimatedDuration, theme);
        elapsed = new TimeDurationControlSet(context, dialogView, R.id.elapsedDuration, theme);
        estimated.setTimeDuration(estimatedSeconds);
        elapsed.setTimeDuration(elapsedSeconds);
        refresh();
        return view;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        callback = (TimerControlSetCallback) activity;
    }

    @Override
    protected void inject(FragmentComponent component) {
        component.inject(this);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putInt(EXTRA_ELAPSED, elapsed.getTimeDurationInSeconds());
        outState.putInt(EXTRA_ESTIMATED, estimated.getTimeDurationInSeconds());
        outState.putLong(EXTRA_STARTED, timerStarted);
    }

    @OnClick(R.id.display_row_edit)
    void openPopup(View view) {
        if (dialog == null) {
            dialog = buildDialog();
        }
        dialog.show();
    }

    private AlertDialog buildDialog() {
        return dialogBuilder.newDialog().setView(dialogView)
                .setPositiveButton(android.R.string.ok, (dialog12, which) -> refreshDisplayView())
                .setOnCancelListener(dialog1 -> refreshDisplayView()).create();
    }

    @OnClick(R.id.timer_container)
    void timerClicked(View view) {
        if (timerActive()) {
            Task task = callback.stopTimer();
            elapsed.setTimeDuration(task.getElapsedSeconds());
            timerStarted = 0;
            chronometer.stop();
            refreshDisplayView();
        } else {
            Task task = callback.startTimer();
            timerStarted = task.getTimerStart();
            chronometer.start();
        }
        updateChronometer();
    }

    @Override
    protected int getLayout() {
        return R.layout.control_set_timers;
    }

    @Override
    public int getIcon() {
        return R.drawable.ic_timer_24dp;
    }

    @Override
    public int controlId() {
        return TAG;
    }

    @Override
    public void initialize(boolean isNewTask, Task task) {
        timerStarted = task.getTimerStart();
        elapsedSeconds = task.getElapsedSeconds();
        estimatedSeconds = task.getEstimatedSeconds();
    }

    @Override
    public boolean hasChanges(Task original) {
        return elapsed.getTimeDurationInSeconds() != original.getElapsedSeconds()
                || estimated.getTimeDurationInSeconds() != original.getEstimatedSeconds();
    }

    @Override
    public void apply(Task task) {
        task.setElapsedSeconds(elapsed.getTimeDurationInSeconds());
        task.setEstimatedSeconds(estimated.getTimeDurationInSeconds());
    }

    private void refresh() {
        refreshDisplayView();
        updateChronometer();
    }

    private void refreshDisplayView() {
        String est = null;
        int estimatedSeconds = estimated.getTimeDurationInSeconds();
        if (estimatedSeconds > 0) {
            est = getString(R.string.TEA_timer_est, DateUtils.formatElapsedTime(estimatedSeconds));
        }
        String elap = null;
        int elapsedSeconds = elapsed.getTimeDurationInSeconds();
        if (elapsedSeconds > 0) {
            elap = getString(R.string.TEA_timer_elap, DateUtils.formatElapsedTime(elapsedSeconds));
        }

        String toDisplay;

        if (!TextUtils.isEmpty(est) && !TextUtils.isEmpty(elap)) {
            toDisplay = est + ", " + elap; //$NON-NLS-1$
        } else if (!TextUtils.isEmpty(est)) {
            toDisplay = est;
        } else if (!TextUtils.isEmpty(elap)) {
            toDisplay = elap;
        } else {
            toDisplay = null;
        }

        if (!TextUtils.isEmpty(toDisplay)) {
            displayEdit.setText(toDisplay);
            displayEdit.setTextColor(getColor(context, R.color.text_primary));
        } else {
            displayEdit.setText(R.string.TEA_timer_controls);
            displayEdit.setTextColor(getColor(context, R.color.text_tertiary));
        }
    }

    private void updateChronometer() {
        timerButton.setImageResource(timerActive() ? R.drawable.ic_pause_24dp : R.drawable.ic_play_arrow_24dp);

        long elapsed = this.elapsed.getTimeDurationInSeconds() * 1000L;
        if (timerActive()) {
            chronometer.setVisibility(View.VISIBLE);
            elapsed += DateUtilities.now() - timerStarted;
            chronometer.setBase(SystemClock.elapsedRealtime() - elapsed);
            if (elapsed > DateUtilities.ONE_DAY) {
                chronometer.setOnChronometerTickListener(cArg -> {
                    long t = SystemClock.elapsedRealtime() - cArg.getBase();
                    cArg.setText(DateFormat.format("d'd' h:mm", t)); //$NON-NLS-1$
                });

            }
            chronometer.start();
        } else {
            chronometer.setVisibility(View.GONE);
            chronometer.stop();
        }
    }

    private boolean timerActive() {
        return timerStarted > 0;
    }
}