diff options
author | Star Rauchenberger <fefferburbia@gmail.com> | 2025-02-08 15:11:23 -0500 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2025-02-08 15:11:23 -0500 |
commit | 712313d825db7ce7c9d4457f7564b27d3dd4ce64 (patch) | |
tree | a4fa488b66b19a825bebd8dfea8cdf97d2e9452b /src | |
parent | 9b8570921477e374f53fa9df183f1776cf345f73 (diff) | |
download | lingo-ap-tracker-712313d825db7ce7c9d4457f7564b27d3dd4ce64.tar.gz lingo-ap-tracker-712313d825db7ce7c9d4457f7564b27d3dd4ce64.tar.bz2 lingo-ap-tracker-712313d825db7ce7c9d4457f7564b27d3dd4ce64.zip |
Added a scrollbar to subway reports
Diffstat (limited to 'src')
-rw-r--r-- | src/report_popup.cpp | 98 | ||||
-rw-r--r-- | src/report_popup.h | 30 | ||||
-rw-r--r-- | src/subway_map.cpp | 127 | ||||
-rw-r--r-- | src/subway_map.h | 7 |
4 files changed, 185 insertions, 77 deletions
diff --git a/src/report_popup.cpp b/src/report_popup.cpp new file mode 100644 index 0000000..d772b32 --- /dev/null +++ b/src/report_popup.cpp | |||
@@ -0,0 +1,98 @@ | |||
1 | #include "report_popup.h" | ||
2 | |||
3 | #include <wx/dcbuffer.h> | ||
4 | |||
5 | #include <map> | ||
6 | #include <string> | ||
7 | |||
8 | #include "global.h" | ||
9 | #include "tracker_state.h" | ||
10 | |||
11 | ReportPopup::ReportPopup(wxWindow* parent) | ||
12 | : wxScrolledCanvas(parent, wxID_ANY) { | ||
13 | SetBackgroundStyle(wxBG_STYLE_PAINT); | ||
14 | |||
15 | unchecked_eye_ = | ||
16 | wxBitmap(wxImage(GetAbsolutePath("assets/unchecked.png").c_str(), | ||
17 | wxBITMAP_TYPE_PNG) | ||
18 | .Scale(32, 32)); | ||
19 | checked_eye_ = wxBitmap( | ||
20 | wxImage(GetAbsolutePath("assets/checked.png").c_str(), wxBITMAP_TYPE_PNG) | ||
21 | .Scale(32, 32)); | ||
22 | |||
23 | SetScrollRate(5, 5); | ||
24 | |||
25 | SetBackgroundColour(*wxBLACK); | ||
26 | Hide(); | ||
27 | |||
28 | Bind(wxEVT_PAINT, &ReportPopup::OnPaint, this); | ||
29 | } | ||
30 | |||
31 | void ReportPopup::SetDoorId(int door_id) { | ||
32 | door_id_ = door_id; | ||
33 | |||
34 | UpdateIndicators(); | ||
35 | } | ||
36 | |||
37 | void ReportPopup::Reset() { | ||
38 | door_id_ = -1; | ||
39 | } | ||
40 | |||
41 | void ReportPopup::UpdateIndicators() { | ||
42 | wxMemoryDC mem_dc; | ||
43 | |||
44 | const std::map<std::string, bool>& report = GetDoorRequirements(door_id_); | ||
45 | |||
46 | int acc_height = 10; | ||
47 | int col_width = 0; | ||
48 | |||
49 | for (const auto& [text, obtained] : report) { | ||
50 | wxSize item_extent = mem_dc.GetTextExtent(text); | ||
51 | int item_height = std::max(32, item_extent.GetHeight()) + 10; | ||
52 | acc_height += item_height; | ||
53 | |||
54 | if (item_extent.GetWidth() > col_width) { | ||
55 | col_width = item_extent.GetWidth(); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | int item_width = col_width + 10 + 32; | ||
60 | int full_width = item_width + 20; | ||
61 | |||
62 | Fit(); | ||
63 | SetVirtualSize(full_width, acc_height); | ||
64 | |||
65 | rendered_ = wxBitmap(full_width, acc_height); | ||
66 | mem_dc.SelectObject(rendered_); | ||
67 | mem_dc.SetPen(*wxTRANSPARENT_PEN); | ||
68 | mem_dc.SetBrush(*wxBLACK_BRUSH); | ||
69 | mem_dc.DrawRectangle({0, 0}, {full_width, acc_height}); | ||
70 | |||
71 | mem_dc.SetFont(GetFont()); | ||
72 | |||
73 | int cur_height = 10; | ||
74 | |||
75 | for (const auto& [text, obtained] : report) { | ||
76 | wxBitmap* eye_ptr = obtained ? &checked_eye_ : &unchecked_eye_; | ||
77 | |||
78 | mem_dc.DrawBitmap(*eye_ptr, wxPoint{10, cur_height}); | ||
79 | |||
80 | mem_dc.SetTextForeground(obtained ? *wxWHITE : *wxRED); | ||
81 | wxSize item_extent = mem_dc.GetTextExtent(text); | ||
82 | mem_dc.DrawText( | ||
83 | text, wxPoint{10 + 32 + 10, | ||
84 | cur_height + (32 - mem_dc.GetFontMetrics().height) / 2}); | ||
85 | |||
86 | cur_height += 10 + 32; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | void ReportPopup::OnPaint(wxPaintEvent& event) { | ||
91 | if (door_id_ != -1) { | ||
92 | wxBufferedPaintDC dc(this); | ||
93 | PrepareDC(dc); | ||
94 | dc.DrawBitmap(rendered_, 0, 0); | ||
95 | } | ||
96 | |||
97 | event.Skip(); | ||
98 | } | ||
diff --git a/src/report_popup.h b/src/report_popup.h new file mode 100644 index 0000000..9e141bf --- /dev/null +++ b/src/report_popup.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #ifndef REPORT_POPUP_H_E065BED4 | ||
2 | #define REPORT_POPUP_H_E065BED4 | ||
3 | |||
4 | #include <wx/wxprec.h> | ||
5 | |||
6 | #ifndef WX_PRECOMP | ||
7 | #include <wx/wx.h> | ||
8 | #endif | ||
9 | |||
10 | class ReportPopup : public wxScrolledCanvas { | ||
11 | public: | ||
12 | explicit ReportPopup(wxWindow* parent); | ||
13 | |||
14 | void SetDoorId(int door_id); | ||
15 | |||
16 | void Reset(); | ||
17 | |||
18 | void UpdateIndicators(); | ||
19 | |||
20 | private: | ||
21 | void OnPaint(wxPaintEvent& event); | ||
22 | |||
23 | int door_id_ = -1; | ||
24 | |||
25 | wxBitmap unchecked_eye_; | ||
26 | wxBitmap checked_eye_; | ||
27 | wxBitmap rendered_; | ||
28 | }; | ||
29 | |||
30 | #endif /* end of include guard: REPORT_POPUP_H_E065BED4 */ | ||
diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 0a250fb..c554b16 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp | |||
@@ -9,6 +9,7 @@ | |||
9 | #include "ap_state.h" | 9 | #include "ap_state.h" |
10 | #include "game_data.h" | 10 | #include "game_data.h" |
11 | #include "global.h" | 11 | #include "global.h" |
12 | #include "report_popup.h" | ||
12 | #include "tracker_state.h" | 13 | #include "tracker_state.h" |
13 | 14 | ||
14 | constexpr int AREA_ACTUAL_SIZE = 21; | 15 | constexpr int AREA_ACTUAL_SIZE = 21; |
@@ -31,14 +32,6 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
31 | return; | 32 | return; |
32 | } | 33 | } |
33 | 34 | ||
34 | unchecked_eye_ = | ||
35 | wxBitmap(wxImage(GetAbsolutePath("assets/unchecked.png").c_str(), | ||
36 | wxBITMAP_TYPE_PNG) | ||
37 | .Scale(32, 32)); | ||
38 | checked_eye_ = wxBitmap( | ||
39 | wxImage(GetAbsolutePath("assets/checked.png").c_str(), wxBITMAP_TYPE_PNG) | ||
40 | .Scale(32, 32)); | ||
41 | |||
42 | tree_ = std::make_unique<quadtree::Quadtree<int, GetItemBox>>( | 35 | tree_ = std::make_unique<quadtree::Quadtree<int, GetItemBox>>( |
43 | quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()), | 36 | quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()), |
44 | static_cast<float>(map_image_.GetHeight())}); | 37 | static_cast<float>(map_image_.GetHeight())}); |
@@ -63,6 +56,8 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
63 | help_button_ = new wxButton(this, wxID_ANY, "Help"); | 56 | help_button_ = new wxButton(this, wxID_ANY, "Help"); |
64 | help_button_->Bind(wxEVT_BUTTON, &SubwayMap::OnClickHelp, this); | 57 | help_button_->Bind(wxEVT_BUTTON, &SubwayMap::OnClickHelp, this); |
65 | SetUpHelpButton(); | 58 | SetUpHelpButton(); |
59 | |||
60 | report_popup_ = new ReportPopup(this); | ||
66 | } | 61 | } |
67 | 62 | ||
68 | void SubwayMap::OnConnect() { | 63 | void SubwayMap::OnConnect() { |
@@ -202,6 +197,8 @@ void SubwayMap::UpdateIndicators() { | |||
202 | } | 197 | } |
203 | } | 198 | } |
204 | 199 | ||
200 | report_popup_->UpdateIndicators(); | ||
201 | |||
205 | Redraw(); | 202 | Redraw(); |
206 | } | 203 | } |
207 | 204 | ||
@@ -310,67 +307,6 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
310 | } | 307 | } |
311 | 308 | ||
312 | if (hovered_item_) { | 309 | if (hovered_item_) { |
313 | // Note that these requirements are duplicated on OnMouseClick so that it | ||
314 | // knows when an item has a hover effect. | ||
315 | const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); | ||
316 | std::optional<int> subway_door = GetRealSubwayDoor(subway_item); | ||
317 | |||
318 | if (subway_door && !GetDoorRequirements(*subway_door).empty()) { | ||
319 | const std::map<std::string, bool> &report = | ||
320 | GetDoorRequirements(*subway_door); | ||
321 | |||
322 | int acc_height = 10; | ||
323 | int col_width = 0; | ||
324 | |||
325 | for (const auto &[text, obtained] : report) { | ||
326 | wxSize item_extent = dc.GetTextExtent(text); | ||
327 | int item_height = std::max(32, item_extent.GetHeight()) + 10; | ||
328 | acc_height += item_height; | ||
329 | |||
330 | if (item_extent.GetWidth() > col_width) { | ||
331 | col_width = item_extent.GetWidth(); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | int item_width = col_width + 10 + 32; | ||
336 | int full_width = item_width + 20; | ||
337 | |||
338 | wxPoint popup_pos = | ||
339 | MapPosToRenderPos({subway_item.x + AREA_ACTUAL_SIZE / 2, | ||
340 | subway_item.y + AREA_ACTUAL_SIZE / 2}); | ||
341 | |||
342 | if (popup_pos.x + full_width > GetSize().GetWidth()) { | ||
343 | popup_pos.x = GetSize().GetWidth() - full_width; | ||
344 | } | ||
345 | if (popup_pos.y + acc_height > GetSize().GetHeight()) { | ||
346 | popup_pos.y = GetSize().GetHeight() - acc_height; | ||
347 | } | ||
348 | |||
349 | dc.SetPen(*wxTRANSPARENT_PEN); | ||
350 | dc.SetBrush(*wxBLACK_BRUSH); | ||
351 | dc.DrawRectangle(popup_pos, {full_width, acc_height}); | ||
352 | |||
353 | dc.SetFont(GetFont()); | ||
354 | |||
355 | int cur_height = 10; | ||
356 | |||
357 | for (const auto &[text, obtained] : report) { | ||
358 | wxBitmap *eye_ptr = obtained ? &checked_eye_ : &unchecked_eye_; | ||
359 | |||
360 | dc.DrawBitmap(*eye_ptr, popup_pos + wxPoint{10, cur_height}); | ||
361 | |||
362 | dc.SetTextForeground(obtained ? *wxWHITE : *wxRED); | ||
363 | wxSize item_extent = dc.GetTextExtent(text); | ||
364 | dc.DrawText( | ||
365 | text, | ||
366 | popup_pos + | ||
367 | wxPoint{10 + 32 + 10, | ||
368 | cur_height + (32 - dc.GetFontMetrics().height) / 2}); | ||
369 | |||
370 | cur_height += 10 + 32; | ||
371 | } | ||
372 | } | ||
373 | |||
374 | if (networks_.IsItemInNetwork(*hovered_item_)) { | 310 | if (networks_.IsItemInNetwork(*hovered_item_)) { |
375 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | 311 | dc.SetBrush(*wxTRANSPARENT_BRUSH); |
376 | 312 | ||
@@ -470,9 +406,7 @@ void SubwayMap::OnMouseMove(wxMouseEvent &event) { | |||
470 | } | 406 | } |
471 | 407 | ||
472 | if (!sticky_hover_ && actual_hover_ != hovered_item_) { | 408 | if (!sticky_hover_ && actual_hover_ != hovered_item_) { |
473 | hovered_item_ = actual_hover_; | 409 | EvaluateHover(); |
474 | |||
475 | Refresh(); | ||
476 | } | 410 | } |
477 | 411 | ||
478 | if (scroll_mode_) { | 412 | if (scroll_mode_) { |
@@ -514,13 +448,11 @@ void SubwayMap::OnMouseClick(wxMouseEvent &event) { | |||
514 | if ((subway_door && !GetDoorRequirements(*subway_door).empty()) || | 448 | if ((subway_door && !GetDoorRequirements(*subway_door).empty()) || |
515 | networks_.IsItemInNetwork(*hovered_item_)) { | 449 | networks_.IsItemInNetwork(*hovered_item_)) { |
516 | if (actual_hover_ != hovered_item_) { | 450 | if (actual_hover_ != hovered_item_) { |
517 | hovered_item_ = actual_hover_; | 451 | EvaluateHover(); |
518 | 452 | ||
519 | if (!hovered_item_) { | 453 | if (!hovered_item_) { |
520 | sticky_hover_ = false; | 454 | sticky_hover_ = false; |
521 | } | 455 | } |
522 | |||
523 | Refresh(); | ||
524 | } else { | 456 | } else { |
525 | sticky_hover_ = !sticky_hover_; | 457 | sticky_hover_ = !sticky_hover_; |
526 | } | 458 | } |
@@ -723,6 +655,51 @@ void SubwayMap::EvaluateScroll(wxPoint pos) { | |||
723 | SetScrollSpeed(scroll_x, scroll_y); | 655 | SetScrollSpeed(scroll_x, scroll_y); |
724 | } | 656 | } |
725 | 657 | ||
658 | void SubwayMap::EvaluateHover() { | ||
659 | hovered_item_ = actual_hover_; | ||
660 | |||
661 | if (hovered_item_) { | ||
662 | // Note that these requirements are duplicated on OnMouseClick so that it | ||
663 | // knows when an item has a hover effect. | ||
664 | const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); | ||
665 | std::optional<int> subway_door = GetRealSubwayDoor(subway_item); | ||
666 | |||
667 | if (subway_door && !GetDoorRequirements(*subway_door).empty()) { | ||
668 | report_popup_->SetDoorId(*subway_door); | ||
669 | |||
670 | wxPoint popupPos = | ||
671 | MapPosToRenderPos({subway_item.x + AREA_ACTUAL_SIZE / 2, | ||
672 | subway_item.y + AREA_ACTUAL_SIZE / 2}); | ||
673 | |||
674 | report_popup_->SetClientSize( | ||
675 | report_popup_->GetVirtualSize().GetWidth(), | ||
676 | std::min(GetSize().GetHeight(), | ||
677 | report_popup_->GetVirtualSize().GetHeight())); | ||
678 | |||
679 | if (popupPos.x + report_popup_->GetSize().GetWidth() > | ||
680 | GetSize().GetWidth()) { | ||
681 | popupPos.x = GetSize().GetWidth() - report_popup_->GetSize().GetWidth(); | ||
682 | } | ||
683 | if (popupPos.y + report_popup_->GetSize().GetHeight() > | ||
684 | GetSize().GetHeight()) { | ||
685 | popupPos.y = | ||
686 | GetSize().GetHeight() - report_popup_->GetSize().GetHeight(); | ||
687 | } | ||
688 | report_popup_->SetPosition(popupPos); | ||
689 | |||
690 | report_popup_->Show(); | ||
691 | } else { | ||
692 | report_popup_->Reset(); | ||
693 | report_popup_->Hide(); | ||
694 | } | ||
695 | } else { | ||
696 | report_popup_->Reset(); | ||
697 | report_popup_->Hide(); | ||
698 | } | ||
699 | |||
700 | Refresh(); | ||
701 | } | ||
702 | |||
726 | wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { | 703 | wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { |
727 | return {static_cast<int>(pos.x * render_width_ * zoom_ / | 704 | return {static_cast<int>(pos.x * render_width_ * zoom_ / |
728 | map_image_.GetSize().GetWidth() + | 705 | map_image_.GetSize().GetWidth() + |
diff --git a/src/subway_map.h b/src/subway_map.h index 6aa31f5..b04c2fd 100644 --- a/src/subway_map.h +++ b/src/subway_map.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #include "game_data.h" | 19 | #include "game_data.h" |
20 | #include "network_set.h" | 20 | #include "network_set.h" |
21 | 21 | ||
22 | class ReportPopup; | ||
23 | |||
22 | class SubwayMap : public wxPanel { | 24 | class SubwayMap : public wxPanel { |
23 | public: | 25 | public: |
24 | SubwayMap(wxWindow *parent); | 26 | SubwayMap(wxWindow *parent); |
@@ -46,6 +48,7 @@ class SubwayMap : public wxPanel { | |||
46 | wxPoint RenderPosToMapPos(wxPoint pos) const; | 48 | wxPoint RenderPosToMapPos(wxPoint pos) const; |
47 | 49 | ||
48 | void EvaluateScroll(wxPoint pos); | 50 | void EvaluateScroll(wxPoint pos); |
51 | void EvaluateHover(); | ||
49 | 52 | ||
50 | void SetZoomPos(wxPoint pos); | 53 | void SetZoomPos(wxPoint pos); |
51 | void SetScrollSpeed(int scroll_x, int scroll_y); | 54 | void SetScrollSpeed(int scroll_x, int scroll_y); |
@@ -55,8 +58,6 @@ class SubwayMap : public wxPanel { | |||
55 | 58 | ||
56 | wxImage map_image_; | 59 | wxImage map_image_; |
57 | wxImage owl_image_; | 60 | wxImage owl_image_; |
58 | wxBitmap unchecked_eye_; | ||
59 | wxBitmap checked_eye_; | ||
60 | 61 | ||
61 | wxBitmap rendered_; | 62 | wxBitmap rendered_; |
62 | int render_x_ = 0; | 63 | int render_x_ = 0; |
@@ -88,6 +89,8 @@ class SubwayMap : public wxPanel { | |||
88 | std::optional<int> actual_hover_; | 89 | std::optional<int> actual_hover_; |
89 | bool sticky_hover_ = false; | 90 | bool sticky_hover_ = false; |
90 | 91 | ||
92 | ReportPopup *report_popup_; | ||
93 | |||
91 | NetworkSet networks_; | 94 | NetworkSet networks_; |
92 | std::set<std::string> checked_paintings_; | 95 | std::set<std::string> checked_paintings_; |
93 | 96 | ||