about summary refs log tree commit diff stats
path: root/src/subway_map.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/subway_map.cpp')
-rw-r--r--src/subway_map.cpp181
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 }