Skip to content

Commit

Permalink
Handle long key press
Browse files Browse the repository at this point in the history
Refs: #62
  • Loading branch information
orontee committed Oct 21, 2023
1 parent 995eaa4 commit 71d3673
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 57 deletions.
4 changes: 1 addition & 3 deletions src/app.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ int App::process_event(int event_type, int param_one, int param_two) {
return this->ui->handle_pointer_event(event_type, param_one, param_two);
}
if (ISKEYEVENT(event_type)) {
if (event_type == EVT_KEYPRESS) {
return this->ui->handle_key_pressed(param_one);
}
return this->ui->handle_key_event(event_type, param_one);
}
}
return 0;
Expand Down
24 changes: 14 additions & 10 deletions src/dailyforecastbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,6 @@ class DailyForecastBox : public Widget {
this->draw_frame();
}

int handle_key_pressed(int key) override {
if (key == IV_KEY_PREV or key == IV_KEY_NEXT) {
const auto event_handler = GetEventHandler();
SendEvent(event_handler, EVT_CUSTOM,
CustomEvent::change_daily_forecast_display, 0);
return 1;
}
return 0;
}

private:
static constexpr size_t row_count{8};
static constexpr size_t column_count{9};
Expand Down Expand Up @@ -87,6 +77,20 @@ class DailyForecastBox : public Widget {
ALIGN_RIGHT, ALIGN_RIGHT, ALIGN_RIGHT,
ALIGN_RIGHT, ALIGN_RIGHT, ALIGN_RIGHT};

bool handle_key_press(int key) override {
return (key == IV_KEY_PREV or key == IV_KEY_NEXT);
}

bool handle_key_release(int key) override {
if (key == IV_KEY_PREV or key == IV_KEY_NEXT) {
const auto event_handler = GetEventHandler();
SendEvent(event_handler, EVT_CUSTOM,
CustomEvent::change_daily_forecast_display, 0);
return true;
}
return false;
}

std::pair<std::string, std::string>
generate_precipitation_column_content(const DailyCondition &forecast) const {
const Units units{this->model};
Expand Down
46 changes: 32 additions & 14 deletions src/hourlyforecastbox.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "hourlyforecastbox.h"

#include <boost/log/trivial.hpp>
#include <cmath>
#include <gsl/gsl_interp.h>
#include <inkview.h>
Expand Down Expand Up @@ -51,17 +52,27 @@ void HourlyForecastBox::show() {
this->draw_temperature_curve();
}

int HourlyForecastBox::handle_key_pressed(int key) {
if (key == IV_KEY_PREV) {
this->decrease_forecast_offset();
return 1;
bool HourlyForecastBox::handle_key_press(int key) {
return (key == IV_KEY_PREV or key == IV_KEY_NEXT);
}

bool HourlyForecastBox::handle_key_repeat(int key) {
if (key == IV_KEY_PREV or key == IV_KEY_NEXT) {
this->request_change_display_forecast_display();
return true;
}
return false;
}

if (key == IV_KEY_NEXT) {
bool HourlyForecastBox::handle_key_release(int key) {
if (key == IV_KEY_PREV) {
this->decrease_forecast_offset();
return true;
} else if (key == IV_KEY_NEXT) {
this->increase_forecast_offset();
return 1;
return true;
}
return 0;
return false;
}

void HourlyForecastBox::increase_forecast_offset() {
Expand All @@ -71,12 +82,11 @@ void HourlyForecastBox::increase_forecast_offset() {
std::min(this->forecast_offset + this->visible_bars, max_forecast_offset);
if (updated_forecast_offset != this->forecast_offset) {
this->forecast_offset = updated_forecast_offset;
BOOST_LOG_TRIVIAL(debug)
<< "Forecast offset increased to " << this->forecast_offset;
this->draw_and_update();
} else {
this->forecast_offset = 0;
const auto event_handler = GetEventHandler();
SendEvent(event_handler, EVT_CUSTOM,
CustomEvent::change_daily_forecast_display, 0);
this->request_change_display_forecast_display();
}
}

Expand All @@ -91,11 +101,11 @@ void HourlyForecastBox::decrease_forecast_offset() {

if (updated_forecast_offset != this->forecast_offset) {
this->forecast_offset = updated_forecast_offset;
BOOST_LOG_TRIVIAL(debug)
<< "Forecast offset decreased to " << this->forecast_offset;
this->draw_and_update();
} else {
const auto event_handler = GetEventHandler();
SendEvent(event_handler, EVT_CUSTOM,
CustomEvent::change_daily_forecast_display, 0);
this->request_change_display_forecast_display();
}
}

Expand Down Expand Up @@ -276,4 +286,12 @@ void HourlyForecastBox::draw_precipitation_histogram() const {
}
}

void HourlyForecastBox::request_change_display_forecast_display() {
BOOST_LOG_TRIVIAL(debug) << "Requesting a change of forecast display";
this->forecast_offset = 0;

const auto event_handler = GetEventHandler();
SendEvent(event_handler, EVT_CUSTOM,
CustomEvent::change_daily_forecast_display, 0);
}
} // namespace taranis
10 changes: 8 additions & 2 deletions src/hourlyforecastbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ class HourlyForecastBox : public Widget {

void show() override;

int handle_key_pressed(int key) override;

void increase_forecast_offset();

void decrease_forecast_offset();
Expand Down Expand Up @@ -49,13 +47,21 @@ class HourlyForecastBox : public Widget {

size_t forecast_offset{0};

bool handle_key_press(int key) override;

bool handle_key_repeat(int key) override;

bool handle_key_release(int key) override;

void draw_and_update();

void draw_frame_and_values() const;

void draw_temperature_curve() const;

void draw_precipitation_histogram() const;

void request_change_display_forecast_display();
};

} // namespace taranis
89 changes: 89 additions & 0 deletions src/keys.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#pragma once

#include "inkview.h"
#include <algorithm>
#include <boost/log/trivial.hpp>
#include <memory>
#include <vector>

#include "events.h"

namespace taranis {

struct KeyEventConsumer {
protected:
virtual ~KeyEventConsumer() {}

private:
virtual bool handle_key_press(int key) { return 0; }

virtual bool handle_key_repeat(int key) { return 0; }

virtual bool handle_key_release(int key) { return 0; }

friend struct KeyEventDispatcher;
};

struct KeyEventDispatcher {

int handle_key_event(int event_type, int key) {
BOOST_LOG_TRIVIAL(debug)
<< "Processing event " << format_event_type(event_type) << " for key "
<< key;

std::shared_ptr<KeyEventConsumer> event_consumer{nullptr};
if (event_type == EVT_KEYPRESS) {
for (auto consumer : this->consumers) {
if (consumer->handle_key_press(key)) {
event_consumer = consumer;
}
}
} else if (this->last_event_consumer) {
if (event_type == EVT_KEYREPEAT) {
if (this->last_event_consumer->handle_key_repeat(key)) {
event_consumer = this->last_event_consumer;
}
} else if (event_type == EVT_KEYRELEASE) {
if (this->last_event_consumer->handle_key_release(key)) {
event_consumer = this->last_event_consumer;
}
}
}
if (event_consumer) {
this->last_event_consumer = event_consumer;
BOOST_LOG_TRIVIAL(debug) << "Last key event consumer updated";
return 1;
}
BOOST_LOG_TRIVIAL(debug) << "Key event not consumed";
this->last_event_consumer.reset();
return 0;
}

protected:
void register_key_event_consumer(std::shared_ptr<KeyEventConsumer> consumer) {
const auto found =
std::find(this->consumers.begin(), this->consumers.end(), consumer);
if (found == this->consumers.end()) {
this->consumers.push_back(consumer);
}
}

void
unregister_key_event_consumer(std::shared_ptr<KeyEventConsumer> consumer) {
const auto found =
std::find(this->consumers.begin(), this->consumers.end(), consumer);
if (found != this->consumers.end()) {
this->consumers.erase(found);
if (this->last_event_consumer == consumer) {
this->last_event_consumer.reset();
}
}
}

private:
std::vector<std::shared_ptr<KeyEventConsumer>> consumers;

std::shared_ptr<KeyEventConsumer> last_event_consumer;
};

} // namespace taranis
8 changes: 5 additions & 3 deletions src/menu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@ void MenuButton::set_menu_handler(iv_menuhandler handler) {
this->menu_handler = handler;
}

int MenuButton::handle_key_pressed(int key) {
bool MenuButton::handle_key_press(int key) { return key == IV_KEY_MENU; }

bool MenuButton::handle_key_release(int key) {
if (key == IV_KEY_MENU) {
this->open_menu();
return 1;
return true;
}
return 0;
return false;
}

std::pair<int, int> MenuButton::get_menu_position() const {
Expand Down
6 changes: 4 additions & 2 deletions src/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ class MenuButton : public Button {

void set_menu_handler(iv_menuhandler handler);

int handle_key_pressed(int key) override;

protected:
void on_clicked() override { this->open_menu(); }

Expand All @@ -61,6 +59,10 @@ class MenuButton : public Button {

iv_menuhandler menu_handler;

bool handle_key_press(int key) override;

bool handle_key_release(int key) override;

std::pair<int, int> get_menu_position() const;

void initialize_favorite_location_icon();
Expand Down
26 changes: 9 additions & 17 deletions src/ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "dailyforecastbox.h"
#include "events.h"
#include "history.h"
#include "keys.h"
#include "locationbox.h"
#include "locationlist.h"
#include "menu.h"
Expand All @@ -17,7 +18,8 @@
namespace taranis {

Ui::Ui(std::shared_ptr<Model> model)
: model{model}, icons{new Icons{}}, fonts{new Fonts{}} {
: KeyEventDispatcher{}, model{model}, icons{new Icons{}}, fonts{
new Fonts{}} {
SetPanelType(0);
SetOrientation(0);

Expand Down Expand Up @@ -72,6 +74,10 @@ Ui::Ui(std::shared_ptr<Model> model)
this->children.push_back(this->alerts_button);
this->children.push_back(status_bar);

// A forecast widget will be pushed back by select_forecast_widget()

this->register_key_event_consumer(menu_button);

this->swipe_detector.set_bounding_box(
this->hourly_forecast_box->get_bounding_box());
}
Expand Down Expand Up @@ -101,22 +107,6 @@ int Ui::handle_pointer_event(int event_type, int pointer_pos_x,
return 0;
}

int Ui::handle_key_pressed(int key) {
if (key == IV_KEY_HOME) {
const auto event_handler = GetEventHandler();
SendEvent(event_handler, EVT_EXIT, 0, 0);
return 1;
}

for (auto widget : this->children) {
const auto handled = widget->handle_key_pressed(key);
if (handled) {
return 1;
}
}
return 0;
}

void Ui::switch_forecast_widget() {
this->select_forecast_widget();
auto forecast_widget = this->get_forecast_widget();
Expand Down Expand Up @@ -159,9 +149,11 @@ void Ui::select_forecast_widget() {
: this->hourly_forecast_box;
if (this->children.back() == widget_to_hide) {
this->children.pop_back();
this->unregister_key_event_consumer(widget_to_hide);
}
if (this->children.back() != widget_to_display) {
this->children.push_back(widget_to_display);
this->register_key_event_consumer(widget_to_display);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "fonts.h"
#include "hourlyforecastbox.h"
#include "icons.h"
#include "keys.h"
#include "locationlist.h"
#include "model.h"
#include "swipe.h"
Expand All @@ -19,7 +20,7 @@ template <class T> using optional = std::experimental::optional<T>;

namespace taranis {

class Ui {
class Ui : public KeyEventDispatcher {
public:
// ⚠️ Must be instantiated after application received the EVT_INIT
// event otherwise opening fonts, etc. fails
Expand All @@ -31,8 +32,6 @@ class Ui {
int handle_pointer_event(int event_type, int pointer_pos_x,
int pointer_pos_y);

int handle_key_pressed(int key);

void display_alert() { this->alerts_button->open_dialog_maybe(); }

void switch_forecast_widget();
Expand Down
Loading

0 comments on commit 71d3673

Please sign in to comment.