1 /*
2  * Copyright (C) 2024 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 package com.android.internal.widget.remotecompose.core.operations;
17 
18 import android.util.Log;
19 
20 import com.android.internal.widget.remotecompose.core.CompanionOperation;
21 import com.android.internal.widget.remotecompose.core.Operation;
22 import com.android.internal.widget.remotecompose.core.Operations;
23 import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
24 import com.android.internal.widget.remotecompose.core.RemoteContext;
25 import com.android.internal.widget.remotecompose.core.WireBuffer;
26 
27 import java.util.List;
28 
29 /**
30  * Describe some basic information for a RemoteCompose document
31  * <p>
32  * It encodes the version of the document (following semantic versioning) as well
33  * as the dimensions of the document in pixels.
34  */
35 public class RootContentBehavior implements RemoteComposeOperation {
36 
37     int mScroll = NONE;
38     int mSizing = NONE;
39 
40     int mAlignment = ALIGNMENT_CENTER;
41 
42     int mMode = NONE;
43 
44     protected static final String TAG = "RootContentBehavior";
45 
46     public static final int NONE = 0;
47 
48     ///////////////////////////////////////////////////////////////////////////////////////////////
49     // Scrolling
50     ///////////////////////////////////////////////////////////////////////////////////////////////
51     public static final int SCROLL_HORIZONTAL = 1;
52     public static final int SCROLL_VERTICAL = 2;
53 
54     ///////////////////////////////////////////////////////////////////////////////////////////////
55     // Sizing
56     ///////////////////////////////////////////////////////////////////////////////////////////////
57     public static final int SIZING_LAYOUT = 1;
58     public static final int SIZING_SCALE = 2;
59 
60     ///////////////////////////////////////////////////////////////////////////////////////////////
61     // Sizing
62     ///////////////////////////////////////////////////////////////////////////////////////////////
63     public static final int ALIGNMENT_TOP = 1;
64     public static final int ALIGNMENT_VERTICAL_CENTER = 2;
65     public static final int ALIGNMENT_BOTTOM = 4;
66     public static final int ALIGNMENT_START = 16;
67     public static final int ALIGNMENT_HORIZONTAL_CENTER = 32;
68     public static final int ALIGNMENT_END = 64;
69     public static final int ALIGNMENT_CENTER = ALIGNMENT_HORIZONTAL_CENTER
70             + ALIGNMENT_VERTICAL_CENTER;
71 
72     ///////////////////////////////////////////////////////////////////////////////////////////////
73     // Layout mode
74     ///////////////////////////////////////////////////////////////////////////////////////////////
75     public static final int LAYOUT_HORIZONTAL_MATCH_PARENT = 1;
76     public static final int LAYOUT_HORIZONTAL_WRAP_CONTENT = 2;
77     public static final int LAYOUT_HORIZONTAL_FIXED = 4;
78     public static final int LAYOUT_VERTICAL_MATCH_PARENT = 8;
79     public static final int LAYOUT_VERTICAL_WRAP_CONTENT = 16;
80     public static final int LAYOUT_VERTICAL_FIXED = 32;
81     public static final int LAYOUT_MATCH_PARENT =
82             LAYOUT_HORIZONTAL_MATCH_PARENT + LAYOUT_VERTICAL_MATCH_PARENT;
83     public static final int LAYOUT_WRAP_CONTENT =
84             LAYOUT_HORIZONTAL_WRAP_CONTENT + LAYOUT_VERTICAL_WRAP_CONTENT;
85 
86     ///////////////////////////////////////////////////////////////////////////////////////////////
87     // Sizing mode
88     ///////////////////////////////////////////////////////////////////////////////////////////////
89 
90     public static final int SCALE_INSIDE = 1;
91     public static final int SCALE_FILL_WIDTH = 2;
92     public static final int SCALE_FILL_HEIGHT = 3;
93     public static final int SCALE_FIT = 4;
94     public static final int SCALE_CROP = 5;
95     public static final int SCALE_FILL_BOUNDS = 6;
96 
97     public static final Companion COMPANION = new Companion();
98 
99     /**
100      * Sets the way the player handles the content
101      *
102      * @param scroll    set the horizontal behavior (NONE|SCROLL_HORIZONTAL|SCROLL_VERTICAL)
103      * @param alignment set the alignment of the content (TOP|CENTER|BOTTOM|START|END)
104      * @param sizing    set the type of sizing for the content (NONE|SIZING_LAYOUT|SIZING_SCALE)
105      * @param mode      set the mode of sizing, either LAYOUT modes or SCALE modes
106      *                  the LAYOUT modes are:
107      *                  - LAYOUT_MATCH_PARENT
108      *                  - LAYOUT_WRAP_CONTENT
109      *                  or adding an horizontal mode and a vertical mode:
110      *                  - LAYOUT_HORIZONTAL_MATCH_PARENT
111      *                  - LAYOUT_HORIZONTAL_WRAP_CONTENT
112      *                  - LAYOUT_HORIZONTAL_FIXED
113      *                  - LAYOUT_VERTICAL_MATCH_PARENT
114      *                  - LAYOUT_VERTICAL_WRAP_CONTENT
115      *                  - LAYOUT_VERTICAL_FIXED
116      *                  The LAYOUT_*_FIXED modes will use the intrinsic document size
117      */
RootContentBehavior(int scroll, int alignment, int sizing, int mode)118     public RootContentBehavior(int scroll, int alignment, int sizing, int mode) {
119         switch (scroll) {
120             case NONE:
121             case SCROLL_HORIZONTAL:
122             case SCROLL_VERTICAL:
123                 mScroll = scroll;
124                 break;
125             default: {
126                 Log.e(TAG, "incorrect scroll value " + scroll);
127             }
128         }
129         if (alignment == ALIGNMENT_CENTER) {
130             mAlignment = alignment;
131         } else {
132             int horizontalContentAlignment = alignment & 0xF0;
133             int verticalContentAlignment = alignment & 0xF;
134             boolean validHorizontalAlignment = horizontalContentAlignment == ALIGNMENT_START
135                     || horizontalContentAlignment == ALIGNMENT_HORIZONTAL_CENTER
136                     || horizontalContentAlignment == ALIGNMENT_END;
137             boolean validVerticalAlignment = verticalContentAlignment == ALIGNMENT_TOP
138                     || verticalContentAlignment == ALIGNMENT_VERTICAL_CENTER
139                     || verticalContentAlignment == ALIGNMENT_BOTTOM;
140             if (validHorizontalAlignment && validVerticalAlignment) {
141                 mAlignment = alignment;
142             } else {
143                 Log.e(TAG, "incorrect alignment "
144                         + " h: " + horizontalContentAlignment
145                         + " v: " + verticalContentAlignment);
146             }
147         }
148         switch (sizing) {
149             case SIZING_LAYOUT: {
150                 Log.e(TAG, "sizing_layout is not yet supported");
151             }
152             break;
153             case SIZING_SCALE: {
154                 mSizing = sizing;
155             }
156             break;
157             default: {
158                 Log.e(TAG, "incorrect sizing value " + sizing);
159             }
160         }
161         if (mSizing == SIZING_LAYOUT) {
162             if (mode != NONE) {
163                 Log.e(TAG, "mode for sizing layout is not yet supported");
164             }
165         } else if (mSizing == SIZING_SCALE) {
166             switch (mode) {
167                 case SCALE_INSIDE:
168                 case SCALE_FIT:
169                 case SCALE_FILL_WIDTH:
170                 case SCALE_FILL_HEIGHT:
171                 case SCALE_CROP:
172                 case SCALE_FILL_BOUNDS:
173                     mMode = mode;
174                     break;
175                 default: {
176                     Log.e(TAG, "incorrect mode for scale sizing, mode: " + mode);
177                 }
178             }
179         }
180     }
181 
182     @Override
write(WireBuffer buffer)183     public void write(WireBuffer buffer) {
184         COMPANION.apply(buffer, mScroll, mAlignment, mSizing, mMode);
185     }
186 
187     @Override
toString()188     public String toString() {
189         return "ROOT_CONTENT_BEHAVIOR scroll: " + mScroll
190                 + " sizing: " + mSizing + " mode: " + mMode;
191     }
192 
193     @Override
apply(RemoteContext context)194     public void apply(RemoteContext context) {
195         context.setRootContentBehavior(mScroll, mAlignment, mSizing, mMode);
196     }
197 
198     @Override
deepToString(String indent)199     public String deepToString(String indent) {
200         return toString();
201     }
202 
203     public static class Companion implements CompanionOperation {
Companion()204         private Companion() {
205         }
206 
207         @Override
name()208         public String name() {
209             return "RootContentBehavior";
210         }
211 
212         @Override
id()213         public int id() {
214             return Operations.ROOT_CONTENT_BEHAVIOR;
215         }
216 
apply(WireBuffer buffer, int scroll, int alignment, int sizing, int mode)217         public void apply(WireBuffer buffer, int scroll, int alignment, int sizing, int mode) {
218             buffer.start(Operations.ROOT_CONTENT_BEHAVIOR);
219             buffer.writeInt(scroll);
220             buffer.writeInt(alignment);
221             buffer.writeInt(sizing);
222             buffer.writeInt(mode);
223         }
224 
225         @Override
read(WireBuffer buffer, List<Operation> operations)226         public void read(WireBuffer buffer, List<Operation> operations) {
227             int scroll = buffer.readInt();
228             int alignment = buffer.readInt();
229             int sizing = buffer.readInt();
230             int mode = buffer.readInt();
231             RootContentBehavior rootContentBehavior =
232                     new RootContentBehavior(scroll, alignment, sizing, mode);
233             operations.add(rootContentBehavior);
234         }
235     }
236 }
237