1 /*
2 * Copyright 2020, 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 #include "touch_button_example.h"
18
19 #include <stddef.h>
20 #include <stdint.h>
21
22 #include "example_utils.h"
23 #include "layout/touch_button_layout.h"
24
25 namespace teeui {
26 namespace example {
27 namespace touch_button {
28
translateLabels(Layout * layout)29 template <typename Layout> static void translateLabels(Layout* layout) {
30 translateLabel<LabelOK>(layout);
31 translateLabel<LabelCancel>(layout);
32 translateLabel<LabelTitle>(layout);
33 translateLabel<LabelHint>(layout);
34 }
35
36 class GUIStateTouch : public ITeeuiExample {
37 private:
38 bool okTapped_ = false;
39 bool cancelTapped_ = false;
40 EventResult eventResult_ = EventResult::NONE;
41
42 public:
43 bool inverted_;
44 std::string confirmationMessage_;
45 layout_t<ConfUILayout> layoutInstance_ = {};
46
GUIStateTouch()47 GUIStateTouch() : okTapped_(false), cancelTapped_(false), inverted_(false), layoutInstance_{} {}
48
isOkTapped() const49 bool isOkTapped() const { return okTapped_; }
isCancelTapped() const50 bool isCancelTapped() const { return cancelTapped_; }
51
tapOk(Event e)52 Error tapOk(Event e) {
53 if (e.event_ == EventType::KeyUp) {
54 okTapped_ = true;
55 eventResult_ = EventResult::CONFIRM;
56 }
57 return Error::OK;
58 }
59
tapCancel(Event e)60 Error tapCancel(Event e) {
61 if (e.event_ == EventType::KeyUp) {
62 cancelTapped_ = true;
63 eventResult_ = EventResult::CANCEL;
64 }
65 return Error::OK;
66 }
67
selectLanguage(const char * language_id)68 void selectLanguage(const char* language_id) override {
69 teeui::localization::selectLangId(language_id);
70 translateLabels(&layoutInstance_);
71 }
72
setConfirmationMessage(std::string confirmationMessage)73 void setConfirmationMessage(std::string confirmationMessage) override {
74 confirmationMessage_ = std::move(confirmationMessage);
75 std::get<LabelBody>(layoutInstance_)
76 .setText({&*confirmationMessage_.begin(), &*confirmationMessage_.end()});
77 }
78
79 uint32_t setDeviceInfo(DeviceInfo device_info, bool magnified, bool inverted = false) override;
80
81 EventResult onEvent(uint32_t x, uint32_t y, uint32_t) override;
82
83 uint32_t renderUIIntoBuffer(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint32_t lineStride,
84 uint32_t* buffer,
85 size_t buffer_size_in_elements_not_bytes) override;
86 };
87
createTeeuiExample()88 std::unique_ptr<ITeeuiExample> createTeeuiExample() {
89 return std::make_unique<GUIStateTouch>();
90 }
91
onEvent(uint32_t x,uint32_t y,uint32_t)92 EventResult GUIStateTouch::onEvent(uint32_t x, uint32_t y, uint32_t) {
93 eventResult_ = EventResult::NONE;
94 Event event{x, y, EventType::KeyUp};
95 handleAllEvent(layoutInstance_, event);
96 return eventResult_;
97 }
98
setLayoutParams(DeviceInfo & deviceInfo,bool magnified,bool inverted)99 static context<ConfUIParameters> setLayoutParams(DeviceInfo& deviceInfo, bool magnified,
100 bool inverted) {
101 context<ConfUIParameters> ctx(deviceInfo.mm2px_, deviceInfo.dp2px_);
102 ctx.setParam<RightEdgeOfScreen>(pxs(deviceInfo.width_));
103 ctx.setParam<BottomOfScreen>(pxs(deviceInfo.height_));
104 if (magnified) {
105 ctx.setParam<DefaultFontSize>(18_dp);
106 ctx.setParam<BodyFontSize>(20_dp);
107 } else {
108 ctx.setParam<DefaultFontSize>(14_dp);
109 ctx.setParam<BodyFontSize>(16_dp);
110 }
111 if (inverted) {
112 ctx.setParam<ShieldColor>(kShieldColorInv);
113 ctx.setParam<ColorText>(kTextColorInv);
114 ctx.setParam<ColorBG>(kBackGroundColorInv);
115 ctx.setParam<ColorButton>(kShieldColorInv);
116 } else {
117 ctx.setParam<ShieldColor>(kShieldColor);
118 ctx.setParam<ColorText>(kTextColor);
119 ctx.setParam<ColorBG>(kBackGroundColor);
120 ctx.setParam<ColorButton>(kShieldColor);
121 }
122 return ctx;
123 }
124
setDeviceInfo(DeviceInfo device_info,bool magnified,bool inverted)125 uint32_t GUIStateTouch::setDeviceInfo(DeviceInfo device_info, bool magnified, bool inverted) {
126 layoutInstance_ =
127 instantiateLayout(ConfUILayout(), setLayoutParams(device_info, magnified, inverted));
128 inverted_ = inverted;
129 std::get<LabelOK>(layoutInstance_)
130 .setCB(makeCallback<Error, Event>(
131 [](Event e, void* p) -> Error { return reinterpret_cast<GUIStateTouch*>(p)->tapOk(e); },
132 this));
133 std::get<LabelCancel>(layoutInstance_)
134 .setCB(makeCallback<Error, Event>(
135 [](Event e, void* p) -> Error {
136 return reinterpret_cast<GUIStateTouch*>(p)->tapCancel(e);
137 },
138 this));
139 return 0;
140 }
141
renderUIIntoBuffer(uint32_t x,uint32_t y,uint32_t w,uint32_t h,uint32_t lineStride,uint32_t * buffer,size_t buffer_size_in_elements_not_bytes)142 uint32_t GUIStateTouch::renderUIIntoBuffer(uint32_t x, uint32_t y, uint32_t w, uint32_t h,
143 uint32_t lineStride, uint32_t* buffer,
144 size_t buffer_size_in_elements_not_bytes) {
145 uint32_t afterLastPixelIndex = 0;
146 if (__builtin_add_overflow(y, h, &afterLastPixelIndex) ||
147 __builtin_add_overflow(afterLastPixelIndex, -1, &afterLastPixelIndex) ||
148 __builtin_mul_overflow(afterLastPixelIndex, lineStride, &afterLastPixelIndex) ||
149 __builtin_add_overflow(afterLastPixelIndex, x, &afterLastPixelIndex) ||
150 __builtin_add_overflow(afterLastPixelIndex, w, &afterLastPixelIndex) ||
151 afterLastPixelIndex > buffer_size_in_elements_not_bytes) {
152 return uint32_t(Error::OutOfBoundsDrawing);
153 }
154
155 uint32_t* begin = buffer + (y * lineStride + x);
156
157 Color bgColor = inverted_ ? kBackGroundColorInv : kBackGroundColor;
158
159 for (uint32_t yi = 0; yi < h; ++yi) {
160 for (uint32_t xi = 0; xi < w; ++xi) {
161 begin[xi] = bgColor;
162 }
163 begin += lineStride;
164 }
165 FrameBuffer fb;
166 fb.left_ = x;
167 fb.top_ = y;
168 fb.width_ = w;
169 fb.height_ = h;
170 fb.buffer_ = buffer;
171 fb.size_in_elements_ = buffer_size_in_elements_not_bytes;
172 fb.lineStride_ = lineStride;
173
174 auto pixelDrawer = makePixelDrawer(
175 [&fb](uint32_t x, uint32_t y, Color color) -> Error { return fb.drawPixel(x, y, color); });
176
177 if (auto error = drawElements(layoutInstance_, pixelDrawer)) {
178 return uint32_t(error.code());
179 }
180
181 return 0; // OK
182 }
183
184 } // namespace touch_button
185 } // namespace example
186 } // namespace teeui
187