From f9d209b21596e5aac09a7743385065803749f6a0 Mon Sep 17 00:00:00 2001 From: Star Rauchenberger Date: Thu, 6 Jun 2024 11:09:15 -0400 Subject: Subway: Click to activate scroll / sticky popup --- src/subway_map.cpp | 97 ++++++++++++++++++++++++++++++++++++++---------------- src/subway_map.h | 6 ++++ 2 files changed, 74 insertions(+), 29 deletions(-) diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 9175514..77f6ae6 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp @@ -53,6 +53,7 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { Bind(wxEVT_MOTION, &SubwayMap::OnMouseMove, this); Bind(wxEVT_MOUSEWHEEL, &SubwayMap::OnMouseScroll, this); Bind(wxEVT_LEAVE_WINDOW, &SubwayMap::OnMouseLeave, this); + Bind(wxEVT_LEFT_DOWN, &SubwayMap::OnMouseClick, this); Bind(wxEVT_TIMER, &SubwayMap::OnTimer, this); zoom_slider_ = new wxSlider(this, wxID_ANY, 0, 0, 8, {15, 15}); @@ -216,6 +217,8 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { } if (hovered_item_) { + // Note that these requirements are duplicated on OnMouseClick so that it + // knows when an item has a hover effect. const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); if (subway_item.door && !GetDoorRequirements(*subway_item.door).empty()) { const std::map &report = @@ -354,44 +357,22 @@ void SubwayMap::OnMouseMove(wxMouseEvent &event) { std::vector hovered = tree_->query( {static_cast(mouse_pos.x), static_cast(mouse_pos.y), 2, 2}); - std::optional new_hovered_item; if (!hovered.empty()) { - new_hovered_item = hovered[0]; + actual_hover_= hovered[0]; + } else { + actual_hover_ = std::nullopt; } - if (new_hovered_item != hovered_item_) { - hovered_item_ = new_hovered_item; + if (!sticky_hover_ && actual_hover_ != hovered_item_) { + hovered_item_ = actual_hover_; Refresh(); } - int scroll_x; - int scroll_y; - if (event.GetPosition().x < GetSize().GetWidth() / 9) { - scroll_x = 20; - } else if (event.GetPosition().x < GetSize().GetWidth() / 6) { - scroll_x = 5; - } else if (event.GetPosition().x > 8 * GetSize().GetWidth() / 9) { - scroll_x = -20; - } else if (event.GetPosition().x > 5 * GetSize().GetWidth() / 6) { - scroll_x = -5; - } else { - scroll_x = 0; - } - if (event.GetPosition().y < GetSize().GetHeight() / 9) { - scroll_y = 20; - } else if (event.GetPosition().y < GetSize().GetHeight() / 6) { - scroll_y = 5; - } else if (event.GetPosition().y > 8 * GetSize().GetHeight() / 9) { - scroll_y = -20; - } else if (event.GetPosition().y > 5 * GetSize().GetHeight() / 6) { - scroll_y = -5; - } else { - scroll_y = 0; + if (scroll_mode_) { + EvaluateScroll(event.GetPosition()); } - SetScrollSpeed(scroll_x, scroll_y); - mouse_position_ = event.GetPosition(); event.Skip(); @@ -417,6 +398,35 @@ void SubwayMap::OnMouseLeave(wxMouseEvent &event) { mouse_position_ = std::nullopt; } +void SubwayMap::OnMouseClick(wxMouseEvent &event) { + if (sticky_hover_) { + sticky_hover_ = false; + + if (actual_hover_ != hovered_item_) { + hovered_item_ = actual_hover_; + + Refresh(); + } + } else if (hovered_item_) { + const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); + if ((subway_item.door && !GetDoorRequirements(*subway_item.door).empty()) || + networks_.IsItemInNetwork(*hovered_item_)) { + sticky_hover_ = true; + } + } else if (scroll_mode_) { + scroll_mode_ = false; + + SetScrollSpeed(0, 0); + } else if (event.GetPosition().x < GetSize().GetWidth() / 6 || + event.GetPosition().x > 5 * GetSize().GetWidth() / 6 || + event.GetPosition().y < GetSize().GetHeight() / 6 || + event.GetPosition().y > 5 * GetSize().GetHeight() / 6) { + scroll_mode_ = true; + + EvaluateScroll(event.GetPosition()); + } +} + void SubwayMap::OnTimer(wxTimerEvent &event) { SetZoomPos({zoom_x_ + scroll_x_, zoom_y_ + scroll_y_}); Refresh(); @@ -504,6 +514,35 @@ void SubwayMap::Redraw() { } } +void SubwayMap::EvaluateScroll(wxPoint pos) { + int scroll_x; + int scroll_y; + if (pos.x < GetSize().GetWidth() / 9) { + scroll_x = 20; + } else if (pos.x < GetSize().GetWidth() / 6) { + scroll_x = 5; + } else if (pos.x > 8 * GetSize().GetWidth() / 9) { + scroll_x = -20; + } else if (pos.x > 5 * GetSize().GetWidth() / 6) { + scroll_x = -5; + } else { + scroll_x = 0; + } + if (pos.y < GetSize().GetHeight() / 9) { + scroll_y = 20; + } else if (pos.y < GetSize().GetHeight() / 6) { + scroll_y = 5; + } else if (pos.y > 8 * GetSize().GetHeight() / 9) { + scroll_y = -20; + } else if (pos.y > 5 * GetSize().GetHeight() / 6) { + scroll_y = -5; + } else { + scroll_y = 0; + } + + SetScrollSpeed(scroll_x, scroll_y); +} + wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { return {static_cast(pos.x * render_width_ * zoom_ / map_image_.GetSize().GetWidth() + diff --git a/src/subway_map.h b/src/subway_map.h index 986998a..8b8c6a6 100644 --- a/src/subway_map.h +++ b/src/subway_map.h @@ -32,6 +32,7 @@ class SubwayMap : public wxPanel { void OnMouseMove(wxMouseEvent &event); void OnMouseScroll(wxMouseEvent &event); void OnMouseLeave(wxMouseEvent &event); + void OnMouseClick(wxMouseEvent &event); void OnTimer(wxTimerEvent &event); void OnZoomSlide(wxCommandEvent &event); @@ -41,6 +42,8 @@ class SubwayMap : public wxPanel { wxPoint MapPosToVirtualPos(wxPoint pos) const; wxPoint RenderPosToMapPos(wxPoint pos) const; + void EvaluateScroll(wxPoint pos); + void SetZoomPos(wxPoint pos); void SetScrollSpeed(int scroll_x, int scroll_y); void SetZoom(double zoom, wxPoint static_point); @@ -60,6 +63,7 @@ class SubwayMap : public wxPanel { int zoom_x_ = 0; // in render space int zoom_y_ = 0; + bool scroll_mode_ = false; wxTimer* scroll_timer_; int scroll_x_ = 0; int scroll_y_ = 0; @@ -74,6 +78,8 @@ class SubwayMap : public wxPanel { std::unique_ptr> tree_; std::optional hovered_item_; + std::optional actual_hover_; + bool sticky_hover_ = false; NetworkSet networks_; std::set checked_paintings_; -- cgit 1.4.1