mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-04-10 19:15:13 +00:00
Added a system status component
This commit is contained in:
parent
eeff59773d
commit
86a554d1b2
|
|
@ -18,6 +18,7 @@
|
||||||
#include "MameNames.h"
|
#include "MameNames.h"
|
||||||
#include "Scripting.h"
|
#include "Scripting.h"
|
||||||
#include "SystemData.h"
|
#include "SystemData.h"
|
||||||
|
#include "SystemStatus.h"
|
||||||
#include "UIModeController.h"
|
#include "UIModeController.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "utils/FileSystemUtil.h"
|
#include "utils/FileSystemUtil.h"
|
||||||
|
|
@ -2103,10 +2104,12 @@ returnValue = Utils::Platform::launchGameUnix(command, startDirectory, runInBack
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unless we're running in the background while the game is launched, re-enable the text
|
// Unless we're running in the background while the game is launched, re-enable the text
|
||||||
// scrolling that was disabled in ViewController.
|
// scrolling that was disabled in ViewController. Also poll the system status immediately
|
||||||
|
// in case something changed while the game was running.
|
||||||
if (!runInBackground) {
|
if (!runInBackground) {
|
||||||
window->setAllowTextScrolling(true);
|
window->setAllowTextScrolling(true);
|
||||||
window->setAllowFileAnimation(true);
|
window->setAllowFileAnimation(true);
|
||||||
|
SystemStatus::getInstance().pollImmediately();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update number of times the game has been launched.
|
// Update number of times the game has been launched.
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include "FileFilterIndex.h"
|
#include "FileFilterIndex.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include "SystemData.h"
|
#include "SystemData.h"
|
||||||
|
#include "SystemStatus.h"
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "components/HelpComponent.h"
|
#include "components/HelpComponent.h"
|
||||||
#include "guis/GuiTextEditKeyboardPopup.h"
|
#include "guis/GuiTextEditKeyboardPopup.h"
|
||||||
|
|
@ -36,6 +37,7 @@ GuiSettings::GuiSettings(std::string title)
|
||||||
, mNeedsGoToStart {false}
|
, mNeedsGoToStart {false}
|
||||||
, mNeedsGoToSystem {false}
|
, mNeedsGoToSystem {false}
|
||||||
, mNeedsGoToGroupedCollections {false}
|
, mNeedsGoToGroupedCollections {false}
|
||||||
|
, mNeedsUpdateStatusComponents {false}
|
||||||
, mInvalidateCachedBackground {false}
|
, mInvalidateCachedBackground {false}
|
||||||
{
|
{
|
||||||
addChild(&mMenu);
|
addChild(&mMenu);
|
||||||
|
|
@ -143,6 +145,15 @@ void GuiSettings::save()
|
||||||
ViewController::getInstance()->goToSystem(SystemData::sSystemVector.front(), false);
|
ViewController::getInstance()->goToSystem(SystemData::sSystemVector.front(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mNeedsUpdateStatusComponents) {
|
||||||
|
SystemStatus::getInstance().setCheckFlags();
|
||||||
|
SystemStatus::getInstance().pollImmediately();
|
||||||
|
// If we're not done within this time window it's not the end of the world,
|
||||||
|
// the indicators will still get updated during the next poll.
|
||||||
|
SDL_Delay(100);
|
||||||
|
mWindow->updateSystemStatusComponents();
|
||||||
|
}
|
||||||
|
|
||||||
if (mNeedsCollectionsUpdate) {
|
if (mNeedsCollectionsUpdate) {
|
||||||
auto state = ViewController::getInstance()->getState();
|
auto state = ViewController::getInstance()->getState();
|
||||||
// If we're in any view other than the grouped custom collections, always jump to the
|
// If we're in any view other than the grouped custom collections, always jump to the
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ public:
|
||||||
mGoToSystem = goToSystem;
|
mGoToSystem = goToSystem;
|
||||||
};
|
};
|
||||||
void setNeedsGoToGroupedCollections() { mNeedsGoToGroupedCollections = true; }
|
void setNeedsGoToGroupedCollections() { mNeedsGoToGroupedCollections = true; }
|
||||||
|
void setNeedsUpdateStatusComponents() { mNeedsUpdateStatusComponents = true; }
|
||||||
void setNeedsCloseMenu(std::function<void()> closeFunction)
|
void setNeedsCloseMenu(std::function<void()> closeFunction)
|
||||||
{
|
{
|
||||||
mCloseMenuFunction = closeFunction;
|
mCloseMenuFunction = closeFunction;
|
||||||
|
|
@ -84,6 +85,7 @@ private:
|
||||||
bool mNeedsGoToStart;
|
bool mNeedsGoToStart;
|
||||||
bool mNeedsGoToSystem;
|
bool mNeedsGoToSystem;
|
||||||
bool mNeedsGoToGroupedCollections;
|
bool mNeedsGoToGroupedCollections;
|
||||||
|
bool mNeedsUpdateStatusComponents;
|
||||||
bool mInvalidateCachedBackground;
|
bool mInvalidateCachedBackground;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "components/LottieAnimComponent.h"
|
#include "components/LottieAnimComponent.h"
|
||||||
#include "components/RatingComponent.h"
|
#include "components/RatingComponent.h"
|
||||||
#include "components/ScrollableContainer.h"
|
#include "components/ScrollableContainer.h"
|
||||||
|
#include "components/SystemStatusComponent.h"
|
||||||
#include "components/TextComponent.h"
|
#include "components/TextComponent.h"
|
||||||
#include "components/VideoFFmpegComponent.h"
|
#include "components/VideoFFmpegComponent.h"
|
||||||
#include "components/primary/CarouselComponent.h"
|
#include "components/primary/CarouselComponent.h"
|
||||||
|
|
|
||||||
|
|
@ -92,10 +92,14 @@ void GamelistView::onShow()
|
||||||
video->stopVideoPlayer();
|
video->stopVideoPlayer();
|
||||||
|
|
||||||
mWindow->passClockComponents(&mClockComponents);
|
mWindow->passClockComponents(&mClockComponents);
|
||||||
|
mWindow->passSystemStatusComponents(&mSystemStatusComponents);
|
||||||
|
|
||||||
for (auto& clock : mClockComponents)
|
for (auto& clock : mClockComponents)
|
||||||
clock->update(500);
|
clock->update(500);
|
||||||
|
|
||||||
|
for (auto& systemstatus : mSystemStatusComponents)
|
||||||
|
systemstatus->update(SystemStatus::updateTime);
|
||||||
|
|
||||||
mLastUpdated = nullptr;
|
mLastUpdated = nullptr;
|
||||||
GuiComponent::onShow();
|
GuiComponent::onShow();
|
||||||
|
|
||||||
|
|
@ -365,6 +369,11 @@ void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
mClockComponents.emplace_back(std::make_unique<DateTimeComponent>());
|
mClockComponents.emplace_back(std::make_unique<DateTimeComponent>());
|
||||||
mClockComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
mClockComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
}
|
}
|
||||||
|
else if (element.second.type == "systemstatus") {
|
||||||
|
mSystemStatusComponents.emplace_back(std::make_unique<SystemStatusComponent>());
|
||||||
|
mSystemStatusComponents.back()->applyTheme(theme, "gamelist", element.first, ALL);
|
||||||
|
mSystemStatusComponents.back()->updateGrid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -375,6 +384,14 @@ void GamelistView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||||
mClockComponents.back()->update(1000);
|
mClockComponents.back()->update(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mSystemStatusComponents.empty()) {
|
||||||
|
// Apply a default systemstatus if the theme does not contain any configuration for it.
|
||||||
|
mSystemStatusComponents.emplace_back(std::make_unique<SystemStatusComponent>());
|
||||||
|
mSystemStatusComponents.back()->applyTheme(theme, "gamelist", "systemstatus_default",
|
||||||
|
ThemeFlags::ALL);
|
||||||
|
mSystemStatusComponents.back()->updateGrid();
|
||||||
|
}
|
||||||
|
|
||||||
if (mPrimary == nullptr) {
|
if (mPrimary == nullptr) {
|
||||||
mTextList = std::make_unique<TextListComponent<FileData*>>();
|
mTextList = std::make_unique<TextListComponent<FileData*>>();
|
||||||
mPrimary = mTextList.get();
|
mPrimary = mTextList.get();
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ private:
|
||||||
std::vector<std::unique_ptr<TextComponent>> mGamelistInfoComponents;
|
std::vector<std::unique_ptr<TextComponent>> mGamelistInfoComponents;
|
||||||
std::vector<std::unique_ptr<HelpComponent>> mHelpComponents;
|
std::vector<std::unique_ptr<HelpComponent>> mHelpComponents;
|
||||||
std::vector<std::unique_ptr<DateTimeComponent>> mClockComponents;
|
std::vector<std::unique_ptr<DateTimeComponent>> mClockComponents;
|
||||||
|
std::vector<std::unique_ptr<SystemStatusComponent>> mSystemStatusComponents;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ES_APP_VIEWS_GAMELIST_VIEW_H
|
#endif // ES_APP_VIEWS_GAMELIST_VIEW_H
|
||||||
|
|
|
||||||
|
|
@ -248,6 +248,8 @@ void SystemView::onCursorChanged(const CursorState& state)
|
||||||
{
|
{
|
||||||
mWindow->passHelpComponents(nullptr);
|
mWindow->passHelpComponents(nullptr);
|
||||||
mWindow->passClockComponents(&mSystemElements[mPrimary->getCursor()].clockComponents);
|
mWindow->passClockComponents(&mSystemElements[mPrimary->getCursor()].clockComponents);
|
||||||
|
mWindow->passSystemStatusComponents(
|
||||||
|
&mSystemElements[mPrimary->getCursor()].systemStatusComponents);
|
||||||
|
|
||||||
if (Settings::getInstance()->getBool("CustomEventScripts") &&
|
if (Settings::getInstance()->getBool("CustomEventScripts") &&
|
||||||
Settings::getInstance()->getBool("CustomEventScriptsBrowsing")) {
|
Settings::getInstance()->getBool("CustomEventScriptsBrowsing")) {
|
||||||
|
|
@ -260,6 +262,9 @@ void SystemView::onCursorChanged(const CursorState& state)
|
||||||
for (auto& clock : mSystemElements[mPrimary->getCursor()].clockComponents)
|
for (auto& clock : mSystemElements[mPrimary->getCursor()].clockComponents)
|
||||||
clock->update(1000);
|
clock->update(1000);
|
||||||
|
|
||||||
|
for (auto& systemstatus : mSystemElements[mPrimary->getCursor()].systemStatusComponents)
|
||||||
|
systemstatus->update(SystemStatus::updateTime);
|
||||||
|
|
||||||
// Reset horizontally scrolling text.
|
// Reset horizontally scrolling text.
|
||||||
for (auto& text : mSystemElements[mPrimary->getCursor()].gameCountComponents)
|
for (auto& text : mSystemElements[mPrimary->getCursor()].gameCountComponents)
|
||||||
text->resetComponent();
|
text->resetComponent();
|
||||||
|
|
@ -745,6 +750,13 @@ void SystemView::populate()
|
||||||
elements.clockComponents.back()->applyTheme(theme, "system", element.first,
|
elements.clockComponents.back()->applyTheme(theme, "system", element.first,
|
||||||
ThemeFlags::ALL);
|
ThemeFlags::ALL);
|
||||||
}
|
}
|
||||||
|
else if (element.second.type == "systemstatus") {
|
||||||
|
elements.systemStatusComponents.emplace_back(
|
||||||
|
std::make_unique<SystemStatusComponent>());
|
||||||
|
elements.systemStatusComponents.back()->applyTheme(
|
||||||
|
theme, "system", element.first, ThemeFlags::ALL);
|
||||||
|
elements.systemStatusComponents.back()->updateGrid();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -756,6 +768,14 @@ void SystemView::populate()
|
||||||
elements.clockComponents.back()->update(1000);
|
elements.clockComponents.back()->update(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (elements.systemStatusComponents.empty()) {
|
||||||
|
// Apply a default systemstatus if the theme does not contain any configuration for it.
|
||||||
|
elements.systemStatusComponents.emplace_back(std::make_unique<SystemStatusComponent>());
|
||||||
|
elements.systemStatusComponents.back()->applyTheme(
|
||||||
|
theme, "system", "systemstatus_default", ThemeFlags::ALL);
|
||||||
|
elements.systemStatusComponents.back()->updateGrid();
|
||||||
|
}
|
||||||
|
|
||||||
std::stable_sort(
|
std::stable_sort(
|
||||||
elements.children.begin(), elements.children.end(),
|
elements.children.begin(), elements.children.end(),
|
||||||
[](GuiComponent* a, GuiComponent* b) { return b->getZIndex() > a->getZIndex(); });
|
[](GuiComponent* a, GuiComponent* b) { return b->getZIndex() > a->getZIndex(); });
|
||||||
|
|
@ -921,6 +941,8 @@ void SystemView::populate()
|
||||||
mWindow->passHelpComponents(&mSystemElements[mPrimary->getCursor()].helpComponents);
|
mWindow->passHelpComponents(&mSystemElements[mPrimary->getCursor()].helpComponents);
|
||||||
|
|
||||||
mWindow->passClockComponents(&mSystemElements[mPrimary->getCursor()].clockComponents);
|
mWindow->passClockComponents(&mSystemElements[mPrimary->getCursor()].clockComponents);
|
||||||
|
mWindow->passSystemStatusComponents(
|
||||||
|
&mSystemElements[mPrimary->getCursor()].systemStatusComponents);
|
||||||
|
|
||||||
mFadeTransitions = (static_cast<ViewTransitionAnimation>(Settings::getInstance()->getInt(
|
mFadeTransitions = (static_cast<ViewTransitionAnimation>(Settings::getInstance()->getInt(
|
||||||
"TransitionsSystemToSystem")) == ViewTransitionAnimation::FADE);
|
"TransitionsSystemToSystem")) == ViewTransitionAnimation::FADE);
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
#include "components/LottieAnimComponent.h"
|
#include "components/LottieAnimComponent.h"
|
||||||
#include "components/RatingComponent.h"
|
#include "components/RatingComponent.h"
|
||||||
#include "components/ScrollableContainer.h"
|
#include "components/ScrollableContainer.h"
|
||||||
|
#include "components/SystemStatusComponent.h"
|
||||||
#include "components/TextComponent.h"
|
#include "components/TextComponent.h"
|
||||||
#include "components/VideoFFmpegComponent.h"
|
#include "components/VideoFFmpegComponent.h"
|
||||||
#include "components/primary/CarouselComponent.h"
|
#include "components/primary/CarouselComponent.h"
|
||||||
|
|
@ -139,6 +140,7 @@ private:
|
||||||
std::vector<std::unique_ptr<RatingComponent>> ratingComponents;
|
std::vector<std::unique_ptr<RatingComponent>> ratingComponents;
|
||||||
std::vector<std::unique_ptr<HelpComponent>> helpComponents;
|
std::vector<std::unique_ptr<HelpComponent>> helpComponents;
|
||||||
std::vector<std::unique_ptr<DateTimeComponent>> clockComponents;
|
std::vector<std::unique_ptr<DateTimeComponent>> clockComponents;
|
||||||
|
std::vector<std::unique_ptr<SystemStatusComponent>> systemStatusComponents;
|
||||||
};
|
};
|
||||||
|
|
||||||
Renderer* mRenderer;
|
Renderer* mRenderer;
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ set(CORE_HEADERS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ScrollIndicatorComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ScrollIndicatorComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SliderComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SliderComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SwitchComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SwitchComponent.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SystemStatusComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextEditComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextEditComponent.h
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoComponent.h
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoComponent.h
|
||||||
|
|
@ -139,6 +140,7 @@ set(CORE_SOURCES
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ScrollableContainer.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/ScrollableContainer.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SliderComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SliderComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SwitchComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SwitchComponent.cpp
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/SystemStatusComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextEditComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/TextEditComponent.cpp
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoComponent.cpp
|
${CMAKE_CURRENT_SOURCE_DIR}/src/components/VideoComponent.cpp
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,15 @@ void SystemStatus::setCheckFlags()
|
||||||
mCheckWifi = Settings::getInstance()->getBool("SystemStatusWifi");
|
mCheckWifi = Settings::getInstance()->getBool("SystemStatusWifi");
|
||||||
mCheckCellular = Settings::getInstance()->getBool("SystemStatusCellular");
|
mCheckCellular = Settings::getInstance()->getBool("SystemStatusCellular");
|
||||||
mCheckBattery = Settings::getInstance()->getBool("SystemStatusBattery");
|
mCheckBattery = Settings::getInstance()->getBool("SystemStatusBattery");
|
||||||
|
|
||||||
|
if (!mCheckBluetooth)
|
||||||
|
mHasBluetooth = false;
|
||||||
|
if (!mCheckWifi)
|
||||||
|
mHasWifi = false;
|
||||||
|
if (!mCheckCellular)
|
||||||
|
mHasCellular = false;
|
||||||
|
if (!mCheckBattery)
|
||||||
|
mHasBattery = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SystemStatus::setPolling(const bool state)
|
void SystemStatus::setPolling(const bool state)
|
||||||
|
|
@ -116,13 +125,33 @@ void SystemStatus::setPolling(const bool state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemStatus::Status SystemStatus::getStatus()
|
SystemStatus::Status SystemStatus::getStatus(const bool update)
|
||||||
{
|
{
|
||||||
#if defined(__ANDROID__)
|
#if defined(__ANDROID__)
|
||||||
getStatusBluetooth();
|
if (update) {
|
||||||
getStatusWifi();
|
getStatusBluetooth();
|
||||||
getStatusCellular();
|
getStatusWifi();
|
||||||
getStatusBattery();
|
getStatusCellular();
|
||||||
|
getStatusBattery();
|
||||||
|
#if (DEBUG_SYSTEM_STATUS)
|
||||||
|
std::string status {"Bluetooth "};
|
||||||
|
status.append(mHasBluetooth ? "enabled" : "disabled")
|
||||||
|
.append(", Wi-Fi ")
|
||||||
|
.append(mHasWifi ? "enabled" : "disabled")
|
||||||
|
.append(", cellular ")
|
||||||
|
.append(mHasCellular ? "enabled" : "disabled")
|
||||||
|
.append(", battery ")
|
||||||
|
.append(mHasBattery ? "enabled" : "disabled");
|
||||||
|
if (mHasBattery) {
|
||||||
|
status.append(" (")
|
||||||
|
.append(mBatteryCharging ? "charging" : "not charging")
|
||||||
|
.append(" and at ")
|
||||||
|
.append(std::to_string(mBatteryCapacity))
|
||||||
|
.append("% capacity)");
|
||||||
|
}
|
||||||
|
LOG(LogDebug) << "SystemStatus::getStatus(): " << status;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mStatus.hasBluetooth = mHasBluetooth;
|
mStatus.hasBluetooth = mHasBluetooth;
|
||||||
|
|
@ -166,7 +195,7 @@ void SystemStatus::pollStatus()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int delayValue {0};
|
int delayValue {0};
|
||||||
while (!mPollImmediately && !mExitPolling && delayValue < 3000) {
|
while (!mPollImmediately && !mExitPolling && delayValue < pollingTime) {
|
||||||
delayValue += 100;
|
delayValue += 100;
|
||||||
SDL_Delay(100);
|
SDL_Delay(100);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ public:
|
||||||
void setCheckFlags();
|
void setCheckFlags();
|
||||||
void setPolling(const bool state);
|
void setPolling(const bool state);
|
||||||
void pollImmediately() { mPollImmediately = true; }
|
void pollImmediately() { mPollImmediately = true; }
|
||||||
|
const bool getPollImmediately() { return mPollImmediately; }
|
||||||
|
|
||||||
struct Status {
|
struct Status {
|
||||||
bool hasBluetooth;
|
bool hasBluetooth;
|
||||||
|
|
@ -42,7 +43,10 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Status getStatus();
|
Status getStatus(const bool update = true);
|
||||||
|
|
||||||
|
static constexpr int updateTime {300};
|
||||||
|
static constexpr int pollingTime {2500};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SystemStatus() noexcept;
|
SystemStatus() noexcept;
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,8 @@ std::map<std::string, std::map<std::string, std::string>> ThemeData::sPropertyAt
|
||||||
{"customControllerIcon", "controller"}}},
|
{"customControllerIcon", "controller"}}},
|
||||||
{"helpsystem",
|
{"helpsystem",
|
||||||
{{"customButtonIcon", "button"}}},
|
{{"customButtonIcon", "button"}}},
|
||||||
|
{"systemstatus",
|
||||||
|
{{"customIcon", "icon"}}},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
|
std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
|
||||||
|
|
@ -589,6 +591,22 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
|
||||||
{"lineSpacing", FLOAT},
|
{"lineSpacing", FLOAT},
|
||||||
{"format", STRING},
|
{"format", STRING},
|
||||||
{"opacity", FLOAT}}},
|
{"opacity", FLOAT}}},
|
||||||
|
{"systemstatus",
|
||||||
|
{{"pos", NORMALIZED_PAIR},
|
||||||
|
{"size", NORMALIZED_PAIR},
|
||||||
|
{"origin", NORMALIZED_PAIR},
|
||||||
|
{"fontPath", PATH},
|
||||||
|
{"textRelativeScale", FLOAT},
|
||||||
|
{"color", COLOR},
|
||||||
|
{"backgroundColor", COLOR},
|
||||||
|
{"backgroundColorEnd", COLOR},
|
||||||
|
{"backgroundGradientType", STRING},
|
||||||
|
{"backgroundPadding", NORMALIZED_PAIR},
|
||||||
|
{"backgroundCornerRadius", FLOAT},
|
||||||
|
{"entries", STRING},
|
||||||
|
{"entrySpacing", FLOAT},
|
||||||
|
{"customIcon", PATH},
|
||||||
|
{"opacity", FLOAT}}},
|
||||||
{"sound",
|
{"sound",
|
||||||
{{"path", PATH}}}};
|
{{"path", PATH}}}};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ Window::Window() noexcept
|
||||||
: mRenderer {Renderer::getInstance()}
|
: mRenderer {Renderer::getInstance()}
|
||||||
, mHelpComponents {nullptr}
|
, mHelpComponents {nullptr}
|
||||||
, mClockComponents {nullptr}
|
, mClockComponents {nullptr}
|
||||||
|
, mSystemStatusComponents {nullptr}
|
||||||
, mSplashTextPositions {0.0f, 0.0f, 0.0f, 0.0f}
|
, mSplashTextPositions {0.0f, 0.0f, 0.0f, 0.0f}
|
||||||
, mBackgroundOverlayOpacity {1.0f}
|
, mBackgroundOverlayOpacity {1.0f}
|
||||||
, mScreensaver {nullptr}
|
, mScreensaver {nullptr}
|
||||||
|
|
@ -465,6 +466,11 @@ void Window::update(int deltaTime)
|
||||||
clockComponent->update(deltaTime);
|
clockComponent->update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mSystemStatusComponents != nullptr) {
|
||||||
|
for (auto& systemStatusComponent : *mSystemStatusComponents)
|
||||||
|
systemStatusComponent->update(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__ANDROID__) || defined(__IOS__)
|
#if defined(__ANDROID__) || defined(__IOS__)
|
||||||
if (Settings::getInstance()->getBool("InputTouchOverlay"))
|
if (Settings::getInstance()->getBool("InputTouchOverlay"))
|
||||||
InputOverlay::getInstance().update(deltaTime);
|
InputOverlay::getInstance().update(deltaTime);
|
||||||
|
|
@ -692,6 +698,11 @@ void Window::render()
|
||||||
clockComponent->render(trans);
|
clockComponent->render(trans);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mSystemStatusComponents != nullptr) {
|
||||||
|
for (auto& systemStatusComponent : *mSystemStatusComponents)
|
||||||
|
systemStatusComponent->render(trans);
|
||||||
|
}
|
||||||
|
|
||||||
if (mInfoPopup)
|
if (mInfoPopup)
|
||||||
mInfoPopup->render(trans);
|
mInfoPopup->render(trans);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,11 @@
|
||||||
#include "HelpPrompt.h"
|
#include "HelpPrompt.h"
|
||||||
#include "InputConfig.h"
|
#include "InputConfig.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
|
#include "SystemStatus.h"
|
||||||
#include "components/DateTimeComponent.h"
|
#include "components/DateTimeComponent.h"
|
||||||
#include "components/HelpComponent.h"
|
#include "components/HelpComponent.h"
|
||||||
#include "components/ImageComponent.h"
|
#include "components/ImageComponent.h"
|
||||||
|
#include "components/SystemStatusComponent.h"
|
||||||
#include "components/TextComponent.h"
|
#include "components/TextComponent.h"
|
||||||
#include "guis/GuiInfoPopup.h"
|
#include "guis/GuiInfoPopup.h"
|
||||||
#include "resources/Font.h"
|
#include "resources/Font.h"
|
||||||
|
|
@ -179,6 +181,20 @@ public:
|
||||||
mClockComponents = clockComponents;
|
mClockComponents = clockComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void passSystemStatusComponents(
|
||||||
|
std::vector<std::unique_ptr<SystemStatusComponent>>* systemstatusComponents)
|
||||||
|
{
|
||||||
|
mSystemStatusComponents = systemstatusComponents;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateSystemStatusComponents()
|
||||||
|
{
|
||||||
|
if (mSystemStatusComponents != nullptr) {
|
||||||
|
for (auto& systemStatusComponent : *mSystemStatusComponents)
|
||||||
|
systemStatusComponent->update(SystemStatus::pollingTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Window() noexcept;
|
Window() noexcept;
|
||||||
~Window();
|
~Window();
|
||||||
|
|
@ -198,6 +214,7 @@ private:
|
||||||
std::vector<std::unique_ptr<HelpComponent>>* mHelpComponents;
|
std::vector<std::unique_ptr<HelpComponent>>* mHelpComponents;
|
||||||
std::unique_ptr<HelpComponent> mHelp;
|
std::unique_ptr<HelpComponent> mHelp;
|
||||||
std::vector<std::unique_ptr<DateTimeComponent>>* mClockComponents;
|
std::vector<std::unique_ptr<DateTimeComponent>>* mClockComponents;
|
||||||
|
std::vector<std::unique_ptr<SystemStatusComponent>>* mSystemStatusComponents;
|
||||||
std::unique_ptr<ImageComponent> mBackgroundOverlay;
|
std::unique_ptr<ImageComponent> mBackgroundOverlay;
|
||||||
std::unique_ptr<ImageComponent> mSplash;
|
std::unique_ptr<ImageComponent> mSplash;
|
||||||
std::unique_ptr<TextComponent> mSplashTextScanning;
|
std::unique_ptr<TextComponent> mSplashTextScanning;
|
||||||
|
|
|
||||||
391
es-core/src/components/SystemStatusComponent.cpp
Normal file
391
es-core/src/components/SystemStatusComponent.cpp
Normal file
|
|
@ -0,0 +1,391 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
//
|
||||||
|
// ES-DE Frontend
|
||||||
|
// SystemStatusComponent.cpp
|
||||||
|
//
|
||||||
|
// Displays system status information (Bluetooth, Wi-Fi, cellular and battery).
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "components/SystemStatusComponent.h"
|
||||||
|
|
||||||
|
#include "SystemStatus.h"
|
||||||
|
#include "Window.h"
|
||||||
|
#include "utils/FileSystemUtil.h"
|
||||||
|
|
||||||
|
#define PREFIX "icon_"
|
||||||
|
|
||||||
|
SystemStatusComponent::SystemStatusComponent()
|
||||||
|
: mRenderer {Renderer::getInstance()}
|
||||||
|
, mHasBluetooth {false}
|
||||||
|
, mHasWifi {false}
|
||||||
|
, mHasCellular {false}
|
||||||
|
, mHasBattery {false}
|
||||||
|
, mBatteryCharging {false}
|
||||||
|
, mBatteryCapacity {100}
|
||||||
|
, mEntries {sAllowedEntries}
|
||||||
|
, mColorShift {0xFFFFFFFF}
|
||||||
|
, mBackgroundColor {0x00000000}
|
||||||
|
, mBackgroundColorEnd {0x00000000}
|
||||||
|
, mAccumulator {0}
|
||||||
|
, mAccumulatorAndroid {0}
|
||||||
|
, mBackgroundPadding {0.0f, 0.0f}
|
||||||
|
, mBackgroundCornerRadius {0.0f}
|
||||||
|
, mColorGradientHorizontal {true}
|
||||||
|
, mEntrySpacing {0.005f * mRenderer->getScreenWidth()}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemStatusComponent::updateGrid()
|
||||||
|
{
|
||||||
|
mGrid.reset();
|
||||||
|
|
||||||
|
if (Settings::getInstance()->getBool("SystemStatusDisplayAll")) {
|
||||||
|
mHasBluetooth = true;
|
||||||
|
mHasWifi = true;
|
||||||
|
mHasCellular = true;
|
||||||
|
mHasBattery = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDisplayEntries.clear();
|
||||||
|
|
||||||
|
if (mHasBluetooth && Settings::getInstance()->getBool("SystemStatusBluetooth") &&
|
||||||
|
std::find(mEntries.cbegin(), mEntries.cend(), "bluetooth") != mEntries.cend())
|
||||||
|
mDisplayEntries.emplace_back("bluetooth");
|
||||||
|
if (mHasWifi && Settings::getInstance()->getBool("SystemStatusWifi") &&
|
||||||
|
std::find(mEntries.cbegin(), mEntries.cend(), "wifi") != mEntries.cend())
|
||||||
|
mDisplayEntries.emplace_back("wifi");
|
||||||
|
if (mHasCellular && Settings::getInstance()->getBool("SystemStatusCellular") &&
|
||||||
|
std::find(mEntries.cbegin(), mEntries.cend(), "cellular") != mEntries.cend())
|
||||||
|
mDisplayEntries.emplace_back("cellular");
|
||||||
|
if (mHasBattery && Settings::getInstance()->getBool("SystemStatusBattery") &&
|
||||||
|
std::find(mEntries.cbegin(), mEntries.cend(), "battery") != mEntries.cend())
|
||||||
|
mDisplayEntries.emplace_back("battery");
|
||||||
|
|
||||||
|
if (mDisplayEntries.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const bool batteryText {Settings::getInstance()->getBool("SystemStatusBattery") &&
|
||||||
|
Settings::getInstance()->getBool("SystemStatusBatteryPercentage")};
|
||||||
|
|
||||||
|
int numEntries {static_cast<int>(mDisplayEntries.size())};
|
||||||
|
if (mEntrySpacing != 0.0f)
|
||||||
|
numEntries += numEntries - 1;
|
||||||
|
if (mHasBattery && batteryText)
|
||||||
|
++numEntries;
|
||||||
|
|
||||||
|
mGrid = std::make_shared<ComponentGrid>(glm::ivec2 {numEntries, 1});
|
||||||
|
mEntryMap.clear();
|
||||||
|
|
||||||
|
float width {0.0f};
|
||||||
|
int i {0};
|
||||||
|
|
||||||
|
for (auto it = mDisplayEntries.cbegin(); it != mDisplayEntries.cend(); ++it) {
|
||||||
|
if (*it == "battery") {
|
||||||
|
mBattery = std::make_shared<ImageComponent>(false, true);
|
||||||
|
mBattery->setImage(mIconPathMap["battery_full"]);
|
||||||
|
mBattery->setColorShift(mColorShift);
|
||||||
|
mBattery->setResize(0, mSize.y);
|
||||||
|
mBattery->setOpacity(mThemeOpacity);
|
||||||
|
width += std::round(mBattery->getSize().x);
|
||||||
|
mGrid->setEntry(mBattery, glm::ivec2 {i, 0}, false, false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::shared_ptr<ImageComponent> icon {std::make_shared<ImageComponent>(false, true)};
|
||||||
|
icon->setImage(mIconPathMap[*it]);
|
||||||
|
icon->setColorShift(mColorShift);
|
||||||
|
icon->setResize(0, mSize.y);
|
||||||
|
icon->setOpacity(mThemeOpacity);
|
||||||
|
width += std::round(icon->getSize().x);
|
||||||
|
mGrid->setEntry(icon, glm::ivec2 {i, 0}, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
mEntryMap[*it] = i;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
if (mEntrySpacing != 0.0f && *it != mDisplayEntries.back()) {
|
||||||
|
++i;
|
||||||
|
width += mEntrySpacing;
|
||||||
|
mGrid->setEntry(std::make_shared<GuiComponent>(), glm::ivec2 {i, 0}, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mHasBattery && batteryText) {
|
||||||
|
// We set the initial value to "100%" to calculate the cell size based on this, as this
|
||||||
|
// will be the longest text that will ever be displayed for the battery capacity.
|
||||||
|
mBatteryPercentage = std::make_shared<TextComponent>(
|
||||||
|
"100%", mFont, 0xFFFFFFFF, ALIGN_LEFT, ALIGN_CENTER, glm::ivec2 {1, 0},
|
||||||
|
glm::vec3 {0.0f, 0.0f, 0.0f}, glm::vec2 {0.0f, 0.0f}, 0x00000000, 1.0f);
|
||||||
|
mBatteryPercentage->setColor(mColorShift);
|
||||||
|
mBatteryPercentage->setOpacity(mThemeOpacity);
|
||||||
|
width += mBatteryPercentage->getSize().x;
|
||||||
|
mEntryMap["batteryText"] = i;
|
||||||
|
mGrid->setEntry(mBatteryPercentage, glm::ivec2 {i, 0}, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i {0}; i < static_cast<int>(mGrid->getChildCount()); ++i) {
|
||||||
|
mGrid->setColWidthPerc(i, mGrid->getChild(i)->getSize().x / width);
|
||||||
|
if (mHasBattery && batteryText && i == static_cast<int>(mGrid->getChildCount()) - 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (mEntrySpacing != 0.0f && i != static_cast<int>(mGrid->getChildCount()) - 1) {
|
||||||
|
++i;
|
||||||
|
mGrid->setColWidthPerc(i, mEntrySpacing / width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mGrid->setSize(width, mSize.y);
|
||||||
|
mGrid->setOrigin(mOrigin);
|
||||||
|
mSize.x = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemStatusComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
|
const std::string& view,
|
||||||
|
const std::string& element,
|
||||||
|
unsigned int properties)
|
||||||
|
{
|
||||||
|
// Apply default settings as the theme may not define any configuration.
|
||||||
|
const glm::vec2 scale {glm::vec2 {Renderer::getScreenWidth(), Renderer::getScreenHeight()}};
|
||||||
|
mPosition = glm::vec3 {0.984f * scale.x, 0.016f * scale.y, 0.0f};
|
||||||
|
mSize = glm::vec2 {0.0f, 0.035f} * scale;
|
||||||
|
mOrigin = glm::vec2 {1.0f, 0.0f};
|
||||||
|
mColor = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
mIconPathMap.clear();
|
||||||
|
mIconPathMap["bluetooth"] = ":/graphics/systemstatus/bluetooth.svg";
|
||||||
|
mIconPathMap["wifi"] = ":/graphics/systemstatus/wifi.svg";
|
||||||
|
mIconPathMap["cellular"] = ":/graphics/systemstatus/cellular.svg";
|
||||||
|
mIconPathMap["battery_charging"] = ":/graphics/systemstatus/battery_charging.svg";
|
||||||
|
mIconPathMap["battery_low"] = ":/graphics/systemstatus/battery_low.svg";
|
||||||
|
mIconPathMap["battery_medium"] = ":/graphics/systemstatus/battery_medium.svg";
|
||||||
|
mIconPathMap["battery_high"] = ":/graphics/systemstatus/battery_high.svg";
|
||||||
|
mIconPathMap["battery_full"] = ":/graphics/systemstatus/battery_full.svg";
|
||||||
|
|
||||||
|
GuiComponent::applyTheme(theme, view, element, properties);
|
||||||
|
|
||||||
|
const ThemeData::ThemeElement* elem {theme->getElement(view, element, "systemstatus")};
|
||||||
|
|
||||||
|
float textRelativeScale {0.9f};
|
||||||
|
|
||||||
|
if (!elem) {
|
||||||
|
mSize = glm::round(mSize);
|
||||||
|
mFont = {Font::get(mSize.y * textRelativeScale, FONT_PATH_LIGHT)};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSize.x = 0.0f;
|
||||||
|
mSize.y = glm::clamp(mSize.y, 0.01f * scale.y, 0.5f * scale.y);
|
||||||
|
mSize = glm::round(mSize);
|
||||||
|
|
||||||
|
if (elem->has("textRelativeScale"))
|
||||||
|
textRelativeScale = glm::clamp(elem->get<float>("textRelativeScale"), 0.5f, 1.0f);
|
||||||
|
|
||||||
|
if (elem->has("fontPath"))
|
||||||
|
mFont = {Font::get(mSize.y * textRelativeScale, elem->get<std::string>("fontPath"))};
|
||||||
|
else
|
||||||
|
mFont = {Font::get(mSize.y * textRelativeScale, FONT_PATH_LIGHT)};
|
||||||
|
|
||||||
|
if (elem->has("color"))
|
||||||
|
mColorShift = elem->get<unsigned int>("color");
|
||||||
|
|
||||||
|
if (elem->has("colorEnd"))
|
||||||
|
mColorShiftEnd = elem->get<unsigned int>("colorEnd");
|
||||||
|
else
|
||||||
|
mColorShiftEnd = mColorShift;
|
||||||
|
|
||||||
|
if (elem->has("backgroundColor")) {
|
||||||
|
mBackgroundColor = elem->get<unsigned int>("backgroundColor");
|
||||||
|
|
||||||
|
if (elem->has("backgroundColorEnd"))
|
||||||
|
mBackgroundColorEnd = elem->get<unsigned int>("backgroundColorEnd");
|
||||||
|
else
|
||||||
|
mBackgroundColorEnd = mBackgroundColor;
|
||||||
|
|
||||||
|
if (elem->has("backgroundGradientType")) {
|
||||||
|
const std::string& backgroundGradientType {
|
||||||
|
elem->get<std::string>("backgroundGradientType")};
|
||||||
|
if (backgroundGradientType == "horizontal") {
|
||||||
|
mColorGradientHorizontal = true;
|
||||||
|
}
|
||||||
|
else if (backgroundGradientType == "vertical") {
|
||||||
|
mColorGradientHorizontal = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mColorGradientHorizontal = true;
|
||||||
|
LOG(LogWarning) << "SystemStatusComponent: Invalid theme configuration, property "
|
||||||
|
"\"backgroundGradientType\" for element \""
|
||||||
|
<< element.substr(13) << "\" defined as \""
|
||||||
|
<< backgroundGradientType << "\"";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem->has("backgroundPadding")) {
|
||||||
|
const glm::vec2 backgroundPadding {
|
||||||
|
glm::clamp(elem->get<glm::vec2>("backgroundPadding"), 0.0f, 0.2f)};
|
||||||
|
mBackgroundPadding.x = backgroundPadding.x * mRenderer->getScreenWidth();
|
||||||
|
mBackgroundPadding.y = backgroundPadding.y * mRenderer->getScreenHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem->has("backgroundCornerRadius")) {
|
||||||
|
mBackgroundCornerRadius =
|
||||||
|
glm::clamp(elem->get<float>("backgroundCornerRadius"), 0.0f, 0.5f) *
|
||||||
|
mRenderer->getScreenWidth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem->has("entries")) {
|
||||||
|
// Replace possible whitespace separators with commas.
|
||||||
|
std::string entriesTag {Utils::String::toLower(elem->get<std::string>("entries"))};
|
||||||
|
for (auto& character : entriesTag) {
|
||||||
|
if (std::isspace(character))
|
||||||
|
character = ',';
|
||||||
|
}
|
||||||
|
entriesTag = Utils::String::replace(entriesTag, ",,", ",");
|
||||||
|
std::vector<std::string> entries {Utils::String::delimitedStringToVector(entriesTag, ",")};
|
||||||
|
|
||||||
|
// If the "all" value has been set then leave mEntries fully populated.
|
||||||
|
if (std::find(entries.begin(), entries.end(), "all") == entries.end()) {
|
||||||
|
mEntries.clear();
|
||||||
|
for (auto& allowedEntry : sAllowedEntries) {
|
||||||
|
if (std::find(entries.cbegin(), entries.cend(), allowedEntry) != entries.cend())
|
||||||
|
mEntries.emplace_back(allowedEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elem->has("entrySpacing")) {
|
||||||
|
mEntrySpacing = std::round(glm::clamp(elem->get<float>("entrySpacing"), 0.0f, 0.04f) *
|
||||||
|
mRenderer->getScreenWidth());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom entry icons.
|
||||||
|
// The names may look a bit strange when combined with the PREFIX string "icon_" but it's
|
||||||
|
// because ThemeData adds this prefix to avoid name collisions when using XML attributes.
|
||||||
|
if (elem->has(PREFIX "icon_wifi"))
|
||||||
|
mIconPathMap["wifi"] = elem->get<std::string>(PREFIX "icon_wifi");
|
||||||
|
if (elem->has(PREFIX "icon_bluetooth"))
|
||||||
|
mIconPathMap["bluetooth"] = elem->get<std::string>(PREFIX "icon_bluetooth");
|
||||||
|
if (elem->has(PREFIX "icon_cellular"))
|
||||||
|
mIconPathMap["cellular"] = elem->get<std::string>(PREFIX "icon_cellular");
|
||||||
|
if (elem->has(PREFIX "icon_battery_charging"))
|
||||||
|
mIconPathMap["battery_charging"] = elem->get<std::string>(PREFIX "icon_battery_charging");
|
||||||
|
if (elem->has(PREFIX "icon_battery_low"))
|
||||||
|
mIconPathMap["icon_battery_low"] = elem->get<std::string>(PREFIX "icon_battery_low");
|
||||||
|
if (elem->has(PREFIX "icon_battery_medium"))
|
||||||
|
mIconPathMap["battery_medium"] = elem->get<std::string>(PREFIX "icon_battery_medium");
|
||||||
|
if (elem->has(PREFIX "icon_battery_high"))
|
||||||
|
mIconPathMap["battery_high"] = elem->get<std::string>(PREFIX "icon_battery_high");
|
||||||
|
if (elem->has(PREFIX "icon_battery_full"))
|
||||||
|
mIconPathMap["battery_full"] = elem->get<std::string>(PREFIX "icon_battery_full");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemStatusComponent::update(int deltaTime)
|
||||||
|
{
|
||||||
|
if (mEntries.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
mAccumulator += deltaTime;
|
||||||
|
mAccumulatorAndroid += deltaTime;
|
||||||
|
|
||||||
|
if (mAccumulator >= SystemStatus::updateTime) {
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
// For Android we poll on the main thread instead of in a separate thread.
|
||||||
|
SystemStatus::Status status;
|
||||||
|
if (mAccumulatorAndroid >= SystemStatus::pollingTime ||
|
||||||
|
SystemStatus::getInstance().getPollImmediately()) {
|
||||||
|
status = SystemStatus::getInstance().getStatus(true);
|
||||||
|
mAccumulatorAndroid = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
status = SystemStatus::getInstance().getStatus(false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
SystemStatus::Status status {SystemStatus::getInstance().getStatus()};
|
||||||
|
#endif
|
||||||
|
mAccumulator = 0;
|
||||||
|
|
||||||
|
bool statusChanged {false};
|
||||||
|
bool batteryStatusChanged {false};
|
||||||
|
|
||||||
|
if (mHasBluetooth != status.hasBluetooth) {
|
||||||
|
mHasBluetooth = status.hasBluetooth;
|
||||||
|
statusChanged = true;
|
||||||
|
}
|
||||||
|
if (mHasWifi != status.hasWifi) {
|
||||||
|
mHasWifi = status.hasWifi;
|
||||||
|
statusChanged = true;
|
||||||
|
}
|
||||||
|
if (mHasCellular != status.hasCellular) {
|
||||||
|
mHasCellular = status.hasCellular;
|
||||||
|
statusChanged = true;
|
||||||
|
}
|
||||||
|
if (mHasBattery != status.hasBattery) {
|
||||||
|
mHasBattery = status.hasBattery;
|
||||||
|
statusChanged = true;
|
||||||
|
batteryStatusChanged = true;
|
||||||
|
}
|
||||||
|
if (mHasBattery && mBatteryCharging != status.batteryCharging) {
|
||||||
|
mBatteryCharging = status.batteryCharging;
|
||||||
|
batteryStatusChanged = true;
|
||||||
|
}
|
||||||
|
if (mHasBattery && mBatteryCapacity != status.batteryCapacity) {
|
||||||
|
mBatteryCapacity = status.batteryCapacity;
|
||||||
|
batteryStatusChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (statusChanged)
|
||||||
|
updateGrid();
|
||||||
|
|
||||||
|
if (mHasBattery && batteryStatusChanged) {
|
||||||
|
if (mBatteryPercentage != nullptr)
|
||||||
|
mBatteryPercentage->setValue(std::to_string(mBatteryCapacity) + "%");
|
||||||
|
|
||||||
|
if (mBatteryCharging)
|
||||||
|
mBattery->setImage(mIconPathMap["battery_charging"]);
|
||||||
|
else if (mBatteryCapacity >= 0 && mBatteryCapacity <= 25)
|
||||||
|
mBattery->setImage(mIconPathMap["battery_low"]);
|
||||||
|
else if (mBatteryCapacity >= 26 && mBatteryCapacity <= 60)
|
||||||
|
mBattery->setImage(mIconPathMap["battery_medium"]);
|
||||||
|
else if (mBatteryCapacity >= 61 && mBatteryCapacity <= 90)
|
||||||
|
mBattery->setImage(mIconPathMap["battery_high"]);
|
||||||
|
else if (mBatteryCapacity > 90)
|
||||||
|
mBattery->setImage(mIconPathMap["battery_full"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemStatusComponent::render(const glm::mat4& parentTrans)
|
||||||
|
{
|
||||||
|
if (mDisplayEntries.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mBackgroundColor != 0x00000000) {
|
||||||
|
const glm::vec3 positionTemp {mPosition};
|
||||||
|
mPosition.x -= mBackgroundPadding.x / 2.0f;
|
||||||
|
mPosition.y -= mBackgroundPadding.y / 2.0f;
|
||||||
|
|
||||||
|
const glm::mat4 trans {parentTrans * getTransform()};
|
||||||
|
mRenderer->setMatrix(trans);
|
||||||
|
|
||||||
|
mRenderer->drawRect(0.0f, 0.0f, mSize.x + mBackgroundPadding.x,
|
||||||
|
mSize.y + mBackgroundPadding.y, mBackgroundColor, mBackgroundColorEnd,
|
||||||
|
mColorGradientHorizontal, mThemeOpacity, 1.0f,
|
||||||
|
Renderer::BlendFactor::SRC_ALPHA,
|
||||||
|
Renderer::BlendFactor::ONE_MINUS_SRC_ALPHA, mBackgroundCornerRadius);
|
||||||
|
|
||||||
|
mPosition = positionTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mGrid) {
|
||||||
|
mGrid->setPosition(mPosition);
|
||||||
|
mGrid->setRotationOrigin(mRotationOrigin);
|
||||||
|
mGrid->setRotation(mRotation);
|
||||||
|
|
||||||
|
if (Settings::getInstance()->getBool("DebugImage")) {
|
||||||
|
const glm::mat4 trans {parentTrans * getTransform()};
|
||||||
|
mRenderer->setMatrix(trans);
|
||||||
|
mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0xFF000033, 0xFF000033);
|
||||||
|
}
|
||||||
|
|
||||||
|
mGrid->render(parentTrans);
|
||||||
|
}
|
||||||
|
}
|
||||||
67
es-core/src/components/SystemStatusComponent.h
Normal file
67
es-core/src/components/SystemStatusComponent.h
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
//
|
||||||
|
// ES-DE Frontend
|
||||||
|
// SystemStatusComponent.h
|
||||||
|
//
|
||||||
|
// Displays system status information (Bluetooth, Wi-Fi, cellular and battery).
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef ES_CORE_COMPONENTS_SYSTEM_STATUS_COMPONENT_H
|
||||||
|
#define ES_CORE_COMPONENTS_SYSTEM_STATUS_COMPONENT_H
|
||||||
|
|
||||||
|
#include "GuiComponent.h"
|
||||||
|
#include "components/ComponentGrid.h"
|
||||||
|
#include "components/ImageComponent.h"
|
||||||
|
#include "components/TextComponent.h"
|
||||||
|
#include "renderers/Renderer.h"
|
||||||
|
#include "resources/Font.h"
|
||||||
|
|
||||||
|
class SystemStatusComponent : public GuiComponent
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SystemStatusComponent();
|
||||||
|
void updateGrid();
|
||||||
|
|
||||||
|
void applyTheme(const std::shared_ptr<ThemeData>& theme,
|
||||||
|
const std::string& view,
|
||||||
|
const std::string& element,
|
||||||
|
unsigned int properties) override;
|
||||||
|
|
||||||
|
void update(int deltaTime) override;
|
||||||
|
void render(const glm::mat4& parent) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Renderer* mRenderer;
|
||||||
|
std::shared_ptr<ComponentGrid> mGrid;
|
||||||
|
std::shared_ptr<Font> mFont;
|
||||||
|
|
||||||
|
std::shared_ptr<ImageComponent> mBattery;
|
||||||
|
std::shared_ptr<TextComponent> mBatteryPercentage;
|
||||||
|
|
||||||
|
bool mHasBluetooth;
|
||||||
|
bool mHasWifi;
|
||||||
|
bool mHasCellular;
|
||||||
|
bool mHasBattery;
|
||||||
|
bool mBatteryCharging;
|
||||||
|
int mBatteryCapacity;
|
||||||
|
|
||||||
|
std::vector<std::string> mEntries;
|
||||||
|
std::vector<std::string> mDisplayEntries;
|
||||||
|
std::map<std::string, int> mEntryMap;
|
||||||
|
std::map<std::string, std::string> mIconPathMap;
|
||||||
|
|
||||||
|
static inline std::vector<std::string> sAllowedEntries {"bluetooth", "wifi", "cellular",
|
||||||
|
"battery"};
|
||||||
|
|
||||||
|
unsigned int mColorShift;
|
||||||
|
unsigned int mBackgroundColor;
|
||||||
|
unsigned int mBackgroundColorEnd;
|
||||||
|
int mAccumulator;
|
||||||
|
int mAccumulatorAndroid;
|
||||||
|
glm::vec2 mBackgroundPadding;
|
||||||
|
float mBackgroundCornerRadius;
|
||||||
|
bool mColorGradientHorizontal;
|
||||||
|
float mEntrySpacing;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ES_CORE_COMPONENTS_SYSTEM_STATUS_COMPONENT_H
|
||||||
Loading…
Reference in a new issue