Merge "Update Stretch Analog clock face" into qt-dev
am: d7af9b8527
Change-Id: I51e921570356643fd1cc9fe4c81751e9097ea182
This commit is contained in:
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
7
packages/SystemUI/res-keyguard/drawable/analog_frame.xml
Normal file
7
packages/SystemUI/res-keyguard/drawable/analog_frame.xml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="250dp"
|
||||||
|
android:width="250dp"
|
||||||
|
android:viewportHeight="380"
|
||||||
|
android:viewportWidth="380">
|
||||||
|
<path android:fillColor="#000000" android:pathData="M190,190m0,2a2,2 0,1 1,0 -4a2,2 0,1 1,0 4"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="250dp"
|
||||||
|
android:width="250dp"
|
||||||
|
android:viewportHeight="380"
|
||||||
|
android:viewportWidth="380">
|
||||||
|
<path android:fillColor="#777777" android:fillType="evenOdd" android:pathData="M203,190C203,185.398 200.608,181.354 197,179.044L197,58C197,54.134 193.866,51 190,51C186.134,51 183,54.134 183,58L183,179.043C179.392,181.354 177,185.397 177,190C177,197.18 182.82,203 190,203C197.18,203 203,197.18 203,190Z"/>
|
||||||
|
</vector>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:height="250dp"
|
||||||
|
android:width="250dp"
|
||||||
|
android:viewportHeight="380"
|
||||||
|
android:viewportWidth="380">
|
||||||
|
<path android:fillColor="#FFFFFF" android:pathData="M192,182.252C195.45,183.14 198,186.272 198,190C198,194.418 194.418,198 190,198C185.582,198 182,194.418 182,190C182,186.272 184.55,183.14 188,182.252L188,10C188,8.895 188.895,8 190,8C191.105,8 192,8.895 192,10L192,182.252Z"/>
|
||||||
|
</vector>
|
||||||
@@ -35,9 +35,27 @@
|
|||||||
android:format24Hour="@string/keyguard_widget_24_hours_format"
|
android:format24Hour="@string/keyguard_widget_24_hours_format"
|
||||||
android:elegantTextHeight="false"
|
android:elegantTextHeight="false"
|
||||||
/>
|
/>
|
||||||
<com.android.keyguard.clock.StretchAnalogClock
|
<com.android.keyguard.clock.ImageClock
|
||||||
android:id="@+id/analog_clock"
|
android:id="@+id/analog_clock"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
/>
|
>
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/hour_hand"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/analog_hour_hand"
|
||||||
|
/>
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/minute_hand"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/analog_minute_hand"
|
||||||
|
/>
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/analog_frame"
|
||||||
|
/>
|
||||||
|
</com.android.keyguard.clock.ImageClock>
|
||||||
</com.android.keyguard.clock.ClockLayout>
|
</com.android.keyguard.clock.ClockLayout>
|
||||||
@@ -413,6 +413,6 @@ number">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.
|
|||||||
<string name="clock_title_bubble" translatable="false">Bubble</string>
|
<string name="clock_title_bubble" translatable="false">Bubble</string>
|
||||||
<!-- Title for Stretch clock face that will appear in the picker app next to a preview image of
|
<!-- Title for Stretch clock face that will appear in the picker app next to a preview image of
|
||||||
the clock face. [CHAR LIMIT=8] -->
|
the clock face. [CHAR LIMIT=8] -->
|
||||||
<string name="clock_title_stretch" translatable="false">Stretch</string>
|
<string name="clock_title_analog" translatable="false">Analog</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ import java.util.TimeZone;
|
|||||||
/**
|
/**
|
||||||
* Controller for Stretch clock that can appear on lock screen and AOD.
|
* Controller for Stretch clock that can appear on lock screen and AOD.
|
||||||
*/
|
*/
|
||||||
public class StretchAnalogClockController implements ClockPlugin {
|
public class AnalogClockController implements ClockPlugin {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resources used to get title and thumbnail.
|
* Resources used to get title and thumbnail.
|
||||||
@@ -60,9 +60,9 @@ public class StretchAnalogClockController implements ClockPlugin {
|
|||||||
/**
|
/**
|
||||||
* Custom clock shown on AOD screen and behind stack scroller on lock.
|
* Custom clock shown on AOD screen and behind stack scroller on lock.
|
||||||
*/
|
*/
|
||||||
private View mBigClockView;
|
private ClockLayout mBigClockView;
|
||||||
private TextClock mDigitalClock;
|
private TextClock mDigitalClock;
|
||||||
private StretchAnalogClock mAnalogClock;
|
private ImageClock mAnalogClock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Small clock shown on lock screen above stack scroller.
|
* Small clock shown on lock screen above stack scroller.
|
||||||
@@ -82,7 +82,7 @@ public class StretchAnalogClockController implements ClockPlugin {
|
|||||||
* @param inflater Inflater used to inflate custom clock views.
|
* @param inflater Inflater used to inflate custom clock views.
|
||||||
* @param colorExtractor Extracts accent color from wallpaper.
|
* @param colorExtractor Extracts accent color from wallpaper.
|
||||||
*/
|
*/
|
||||||
public StretchAnalogClockController(Resources res, LayoutInflater inflater,
|
public AnalogClockController(Resources res, LayoutInflater inflater,
|
||||||
SysuiColorExtractor colorExtractor) {
|
SysuiColorExtractor colorExtractor) {
|
||||||
mResources = res;
|
mResources = res;
|
||||||
mLayoutInflater = inflater;
|
mLayoutInflater = inflater;
|
||||||
@@ -90,7 +90,7 @@ public class StretchAnalogClockController implements ClockPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createViews() {
|
private void createViews() {
|
||||||
mBigClockView = mLayoutInflater.inflate(R.layout.stretchanalog_clock, null);
|
mBigClockView = (ClockLayout) mLayoutInflater.inflate(R.layout.analog_clock, null);
|
||||||
mAnalogClock = mBigClockView.findViewById(R.id.analog_clock);
|
mAnalogClock = mBigClockView.findViewById(R.id.analog_clock);
|
||||||
mDigitalClock = mBigClockView.findViewById(R.id.digital_clock);
|
mDigitalClock = mBigClockView.findViewById(R.id.digital_clock);
|
||||||
|
|
||||||
@@ -114,17 +114,17 @@ public class StretchAnalogClockController implements ClockPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "stretch";
|
return "analog";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return mResources.getString(R.string.clock_title_stretch);
|
return mResources.getString(R.string.clock_title_analog);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Bitmap getThumbnail() {
|
public Bitmap getThumbnail() {
|
||||||
return BitmapFactory.decodeResource(mResources, R.drawable.stretch_thumbnail);
|
return BitmapFactory.decodeResource(mResources, R.drawable.analog_thumbnail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -175,13 +175,14 @@ public class StretchAnalogClockController implements ClockPlugin {
|
|||||||
}
|
}
|
||||||
final int length = colorPalette.length;
|
final int length = colorPalette.length;
|
||||||
mDigitalClock.setTextColor(colorPalette[Math.max(0, length - 5)]);
|
mDigitalClock.setTextColor(colorPalette[Math.max(0, length - 5)]);
|
||||||
mAnalogClock.setClockColor(colorPalette[Math.max(0, length - 5)],
|
mAnalogClock.setClockColors(colorPalette[Math.max(0, length - 5)],
|
||||||
colorPalette[Math.max(0, length - 2)]);
|
colorPalette[Math.max(0, length - 2)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTimeTick() {
|
public void onTimeTick() {
|
||||||
mAnalogClock.onTimeChanged();
|
mAnalogClock.onTimeChanged();
|
||||||
|
mBigClockView.onTimeChanged();
|
||||||
mDigitalClock.refresh();
|
mDigitalClock.refresh();
|
||||||
mLockClock.refresh();
|
mLockClock.refresh();
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ public class BubbleClockController implements ClockPlugin {
|
|||||||
/**
|
/**
|
||||||
* Custom clock shown on AOD screen and behind stack scroller on lock.
|
* Custom clock shown on AOD screen and behind stack scroller on lock.
|
||||||
*/
|
*/
|
||||||
private View mView;
|
private ClockLayout mView;
|
||||||
private TextClock mDigitalClock;
|
private TextClock mDigitalClock;
|
||||||
private ImageClock mAnalogClock;
|
private ImageClock mAnalogClock;
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ public class BubbleClockController implements ClockPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createViews() {
|
private void createViews() {
|
||||||
mView = mLayoutInflater.inflate(R.layout.bubble_clock, null);
|
mView = (ClockLayout) mLayoutInflater.inflate(R.layout.bubble_clock, null);
|
||||||
mDigitalClock = (TextClock) mView.findViewById(R.id.digital_clock);
|
mDigitalClock = (TextClock) mView.findViewById(R.id.digital_clock);
|
||||||
mAnalogClock = (ImageClock) mView.findViewById(R.id.analog_clock);
|
mAnalogClock = (ImageClock) mView.findViewById(R.id.analog_clock);
|
||||||
|
|
||||||
@@ -186,6 +186,7 @@ public class BubbleClockController implements ClockPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onTimeTick() {
|
public void onTimeTick() {
|
||||||
mAnalogClock.onTimeChanged();
|
mAnalogClock.onTimeChanged();
|
||||||
|
mView.onTimeChanged();
|
||||||
mDigitalClock.refresh();
|
mDigitalClock.refresh();
|
||||||
mLockClock.refresh();
|
mLockClock.refresh();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import com.android.keyguard.R;
|
|||||||
*/
|
*/
|
||||||
public class ClockLayout extends FrameLayout {
|
public class ClockLayout extends FrameLayout {
|
||||||
|
|
||||||
|
private static final int ANALOG_CLOCK_SHIFT_FACTOR = 3;
|
||||||
/**
|
/**
|
||||||
* Clock face views.
|
* Clock face views.
|
||||||
*/
|
*/
|
||||||
@@ -73,7 +74,14 @@ public class ClockLayout extends FrameLayout {
|
|||||||
@Override
|
@Override
|
||||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
super.onLayout(changed, left, top, right, bottom);
|
super.onLayout(changed, left, top, right, bottom);
|
||||||
|
positionChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onTimeChanged() {
|
||||||
|
positionChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void positionChildren() {
|
||||||
final float offsetX = getBurnInOffset(mBurnInPreventionOffsetX * 2, true)
|
final float offsetX = getBurnInOffset(mBurnInPreventionOffsetX * 2, true)
|
||||||
- mBurnInPreventionOffsetX;
|
- mBurnInPreventionOffsetX;
|
||||||
final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY * 2, false)
|
final float offsetY = getBurnInOffset(mBurnInPreventionOffsetY * 2, false)
|
||||||
@@ -89,9 +97,9 @@ public class ClockLayout extends FrameLayout {
|
|||||||
// Put the analog clock in the middle of the screen.
|
// Put the analog clock in the middle of the screen.
|
||||||
if (mAnalogClock != null) {
|
if (mAnalogClock != null) {
|
||||||
mAnalogClock.setX(Math.max(0f, 0.5f * (getWidth() - mAnalogClock.getWidth()))
|
mAnalogClock.setX(Math.max(0f, 0.5f * (getWidth() - mAnalogClock.getWidth()))
|
||||||
+ offsetX);
|
+ ANALOG_CLOCK_SHIFT_FACTOR * offsetX);
|
||||||
mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight()))
|
mAnalogClock.setY(Math.max(0f, 0.5f * (getHeight() - mAnalogClock.getHeight()))
|
||||||
+ offsetY);
|
+ ANALOG_CLOCK_SHIFT_FACTOR * offsetY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -142,8 +142,7 @@ public final class ClockManager {
|
|||||||
|
|
||||||
addBuiltinClock(() -> new DefaultClockController(res, layoutInflater, colorExtractor));
|
addBuiltinClock(() -> new DefaultClockController(res, layoutInflater, colorExtractor));
|
||||||
addBuiltinClock(() -> new BubbleClockController(res, layoutInflater, colorExtractor));
|
addBuiltinClock(() -> new BubbleClockController(res, layoutInflater, colorExtractor));
|
||||||
addBuiltinClock(() -> new StretchAnalogClockController(res, layoutInflater,
|
addBuiltinClock(() -> new AnalogClockController(res, layoutInflater, colorExtractor));
|
||||||
colorExtractor));
|
|
||||||
|
|
||||||
// Store the size of the display for generation of clock preview.
|
// Store the size of the display for generation of clock preview.
|
||||||
DisplayMetrics dm = res.getDisplayMetrics();
|
DisplayMetrics dm = res.getDisplayMetrics();
|
||||||
|
|||||||
@@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019 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.keyguard.clock;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Analog clock where the minute hand extends off of the screen.
|
|
||||||
*/
|
|
||||||
public class StretchAnalogClock extends View {
|
|
||||||
|
|
||||||
private static final int DEFAULT_COLOR = Color.parseColor("#F5C983");
|
|
||||||
private static final float HOUR_STROKE_WIDTH = 60f;
|
|
||||||
private static final float MINUTE_STROKE_WIDTH = 20f;
|
|
||||||
private static final float CENTER_GAP_AND_CIRCLE_RADIUS = 80f;
|
|
||||||
|
|
||||||
private final Paint mHourPaint = new Paint();
|
|
||||||
private final Paint mMinutePaint = new Paint();
|
|
||||||
private Calendar mTime = Calendar.getInstance(TimeZone.getDefault());
|
|
||||||
private TimeZone mTimeZone;
|
|
||||||
|
|
||||||
public StretchAnalogClock(Context context) {
|
|
||||||
this(context, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StretchAnalogClock(Context context, AttributeSet attrs) {
|
|
||||||
this(context, attrs, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StretchAnalogClock(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
||||||
this(context, attrs, defStyleAttr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public StretchAnalogClock(Context context, AttributeSet attrs, int defStyleAttr,
|
|
||||||
int defStyleRes) {
|
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call when the time changes to update the clock hands.
|
|
||||||
*/
|
|
||||||
public void onTimeChanged() {
|
|
||||||
mTime.setTimeInMillis(System.currentTimeMillis());
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call when the time zone has changed to update clock hands.
|
|
||||||
*
|
|
||||||
* @param timeZone The updated time zone that will be used.
|
|
||||||
*/
|
|
||||||
public void onTimeZoneChanged(TimeZone timeZone) {
|
|
||||||
mTime.setTimeZone(timeZone);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the colors to use on the clock face.
|
|
||||||
* @param dark Darker color obtained from color palette.
|
|
||||||
* @param light Lighter color obtained from color palette.
|
|
||||||
*/
|
|
||||||
public void setClockColor(int dark, int light) {
|
|
||||||
mHourPaint.setColor(dark);
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init() {
|
|
||||||
mHourPaint.setColor(DEFAULT_COLOR);
|
|
||||||
mHourPaint.setStrokeWidth(HOUR_STROKE_WIDTH);
|
|
||||||
mHourPaint.setAntiAlias(true);
|
|
||||||
mHourPaint.setStrokeCap(Paint.Cap.ROUND);
|
|
||||||
|
|
||||||
mMinutePaint.setColor(Color.WHITE);
|
|
||||||
mMinutePaint.setStrokeWidth(MINUTE_STROKE_WIDTH);
|
|
||||||
mMinutePaint.setAntiAlias(true);
|
|
||||||
mMinutePaint.setStrokeCap(Paint.Cap.ROUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDraw(Canvas canvas) {
|
|
||||||
final float centerX = getWidth() / 2f;
|
|
||||||
final float centerY = getHeight() / 2f;
|
|
||||||
|
|
||||||
final float minutesRotation = mTime.get(Calendar.MINUTE) * 6f;
|
|
||||||
final float hoursRotation = mTime.get(Calendar.HOUR) * 30
|
|
||||||
+ mTime.get(Calendar.MINUTE) * 0.5f;
|
|
||||||
|
|
||||||
// Compute length of clock hands. Hour hand is 60% the length from center to edge
|
|
||||||
// and minute hand is twice the length to make sure it extends past screen edge.
|
|
||||||
double sMinuteHandLengthFactor = Math.sin(2d * Math.PI * minutesRotation / 360d);
|
|
||||||
float sMinuteHandLength = (float) (2d * (centerY + (centerX - centerY)
|
|
||||||
* sMinuteHandLengthFactor * sMinuteHandLengthFactor));
|
|
||||||
double sHourHandLengthFactor = Math.sin(2d * Math.PI * hoursRotation / 360d);
|
|
||||||
float sHourHandLength = (float) (0.6d * (centerY + (centerX - centerY)
|
|
||||||
* sHourHandLengthFactor * sHourHandLengthFactor));
|
|
||||||
|
|
||||||
canvas.save();
|
|
||||||
|
|
||||||
canvas.rotate(minutesRotation, centerX, centerY);
|
|
||||||
canvas.drawLine(
|
|
||||||
centerX,
|
|
||||||
centerY + CENTER_GAP_AND_CIRCLE_RADIUS,
|
|
||||||
centerX,
|
|
||||||
centerY - sMinuteHandLength,
|
|
||||||
mMinutePaint);
|
|
||||||
|
|
||||||
canvas.rotate(hoursRotation - minutesRotation, centerX, centerY);
|
|
||||||
canvas.drawLine(
|
|
||||||
centerX,
|
|
||||||
centerY + CENTER_GAP_AND_CIRCLE_RADIUS,
|
|
||||||
centerX,
|
|
||||||
centerY - sHourHandLength,
|
|
||||||
mHourPaint);
|
|
||||||
|
|
||||||
canvas.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onAttachedToWindow() {
|
|
||||||
super.onAttachedToWindow();
|
|
||||||
mTime.setTimeZone(mTimeZone != null ? mTimeZone : TimeZone.getDefault());
|
|
||||||
onTimeChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -38,9 +38,9 @@ import org.mockito.MockitoAnnotations;
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
@RunWithLooper
|
@RunWithLooper
|
||||||
public final class StretchAnalogClockControllerTest extends SysuiTestCase {
|
public final class AnalogClockControllerTest extends SysuiTestCase {
|
||||||
|
|
||||||
private StretchAnalogClockController mClockController;
|
private AnalogClockController mClockController;
|
||||||
@Mock SysuiColorExtractor mMockColorExtractor;
|
@Mock SysuiColorExtractor mMockColorExtractor;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -49,7 +49,7 @@ public final class StretchAnalogClockControllerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
Resources res = getContext().getResources();
|
Resources res = getContext().getResources();
|
||||||
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
|
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
|
||||||
mClockController = new StretchAnalogClockController(res, layoutInflater,
|
mClockController = new AnalogClockController(res, layoutInflater,
|
||||||
mMockColorExtractor);
|
mMockColorExtractor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user