diff options
Diffstat (limited to 'src/subway_map.cpp')
-rw-r--r-- | src/subway_map.cpp | 181 |
1 files changed, 129 insertions, 52 deletions
diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 6070fd5..2e7b36f 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp | |||
@@ -33,6 +33,14 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | |||
33 | return; | 33 | return; |
34 | } | 34 | } |
35 | 35 | ||
36 | unchecked_eye_ = | ||
37 | wxBitmap(wxImage(GetAbsolutePath("assets/unchecked.png").c_str(), | ||
38 | wxBITMAP_TYPE_PNG) | ||
39 | .Scale(32, 32)); | ||
40 | checked_eye_ = wxBitmap( | ||
41 | wxImage(GetAbsolutePath("assets/checked.png").c_str(), wxBITMAP_TYPE_PNG) | ||
42 | .Scale(32, 32)); | ||
43 | |||
36 | tree_ = std::make_unique<quadtree::Quadtree<int, GetItemBox>>( | 44 | tree_ = std::make_unique<quadtree::Quadtree<int, GetItemBox>>( |
37 | quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()), | 45 | quadtree::Box<float>{0, 0, static_cast<float>(map_image_.GetWidth()), |
38 | static_cast<float>(map_image_.GetHeight())}); | 46 | static_cast<float>(map_image_.GetHeight())}); |
@@ -113,75 +121,144 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
113 | wxBufferedPaintDC dc(this); | 121 | wxBufferedPaintDC dc(this); |
114 | dc.DrawBitmap(rendered_, 0, 0); | 122 | dc.DrawBitmap(rendered_, 0, 0); |
115 | 123 | ||
116 | if (hovered_item_ && networks_.IsItemInNetwork(*hovered_item_)) { | 124 | if (hovered_item_) { |
117 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | 125 | const SubwayItem &subway_item = GD_GetSubwayItem(*hovered_item_); |
126 | if (subway_item.door && !GetDoorRequirements(*subway_item.door).empty()) { | ||
127 | const std::map<std::string, bool> &report = | ||
128 | GetDoorRequirements(*subway_item.door); | ||
118 | 129 | ||
119 | for (const auto &[item_id1, item_id2] : | 130 | int acc_height = 10; |
120 | networks_.GetNetworkGraph(*hovered_item_)) { | 131 | int col_width = 0; |
121 | const SubwayItem &item1 = GD_GetSubwayItem(item_id1); | ||
122 | const SubwayItem &item2 = GD_GetSubwayItem(item_id2); | ||
123 | 132 | ||
124 | int item1_x = (item1.x + AREA_ACTUAL_SIZE / 2) * render_width_ / map_image_.GetWidth() + render_x_; | 133 | for (const auto &[text, obtained] : report) { |
125 | int item1_y = (item1.y + AREA_ACTUAL_SIZE / 2) * render_width_ / map_image_.GetWidth() + render_y_; | 134 | wxSize item_extent = dc.GetTextExtent(text); |
135 | int item_height = std::max(32, item_extent.GetHeight()) + 10; | ||
136 | acc_height += item_height; | ||
126 | 137 | ||
127 | int item2_x = (item2.x + AREA_ACTUAL_SIZE / 2) * render_width_ / map_image_.GetWidth() + render_x_; | 138 | if (item_extent.GetWidth() > col_width) { |
128 | int item2_y = (item2.y + AREA_ACTUAL_SIZE / 2) * render_width_ / map_image_.GetWidth() + render_y_; | 139 | col_width = item_extent.GetWidth(); |
140 | } | ||
141 | } | ||
142 | |||
143 | int item_width = col_width + 10 + 32; | ||
144 | int full_width = item_width + 20; | ||
145 | |||
146 | int popup_x = (subway_item.x + AREA_ACTUAL_SIZE / 2) * render_width_ / | ||
147 | map_image_.GetWidth() + | ||
148 | render_x_; | ||
149 | int popup_y = (subway_item.y + AREA_ACTUAL_SIZE / 2) * render_width_ / | ||
150 | map_image_.GetWidth() + | ||
151 | render_y_; | ||
152 | |||
153 | if (popup_x + full_width > GetSize().GetWidth()) { | ||
154 | popup_x = GetSize().GetWidth() - full_width; | ||
155 | } | ||
156 | if (popup_y + acc_height > GetSize().GetHeight()) { | ||
157 | popup_y = GetSize().GetHeight() - acc_height; | ||
158 | } | ||
129 | 159 | ||
130 | int left = std::min(item1_x, item2_x); | 160 | dc.SetPen(*wxTRANSPARENT_PEN); |
131 | int top = std::min(item1_y, item2_y); | 161 | dc.SetBrush(*wxBLACK_BRUSH); |
132 | int right = std::max(item1_x, item2_x); | 162 | dc.DrawRectangle({popup_x, popup_y}, {full_width, acc_height}); |
133 | int bottom = std::max(item1_y, item2_y); | ||
134 | 163 | ||
135 | int halfwidth = right - left; | 164 | dc.SetFont(GetFont()); |
136 | int halfheight = bottom - top; | ||
137 | 165 | ||
138 | if (halfwidth < 4 || halfheight < 4) { | 166 | int cur_height = 10; |
139 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4)); | ||
140 | dc.DrawLine(item1_x, item1_y, item2_x, item2_y); | ||
141 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); | ||
142 | dc.DrawLine(item1_x, item1_y, item2_x, item2_y); | ||
143 | } else { | ||
144 | int ellipse_x; | ||
145 | int ellipse_y; | ||
146 | double start; | ||
147 | double end; | ||
148 | 167 | ||
149 | if (item1_x > item2_x) { | 168 | for (const auto& [text, obtained] : report) { |
150 | ellipse_y = top; | 169 | wxBitmap *eye_ptr = obtained ? &unchecked_eye_ : &checked_eye_; |
151 | 170 | ||
152 | if (item1_y > item2_y) { | 171 | dc.DrawBitmap(*eye_ptr, {popup_x + 10, popup_y + cur_height}); |
153 | ellipse_x = left - halfwidth; | ||
154 | 172 | ||
155 | start = 0; | 173 | dc.SetTextForeground(obtained ? *wxWHITE : *wxRED); |
156 | end = 90; | 174 | wxSize item_extent = dc.GetTextExtent(text); |
157 | } else { | 175 | dc.DrawText( |
158 | ellipse_x = left; | 176 | text, |
177 | {popup_x + 10 + 32 + 10, | ||
178 | popup_y + cur_height + (32 - dc.GetFontMetrics().height) / 2}); | ||
159 | 179 | ||
160 | start = 90; | 180 | cur_height += 10 + 32; |
161 | end = 180; | 181 | } |
162 | } | 182 | } |
183 | |||
184 | if (networks_.IsItemInNetwork(*hovered_item_)) { | ||
185 | dc.SetBrush(*wxTRANSPARENT_BRUSH); | ||
186 | |||
187 | for (const auto &[item_id1, item_id2] : | ||
188 | networks_.GetNetworkGraph(*hovered_item_)) { | ||
189 | const SubwayItem &item1 = GD_GetSubwayItem(item_id1); | ||
190 | const SubwayItem &item2 = GD_GetSubwayItem(item_id2); | ||
191 | |||
192 | int item1_x = (item1.x + AREA_ACTUAL_SIZE / 2) * render_width_ / | ||
193 | map_image_.GetWidth() + | ||
194 | render_x_; | ||
195 | int item1_y = (item1.y + AREA_ACTUAL_SIZE / 2) * render_width_ / | ||
196 | map_image_.GetWidth() + | ||
197 | render_y_; | ||
198 | |||
199 | int item2_x = (item2.x + AREA_ACTUAL_SIZE / 2) * render_width_ / | ||
200 | map_image_.GetWidth() + | ||
201 | render_x_; | ||
202 | int item2_y = (item2.y + AREA_ACTUAL_SIZE / 2) * render_width_ / | ||
203 | map_image_.GetWidth() + | ||
204 | render_y_; | ||
205 | |||
206 | int left = std::min(item1_x, item2_x); | ||
207 | int top = std::min(item1_y, item2_y); | ||
208 | int right = std::max(item1_x, item2_x); | ||
209 | int bottom = std::max(item1_y, item2_y); | ||
210 | |||
211 | int halfwidth = right - left; | ||
212 | int halfheight = bottom - top; | ||
213 | |||
214 | if (halfwidth < 4 || halfheight < 4) { | ||
215 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4)); | ||
216 | dc.DrawLine(item1_x, item1_y, item2_x, item2_y); | ||
217 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); | ||
218 | dc.DrawLine(item1_x, item1_y, item2_x, item2_y); | ||
163 | } else { | 219 | } else { |
164 | ellipse_y = top - halfheight; | 220 | int ellipse_x; |
221 | int ellipse_y; | ||
222 | double start; | ||
223 | double end; | ||
165 | 224 | ||
166 | if (item1_y > item2_y) { | 225 | if (item1_x > item2_x) { |
167 | ellipse_x = left - halfwidth; | 226 | ellipse_y = top; |
168 | 227 | ||
169 | start = 270; | 228 | if (item1_y > item2_y) { |
170 | end = 360; | 229 | ellipse_x = left - halfwidth; |
230 | |||
231 | start = 0; | ||
232 | end = 90; | ||
233 | } else { | ||
234 | ellipse_x = left; | ||
235 | |||
236 | start = 90; | ||
237 | end = 180; | ||
238 | } | ||
171 | } else { | 239 | } else { |
172 | ellipse_x = left; | 240 | ellipse_y = top - halfheight; |
241 | |||
242 | if (item1_y > item2_y) { | ||
243 | ellipse_x = left - halfwidth; | ||
173 | 244 | ||
174 | start = 180; | 245 | start = 270; |
175 | end = 270; | 246 | end = 360; |
247 | } else { | ||
248 | ellipse_x = left; | ||
249 | |||
250 | start = 180; | ||
251 | end = 270; | ||
252 | } | ||
176 | } | 253 | } |
177 | } | ||
178 | 254 | ||
179 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4)); | 255 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4)); |
180 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2, | 256 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2, |
181 | start, end); | 257 | start, end); |
182 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); | 258 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); |
183 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2, | 259 | dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2, |
184 | start, end); | 260 | start, end); |
261 | } | ||
185 | } | 262 | } |
186 | } | 263 | } |
187 | } | 264 | } |