Skip to content

Commit

Permalink
Support for modal widgets
Browse files Browse the repository at this point in the history
Refs: #66
  • Loading branch information
orontee committed Nov 8, 2023
1 parent b17d580 commit d27bbdf
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 11 deletions.
10 changes: 9 additions & 1 deletion src/keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,15 @@ struct KeyEventDispatcher {
std::shared_ptr<KeyEventConsumer> event_consumer{nullptr};
if (event_type == EVT_KEYPRESS) {
for (auto consumer : this->consumers) {
if (not this->is_consumer_active(consumer)) {
continue;
}
if (consumer->handle_key_press(key)) {
event_consumer = consumer;
}
}
} else if (this->last_event_consumer) {
} else if (this->last_event_consumer and
this->is_consumer_active(this->last_event_consumer)) {
if (event_type == EVT_KEYREPEAT) {
if (this->last_event_consumer->handle_key_repeat(key)) {
event_consumer = this->last_event_consumer;
Expand Down Expand Up @@ -80,6 +84,10 @@ struct KeyEventDispatcher {
}
}

virtual bool is_consumer_active(std::shared_ptr<KeyEventConsumer> consumer) {
return true;
}

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

Expand Down
56 changes: 46 additions & 10 deletions src/ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,34 @@ Ui::Ui(std::shared_ptr<Model> model)
void Ui::paint() {
ClearScreen();

this->select_forecast_widget();
this->check_modal_visibility();

if (this->visible_modal) {
this->visible_modal->paint();
} else {
this->select_forecast_widget();

for (auto widget : this->children) {
widget->paint();
for (auto widget : this->children) {
widget->paint();
}
}
FullUpdate();
}

int Ui::handle_pointer_event(int event_type, int pointer_pos_x,
int pointer_pos_y) {
if (this->handle_possible_swipe(event_type, pointer_pos_x, pointer_pos_y)) {
return 1;
}
for (auto widget : this->children) {
if (Ui::is_on_widget(pointer_pos_x, pointer_pos_y, widget)) {
return widget->handle_pointer_event(event_type, pointer_pos_x,
pointer_pos_y);
if (this->visible_modal) {
return this->visible_modal->handle_pointer_event(event_type, pointer_pos_x,
pointer_pos_y);
} else {
if (this->handle_possible_swipe(event_type, pointer_pos_x, pointer_pos_y)) {
return 1;
}
for (auto widget : this->children) {
if (Ui::is_on_widget(pointer_pos_x, pointer_pos_y, widget)) {
return widget->handle_pointer_event(event_type, pointer_pos_x,
pointer_pos_y);
}
}
}
return 0;
Expand All @@ -125,6 +136,11 @@ Ui::get_location_from_location_list(size_t index) const {
return this->location_selector->get_location(index);
}

bool Ui::is_consumer_active(std::shared_ptr<KeyEventConsumer> consumer) {
return ((consumer == this->visible_modal) or not this->visible_modal);
// modals expected to register / unregister on visibility change
}

bool Ui::is_on_widget(int pointer_pos_x, int pointer_pos_y,
std::shared_ptr<Widget> widget) {
if (not widget)
Expand All @@ -133,6 +149,26 @@ bool Ui::is_on_widget(int pointer_pos_x, int pointer_pos_y,
return widget->is_in_bouding_box(pointer_pos_x, pointer_pos_y);
}

void Ui::check_modal_visibility() {
const auto found_visible_modal =
std::find_if(this->modals.begin(), this->modals.end(),
[](const auto &modal) { return modal->is_visible(); });

if (found_visible_modal != this->modals.end()) {
if (this->visible_modal != *found_visible_modal) {
BOOST_LOG_TRIVIAL(debug) << "Found visible modal";
this->visible_modal = *found_visible_modal;
this->register_key_event_consumer(this->visible_modal);
}
} else {
if (this->visible_modal) {
BOOST_LOG_TRIVIAL(debug) << "Modal hidden";
this->unregister_key_event_consumer(this->visible_modal);
this->visible_modal = nullptr;
}
}
}

std::shared_ptr<Widget> Ui::get_forecast_widget() const {
auto forecast_widget = this->model->display_daily_forecast
? this->daily_forecast_box
Expand Down
10 changes: 10 additions & 0 deletions src/ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class Ui : public KeyEventDispatcher {

Ui(std::shared_ptr<Model> model);

virtual ~Ui() {}

void paint();

int handle_pointer_event(int event_type, int pointer_pos_x,
Expand All @@ -40,6 +42,9 @@ class Ui : public KeyEventDispatcher {

std::optional<Location> get_location_from_location_list(size_t index) const;

protected:
bool is_consumer_active(std::shared_ptr<KeyEventConsumer> consumer) override;

private:
std::shared_ptr<Model> model;
std::shared_ptr<Icons> icons;
Expand All @@ -55,13 +60,18 @@ class Ui : public KeyEventDispatcher {
std::shared_ptr<LocationSelector> location_selector;

std::vector<std::shared_ptr<Widget>> children;
std::vector<std::shared_ptr<Widget>> modals;

std::shared_ptr<Widget> visible_modal{nullptr};

const int alert_icon_size = 150;
const int button_margin = 25;

static bool is_on_widget(int pointer_pos_x, int pointer_pos_y,
std::shared_ptr<Widget> widget);

void check_modal_visibility();

std::shared_ptr<Widget> get_forecast_widget() const;

void select_forecast_widget();
Expand Down
4 changes: 4 additions & 0 deletions src/widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ struct Widget : public KeyEventConsumer {

int get_height() const { return this->bounding_box.h; }

virtual bool is_modal() const { return false; }
// a modal widget takes control of the screen, and receives all
// keys and pointers events

virtual bool is_visible() const { return true; }

virtual void paint() {
Expand Down

0 comments on commit d27bbdf

Please sign in to comment.