1 /*
2  * Copyright 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.glance.appwidget
18 
19 import android.view.View
20 import android.widget.RemoteViews
21 import androidx.annotation.IdRes
22 import androidx.compose.runtime.Composable
23 import androidx.glance.Emittable
24 import androidx.glance.EmittableWithChildren
25 import androidx.glance.GlanceModifier
26 import androidx.glance.GlanceNode
27 
28 /**
29  * Add [RemoteViews] into a glance composition.
30  *
31  * @param remoteViews the views to add to the composition.
32  * @param modifier modifier used to adjust the layout algorithm or draw decoration content.
33  */
34 @Composable
AndroidRemoteViewsnull35 fun AndroidRemoteViews(remoteViews: RemoteViews, modifier: GlanceModifier = GlanceModifier) {
36     AndroidRemoteViews(remoteViews, View.NO_ID, modifier) {}
37 }
38 
39 /**
40  * Add [RemoteViews] into a glance composition as a container.
41  *
42  * @param remoteViews the views to add to the composition.
43  * @param containerViewId defines the view id of the container in the [RemoteViews] provided. Any
44  *   pre-existing children of that view will be removed with [RemoteViews.removeAllViews], and any
45  *   children defined in the [content] block will be added with [RemoteViews.addView] (or
46  *   [RemoteViews.addStableView] if available on the system).
47  * @param modifier modifier used to adjust the layout algorithm or draw decoration content.
48  * @param content the content that will be added to the provided container.
49  */
50 @Composable
AndroidRemoteViewsnull51 fun AndroidRemoteViews(
52     remoteViews: RemoteViews,
53     @IdRes containerViewId: Int,
54     modifier: GlanceModifier = GlanceModifier,
55     content: @Composable () -> Unit,
56 ) {
57     GlanceNode(
58         factory = ::EmittableAndroidRemoteViews,
59         update = {
60             this.set(remoteViews) { this.remoteViews = it }
61             this.set(containerViewId) { this.containerViewId = it }
62             this.set(modifier) { this.modifier = it }
63         },
64         content = content
65     )
66 }
67 
68 internal class EmittableAndroidRemoteViews : EmittableWithChildren() {
69     override var modifier: GlanceModifier = GlanceModifier
70     var containerViewId: Int = View.NO_ID
71     lateinit var remoteViews: RemoteViews
72 
copynull73     override fun copy(): Emittable =
74         EmittableAndroidRemoteViews().also {
75             it.modifier = modifier
76             if (::remoteViews.isInitialized) {
77                 it.remoteViews = remoteViews
78             }
79             it.containerViewId = containerViewId
80             it.children.addAll(children.map { it.copy() })
81         }
82 
toStringnull83     override fun toString(): String =
84         "AndroidRemoteViews(" +
85             "modifier=$modifier, " +
86             "containerViewId=$containerViewId, " +
87             "remoteViews=${if (::remoteViews.isInitialized) remoteViews else null}, " +
88             "children=[\n${childrenToString()}\n]" +
89             ")"
90 }
91