| 139 | } |
| 140 | |
| 141 | void ClockOffsetActivity::render(RenderLock&&) { |
| 142 | renderer.clearScreen(); |
| 143 | |
| 144 | const auto& metrics = UITheme::getInstance().getMetrics(); |
| 145 | const auto pageWidth = renderer.getScreenWidth(); |
| 146 | const auto pageHeight = renderer.getScreenHeight(); |
| 147 | |
| 148 | GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.headerHeight}, tr(STR_CLOCK_UTC_OFFSET)); |
| 149 | |
| 150 | const int centreY = pageHeight / 2 - 40; |
| 151 | auto widthOf = [&](const char* s) { return renderer.getTextWidth(UI_12_FONT_ID, s, EpdFontFamily::BOLD); }; |
| 152 | constexpr int fieldPaddingX = 6; |
| 153 | constexpr int labelGap = 16; |
| 154 | constexpr int fieldGap = 12; |
| 155 | constexpr int colonGap = 5; |
| 156 | const int lineHeight = renderer.getLineHeight(UI_12_FONT_ID); |
| 157 | const int fieldHeight = lineHeight + 2; |
| 158 | |
| 159 | char signStr[2] = {sign == 1 ? '-' : '+', '\0'}; |
| 160 | char hoursStr[8]; |
| 161 | snprintf(hoursStr, sizeof(hoursStr), "%d", hours); |
| 162 | char minutesStr[8]; |
| 163 | snprintf(minutesStr, sizeof(minutesStr), "%02d", minutesQuarter * MINUTES_PER_QUARTER); |
| 164 | |
| 165 | const int labelWidth = widthOf("UTC"); |
| 166 | const int signBoxW = std::max(widthOf("+"), widthOf("-")) + fieldPaddingX * 2; |
| 167 | const int hoursBoxW = std::max(widthOf("14"), widthOf("12")) + fieldPaddingX * 2; |
| 168 | const int colonWidth = widthOf(":"); |
| 169 | const int minutesBoxW = std::max({widthOf("00"), widthOf("15"), widthOf("30"), widthOf("45")}) + fieldPaddingX * 2; |
| 170 | const int totalWidth = |
| 171 | labelWidth + labelGap + signBoxW + fieldGap + hoursBoxW + colonGap + colonWidth + colonGap + minutesBoxW; |
| 172 | |
| 173 | int x = (pageWidth - totalWidth) / 2; |
| 174 | renderer.drawText(UI_12_FONT_ID, x, centreY, "UTC", true, EpdFontFamily::BOLD); |
| 175 | x += labelWidth + labelGap; |
| 176 | |
| 177 | auto drawField = [&](const char* text, const int boxX, const int boxWidth, const Field field) { |
| 178 | const bool selected = activeField == field; |
| 179 | renderer.fillRectDither(boxX, centreY, boxWidth, fieldHeight, selected ? Color::LightGray : Color::White); |
| 180 | renderer.drawRect(boxX, centreY, boxWidth, fieldHeight, true); |
| 181 | if (selected) { |
| 182 | renderer.drawRect(boxX + 1, centreY + 1, boxWidth - 2, fieldHeight - 2, true); |
| 183 | } |
| 184 | const int textX = boxX + (boxWidth - widthOf(text)) / 2; |
| 185 | renderer.drawText(UI_12_FONT_ID, textX, centreY, text, true, EpdFontFamily::BOLD); |
| 186 | }; |
| 187 | |
| 188 | drawField(signStr, x, signBoxW, FIELD_SIGN); |
| 189 | x += signBoxW + fieldGap; |
| 190 | |
| 191 | drawField(hoursStr, x, hoursBoxW, FIELD_HOURS); |
| 192 | x += hoursBoxW + colonGap; |
| 193 | |
| 194 | renderer.drawText(UI_12_FONT_ID, x, centreY, ":", true, EpdFontFamily::BOLD); |
| 195 | x += colonWidth + colonGap; |
| 196 | |
| 197 | drawField(minutesStr, x, minutesBoxW, FIELD_MINUTES); |
| 198 |
nothing calls this directly
no test coverage detected