about summary refs log tree commit diff stats
path: root/src/area_popup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/area_popup.cpp')
-rw-r--r--src/area_popup.cpp188
1 files changed, 135 insertions, 53 deletions
diff --git a/src/area_popup.cpp b/src/area_popup.cpp index 6e70315..c95e492 100644 --- a/src/area_popup.cpp +++ b/src/area_popup.cpp
@@ -2,62 +2,68 @@
2 2
3#include <wx/dcbuffer.h> 3#include <wx/dcbuffer.h>
4 4
5#include <algorithm>
6
5#include "ap_state.h" 7#include "ap_state.h"
6#include "game_data.h" 8#include "game_data.h"
7#include "global.h" 9#include "global.h"
10#include "icons.h"
8#include "tracker_config.h" 11#include "tracker_config.h"
12#include "tracker_panel.h"
9#include "tracker_state.h" 13#include "tracker_state.h"
10 14
11AreaPopup::AreaPopup(wxWindow* parent, int area_id) 15AreaPopup::AreaPopup(wxWindow* parent, int area_id)
12 : wxScrolledCanvas(parent, wxID_ANY), area_id_(area_id) { 16 : wxScrolledCanvas(parent, wxID_ANY), area_id_(area_id) {
13 SetBackgroundStyle(wxBG_STYLE_PAINT); 17 SetBackgroundStyle(wxBG_STYLE_PAINT);
14 18
15 unchecked_eye_ = 19 LoadIcons();
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 20
21 // TODO: This is slow on high-DPI screens.
23 SetScrollRate(5, 5); 22 SetScrollRate(5, 5);
24 23
25 SetBackgroundColour(*wxBLACK); 24 SetBackgroundColour(*wxBLACK);
26 Hide(); 25 Hide();
27 26
28 Bind(wxEVT_PAINT, &AreaPopup::OnPaint, this); 27 Bind(wxEVT_PAINT, &AreaPopup::OnPaint, this);
28 Bind(wxEVT_DPI_CHANGED, &AreaPopup::OnDPIChanged, this);
29 29
30 UpdateIndicators(); 30 ResetIndicators();
31} 31}
32 32
33void AreaPopup::UpdateIndicators() { 33void AreaPopup::ResetIndicators() {
34 indicators_.clear();
35
34 const MapArea& map_area = GD_GetMapArea(area_id_); 36 const MapArea& map_area = GD_GetMapArea(area_id_);
37 wxFont the_font = GetFont().Scale(GetDPIScaleFactor());
38 TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent());
35 39
36 // Start calculating extents. 40 // Start calculating extents.
37 wxMemoryDC mem_dc; 41 wxMemoryDC mem_dc;
38 mem_dc.SetFont(GetFont().Bold()); 42 mem_dc.SetFont(the_font.Bold());
39 wxSize header_extent = mem_dc.GetTextExtent(map_area.name); 43 header_extent_ = mem_dc.GetTextExtent(map_area.name);
40 44
41 int acc_height = header_extent.GetHeight() + 20; 45 int acc_height = header_extent_.GetHeight() + FromDIP(20);
42 int col_width = 0; 46 int col_width = 0;
43 47
44 mem_dc.SetFont(GetFont()); 48 mem_dc.SetFont(the_font);
45
46 std::vector<int> real_locations;
47 49
48 for (int section_id = 0; section_id < map_area.locations.size(); 50 for (int section_id = 0; section_id < map_area.locations.size();
49 section_id++) { 51 section_id++) {
50 const Location& location = map_area.locations.at(section_id); 52 const Location& location = map_area.locations.at(section_id);
51 53 if ((!AP_IsLocationVisible(location.classification) ||
52 if (!AP_IsLocationVisible(location.classification) && 54 IsLocationPostgame(location.ap_location_id)) &&
53 !(location.hunt && GetTrackerConfig().show_hunt_panels)) { 55 !(location.hunt &&
56 GetTrackerConfig().visible_panels == TrackerConfig::kHUNT_PANELS) &&
57 !(location.single_panel &&
58 GetTrackerConfig().visible_panels == TrackerConfig::kALL_PANELS)) {
54 continue; 59 continue;
55 } 60 }
56 61
57 real_locations.push_back(section_id); 62 indicators_.emplace_back(section_id, kLOCATION, acc_height);
58 63
59 wxSize item_extent = mem_dc.GetTextExtent(location.name); 64 wxSize item_extent = mem_dc.GetTextExtent(location.name);
60 int item_height = std::max(32, item_extent.GetHeight()) + 10; 65 int item_height =
66 std::max(FromDIP(32), item_extent.GetHeight()) + FromDIP(10);
61 acc_height += item_height; 67 acc_height += item_height;
62 68
63 if (item_extent.GetWidth() > col_width) { 69 if (item_extent.GetWidth() > col_width) {
@@ -65,49 +71,107 @@ void AreaPopup::UpdateIndicators() {
65 } 71 }
66 } 72 }
67 73
68 int item_width = col_width + 10 + 32; 74 if (AP_IsPaintingShuffle()) {
69 int full_width = std::max(header_extent.GetWidth(), item_width) + 20; 75 for (int painting_id : map_area.paintings) {
70 76 if (IsPaintingPostgame(painting_id)) {
71 Fit(); 77 continue;
72 SetVirtualSize(full_width, acc_height); 78 }
73
74 rendered_ = wxBitmap(full_width, acc_height);
75 mem_dc.SelectObject(rendered_);
76 mem_dc.SetPen(*wxTRANSPARENT_PEN);
77 mem_dc.SetBrush(*wxBLACK_BRUSH);
78 mem_dc.DrawRectangle({0, 0}, {full_width, acc_height});
79 79
80 mem_dc.SetFont(GetFont().Bold()); 80 indicators_.emplace_back(painting_id, kPAINTING, acc_height);
81 mem_dc.SetTextForeground(*wxWHITE);
82 mem_dc.DrawText(map_area.name,
83 {(full_width - header_extent.GetWidth()) / 2, 10});
84 81
85 int cur_height = header_extent.GetHeight() + 20; 82 const PaintingExit& painting = GD_GetPaintingExit(painting_id);
83 wxSize item_extent = mem_dc.GetTextExtent(painting.display_name);
84 int item_height =
85 std::max(FromDIP(32), item_extent.GetHeight()) + FromDIP(10);
86 acc_height += item_height;
86 87
87 mem_dc.SetFont(GetFont()); 88 if (item_extent.GetWidth() > col_width) {
89 col_width = item_extent.GetWidth();
90 }
91 }
92 }
88 93
89 for (int section_id : real_locations) { 94 int item_width = col_width + FromDIP(10 + 32);
90 const Location& location = map_area.locations.at(section_id); 95 full_width_ = std::max(header_extent_.GetWidth(), item_width) + FromDIP(20);
96 full_height_ = acc_height;
91 97
92 bool checked = 98 Fit();
93 AP_HasCheckedGameLocation(location.ap_location_id) || 99 SetVirtualSize(full_width_, full_height_);
94 (location.hunt && AP_HasCheckedHuntPanel(location.ap_location_id)) ||
95 (IsLocationWinCondition(location) && AP_HasReachedGoal());
96 100
97 wxBitmap* eye_ptr = checked ? &checked_eye_ : &unchecked_eye_; 101 UpdateIndicators();
102}
98 103
99 mem_dc.DrawBitmap(*eye_ptr, {10, cur_height}); 104void AreaPopup::UpdateIndicators() {
105 const MapArea& map_area = GD_GetMapArea(area_id_);
106 wxFont the_font = GetFont().Scale(GetDPIScaleFactor());
107 TrackerPanel* tracker_panel = dynamic_cast<TrackerPanel*>(GetParent());
100 108
101 bool reachable = IsLocationReachable(location.ap_location_id); 109 rendered_ = wxBitmap(full_width_, full_height_);
102 const wxColour* text_color = reachable ? wxWHITE : wxRED;
103 mem_dc.SetTextForeground(*text_color);
104 110
105 wxSize item_extent = mem_dc.GetTextExtent(location.name); 111 wxMemoryDC mem_dc;
106 mem_dc.DrawText( 112 mem_dc.SelectObject(rendered_);
107 location.name, 113 mem_dc.SetPen(*wxTRANSPARENT_PEN);
108 {10 + 32 + 10, cur_height + (32 - mem_dc.GetFontMetrics().height) / 2}); 114 mem_dc.SetBrush(*wxBLACK_BRUSH);
115 mem_dc.DrawRectangle({0, 0}, {full_width_, full_height_});
109 116
110 cur_height += 10 + 32; 117 mem_dc.SetFont(the_font.Bold());
118 mem_dc.SetTextForeground(*wxWHITE);
119 mem_dc.DrawText(map_area.name,
120 {(full_width_ - header_extent_.GetWidth()) / 2, FromDIP(10)});
121
122 mem_dc.SetFont(the_font);
123
124 for (const IndicatorInfo& indicator : indicators_) {
125 switch (indicator.type) {
126 case kLOCATION: {
127 const Location& location = map_area.locations.at(indicator.id);
128
129 bool checked = false;
130 if (IsLocationWinCondition(location)) {
131 checked = AP_HasReachedGoal();
132 } else {
133 checked = AP_HasCheckedGameLocation(location.ap_location_id) ||
134 (location.single_panel &&
135 AP_IsPanelSolved(
136 GD_GetPanel(*location.single_panel).solve_index));
137 }
138
139 const wxBitmap* eye_ptr = checked ? checked_eye_ : unchecked_eye_;
140
141 mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), indicator.y});
142
143 bool reachable = IsLocationReachable(location.ap_location_id);
144 const wxColour* text_color = reachable ? wxWHITE : wxRED;
145 mem_dc.SetTextForeground(*text_color);
146
147 wxSize item_extent = mem_dc.GetTextExtent(location.name);
148 mem_dc.DrawText(
149 location.name,
150 {FromDIP(10 + 32 + 10),
151 indicator.y + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2});
152
153 break;
154 }
155 case kPAINTING: {
156 const PaintingExit& painting = GD_GetPaintingExit(indicator.id);
157
158 bool reachable = IsPaintingReachable(indicator.id);
159 const wxColour* text_color = reachable ? wxWHITE : wxRED;
160 mem_dc.SetTextForeground(*text_color);
161
162 bool checked = reachable && AP_IsPaintingChecked(painting.internal_id);
163 const wxBitmap* eye_ptr = checked ? checked_owl_ : unchecked_owl_;
164 mem_dc.DrawBitmap(*eye_ptr, {FromDIP(10), indicator.y});
165
166 wxSize item_extent = mem_dc.GetTextExtent(painting.display_name);
167 mem_dc.DrawText(
168 painting.display_name,
169 {FromDIP(10 + 32 + 10),
170 indicator.y + (FromDIP(32) - mem_dc.GetFontMetrics().height) / 2});
171
172 break;
173 }
174 }
111 } 175 }
112} 176}
113 177
@@ -118,3 +182,21 @@ void AreaPopup::OnPaint(wxPaintEvent& event) {
118 182
119 event.Skip(); 183 event.Skip();
120} 184}
185
186void AreaPopup::OnDPIChanged(wxDPIChangedEvent& event) {
187 LoadIcons();
188 ResetIndicators();
189
190 event.Skip();
191}
192
193void AreaPopup::LoadIcons() {
194 unchecked_eye_ = GetTheIconCache().GetIcon("assets/unchecked.png",
195 FromDIP(wxSize{32, 32}));
196 checked_eye_ =
197 GetTheIconCache().GetIcon("assets/checked.png", FromDIP(wxSize{32, 32}));
198 unchecked_owl_ =
199 GetTheIconCache().GetIcon("assets/owl.png", FromDIP(wxSize{32, 32}));
200 checked_owl_ = GetTheIconCache().GetIcon("assets/checked_owl.png",
201 FromDIP(wxSize{32, 32}));
202}