~aleteoryx/muditaos

379df3ee7bfa50395b20f50820f92a598d176133 — Lukasz Mastalerz 2 years ago 613d50b
[CP-2040] Character sequence causes file being displayed as empty line in relaxation app

More generic solution for handling too long text to display.
Focuses mostly on Relaxation but other apps also can benefit from it.
M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationMainWindow.cpp +1 -9
@@ 29,18 29,10 @@ namespace gui

    void RelaxationMainWindow::setSoundsList(std::vector<db::multimedia_files::MultimediaFilesRecord> sounds)
    {
        auto trimTittle = [](const std::string &title) {
            std::string shortTittle = title.substr(0, maxDisplayedTitleLength);
            if (shortTittle.back() == incompleteSequenceCharCode) {
                shortTittle.pop_back();
            }
            return shortTittle;
        };

        std::list<gui::Option> menuOptionList;
        auto addRecord = [&](const db::multimedia_files::MultimediaFilesRecord &sound) {
            menuOptionList.emplace_back(std::make_unique<gui::option::OptionBellMenu>(
                trimTittle(sound.tags.title),
                sound.tags.title,
                [=](gui::Item &item) {
                    onActivated(sound);
                    return true;

M products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.cpp => products/BellHybrid/apps/application-bell-relaxation/windows/RelaxationRunningLoopWindow.cpp +16 -13
@@ 17,8 17,10 @@ namespace
    inline constexpr std::chrono::seconds timerTick{1};
    inline constexpr units::SOC dischargingLevelShowTop = 20;
    inline constexpr units::SOC dischargingLowBattery   = 10;
    inline constexpr auto maxPossibleCharsToDisplay     = 25U;
    inline constexpr auto incompleteSequenceCharCode    = '\342';
    inline constexpr auto ellipsisSpace                 = 2u;
    inline constexpr auto ellipsis                      = "...";
    /* charsMultiplier is set a little bit less than max lines which is 2, because of final text formatting */
    inline constexpr auto charsMultiplier = 1.8f;

    bool isBatteryCharging(const Store::Battery::State state)
    {


@@ 72,16 74,15 @@ namespace
        return battery;
    }

    std::string adjustDisplayedTitle(const std::string &title)
    std::string adjustDisplayedTitle(const UTF8 &title, const std::uint32_t maxCharsInLine)
    {
        if (title.length() <= maxPossibleCharsToDisplay) {
        const auto maxTitleLength =
            static_cast<std::uint32_t>(std::round(static_cast<float>(maxCharsInLine) * charsMultiplier));
        if (title.length() <= maxTitleLength) {
            return title;
        }
        std::string newTittle = title.substr(0, maxPossibleCharsToDisplay - 2);
        if (newTittle.back() == incompleteSequenceCharCode) {
            newTittle.pop_back();
        }
        newTittle.append("...");
        auto newTittle = title.substr(0, maxTitleLength - ellipsisSpace);
        newTittle += ellipsis;

        return newTittle;
    }


@@ 110,10 111,12 @@ namespace gui
        }

        if (data && typeid(*data) == typeid(RelaxationSwitchData)) {
            const auto batteryStatus = presenter->handleBatteryStatus();
            auto *audioSwitchData    = static_cast<RelaxationSwitchData *>(data);
            audioContext             = audioSwitchData->getAudioContext();
            title->setText(adjustDisplayedTitle(audioContext->getSound().tags.title));
            const auto batteryStatus  = presenter->handleBatteryStatus();
            auto *audioSwitchData     = static_cast<RelaxationSwitchData *>(data);
            audioContext              = audioSwitchData->getAudioContext();
            const auto maxCharsInLine = title->getTextFormat().getFont()->getCharCountInSpace(
                audioContext->getSound().tags.title, title->getWidth());
            title->setText(adjustDisplayedTitle(audioContext->getSound().tags.title, maxCharsInLine));
            if (batteryStatus.level > dischargingLowBattery) {
                presenter->activate(audioContext->getSound());
            }

M products/BellHybrid/apps/common/src/options/OptionBellMenu.cpp => products/BellHybrid/apps/common/src/options/OptionBellMenu.cpp +21 -3
@@ 1,9 1,24 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <options/OptionBellMenu.hpp>
#include <TextFixedSize.hpp>

namespace
{
    constexpr auto ellipsis       = "...";
    constexpr auto ellipsisSpace  = 2u;
    constexpr auto linesMaxNumber = 1u;

    UTF8 adjustTextLength(const UTF8 &text, const std::uint32_t maxCharsInLine)
    {
        if (maxCharsInLine < text.length()) {
            return text.substr(0, maxCharsInLine - ellipsisSpace) + ellipsis;
        }
        return text;
    }
} // namespace

namespace gui::option
{
    auto OptionBellMenu::build() const -> ListItem *


@@ 20,12 35,15 @@ namespace gui::option
        style::window::decorate(optionBodyHBox);

        auto optionText = new TextFixedSize(optionBodyHBox, 0, 0, 0, 0);
        optionText->setLines(linesMaxNumber);
        optionText->setTextType(gui::TextType::SingleLine);
        optionText->drawUnderline(false);
        optionText->setAlignment(Alignment(gui::Alignment::Horizontal::Center, gui::Alignment::Vertical::Center));
        optionText->setMaximumSize(style::bell_options::default_text_width, style::bell_options::h);
        optionText->setFont(style::window::font::largelight);
        optionText->setRichText(text);

        const auto maxTextCharsToDisplay =
            optionText->getTextFormat().getFont()->getCharCountInSpace(text, style::bell_options::default_text_width);
        optionText->setRichText(adjustTextLength(text, maxTextCharsToDisplay));
        optionItem->dimensionChangedCallback = [optionBodyHBox](gui::Item &, const BoundingBox &newDim) -> bool {
            optionBodyHBox->setArea({0, 0, newDim.w, newDim.h});
            return true;