Automatic sources dropoff on 2020-06-10 18:32:38.095721 The change is generated with prebuilt drop tool. Change-Id: I24cbf6ba6db262a1ae1445db1427a08fee35b3b4
diff --git a/com/android/internal/widget/TextProgressBar.java b/com/android/internal/widget/TextProgressBar.java new file mode 100644 index 0000000..7ca07d4 --- /dev/null +++ b/com/android/internal/widget/TextProgressBar.java
@@ -0,0 +1,184 @@ +/* + * Copyright (C) 2008 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.internal.widget; + +import android.content.Context; +import android.os.SystemClock; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Chronometer; +import android.widget.Chronometer.OnChronometerTickListener; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.RemoteViews.RemoteView; + +/** + * Container that links together a {@link ProgressBar} and {@link Chronometer} + * as children. It subscribes to {@link Chronometer#OnChronometerTickListener} + * and updates the {@link ProgressBar} based on a preset finishing time. + * <p> + * This widget expects to contain two children with specific ids + * {@link android.R.id.progress} and {@link android.R.id.text1}. + * <p> + * If the {@link Chronometer} {@link android.R.attr#layout_width} is + * {@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT}, then the + * {@link android.R.attr#gravity} will be used to automatically move it with + * respect to the {@link ProgressBar} position. For example, if + * {@link android.view.Gravity#LEFT} then the {@link Chronometer} will be placed + * just ahead of the leading edge of the {@link ProgressBar} position. + */ +@RemoteView +public class TextProgressBar extends RelativeLayout implements OnChronometerTickListener { + public static final String TAG = "TextProgressBar"; + + static final int CHRONOMETER_ID = android.R.id.text1; + static final int PROGRESSBAR_ID = android.R.id.progress; + + Chronometer mChronometer = null; + ProgressBar mProgressBar = null; + + long mDurationBase = -1; + int mDuration = -1; + + boolean mChronometerFollow = false; + int mChronometerGravity = Gravity.NO_GRAVITY; + + public TextProgressBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + public TextProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public TextProgressBar(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public TextProgressBar(Context context) { + super(context); + } + + /** + * Catch any interesting children when they are added. + */ + @Override + public void addView(View child, int index, ViewGroup.LayoutParams params) { + super.addView(child, index, params); + + int childId = child.getId(); + if (childId == CHRONOMETER_ID && child instanceof Chronometer) { + mChronometer = (Chronometer) child; + mChronometer.setOnChronometerTickListener(this); + + // Check if Chronometer should move with with ProgressBar + mChronometerFollow = (params.width == ViewGroup.LayoutParams.WRAP_CONTENT); + mChronometerGravity = (mChronometer.getGravity() & + Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); + + } else if (childId == PROGRESSBAR_ID && child instanceof ProgressBar) { + mProgressBar = (ProgressBar) child; + } + } + + /** + * Set the expected termination time of the running {@link Chronometer}. + * This value is used to adjust the {@link ProgressBar} against the elapsed + * time. + * <p> + * Call this <b>after</b> adjusting the {@link Chronometer} base, if + * necessary. + * + * @param durationBase Use the {@link SystemClock#elapsedRealtime} time + * base. + */ + @android.view.RemotableViewMethod + public void setDurationBase(long durationBase) { + mDurationBase = durationBase; + + if (mProgressBar == null || mChronometer == null) { + throw new RuntimeException("Expecting child ProgressBar with id " + + "'android.R.id.progress' and Chronometer id 'android.R.id.text1'"); + } + + // Update the ProgressBar maximum relative to Chronometer base + mDuration = (int) (durationBase - mChronometer.getBase()); + if (mDuration <= 0) { + mDuration = 1; + } + mProgressBar.setMax(mDuration); + } + + /** + * Callback when {@link Chronometer} changes, indicating that we should + * update the {@link ProgressBar} and change the layout if necessary. + */ + public void onChronometerTick(Chronometer chronometer) { + if (mProgressBar == null) { + throw new RuntimeException( + "Expecting child ProgressBar with id 'android.R.id.progress'"); + } + + // Stop Chronometer if we're past duration + long now = SystemClock.elapsedRealtime(); + if (now >= mDurationBase) { + mChronometer.stop(); + } + + // Update the ProgressBar status + int remaining = (int) (mDurationBase - now); + mProgressBar.setProgress(mDuration - remaining); + + // Move the Chronometer if gravity is set correctly + if (mChronometerFollow) { + RelativeLayout.LayoutParams params; + + // Calculate estimate of ProgressBar leading edge position + params = (RelativeLayout.LayoutParams) mProgressBar.getLayoutParams(); + int contentWidth = mProgressBar.getWidth() - (params.leftMargin + params.rightMargin); + int leadingEdge = ((contentWidth * mProgressBar.getProgress()) / + mProgressBar.getMax()) + params.leftMargin; + + // Calculate any adjustment based on gravity + int adjustLeft = 0; + int textWidth = mChronometer.getWidth(); + if (mChronometerGravity == Gravity.END) { + adjustLeft = -textWidth; + } else if (mChronometerGravity == Gravity.CENTER_HORIZONTAL) { + adjustLeft = -(textWidth / 2); + } + + // Limit margin to keep text inside ProgressBar bounds + leadingEdge += adjustLeft; + int rightLimit = contentWidth - params.rightMargin - textWidth; + if (leadingEdge < params.leftMargin) { + leadingEdge = params.leftMargin; + } else if (leadingEdge > rightLimit) { + leadingEdge = rightLimit; + } + + params = (RelativeLayout.LayoutParams) mChronometer.getLayoutParams(); + params.leftMargin = leadingEdge; + + // Request layout to move Chronometer + mChronometer.requestLayout(); + + } + } +}