2020-09-21 17:17:34 +00:00
|
|
|
// SPDX-License-Identifier: MIT
|
2020-06-06 14:48:05 +00:00
|
|
|
//
|
2020-09-21 17:17:34 +00:00
|
|
|
// EmulationStation Desktop Edition
|
2020-06-21 12:25:28 +00:00
|
|
|
// DateTimeComponent.cpp
|
2020-06-06 14:48:05 +00:00
|
|
|
//
|
2020-06-21 12:25:28 +00:00
|
|
|
// Provides the date and time, in absolute (actual date) or relative
|
|
|
|
// (delta from current date and time) form.
|
|
|
|
// Used by the gamelist views.
|
2020-06-06 14:48:05 +00:00
|
|
|
//
|
|
|
|
|
2014-06-20 01:30:09 +00:00
|
|
|
#include "components/DateTimeComponent.h"
|
2017-11-01 22:21:10 +00:00
|
|
|
|
2018-10-13 01:08:15 +00:00
|
|
|
#include "Log.h"
|
|
|
|
#include "Settings.h"
|
2021-07-07 18:31:46 +00:00
|
|
|
#include "utils/StringUtil.h"
|
2013-09-28 22:35:38 +00:00
|
|
|
|
2022-01-19 17:01:54 +00:00
|
|
|
DateTimeComponent::DateTimeComponent()
|
|
|
|
: mDisplayRelative {false}
|
2013-09-28 22:35:38 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
// ISO 8601 date format.
|
|
|
|
setFormat("%Y-%m-%d");
|
2013-09-28 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
2022-01-19 17:01:54 +00:00
|
|
|
DateTimeComponent::DateTimeComponent(const std::string& text,
|
2021-07-07 18:31:46 +00:00
|
|
|
const std::shared_ptr<Font>& font,
|
|
|
|
unsigned int color,
|
|
|
|
Alignment align,
|
2021-08-15 20:03:17 +00:00
|
|
|
glm::vec3 pos,
|
2021-08-16 16:25:01 +00:00
|
|
|
glm::vec2 size,
|
2021-07-07 18:31:46 +00:00
|
|
|
unsigned int bgcolor)
|
2022-01-19 17:01:54 +00:00
|
|
|
: TextComponent {text, font, color, align, pos, size, bgcolor}
|
2022-01-16 17:18:28 +00:00
|
|
|
, mDisplayRelative {false}
|
2013-09-28 22:35:38 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
// ISO 8601 date format.
|
|
|
|
setFormat("%Y-%m-%d");
|
2013-09-28 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DateTimeComponent::setValue(const std::string& val)
|
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
mTime = val;
|
|
|
|
onTextChanged();
|
2013-09-28 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::string DateTimeComponent::getValue() const
|
|
|
|
{
|
2021-07-07 18:31:46 +00:00
|
|
|
// Return time value as a string.
|
2020-06-21 12:25:28 +00:00
|
|
|
return mTime;
|
2013-09-28 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
2018-10-13 01:08:15 +00:00
|
|
|
void DateTimeComponent::setFormat(const std::string& format)
|
2013-09-28 22:35:38 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
mFormat = format;
|
|
|
|
onTextChanged();
|
2013-09-28 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
2018-10-13 01:08:15 +00:00
|
|
|
void DateTimeComponent::setDisplayRelative(bool displayRelative)
|
2013-09-28 22:35:38 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
mDisplayRelative = displayRelative;
|
|
|
|
onTextChanged();
|
2013-09-28 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
2018-10-13 01:08:15 +00:00
|
|
|
void DateTimeComponent::onTextChanged()
|
2013-09-28 22:35:38 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
mText = getDisplayString();
|
|
|
|
TextComponent::onTextChanged();
|
2013-09-28 22:35:38 +00:00
|
|
|
}
|
|
|
|
|
2018-10-13 01:08:15 +00:00
|
|
|
std::string DateTimeComponent::getDisplayString() const
|
2013-09-28 22:35:38 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
if (mDisplayRelative) {
|
2021-11-26 19:55:54 +00:00
|
|
|
// Workaround to handle Unix epoch for different time zones.
|
|
|
|
if (mTime.getTime() < 82800)
|
2020-06-21 12:25:28 +00:00
|
|
|
return "never";
|
2013-09-28 22:35:38 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
Utils::Time::DateTime now(Utils::Time::now());
|
|
|
|
Utils::Time::Duration dur(now.getTime() - mTime.getTime());
|
2013-09-28 22:35:38 +00:00
|
|
|
|
2020-12-17 19:43:52 +00:00
|
|
|
std::string buf;
|
2013-09-28 22:35:38 +00:00
|
|
|
|
2020-07-13 18:58:25 +00:00
|
|
|
if (dur.getDays() > 0)
|
2021-07-07 18:31:46 +00:00
|
|
|
buf = std::to_string(dur.getDays()) + " day" + // Line break.
|
|
|
|
(dur.getDays() > 1 ? "s" : "") + " ago";
|
2020-07-13 18:58:25 +00:00
|
|
|
else if (dur.getHours() > 0)
|
2021-07-07 18:31:46 +00:00
|
|
|
buf = std::to_string(dur.getHours()) + " hour" + // Line break.
|
|
|
|
(dur.getHours() > 1 ? "s" : "") + " ago";
|
2020-07-13 18:58:25 +00:00
|
|
|
else if (dur.getMinutes() > 0)
|
2021-07-07 18:31:46 +00:00
|
|
|
buf = std::to_string(dur.getMinutes()) + " minute" + // Line break.
|
|
|
|
(dur.getMinutes() > 1 ? "s" : "") + " ago";
|
2020-06-21 12:25:28 +00:00
|
|
|
else
|
2021-07-07 18:31:46 +00:00
|
|
|
buf = std::to_string(dur.getSeconds()) + " second" + // Line break.
|
|
|
|
(dur.getSeconds() > 1 || dur.getSeconds() == 0 ? "s" : "") + " ago";
|
2013-09-28 22:35:38 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
return std::string(buf);
|
|
|
|
}
|
2013-09-28 22:35:38 +00:00
|
|
|
|
2020-07-13 18:58:25 +00:00
|
|
|
if (mTime.getTime() == 0)
|
2020-06-21 12:25:28 +00:00
|
|
|
return "unknown";
|
2013-09-28 22:35:38 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
return Utils::Time::timeToString(mTime.getTime(), mFormat);
|
2013-09-28 22:35:38 +00:00
|
|
|
}
|
2013-10-16 23:11:43 +00:00
|
|
|
|
2021-08-15 17:30:31 +00:00
|
|
|
void DateTimeComponent::render(const glm::mat4& parentTrans)
|
2013-10-16 23:11:43 +00:00
|
|
|
{
|
2021-08-15 17:30:31 +00:00
|
|
|
// Render the component.
|
2020-06-21 12:25:28 +00:00
|
|
|
TextComponent::render(parentTrans);
|
2013-10-16 23:11:43 +00:00
|
|
|
}
|
|
|
|
|
2020-06-06 14:48:05 +00:00
|
|
|
void DateTimeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme,
|
2021-07-07 18:31:46 +00:00
|
|
|
const std::string& view,
|
|
|
|
const std::string& element,
|
|
|
|
unsigned int properties)
|
2014-03-25 19:14:09 +00:00
|
|
|
{
|
2020-06-21 12:25:28 +00:00
|
|
|
GuiComponent::applyTheme(theme, view, element, properties);
|
|
|
|
using namespace ThemeFlags;
|
2014-05-03 19:51:50 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "datetime");
|
2020-07-13 18:58:25 +00:00
|
|
|
if (!elem)
|
2020-06-21 12:25:28 +00:00
|
|
|
return;
|
2014-01-19 22:06:13 +00:00
|
|
|
|
2020-07-13 18:58:25 +00:00
|
|
|
if (elem->has("format"))
|
2020-06-21 12:25:28 +00:00
|
|
|
setFormat(elem->get<std::string>("format"));
|
2015-03-05 23:43:38 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
if (properties & COLOR && elem->has("color"))
|
|
|
|
setColor(elem->get<unsigned int>("color"));
|
2014-01-19 22:06:13 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
setRenderBackground(false);
|
|
|
|
if (properties & COLOR && elem->has("backgroundColor")) {
|
|
|
|
setBackgroundColor(elem->get<unsigned int>("backgroundColor"));
|
|
|
|
setRenderBackground(true);
|
|
|
|
}
|
2018-10-13 01:08:15 +00:00
|
|
|
|
2022-02-10 23:19:08 +00:00
|
|
|
if (properties & ALIGNMENT && elem->has("horizontalAlignment")) {
|
|
|
|
std::string str {elem->get<std::string>("horizontalAlignment")};
|
|
|
|
if (str == "left")
|
|
|
|
setHorizontalAlignment(ALIGN_LEFT);
|
|
|
|
else if (str == "center")
|
|
|
|
setHorizontalAlignment(ALIGN_CENTER);
|
|
|
|
else if (str == "right")
|
|
|
|
setHorizontalAlignment(ALIGN_RIGHT);
|
|
|
|
else
|
|
|
|
LOG(LogWarning) << "DateTimeComponent: Invalid theme configuration, property "
|
2022-03-18 19:31:04 +00:00
|
|
|
"<horizontalAlignment> defined as \""
|
2022-02-10 23:19:08 +00:00
|
|
|
<< str << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
if (properties & ALIGNMENT && elem->has("verticalAlignment")) {
|
|
|
|
std::string str {elem->get<std::string>("verticalAlignment")};
|
|
|
|
if (str == "top")
|
|
|
|
setVerticalAlignment(ALIGN_TOP);
|
|
|
|
else if (str == "center")
|
|
|
|
setVerticalAlignment(ALIGN_CENTER);
|
|
|
|
else if (str == "bottom")
|
|
|
|
setVerticalAlignment(ALIGN_BOTTOM);
|
|
|
|
else
|
|
|
|
LOG(LogWarning) << "DateTimeComponent: Invalid theme configuration, property "
|
2022-03-18 19:31:04 +00:00
|
|
|
"<verticalAlignment> defined as \""
|
2022-02-10 23:19:08 +00:00
|
|
|
<< str << "\"";
|
|
|
|
}
|
|
|
|
|
|
|
|
// Legacy themes only.
|
2020-07-13 18:58:25 +00:00
|
|
|
if (properties & ALIGNMENT && elem->has("alignment")) {
|
2022-02-10 23:19:08 +00:00
|
|
|
std::string str {elem->get<std::string>("alignment")};
|
2020-07-13 18:58:25 +00:00
|
|
|
if (str == "left")
|
2020-06-21 12:25:28 +00:00
|
|
|
setHorizontalAlignment(ALIGN_LEFT);
|
2020-07-13 18:58:25 +00:00
|
|
|
else if (str == "center")
|
2020-06-21 12:25:28 +00:00
|
|
|
setHorizontalAlignment(ALIGN_CENTER);
|
2020-07-13 18:58:25 +00:00
|
|
|
else if (str == "right")
|
2020-06-21 12:25:28 +00:00
|
|
|
setHorizontalAlignment(ALIGN_RIGHT);
|
|
|
|
else
|
2022-02-10 23:19:08 +00:00
|
|
|
LOG(LogWarning) << "DateTimeComponent: Invalid theme configuration, property "
|
2022-03-18 19:31:04 +00:00
|
|
|
"<alignment> defined as \""
|
2022-02-10 23:19:08 +00:00
|
|
|
<< str << "\"";
|
2020-06-21 12:25:28 +00:00
|
|
|
}
|
2018-10-13 01:08:15 +00:00
|
|
|
|
2022-08-18 21:44:22 +00:00
|
|
|
if (properties & METADATA && elem->has("metadata")) {
|
|
|
|
mThemeMetadata = "";
|
|
|
|
const std::string metadata {elem->get<std::string>("metadata")};
|
|
|
|
if (metadata == "releasedate" || metadata == "lastplayed") {
|
|
|
|
mThemeMetadata = metadata;
|
|
|
|
}
|
|
|
|
else {
|
2022-08-19 15:11:16 +00:00
|
|
|
LOG(LogError) << "DateTimeComponent: Invalid theme configuration, property "
|
|
|
|
"<metadata> defined as \""
|
|
|
|
<< metadata << "\"";
|
2022-08-18 21:44:22 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-22 20:24:19 +00:00
|
|
|
|
2022-02-13 10:45:06 +00:00
|
|
|
if (mThemeMetadata == "lastplayed")
|
2022-02-12 16:43:20 +00:00
|
|
|
setDisplayRelative(true);
|
|
|
|
|
|
|
|
if (elem->has("displayRelative"))
|
|
|
|
setDisplayRelative(elem->get<bool>("displayRelative"));
|
|
|
|
|
2022-02-09 21:06:34 +00:00
|
|
|
if (properties & LETTER_CASE && elem->has("letterCase")) {
|
|
|
|
std::string letterCase {elem->get<std::string>("letterCase")};
|
|
|
|
if (letterCase == "uppercase") {
|
|
|
|
setUppercase(true);
|
|
|
|
}
|
|
|
|
else if (letterCase == "lowercase") {
|
|
|
|
setLowercase(true);
|
|
|
|
}
|
|
|
|
else if (letterCase == "capitalize") {
|
|
|
|
setCapitalize(true);
|
|
|
|
}
|
|
|
|
else if (letterCase != "none") {
|
2022-03-18 19:31:04 +00:00
|
|
|
LOG(LogWarning) << "DateTimeComponent: Invalid theme configuration, property "
|
|
|
|
"<letterCase> defined as \""
|
|
|
|
<< letterCase << "\"";
|
2022-02-09 21:06:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Legacy themes only.
|
2020-07-13 18:58:25 +00:00
|
|
|
if (properties & FORCE_UPPERCASE && elem->has("forceUppercase"))
|
2020-06-21 12:25:28 +00:00
|
|
|
setUppercase(elem->get<bool>("forceUppercase"));
|
2014-05-03 19:51:50 +00:00
|
|
|
|
2020-07-13 18:58:25 +00:00
|
|
|
if (properties & LINE_SPACING && elem->has("lineSpacing"))
|
2022-02-13 10:45:06 +00:00
|
|
|
setLineSpacing(glm::clamp(elem->get<float>("lineSpacing"), 0.5f, 3.0f));
|
2018-10-13 01:08:15 +00:00
|
|
|
|
2020-06-21 12:25:28 +00:00
|
|
|
setFont(Font::getFromTheme(elem, properties, mFont));
|
2014-01-19 22:06:13 +00:00
|
|
|
}
|