/* * Copyright (C) 2017 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 androidx.wear.widget; import android.os.CountDownTimer; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; /** * Controller for {@link CircularProgressLayout}. */ class CircularProgressLayoutController { private final CircularProgressLayout mLayout; @VisibleForTesting CountDownTimer mTimer; private boolean mIsIndeterminate; private boolean mIsTimerRunning; /** * Called when the timer is finished. */ @Nullable private CircularProgressLayout.OnTimerFinishedListener mOnTimerFinishedListener; CircularProgressLayoutController(CircularProgressLayout layout) { mLayout = layout; } /** * Returns the registered {@link CircularProgressLayout.OnTimerFinishedListener}. */ @Nullable public CircularProgressLayout.OnTimerFinishedListener getOnTimerFinishedListener() { return mOnTimerFinishedListener; } /** * Sets the {@link CircularProgressLayout.OnTimerFinishedListener} to be notified when timer * countdown is finished. */ public void setOnTimerFinishedListener( @Nullable CircularProgressLayout.OnTimerFinishedListener listener) { mOnTimerFinishedListener = listener; } /** Returns true if the progress is shown as an indeterminate spinner. */ boolean isIndeterminate() { return mIsIndeterminate; } /** Returns true if timer is running. */ boolean isTimerRunning() { return mIsTimerRunning; } /** Sets if the progress should be shown as an indeterminate spinner. */ void setIndeterminate(boolean indeterminate) { if (mIsIndeterminate == indeterminate) { return; } mIsIndeterminate = indeterminate; if (mIsIndeterminate) { if (mIsTimerRunning) { stopTimer(); } mLayout.getProgressDrawable().start(); } else { mLayout.getProgressDrawable().stop(); } } void startTimer(long totalTime, long updateInterval) { reset(); mIsTimerRunning = true; mTimer = new CircularProgressTimer(totalTime, updateInterval); mTimer.start(); } void stopTimer() { if (mIsTimerRunning) { mTimer.cancel(); mIsTimerRunning = false; mLayout.getProgressDrawable().setStartEndTrim(0f, 0f); // Reset the progress } } /** * Resets everything. */ void reset() { setIndeterminate(false); // If showing indeterminate progress, stop it stopTimer(); // Stop the previous timer if there is one mLayout.getProgressDrawable().setStartEndTrim(0f, 0f); // Reset the progress } /** * Class to handle timing for {@link CircularProgressLayout}. */ private class CircularProgressTimer extends CountDownTimer { private final long mTotalTime; CircularProgressTimer(long totalTime, long updateInterval) { super(totalTime, updateInterval); mTotalTime = totalTime; } @Override public void onTick(long millisUntilFinished) { mLayout.getProgressDrawable() .setStartEndTrim(0f, 1f - (float) millisUntilFinished / (float) mTotalTime); mLayout.invalidate(); } @Override public void onFinish() { mLayout.getProgressDrawable().setStartEndTrim(0f, 1f); if (mOnTimerFinishedListener != null) { mOnTimerFinishedListener.onTimerFinished(mLayout); } mIsTimerRunning = false; } } }