mirror of
https://github.com/meshtastic/firmware.git
synced 2026-02-04 08:02:00 +00:00
* Added keyboard option to menu. Shows a keyboard layout but does not type. * Keyboard types into text box and wraps. * send FreeText messages from the send submenu - renamed `KEYBOARD` action to `FREE_TEXT` and moved its menu location to the send submenu - opening the FreeText applet from the menu keeps the menu open and disabled the timeout - the FreeText applet writes to inkhud->freetext - the sending a canned message checks inkhud->freetext and if it isn't empty, sends and clears the inkhud->freetext * Text scrolls along with input * handle free text message completion as an event implements `handleFreeText` and `OnFreeText()` for system applets to interface with the FreeText Applet The FreeText Applet generates an `OnFreeText` event when completing a message which is handled by the first system applet with the `handleFreeText` flag set to true. The Menu Applet now handles this event. * call `onFreeText` whenever the FreeText Applet exits allows the menu to consistently restart its auto-close timeout * Add text cursor * Change UI to remove the header and make text box longer Keyboard displays captial letters for legibility Keyboard types captial letters with long press * center FreeText keys and draw symbolic buttons Move input field and keyboard drawing to their own functions: - `drawInputField()` - `drawKeyboard()` Store the keys in a 1-dimensional array Implement a matching array, `keyWidths`, to set key widths relative to the font size * Add character limit and counter * Fix softlock when hitting character limit * Move text box as its own menu page * rework FreeTextApplet into KeyboardApplet - The Keyboard Applet renders an on-screen keyboard at the lower portion of the screen. - Calling `inkhud->openKeyboard()` sends all the user applets to the background and resizes the first system applet with `handleFreeText` set to True to fit above the on-screen keyboard - `inkhud->closeKeyboard()` reverses this layout change * Fix input box rendering and add character limit to menu free text * remove FREE_TEXT menu page and use the FREE_TEXT menu action solely * force update when changing the free text message * reorganize KeyboardApplet - add comments after each row of `key[]` and `keyWidths[]` to preserve formatting - The selected key is now set using the key index directly - rowWidths are pre-calculated in the KeyboardApplet constructor - removed `drawKeyboard()` and implemented `drawKeyLabel()` * implement `Renderer::clearTile()` to clear the region below a tile * add parameter to forceUpdate() for re-rendering the full screen setting the `all` parameter to true in `inkhud->forceUpdate()` now causes the full screen buffer to clear an re-render. This is helpful for when sending applets to the background and the UI needs a clean canvas. System Applets can now set the `alwaysRender` flag true which causes it to re-render on every screen update. This is set to true in the Battery Icon Applet. * clean up tile clearing loops * implement dirty rendering to let applets draw over their previous render - `Applet::requestUpdate()` now has an optional flag to keep the old canvas - If honored, the renderer calls `render(true)` which runs `onDirtyRender()` instead of `onRender()` for said applet - The renderer will not call a dirty render if the full screen is getting re-rendered * simplify arithmetic in clearTile for better understanding * combine Applet::onRender() and Applet::onDirtyRender() into Applet::onRender(bool full) - add new `full` parameter to onRender() in every applet. This parameter can be ignored by most applets. - `Applet::requestUpdate()` has an optional flag that requests a full render by default * implement tile and partial rendering in KeyboardApplet * add comment for drawKeyLabel() * improve clarity of byte operations in clearTile() * remove typo and commented code * fix inaccurate comments * add null check to openKeyboard() and closeKeyboard() --------- Co-authored-by: zeropt <ferr0fluidmann@gmail.com> Co-authored-by: HarukiToreda <116696711+HarukiToreda@users.noreply.github.com>
103 lines
3.4 KiB
C++
103 lines
3.4 KiB
C++
#ifdef MESHTASTIC_INCLUDE_INKHUD
|
|
|
|
#include "./BatteryIconApplet.h"
|
|
|
|
using namespace NicheGraphics;
|
|
|
|
InkHUD::BatteryIconApplet::BatteryIconApplet()
|
|
{
|
|
alwaysRender = true; // render everytime the screen is updated
|
|
|
|
// Show at boot, if user has previously enabled the feature
|
|
if (settings->optionalFeatures.batteryIcon)
|
|
bringToForeground();
|
|
|
|
// Register to our have BatteryIconApplet::onPowerStatusUpdate method called when new power info is available
|
|
// This happens whether or not the battery icon feature is enabled
|
|
powerStatusObserver.observe(&powerStatus->onNewStatus);
|
|
}
|
|
|
|
// We handle power status' even when the feature is disabled,
|
|
// so that we have up to date data ready if the feature is enabled later.
|
|
// Otherwise could be 30s before new status update, with weird battery value displayed
|
|
int InkHUD::BatteryIconApplet::onPowerStatusUpdate(const meshtastic::Status *status)
|
|
{
|
|
// System applets are always active
|
|
assert(isActive());
|
|
|
|
// This method should only receive power statuses
|
|
// If we get a different type of status, something has gone weird elsewhere
|
|
assert(status->getStatusType() == STATUS_TYPE_POWER);
|
|
|
|
meshtastic::PowerStatus *powerStatus = (meshtastic::PowerStatus *)status;
|
|
|
|
// Get the new state of charge %, and round to the nearest 10%
|
|
uint8_t newSocRounded = ((powerStatus->getBatteryChargePercent() + 5) / 10) * 10;
|
|
|
|
// If rounded value has changed, trigger a display update
|
|
// It's okay to requestUpdate before we store the new value, as the update won't run until next loop()
|
|
// Don't trigger an update if the feature is disabled
|
|
if (this->socRounded != newSocRounded && settings->optionalFeatures.batteryIcon)
|
|
requestUpdate();
|
|
|
|
// Store the new value
|
|
this->socRounded = newSocRounded;
|
|
|
|
return 0; // Tell Observable to continue informing other observers
|
|
}
|
|
|
|
void InkHUD::BatteryIconApplet::onRender(bool full)
|
|
{
|
|
// Fill entire tile
|
|
// - size of icon controlled by size of tile
|
|
int16_t l = 0;
|
|
int16_t t = 0;
|
|
uint16_t w = width();
|
|
int16_t h = height();
|
|
|
|
// Clear the region beneath the tile
|
|
// Most applets are drawing onto an empty frame buffer and don't need to do this
|
|
// We do need to do this with the battery though, as it is an "overlay"
|
|
fillRect(l, t, w, h, WHITE);
|
|
|
|
// Vertical centerline
|
|
const int16_t m = t + (h / 2);
|
|
|
|
// =====================
|
|
// Draw battery outline
|
|
// =====================
|
|
|
|
// Positive terminal "bump"
|
|
const int16_t &bumpL = l;
|
|
const uint16_t bumpH = h / 2;
|
|
const int16_t bumpT = m - (bumpH / 2);
|
|
constexpr uint16_t bumpW = 2;
|
|
fillRect(bumpL, bumpT, bumpW, bumpH, BLACK);
|
|
|
|
// Main body of battery
|
|
const int16_t bodyL = bumpL + bumpW;
|
|
const int16_t &bodyT = t;
|
|
const int16_t &bodyH = h;
|
|
const int16_t bodyW = w - bumpW;
|
|
drawRect(bodyL, bodyT, bodyW, bodyH, BLACK);
|
|
|
|
// Erase join between bump and body
|
|
drawLine(bodyL, bumpT, bodyL, bumpT + bumpH - 1, WHITE);
|
|
|
|
// ===================
|
|
// Draw battery level
|
|
// ===================
|
|
|
|
constexpr int16_t slicePad = 2;
|
|
const int16_t sliceL = bodyL + slicePad;
|
|
const int16_t sliceT = bodyT + slicePad;
|
|
const uint16_t sliceH = bodyH - (slicePad * 2);
|
|
uint16_t sliceW = bodyW - (slicePad * 2);
|
|
|
|
sliceW = (sliceW * socRounded) / 100; // Apply percentage
|
|
|
|
hatchRegion(sliceL, sliceT, sliceW, sliceH, 2, BLACK);
|
|
drawRect(sliceL, sliceT, sliceW, sliceH, BLACK);
|
|
}
|
|
|
|
#endif |