Made some logic changes, fixed rendering
This commit is contained in:
@ -26,6 +26,15 @@ void espgui::ChangeValueDisplay<std::string>::initScreen(TftInterface &tft)
|
||||
m_keyboard.start(tft);
|
||||
|
||||
m_needsClear = std::nullopt;
|
||||
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
void espgui::ChangeValueDisplay<std::string>::update()
|
||||
{
|
||||
Base::update();
|
||||
|
||||
m_keyboard.update();
|
||||
}
|
||||
|
||||
void espgui::ChangeValueDisplay<std::string>::redraw(TftInterface &tft)
|
||||
@ -33,11 +42,11 @@ void espgui::ChangeValueDisplay<std::string>::redraw(TftInterface &tft)
|
||||
Base::redraw(tft);
|
||||
|
||||
const auto now_ts = espchrono::millis_clock::now().time_since_epoch();
|
||||
const auto char_width = tft.textWidth("A", 4);
|
||||
const auto maxChars = (tft.width() - 20) / char_width;
|
||||
const auto string = m_value.substr(std::max(0, static_cast<int>(m_value.size()) - maxChars));
|
||||
|
||||
m_valueLabel.redraw(tft, string, TFT_WHITE, TFT_BLACK, 4);
|
||||
const auto char_width = tft.textWidth(m_value, 4) / ((!m_value.empty()) ? m_value.size() : 1);
|
||||
const auto maxChars = (tft.width() - 40) / char_width;
|
||||
const auto substr_from = std::max(0U, m_value.size() < maxChars ? 0 : static_cast<int>(m_value.size()) - maxChars);
|
||||
ESP_LOGI("ChangeValueDisplay<std::string>", "str: %s, strlen: %d, maxChars: %d, tft.width(): %d, char_width: %d, substr_from: %d, textWidth(\"a\")=%d, textWidth: %d", m_value.c_str(), m_value.size(), maxChars, tft.width(), char_width, substr_from, tft.textWidth("a", 4), tft.textWidth(m_value, 4));
|
||||
const auto string = m_value.substr(substr_from);
|
||||
|
||||
if (m_needsClear)
|
||||
{
|
||||
@ -45,14 +54,24 @@ void espgui::ChangeValueDisplay<std::string>::redraw(TftInterface &tft)
|
||||
m_needsClear = std::nullopt;
|
||||
}
|
||||
|
||||
// tft.drawRect(m_valueLabel.x() + tft.textWidth(m_value, 4) + 3, m_valueLabel.y(), 2, tft.fontHeight(4), (now % 1000 < 500) ? TFT_WHITE : TFT_BLACK);
|
||||
m_valueLabel.redraw(tft, string, TFT_WHITE, TFT_BLACK, 4);
|
||||
|
||||
tft.drawRect(m_valueLabel.x() + tft.textWidth(string, 4) + 3, m_valueLabel.y(), 2, tft.fontHeight(4), (now_ts % 1000ms < 500ms) ? TFT_WHITE : TFT_BLACK);
|
||||
|
||||
m_keyboard.redraw(tft);
|
||||
|
||||
m_locked = false;
|
||||
}
|
||||
|
||||
void espgui::ChangeValueDisplay<std::string>::setShownValue(std::string &&value)
|
||||
{
|
||||
if (m_locked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_locked = true;
|
||||
|
||||
m_needsClear = std::move(m_value);
|
||||
m_value = std::move(value);
|
||||
}
|
||||
@ -67,7 +86,6 @@ void espgui::ChangeValueDisplay<std::string>::buttonReleased(Button button)
|
||||
{
|
||||
//Base::buttonReleased(button);
|
||||
m_keyboard.buttonReleased(button);
|
||||
// TODO stop auto scroll
|
||||
}
|
||||
|
||||
void espgui::ChangeValueDisplay<std::string>::confirmValue()
|
||||
@ -80,6 +98,11 @@ void espgui::ChangeValueDisplay<std::string>::confirmValue()
|
||||
|
||||
void espgui::ChangeValueDisplay<std::string>::removeLastCharFromShownValue()
|
||||
{
|
||||
if (m_locked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto val = this->shownValue(); !val.empty())
|
||||
{
|
||||
val.pop_back();
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
|
||||
void start() override;
|
||||
void initScreen(TftInterface &tft) override;
|
||||
void update() override;
|
||||
void redraw(TftInterface &tft) override;
|
||||
|
||||
void buttonPressed(Button button) override;
|
||||
@ -45,6 +46,8 @@ public:
|
||||
void removeLastCharFromShownValue();
|
||||
|
||||
private:
|
||||
bool m_locked{false};
|
||||
|
||||
std::string m_value;
|
||||
|
||||
Label m_valueLabel{12, 55}; // 188, 53
|
||||
|
@ -33,7 +33,7 @@ public:
|
||||
explicit Keyboard(TDisplay &display) : m_display(display) {}
|
||||
|
||||
void start(TftInterface &tft);
|
||||
|
||||
void update();
|
||||
void redraw(TftInterface &tft);
|
||||
|
||||
void buttonPressed(Button button);
|
||||
@ -71,6 +71,18 @@ private:
|
||||
|
||||
bool m_needsStart{};
|
||||
bool m_needsRedraw{};
|
||||
|
||||
std::optional<espchrono::millis_clock::time_point> m_back_pressed_time{};
|
||||
std::optional<espchrono::millis_clock::time_point> m_confirm_pressed_time{};
|
||||
|
||||
struct ButtonHeldInfo
|
||||
{
|
||||
espchrono::millis_clock::time_point nextTimestamp;
|
||||
int counter{};
|
||||
};
|
||||
|
||||
std::optional<ButtonHeldInfo> m_upHeld;
|
||||
std::optional<ButtonHeldInfo> m_downHeld;
|
||||
};
|
||||
|
||||
template<typename TDisplay>
|
||||
@ -96,11 +108,15 @@ void Keyboard<TDisplay>::moveSelectorDown()
|
||||
template<typename TDisplay>
|
||||
void Keyboard<TDisplay>::nextScreen()
|
||||
{
|
||||
|
||||
m_current_screen = static_cast<Screen>(static_cast<uint8_t>(m_current_screen) + uint8_t{1});
|
||||
if (m_current_screen >= Screen::SCREEN_MAX)
|
||||
m_current_screen = Screen::SCREEN_1;
|
||||
|
||||
updateCharLength();
|
||||
|
||||
m_needsStart = true;
|
||||
m_needsRedraw = true;
|
||||
}
|
||||
|
||||
template<typename TDisplay>
|
||||
@ -262,15 +278,22 @@ void Keyboard<TDisplay>::start(TftInterface &tft)
|
||||
|
||||
updateCharLength();
|
||||
drawKeyboard(tft);
|
||||
|
||||
m_upHeld = std::nullopt;
|
||||
m_downHeld = std::nullopt;
|
||||
}
|
||||
|
||||
template<typename TDisplay>
|
||||
void Keyboard<TDisplay>::redraw(TftInterface &tft)
|
||||
{
|
||||
const auto isLandscape = espgui::isLandscape(tft);
|
||||
|
||||
if (m_needsStart)
|
||||
{
|
||||
m_needsStart = false;
|
||||
drawKeyboard(tft, true);
|
||||
tft.fillRect(1, m_keyboard_start_y - 10, tft.width()-1, tft.height() - m_keyboard_start_y - (isLandscape ? 0 : 30), TFT_BLACK);
|
||||
tft.drawSunkenRect(1, m_keyboard_start_y - 10, tft.width()-1, tft.height() - m_keyboard_start_y - (isLandscape ? 0 : 30), TFT_WHITE, TFT_GREY, TFT_BLACK);
|
||||
updateCharLength();
|
||||
}
|
||||
|
||||
if (m_needsRedraw)
|
||||
@ -283,45 +306,122 @@ void Keyboard<TDisplay>::redraw(TftInterface &tft)
|
||||
template<typename TDisplay>
|
||||
void Keyboard<TDisplay>::buttonPressed(Button button)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case Right:
|
||||
{
|
||||
if (m_char_index < m_char_length)
|
||||
m_display.setShownValue(m_display.shownValue() + m_keyset[m_char_index]);
|
||||
else if (m_char_index == m_char_length) // shift
|
||||
{
|
||||
nextScreen();
|
||||
}
|
||||
else if (m_char_index == m_char_length + 1) // space
|
||||
{
|
||||
m_display.setShownValue(m_display.shownValue() + " ");
|
||||
}
|
||||
else if (m_char_index == m_char_length + 2) // backspace
|
||||
{
|
||||
m_display.removeLastCharFromShownValue();
|
||||
}
|
||||
else if (m_char_index == m_char_length + 3) // enter
|
||||
{
|
||||
m_display.confirmValue();
|
||||
}
|
||||
m_confirm_pressed_time = espchrono::millis_clock::now();
|
||||
break;
|
||||
}
|
||||
case Left:
|
||||
popScreen();
|
||||
return;
|
||||
m_back_pressed_time = espchrono::millis_clock::now();
|
||||
break;
|
||||
case Up:
|
||||
moveSelectorLeft();
|
||||
m_needsRedraw = true;
|
||||
m_upHeld = ButtonHeldInfo { .nextTimestamp = espchrono::millis_clock::now() + 300ms };
|
||||
break;
|
||||
case Down:
|
||||
moveSelectorRight();
|
||||
m_needsRedraw = true;
|
||||
m_downHeld = ButtonHeldInfo { .nextTimestamp = espchrono::millis_clock::now() + 300ms };
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TDisplay>
|
||||
void Keyboard<TDisplay>::buttonReleased(espgui::Button button) {}
|
||||
void Keyboard<TDisplay>::buttonReleased(espgui::Button button)
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
switch (button)
|
||||
{
|
||||
case Left:
|
||||
if (!m_back_pressed_time)
|
||||
return;
|
||||
|
||||
if (espchrono::ago(*m_back_pressed_time) < 350ms)
|
||||
m_display.removeLastCharFromShownValue();
|
||||
|
||||
m_back_pressed_time = std::nullopt;
|
||||
break;
|
||||
case Right:
|
||||
if (!m_confirm_pressed_time)
|
||||
return;
|
||||
|
||||
if (espchrono::ago(*m_confirm_pressed_time) < 350ms)
|
||||
{
|
||||
if (m_char_index < m_char_length)
|
||||
m_display.setShownValue(m_display.shownValue() + m_keyset[m_char_index]);
|
||||
else if (m_char_index == m_char_length) // shift
|
||||
{
|
||||
nextScreen();
|
||||
}
|
||||
else if (m_char_index == m_char_length + 1) // space
|
||||
{
|
||||
m_display.setShownValue(m_display.shownValue() + " ");
|
||||
}
|
||||
else if (m_char_index == m_char_length + 2) // backspace
|
||||
{
|
||||
m_display.removeLastCharFromShownValue();
|
||||
}
|
||||
else if (m_char_index == m_char_length + 3) // enter
|
||||
{
|
||||
m_display.confirmValue();
|
||||
}
|
||||
}
|
||||
m_confirm_pressed_time = std::nullopt;
|
||||
break;
|
||||
case Up:
|
||||
m_upHeld = std::nullopt;
|
||||
break;
|
||||
case Down:
|
||||
m_downHeld = std::nullopt;
|
||||
break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TDisplay>
|
||||
void Keyboard<TDisplay>::update()
|
||||
{
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
const auto now = espchrono::millis_clock::now();
|
||||
if (m_back_pressed_time)
|
||||
{
|
||||
if (espchrono::ago(*m_back_pressed_time) > 350ms)
|
||||
{
|
||||
m_back_pressed_time = std::nullopt;
|
||||
popScreen();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_confirm_pressed_time)
|
||||
{
|
||||
if (espchrono::ago(*m_confirm_pressed_time) > 350ms)
|
||||
{
|
||||
m_confirm_pressed_time = std::nullopt;
|
||||
nextScreen();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_upHeld && now >= m_upHeld->nextTimestamp)
|
||||
{
|
||||
m_upHeld->nextTimestamp += m_upHeld->counter > 3 ? 100ms : 200ms;
|
||||
m_upHeld->counter++;
|
||||
moveSelectorLeft();
|
||||
m_needsRedraw = true;
|
||||
}
|
||||
if (m_downHeld && now >= m_downHeld->nextTimestamp)
|
||||
{
|
||||
m_downHeld->nextTimestamp += m_downHeld->counter > 3 ? 100ms : 200ms;
|
||||
m_downHeld->counter++;
|
||||
moveSelectorRight();
|
||||
m_needsRedraw = true;
|
||||
}
|
||||
}
|
||||
} // namespace espgui
|
||||
|
Reference in New Issue
Block a user