• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.annotation.NonNull;
19 
20 import com.android.internal.widget.remotecompose.core.Operation;
21 import com.android.internal.widget.remotecompose.core.Operations;
22 import com.android.internal.widget.remotecompose.core.RemoteComposeOperation;
23 import com.android.internal.widget.remotecompose.core.RemoteContext;
24 import com.android.internal.widget.remotecompose.core.WireBuffer;
25 import com.android.internal.widget.remotecompose.core.documentation.DocumentationBuilder;
26 import com.android.internal.widget.remotecompose.core.documentation.DocumentedOperation;
27 import com.android.internal.widget.remotecompose.core.semantics.ScrollableComponent;
28 
29 import java.util.List;
30 
31 /**
32  * Describe some basic information for a RemoteCompose document
33  *
34  * <p>It encodes the version of the document (following semantic versioning) as well as the
35  * dimensions of the document in pixels.
36  */
37 public class RootContentBehavior extends Operation
38         implements RemoteComposeOperation, ScrollableComponent {
39     private static final int OP_CODE = Operations.ROOT_CONTENT_BEHAVIOR;
40     private static final String CLASS_NAME = "RootContentBehavior";
41     int mScroll = NONE;
42     int mSizing = NONE;
43 
44     int mAlignment = ALIGNMENT_CENTER;
45 
46     int mMode = NONE;
47 
48     protected static final String TAG = "RootContentBehavior";
49 
50     public static final int NONE = ScrollableComponent.SCROLL_NONE;
51 
52     ///////////////////////////////////////////////////////////////////////////////////////////////
53     // Scrolling
54     ///////////////////////////////////////////////////////////////////////////////////////////////
55     public static final int SCROLL_HORIZONTAL = ScrollableComponent.SCROLL_HORIZONTAL;
56     public static final int SCROLL_VERTICAL = ScrollableComponent.SCROLL_VERTICAL;
57 
58     ///////////////////////////////////////////////////////////////////////////////////////////////
59     // Sizing
60     ///////////////////////////////////////////////////////////////////////////////////////////////
61     public static final int SIZING_LAYOUT = 1;
62     public static final int SIZING_SCALE = 2;
63 
64     ///////////////////////////////////////////////////////////////////////////////////////////////
65     // Sizing
66     ///////////////////////////////////////////////////////////////////////////////////////////////
67     public static final int ALIGNMENT_TOP = 1;
68     public static final int ALIGNMENT_VERTICAL_CENTER = 2;
69     public static final int ALIGNMENT_BOTTOM = 4;
70     public static final int ALIGNMENT_START = 16;
71     public static final int ALIGNMENT_HORIZONTAL_CENTER = 32;
72     public static final int ALIGNMENT_END = 64;
73     public static final int ALIGNMENT_CENTER =
74             ALIGNMENT_HORIZONTAL_CENTER + ALIGNMENT_VERTICAL_CENTER;
75 
76     ///////////////////////////////////////////////////////////////////////////////////////////////
77     // Layout mode
78     ///////////////////////////////////////////////////////////////////////////////////////////////
79     public static final int LAYOUT_HORIZONTAL_MATCH_PARENT = 1;
80     public static final int LAYOUT_HORIZONTAL_WRAP_CONTENT = 2;
81     public static final int LAYOUT_HORIZONTAL_FIXED = 4;
82     public static final int LAYOUT_VERTICAL_MATCH_PARENT = 8;
83     public static final int LAYOUT_VERTICAL_WRAP_CONTENT = 16;
84     public static final int LAYOUT_VERTICAL_FIXED = 32;
85     public static final int LAYOUT_MATCH_PARENT =
86             LAYOUT_HORIZONTAL_MATCH_PARENT + LAYOUT_VERTICAL_MATCH_PARENT;
87     public static final int LAYOUT_WRAP_CONTENT =
88             LAYOUT_HORIZONTAL_WRAP_CONTENT + LAYOUT_VERTICAL_WRAP_CONTENT;
89 
90     ///////////////////////////////////////////////////////////////////////////////////////////////
91     // Sizing mode
92     ///////////////////////////////////////////////////////////////////////////////////////////////
93 
94     public static final int SCALE_INSIDE = 1;
95     public static final int SCALE_FILL_WIDTH = 2;
96     public static final int SCALE_FILL_HEIGHT = 3;
97     public static final int SCALE_FIT = 4;
98     public static final int SCALE_CROP = 5;
99     public static final int SCALE_FILL_BOUNDS = 6;
100 
101     /**
102      * Sets the way the player handles the content
103      *
104      * @param scroll set the horizontal behavior (NONE|SCROLL_HORIZONTAL|SCROLL_VERTICAL)
105      * @param alignment set the alignment of the content (TOP|CENTER|BOTTOM|START|END)
106      * @param sizing set the type of sizing for the content (NONE|SIZING_LAYOUT|SIZING_SCALE)
107      * @param mode set the mode of sizing, either LAYOUT modes or SCALE modes the LAYOUT modes are:
108      *     - LAYOUT_MATCH_PARENT - LAYOUT_WRAP_CONTENT or adding an horizontal mode and a vertical
109      *     mode: - LAYOUT_HORIZONTAL_MATCH_PARENT - LAYOUT_HORIZONTAL_WRAP_CONTENT -
110      *     LAYOUT_HORIZONTAL_FIXED - LAYOUT_VERTICAL_MATCH_PARENT - LAYOUT_VERTICAL_WRAP_CONTENT -
111      *     LAYOUT_VERTICAL_FIXED The LAYOUT_*_FIXED modes will use the intrinsic document size
112      */
RootContentBehavior(int scroll, int alignment, int sizing, int mode)113     public RootContentBehavior(int scroll, int alignment, int sizing, int mode) {
114         switch (scroll) {
115             case NONE:
116             case SCROLL_HORIZONTAL:
117             case SCROLL_VERTICAL:
118                 mScroll = scroll;
119                 break;
120             default:
121                 System.out.println(TAG + "incorrect scroll value " + scroll);
122         }
123         if (alignment == ALIGNMENT_CENTER) {
124             mAlignment = alignment;
125         } else {
126             int horizontalContentAlignment = alignment & 0xF0;
127             int verticalContentAlignment = alignment & 0xF;
128             boolean validHorizontalAlignment =
129                     horizontalContentAlignment == ALIGNMENT_START
130                             || horizontalContentAlignment == ALIGNMENT_HORIZONTAL_CENTER
131                             || horizontalContentAlignment == ALIGNMENT_END;
132             boolean validVerticalAlignment =
133                     verticalContentAlignment == ALIGNMENT_TOP
134                             || verticalContentAlignment == ALIGNMENT_VERTICAL_CENTER
135                             || verticalContentAlignment == ALIGNMENT_BOTTOM;
136             if (validHorizontalAlignment && validVerticalAlignment) {
137                 mAlignment = alignment;
138             } else {
139                 System.out.println(
140                         TAG
141                                 + "incorrect alignment "
142                                 + " h: "
143                                 + horizontalContentAlignment
144                                 + " v: "
145                                 + verticalContentAlignment);
146             }
147         }
148         switch (sizing) {
149             case SIZING_LAYOUT:
150                 System.out.println(TAG + "sizing_layout is not yet supported");
151                 break;
152             case SIZING_SCALE:
153                 mSizing = sizing;
154                 break;
155             default:
156                 System.out.println(TAG + "incorrect sizing value " + sizing);
157         }
158         if (mSizing == SIZING_LAYOUT) {
159             if (mode != NONE) {
160                 System.out.println(TAG + "mode for sizing layout is not yet supported");
161             }
162         } else if (mSizing == SIZING_SCALE) {
163             switch (mode) {
164                 case SCALE_INSIDE:
165                 case SCALE_FIT:
166                 case SCALE_FILL_WIDTH:
167                 case SCALE_FILL_HEIGHT:
168                 case SCALE_CROP:
169                 case SCALE_FILL_BOUNDS:
170                     mMode = mode;
171                     break;
172                 default:
173                     System.out.println(TAG + "incorrect mode for scale sizing, mode: " + mode);
174             }
175         }
176     }
177 
178     @Override
write(@onNull WireBuffer buffer)179     public void write(@NonNull WireBuffer buffer) {
180         apply(buffer, mScroll, mAlignment, mSizing, mMode);
181     }
182 
183     @NonNull
184     @Override
toString()185     public String toString() {
186         return "ROOT_CONTENT_BEHAVIOR scroll: "
187                 + mScroll
188                 + " sizing: "
189                 + mSizing
190                 + " mode: "
191                 + mMode;
192     }
193 
194     @Override
apply(@onNull RemoteContext context)195     public void apply(@NonNull RemoteContext context) {
196         context.setRootContentBehavior(mScroll, mAlignment, mSizing, mMode);
197     }
198 
199     @NonNull
200     @Override
deepToString(@onNull String indent)201     public String deepToString(@NonNull String indent) {
202         return toString();
203     }
204 
205     /**
206      * The name of the class
207      *
208      * @return the name
209      */
210     @NonNull
name()211     public static String name() {
212         return CLASS_NAME;
213     }
214 
215     /**
216      * The OP_CODE for this command
217      *
218      * @return the opcode
219      */
id()220     public static int id() {
221         return OP_CODE;
222     }
223 
224     /**
225      * Write the operation on the buffer
226      *
227      * @param buffer
228      * @param scroll
229      * @param alignment
230      * @param sizing
231      * @param mode
232      */
apply( @onNull WireBuffer buffer, int scroll, int alignment, int sizing, int mode)233     public static void apply(
234             @NonNull WireBuffer buffer, int scroll, int alignment, int sizing, int mode) {
235         buffer.start(OP_CODE);
236         buffer.writeInt(scroll);
237         buffer.writeInt(alignment);
238         buffer.writeInt(sizing);
239         buffer.writeInt(mode);
240     }
241 
242     /**
243      * Read this operation and add it to the list of operations
244      *
245      * @param buffer the buffer to read
246      * @param operations the list of operations that will be added to
247      */
read(@onNull WireBuffer buffer, @NonNull List<Operation> operations)248     public static void read(@NonNull WireBuffer buffer, @NonNull List<Operation> operations) {
249         int scroll = buffer.readInt();
250         int alignment = buffer.readInt();
251         int sizing = buffer.readInt();
252         int mode = buffer.readInt();
253         RootContentBehavior rootContentBehavior =
254                 new RootContentBehavior(scroll, alignment, sizing, mode);
255         operations.add(rootContentBehavior);
256     }
257 
258     /**
259      * Populate the documentation with a description of this operation
260      *
261      * @param doc to append the description to.
262      */
documentation(@onNull DocumentationBuilder doc)263     public static void documentation(@NonNull DocumentationBuilder doc) {
264         doc.operation("Protocol Operations", OP_CODE, CLASS_NAME)
265                 .description("Describes the behaviour of the root")
266                 .field(DocumentedOperation.INT, "scroll", "scroll")
267                 .possibleValues("SCROLL_HORIZONTAL", SCROLL_HORIZONTAL)
268                 .possibleValues("SCROLL_VERTICAL", SCROLL_VERTICAL)
269                 .field(DocumentedOperation.INT, "alignment", "alignment")
270                 .possibleValues("ALIGNMENT_TOP", ALIGNMENT_TOP)
271                 .possibleValues("ALIGNMENT_VERTICAL_CENTER", ALIGNMENT_VERTICAL_CENTER)
272                 .possibleValues("ALIGNMENT_BOTTOM", ALIGNMENT_BOTTOM)
273                 .possibleValues("ALIGNMENT_START", ALIGNMENT_START)
274                 .possibleValues("ALIGNMENT_START", ALIGNMENT_START)
275                 .possibleValues("ALIGNMENT_END", ALIGNMENT_END)
276                 .field(DocumentedOperation.INT, "sizing", "sizing")
277                 .possibleValues("SCALE_INSIDE", SCALE_INSIDE)
278                 .possibleValues("SCALE_FIT", SCALE_FIT)
279                 .possibleValues("SCALE_FILL_WIDTH", SCALE_FILL_WIDTH)
280                 .possibleValues("SCALE_FILL_HEIGHT", SCALE_FILL_HEIGHT)
281                 .possibleValues("SCALE_CROP", SCALE_CROP)
282                 .possibleValues("SCALE_FILL_BOUNDS", SCALE_FILL_BOUNDS)
283                 .field(DocumentedOperation.INT, "mode", "mode")
284                 .possibleValues("LAYOUT_HORIZONTAL_MATCH_PARENT", LAYOUT_HORIZONTAL_MATCH_PARENT)
285                 .possibleValues("LAYOUT_HORIZONTAL_WRAP_CONTENT", LAYOUT_HORIZONTAL_WRAP_CONTENT)
286                 .possibleValues("LAYOUT_HORIZONTAL_FIXED", LAYOUT_HORIZONTAL_FIXED)
287                 .possibleValues("LAYOUT_VERTICAL_MATCH_PARENT", LAYOUT_VERTICAL_MATCH_PARENT)
288                 .possibleValues("LAYOUT_VERTICAL_WRAP_CONTENT", LAYOUT_VERTICAL_WRAP_CONTENT)
289                 .possibleValues("LAYOUT_VERTICAL_FIXED", LAYOUT_VERTICAL_FIXED)
290                 .possibleValues("LAYOUT_MATCH_PARENT", LAYOUT_MATCH_PARENT)
291                 .possibleValues("LAYOUT_WRAP_CONTENT", LAYOUT_WRAP_CONTENT);
292     }
293 
294     @Override
isInterestingForSemantics()295     public boolean isInterestingForSemantics() {
296         return mScroll != SCROLL_NONE;
297     }
298 
299     @Override
supportsScrollByOffset()300     public boolean supportsScrollByOffset() {
301         return mScroll != SCROLL_NONE;
302     }
303 
304     @Override
scrollByOffset(RemoteContext context, int offset)305     public int scrollByOffset(RemoteContext context, int offset) {
306         // TODO implement scroll handling
307         return offset;
308     }
309 
310     @Override
scrollDirection()311     public int scrollDirection() {
312         return mScroll;
313     }
314 }
315