diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt index 44f3fbc58eaf7..275c7788edd3b 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt @@ -16,6 +16,20 @@ package com.android.systemui.controls.ui +/** + * All controls need to respond to changes in state and handle user-generated events. + * Implementations of this interface provide these different means by adding their own + * event handlers, and will update the control ui as they see fit. + */ interface Behavior { - fun apply(cvh: ControlViewHolder, cws: ControlWithState) + + /** + * Only called once per instance + */ + fun initialize(cvh: ControlViewHolder) + + /** + * Will be invoked on every update provided to the Control + */ + fun bind(cws: ControlWithState) } diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt index aec207518b9f1..feaea7c0d835b 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt @@ -37,6 +37,8 @@ import com.android.systemui.controls.controller.ControlsController import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.R +import kotlin.reflect.KClass + private const val UPDATE_DELAY_IN_MILLIS = 3000L class ControlViewHolder( @@ -54,6 +56,7 @@ class ControlViewHolder( val clipLayer: ClipDrawable lateinit var cws: ControlWithState var cancelUpdate: Runnable? = null + var behavior: Behavior? = null init { val ld = layout.getBackground() as LayerDrawable @@ -83,7 +86,14 @@ class ControlViewHolder( }) } - findBehavior(status, template).apply(this, cws) + val clazz = findBehavior(status, template) + if (behavior == null || behavior!!::class != clazz) { + // Behavior changes can signal a change in template from the app or + // first time setup + behavior = clazz.java.newInstance() + behavior?.initialize(this) + } + behavior?.bind(cws) } fun actionResponse(@ControlAction.ResponseResult response: Int) { @@ -115,21 +125,14 @@ class ControlViewHolder( controlsController.action(cws.ci, action) } - private fun findBehavior(status: Int, template: ControlTemplate): Behavior { + private fun findBehavior(status: Int, template: ControlTemplate): KClass { return when { - status == Control.STATUS_UNKNOWN -> UnknownBehavior() - template is ToggleTemplate -> ToggleBehavior() - template is ToggleRangeTemplate -> ToggleRangeBehavior() - template is TemperatureControlTemplate -> TemperatureControlBehavior() - template is ThumbnailTemplate -> StaticBehavior(uiExecutor, bgExecutor) - else -> { - object : Behavior { - override fun apply(cvh: ControlViewHolder, cws: ControlWithState) { - cvh.status.setText(cws.control?.getStatusText()) - cvh.applyRenderInfo(RenderInfo.lookup(cws.ci.deviceType, false)) - } - } - } + status == Control.STATUS_UNKNOWN -> UnknownBehavior::class + template is ToggleTemplate -> ToggleBehavior::class + template is ToggleRangeTemplate -> ToggleRangeBehavior::class + template is TemperatureControlTemplate -> TemperatureControlBehavior::class + template is ThumbnailTemplate -> StaticBehavior::class + else -> DefaultBehavior::class } } @@ -142,9 +145,12 @@ class ControlViewHolder( icon.setImageIcon(Icon.createWithResource(context, ri.iconResourceId)) icon.setImageTintList(fg) - clipLayer.getDrawable().setTintBlendMode(BlendMode.HUE) - clipLayer.getDrawable().setTintList(bg) + clipLayer.getDrawable().apply { + setTintBlendMode(BlendMode.HUE) + setTintList(bg) + } } + fun setEnabled(enabled: Boolean) { status.setEnabled(enabled) icon.setEnabled(enabled) diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt new file mode 100644 index 0000000000000..17479293f7dcb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DefaultBehavior.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2020 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.systemui.controls.ui + +class DefaultBehavior : Behavior { + lateinit var cvh: ControlViewHolder + + override fun initialize(cvh: ControlViewHolder) { + this.cvh = cvh + } + + override fun bind(cws: ControlWithState) { + cvh.status.setText(cws.control?.getStatusText() ?: "") + cvh.setEnabled(false) + cvh.applyRenderInfo(RenderInfo.lookup(cws.ci.deviceType, false)) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/StaticBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/StaticBehavior.kt index 340cdc0c854b3..c006d6fca7e2b 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/StaticBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/StaticBehavior.kt @@ -24,20 +24,20 @@ import android.service.controls.templates.ThumbnailTemplate import com.android.systemui.R import com.android.systemui.controls.ui.ControlActionCoordinator.MAX_LEVEL -import java.util.concurrent.Executor - /** * Used for controls that cannot be interacted with. Information is presented to the user * but no actions can be taken. If using a ThumbnailTemplate, the background image will * be changed. */ -class StaticBehavior( - val uiExecutor: Executor, - val bgExecutor: Executor -) : Behavior { +class StaticBehavior() : Behavior { lateinit var control: Control + lateinit var cvh: ControlViewHolder - override fun apply(cvh: ControlViewHolder, cws: ControlWithState) { + override fun initialize(cvh: ControlViewHolder) { + this.cvh = cvh + } + + override fun bind(cws: ControlWithState) { this.control = cws.control!! cvh.status.setText(control.getStatusText()) @@ -51,12 +51,12 @@ class StaticBehavior( val template = control.getControlTemplate() if (template is ThumbnailTemplate) { - bgExecutor.execute { + cvh.bgExecutor.execute { // clear the default tinting in favor of only using alpha val drawable = template.getThumbnail().loadDrawable(cvh.context) drawable.setTintList(null) drawable.setAlpha((0.45 * 255).toInt()) - uiExecutor.execute { + cvh.uiExecutor.execute { val radius = cvh.context.getResources() .getDimensionPixelSize(R.dimen.control_corner_radius).toFloat() clipLayer.setDrawable(CornerDrawable(drawable, radius)) diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt index 7661c6fb0bec5..239d2e5477bf8 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt @@ -16,12 +16,10 @@ package com.android.systemui.controls.ui -import android.content.Context import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.service.controls.Control import android.service.controls.templates.TemperatureControlTemplate -import android.widget.TextView import com.android.systemui.R import com.android.systemui.controls.ui.ControlActionCoordinator.MIN_LEVEL @@ -32,15 +30,15 @@ class TemperatureControlBehavior : Behavior { lateinit var control: Control lateinit var cvh: ControlViewHolder lateinit var template: TemperatureControlTemplate - lateinit var status: TextView - lateinit var context: Context - override fun apply(cvh: ControlViewHolder, cws: ControlWithState) { - this.control = cws.control!! + override fun initialize(cvh: ControlViewHolder) { this.cvh = cvh - status = cvh.status + } - status.setText(control.getStatusText()) + override fun bind(cws: ControlWithState) { + this.control = cws.control!! + + cvh.status.setText(control.getStatusText()) val ld = cvh.layout.getBackground() as LayerDrawable clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt index 4c35d26c6281b..d306d7c84e7f6 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt @@ -16,11 +16,9 @@ package com.android.systemui.controls.ui -import android.content.Context import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.view.View -import android.widget.TextView import android.service.controls.Control import android.service.controls.templates.ToggleTemplate @@ -33,21 +31,21 @@ class ToggleBehavior : Behavior { lateinit var template: ToggleTemplate lateinit var control: Control lateinit var cvh: ControlViewHolder - lateinit var context: Context - lateinit var status: TextView - override fun apply(cvh: ControlViewHolder, cws: ControlWithState) { - this.control = cws.control!! + override fun initialize(cvh: ControlViewHolder) { this.cvh = cvh - status = cvh.status - - status.setText(control.getStatusText()) - - template = control.getControlTemplate() as ToggleTemplate + cvh.setEnabled(false) cvh.layout.setOnClickListener(View.OnClickListener() { ControlActionCoordinator.toggle(cvh, template.getTemplateId(), template.isChecked()) }) + } + + override fun bind(cws: ControlWithState) { + this.control = cws.control!! + + cvh.status.setText(control.getStatusText()) + template = control.getControlTemplate() as ToggleTemplate val ld = cvh.layout.getBackground() as LayerDrawable clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt index 8d65ca344d171..45d73979dd680 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt @@ -51,17 +51,13 @@ class ToggleRangeBehavior : Behavior { private const val DEFAULT_FORMAT = "%.1f" } - override fun apply(cvh: ControlViewHolder, cws: ControlWithState) { - this.control = cws.control!! + override fun initialize(cvh: ControlViewHolder) { this.cvh = cvh - - statusExtra = cvh.statusExtra status = cvh.status - - status.setText(control.getStatusText()) - context = status.getContext() + cvh.setEnabled(false) + val gestureListener = ToggleRangeGestureListener(cvh.layout) val gestureDetector = GestureDetector(context, gestureListener) cvh.layout.setOnTouchListener({ v: View, e: MotionEvent -> @@ -77,6 +73,13 @@ class ToggleRangeBehavior : Behavior { return@setOnTouchListener false }) + } + + override fun bind(cws: ControlWithState) { + this.control = cws.control!! + + statusExtra = cvh.statusExtra + status.setText(control.getStatusText()) val ld = cvh.layout.getBackground() as LayerDrawable clipLayer = ld.findDrawableByLayerId(R.id.clip_layer) diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/UnknownBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/UnknownBehavior.kt index 27f1b336e6b23..1f33b8515dc70 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/UnknownBehavior.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/UnknownBehavior.kt @@ -17,7 +17,13 @@ package com.android.systemui.controls.ui class UnknownBehavior : Behavior { - override fun apply(cvh: ControlViewHolder, cws: ControlWithState) { + lateinit var cvh: ControlViewHolder + + override fun initialize(cvh: ControlViewHolder) { + this.cvh = cvh + } + + override fun bind(cws: ControlWithState) { cvh.status.setText(cvh.context.getString(com.android.internal.R.string.loading)) cvh.setEnabled(false) cvh.applyRenderInfo(RenderInfo.lookup(cws.ci.deviceType, false))