about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/ap_state.cpp21
-rw-r--r--src/game_data.cpp25
-rw-r--r--src/game_data.h4
-rw-r--r--src/network_set.cpp68
-rw-r--r--src/network_set.h28
-rw-r--r--src/subway_map.cpp129
-rw-r--r--src/subway_map.h12
-rw-r--r--src/tracker_frame.cpp13
-rw-r--r--src/tracker_frame.h3
10 files changed, 289 insertions, 15 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d6170a1..6dc2f4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -45,6 +45,7 @@ add_executable(lingo_ap_tracker
45 "src/settings_dialog.cpp" 45 "src/settings_dialog.cpp"
46 "src/global.cpp" 46 "src/global.cpp"
47 "src/subway_map.cpp" 47 "src/subway_map.cpp"
48 "src/network_set.cpp"
48 "vendor/whereami/whereami.c" 49 "vendor/whereami/whereami.c"
49) 50)
50set_property(TARGET lingo_ap_tracker PROPERTY CXX_STANDARD 20) 51set_property(TARGET lingo_ap_tracker PROPERTY CXX_STANDARD 20)
diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 8feb78b..b057beb 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp
@@ -173,7 +173,7 @@ struct APState {
173 TrackerLog("Location: " + std::to_string(location_id)); 173 TrackerLog("Location: " + std::to_string(location_id));
174 } 174 }
175 175
176 RefreshTracker(); 176 RefreshTracker(false);
177 }); 177 });
178 178
179 apclient->set_slot_disconnected_handler([this]() { 179 apclient->set_slot_disconnected_handler([this]() {
@@ -197,7 +197,7 @@ struct APState {
197 TrackerLog("Item: " + std::to_string(item.item)); 197 TrackerLog("Item: " + std::to_string(item.item));
198 } 198 }
199 199
200 RefreshTracker(); 200 RefreshTracker(false);
201 }); 201 });
202 202
203 apclient->set_retrieved_handler( 203 apclient->set_retrieved_handler(
@@ -206,14 +206,14 @@ struct APState {
206 HandleDataStorage(key, value); 206 HandleDataStorage(key, value);
207 } 207 }
208 208
209 RefreshTracker(); 209 RefreshTracker(false);
210 }); 210 });
211 211
212 apclient->set_set_reply_handler([this](const std::string& key, 212 apclient->set_set_reply_handler([this](const std::string& key,
213 const nlohmann::json& value, 213 const nlohmann::json& value,
214 const nlohmann::json&) { 214 const nlohmann::json&) {
215 HandleDataStorage(key, value); 215 HandleDataStorage(key, value);
216 RefreshTracker(); 216 RefreshTracker(false);
217 }); 217 });
218 218
219 apclient->set_slot_connected_handler([this]( 219 apclient->set_slot_connected_handler([this](
@@ -271,7 +271,7 @@ struct APState {
271 connected = true; 271 connected = true;
272 has_connection_result = true; 272 has_connection_result = true;
273 273
274 RefreshTracker(); 274 RefreshTracker(true);
275 275
276 std::list<std::string> corrected_keys; 276 std::list<std::string> corrected_keys;
277 for (const std::string& key : tracked_data_storage_keys) { 277 for (const std::string& key : tracked_data_storage_keys) {
@@ -353,7 +353,7 @@ struct APState {
353 } 353 }
354 354
355 if (connected) { 355 if (connected) {
356 RefreshTracker(); 356 RefreshTracker(false);
357 } else { 357 } else {
358 client_active = false; 358 client_active = false;
359 } 359 }
@@ -407,11 +407,16 @@ struct APState {
407 return data_storage.count(key) && std::any_cast<bool>(data_storage.at(key)); 407 return data_storage.count(key) && std::any_cast<bool>(data_storage.at(key));
408 } 408 }
409 409
410 void RefreshTracker() { 410 void RefreshTracker(bool reset) {
411 TrackerLog("Refreshing display..."); 411 TrackerLog("Refreshing display...");
412 412
413 RecalculateReachability(); 413 RecalculateReachability();
414 tracker_frame->UpdateIndicators(); 414
415 if (reset) {
416 tracker_frame->ResetIndicators();
417 } else {
418 tracker_frame->UpdateIndicators();
419 }
415 } 420 }
416 421
417 int64_t GetItemId(const std::string& item_name) { 422 int64_t GetItemId(const std::string& item_name) {
diff --git a/src/game_data.cpp b/src/game_data.cpp index 4348967..74f872c 100644 --- a/src/game_data.cpp +++ b/src/game_data.cpp
@@ -62,6 +62,9 @@ struct GameData {
62 62
63 std::vector<int> sunwarp_doors_; 63 std::vector<int> sunwarp_doors_;
64 64
65 std::map<std::string, int> subway_item_by_painting_;
66 std::map<SubwaySunwarp, int> subway_item_by_sunwarp_;
67
65 bool loaded_area_data_ = false; 68 bool loaded_area_data_ = false;
66 std::set<std::string> malconfigured_areas_; 69 std::set<std::string> malconfigured_areas_;
67 70
@@ -624,7 +627,10 @@ struct GameData {
624 627
625 if (subway_it["paintings"]) { 628 if (subway_it["paintings"]) {
626 for (const auto &painting_it : subway_it["paintings"]) { 629 for (const auto &painting_it : subway_it["paintings"]) {
627 subway_item.paintings.push_back(painting_it.as<std::string>()); 630 std::string painting_id = painting_it.as<std::string>();
631
632 subway_item.paintings.push_back(painting_id);
633 subway_item_by_painting_[painting_id] = subway_item.id;
628 } 634 }
629 } 635 }
630 636
@@ -649,6 +655,11 @@ struct GameData {
649 } 655 }
650 656
651 subway_item.sunwarp = sunwarp; 657 subway_item.sunwarp = sunwarp;
658
659 subway_item_by_sunwarp_[sunwarp] = subway_item.id;
660
661 subway_item.door =
662 AddOrGetDoor("Sunwarps", std::to_string(sunwarp.dots) + " Sunwarp");
652 } 663 }
653 664
654 if (subway_it["special"]) { 665 if (subway_it["special"]) {
@@ -715,6 +726,10 @@ GameData &GetState() {
715 726
716} // namespace 727} // namespace
717 728
729bool SubwaySunwarp::operator<(const SubwaySunwarp& rhs) const {
730 return std::tie(dots, type) < std::tie(rhs.dots, rhs.type);
731}
732
718const std::vector<MapArea> &GD_GetMapAreas() { return GetState().map_areas_; } 733const std::vector<MapArea> &GD_GetMapAreas() { return GetState().map_areas_; }
719 734
720const MapArea &GD_GetMapArea(int id) { return GetState().map_areas_.at(id); } 735const MapArea &GD_GetMapArea(int id) { return GetState().map_areas_.at(id); }
@@ -764,3 +779,11 @@ const std::vector<SubwayItem> &GD_GetSubwayItems() {
764const SubwayItem &GD_GetSubwayItem(int id) { 779const SubwayItem &GD_GetSubwayItem(int id) {
765 return GetState().subway_items_.at(id); 780 return GetState().subway_items_.at(id);
766} 781}
782
783int GD_GetSubwayItemForPainting(const std::string& painting_id) {
784 return GetState().subway_item_by_painting_.at(painting_id);
785}
786
787int GD_GetSubwayItemForSunwarp(const SubwaySunwarp &sunwarp) {
788 return GetState().subway_item_by_sunwarp_.at(sunwarp);
789}
diff --git a/src/game_data.h b/src/game_data.h index 37d1eb3..3afaec3 100644 --- a/src/game_data.h +++ b/src/game_data.h
@@ -128,6 +128,8 @@ enum class SubwaySunwarpType {
128struct SubwaySunwarp { 128struct SubwaySunwarp {
129 int dots; 129 int dots;
130 SubwaySunwarpType type; 130 SubwaySunwarpType type;
131
132 bool operator<(const SubwaySunwarp& rhs) const;
131}; 133};
132 134
133struct SubwayItem { 135struct SubwayItem {
@@ -156,5 +158,7 @@ const std::vector<int>& GD_GetSunwarpDoors();
156int GD_GetRoomForSunwarp(int index); 158int GD_GetRoomForSunwarp(int index);
157const std::vector<SubwayItem>& GD_GetSubwayItems(); 159const std::vector<SubwayItem>& GD_GetSubwayItems();
158const SubwayItem& GD_GetSubwayItem(int id); 160const SubwayItem& GD_GetSubwayItem(int id);
161int GD_GetSubwayItemForPainting(const std::string& painting_id);
162int GD_GetSubwayItemForSunwarp(const SubwaySunwarp& sunwarp);
159 163
160#endif /* end of include guard: GAME_DATA_H_9C42AC51 */ 164#endif /* end of include guard: GAME_DATA_H_9C42AC51 */
diff --git a/src/network_set.cpp b/src/network_set.cpp new file mode 100644 index 0000000..3238dcd --- /dev/null +++ b/src/network_set.cpp
@@ -0,0 +1,68 @@
1#include "network_set.h"
2
3void NetworkSet::Clear() {
4 networks_.clear();
5 network_by_item_.clear();
6}
7
8int NetworkSet::AddLink(int id1, int id2) {
9 if (id2 > id1) {
10 // Make sure id1 < id2
11 std::swap(id1, id2);
12 }
13
14 if (network_by_item_.count(id1)) {
15 if (network_by_item_.count(id2)) {
16 int network_id1 = network_by_item_[id1];
17 int network_id2 = network_by_item_[id2];
18
19 networks_[network_id1].emplace(id1, id2);
20
21 if (network_id1 != network_id2) {
22 for (const auto& [other_id1, other_id2] : networks_[network_id2]) {
23 network_by_item_[other_id1] = network_id1;
24 network_by_item_[other_id2] = network_id1;
25 }
26
27 networks_[network_id1].merge(networks_[network_id2]);
28 networks_[network_id2].clear();
29 }
30
31 return network_id1;
32 } else {
33 int network_id = network_by_item_[id1];
34 network_by_item_[id2] = network_id;
35 networks_[network_id].emplace(id1, id2);
36
37 return network_id;
38 }
39 } else {
40 if (network_by_item_.count(id2)) {
41 int network_id = network_by_item_[id2];
42 network_by_item_[id1] = network_id;
43 networks_[network_id].emplace(id1, id2);
44
45 return network_id;
46 } else {
47 int network_id = networks_.size();
48 network_by_item_[id1] = network_id;
49 network_by_item_[id2] = network_id;
50 networks_.emplace_back();
51 networks_[network_id] = {{id1, id2}};
52
53 return network_id;
54 }
55 }
56}
57
58bool NetworkSet::IsItemInNetwork(int id) const {
59 return network_by_item_.count(id);
60}
61
62int NetworkSet::GetNetworkWithItem(int id) const {
63 return network_by_item_.at(id);
64}
65
66const std::set<std::pair<int, int>>& NetworkSet::GetNetworkGraph(int id) const {
67 return networks_.at(id);
68}
diff --git a/src/network_set.h b/src/network_set.h new file mode 100644 index 0000000..e0ef043 --- /dev/null +++ b/src/network_set.h
@@ -0,0 +1,28 @@
1#ifndef NETWORK_SET_H_3036B8E3
2#define NETWORK_SET_H_3036B8E3
3
4#include <map>
5#include <optional>
6#include <set>
7#include <utility>
8#include <vector>
9
10class NetworkSet {
11 public:
12 void Clear();
13
14 int AddLink(int id1, int id2);
15
16 bool IsItemInNetwork(int id) const;
17
18 int GetNetworkWithItem(int id) const;
19
20 const std::set<std::pair<int, int>>& GetNetworkGraph(int id) const;
21
22 private:
23
24 std::vector<std::set<std::pair<int, int>>> networks_;
25 std::map<int, int> network_by_item_;
26};
27
28#endif /* end of include guard: NETWORK_SET_H_3036B8E3 */
diff --git a/src/subway_map.cpp b/src/subway_map.cpp index f857270..a03f0d8 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp
@@ -2,6 +2,9 @@
2 2
3#include <wx/dcbuffer.h> 3#include <wx/dcbuffer.h>
4 4
5#include <sstream>
6
7#include "ap_state.h"
5#include "game_data.h" 8#include "game_data.h"
6#include "global.h" 9#include "global.h"
7#include "tracker_state.h" 10#include "tracker_state.h"
@@ -42,10 +45,61 @@ SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) {
42 Bind(wxEVT_MOTION, &SubwayMap::OnMouseMove, this); 45 Bind(wxEVT_MOTION, &SubwayMap::OnMouseMove, this);
43} 46}
44 47
48void SubwayMap::OnConnect() {
49 networks_.Clear();
50
51 std::map<std::string, std::vector<int>> tagged;
52 for (const SubwayItem &subway_item : GD_GetSubwayItems()) {
53 if (AP_IsPaintingShuffle() && !subway_item.paintings.empty()) {
54 continue;
55 }
56
57 for (const std::string &tag : subway_item.tags) {
58 tagged[tag].push_back(subway_item.id);
59 }
60
61 if (!AP_IsSunwarpShuffle() && subway_item.sunwarp && subway_item.sunwarp->type != SubwaySunwarpType::kFinal) {
62 std::ostringstream tag;
63 tag << "sunwarp" << subway_item.sunwarp->dots;
64
65 tagged[tag.str()].push_back(subway_item.id);
66 }
67 }
68
69 for (const auto &[tag, items] : tagged) {
70 // Pairwise connect all items with the same tag.
71 for (auto tag_it1 = items.begin(); std::next(tag_it1) != items.end();
72 tag_it1++) {
73 for (auto tag_it2 = std::next(tag_it1); tag_it2 != items.end();
74 tag_it2++) {
75 networks_.AddLink(*tag_it1, *tag_it2);
76 }
77 }
78 }
79
80 checked_paintings_.clear();
81}
82
45void SubwayMap::UpdateIndicators() { 83void SubwayMap::UpdateIndicators() {
46 Redraw(); 84 Redraw();
47} 85}
48 86
87void SubwayMap::UpdatePainting(std::string from_painting_id,
88 std::optional<std::string> to_painting_id) {
89 checked_paintings_.insert(from_painting_id);
90
91 if (to_painting_id) {
92 networks_.AddLink(GD_GetSubwayItemForPainting(from_painting_id),
93 GD_GetSubwayItemForPainting(*to_painting_id));
94 }
95}
96
97void SubwayMap::UpdateSunwarp(SubwaySunwarp from_sunwarp,
98 SubwaySunwarp to_sunwarp) {
99 networks_.AddLink(GD_GetSubwayItemForSunwarp(from_sunwarp),
100 GD_GetSubwayItemForSunwarp(to_sunwarp));
101}
102
49void SubwayMap::OnPaint(wxPaintEvent &event) { 103void SubwayMap::OnPaint(wxPaintEvent &event) {
50 if (GetSize() != rendered_.GetSize()) { 104 if (GetSize() != rendered_.GetSize()) {
51 Redraw(); 105 Redraw();
@@ -54,6 +108,73 @@ void SubwayMap::OnPaint(wxPaintEvent &event) {
54 wxBufferedPaintDC dc(this); 108 wxBufferedPaintDC dc(this);
55 dc.DrawBitmap(rendered_, 0, 0); 109 dc.DrawBitmap(rendered_, 0, 0);
56 110
111 if (hovered_item_ && networks_.IsItemInNetwork(*hovered_item_)) {
112 dc.SetBrush(*wxTRANSPARENT_BRUSH);
113
114 int network_id = networks_.GetNetworkWithItem(*hovered_item_);
115 for (const auto &[item_id1, item_id2] :
116 networks_.GetNetworkGraph(network_id)) {
117 const SubwayItem &item1 = GD_GetSubwayItem(item_id1);
118 const SubwayItem &item2 = GD_GetSubwayItem(item_id2);
119
120 int item1_x = (item1.x + AREA_ACTUAL_SIZE / 2) * render_width_ / map_image_.GetWidth() + render_x_;
121 int item1_y = (item1.y + AREA_ACTUAL_SIZE / 2) * render_width_ / map_image_.GetWidth() + render_y_;
122
123 int item2_x = (item2.x + AREA_ACTUAL_SIZE / 2) * render_width_ / map_image_.GetWidth() + render_x_;
124 int item2_y = (item2.y + AREA_ACTUAL_SIZE / 2) * render_width_ / map_image_.GetWidth() + render_y_;
125
126 int left = std::min(item1_x, item2_x);
127 int top = std::min(item1_y, item2_y);
128 int right = std::max(item1_x, item2_x);
129 int bottom = std::max(item1_y, item2_y);
130
131 int halfwidth = right - left;
132 int halfheight = bottom - top;
133
134 int ellipse_x;
135 int ellipse_y;
136 double start;
137 double end;
138
139 if (item1_x > item2_x) {
140 ellipse_y = top;
141
142 if (item1_y > item2_y) {
143 ellipse_x = left - halfwidth;
144
145 start = 0;
146 end = 90;
147 } else {
148 ellipse_x = left;
149
150 start = 90;
151 end = 180;
152 }
153 } else {
154 ellipse_y = top - halfheight;
155
156 if (item1_y > item2_y) {
157 ellipse_x = left - halfwidth;
158
159 start = 270;
160 end = 360;
161 } else {
162 ellipse_x = left;
163
164 start = 180;
165 end = 270;
166 }
167 }
168
169 dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4));
170 dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2,
171 start, end);
172 dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2));
173 dc.DrawEllipticArc(ellipse_x, ellipse_y, halfwidth * 2, halfheight * 2,
174 start, end);
175 }
176 }
177
57 event.Skip(); 178 event.Skip();
58} 179}
59 180
@@ -73,13 +194,9 @@ void SubwayMap::OnMouseMove(wxMouseEvent &event) {
73 } 194 }
74 195
75 if (new_hovered_item != hovered_item_) { 196 if (new_hovered_item != hovered_item_) {
76 if (new_hovered_item) {
77 wxLogVerbose("Hovered: %d", *new_hovered_item);
78 } else {
79 wxLogVerbose("Un-hovered: %d", *hovered_item_);
80 }
81
82 hovered_item_ = new_hovered_item; 197 hovered_item_ = new_hovered_item;
198
199 Refresh();
83 } 200 }
84 201
85 event.Skip(); 202 event.Skip();
diff --git a/src/subway_map.h b/src/subway_map.h index 6cb5c63..1637125 100644 --- a/src/subway_map.h +++ b/src/subway_map.h
@@ -9,15 +9,24 @@
9 9
10#include <memory> 10#include <memory>
11#include <optional> 11#include <optional>
12#include <set>
13#include <string>
12#include <vector> 14#include <vector>
13 15
14#include <quadtree/Quadtree.h> 16#include <quadtree/Quadtree.h>
15 17
18#include "game_data.h"
19#include "network_set.h"
20
16class SubwayMap : public wxPanel { 21class SubwayMap : public wxPanel {
17 public: 22 public:
18 SubwayMap(wxWindow *parent); 23 SubwayMap(wxWindow *parent);
19 24
25 void OnConnect();
20 void UpdateIndicators(); 26 void UpdateIndicators();
27 void UpdatePainting(std::string from_painting_id,
28 std::optional<std::string> to_painting_id);
29 void UpdateSunwarp(SubwaySunwarp from_sunwarp, SubwaySunwarp to_sunwarp);
21 30
22 private: 31 private:
23 void OnPaint(wxPaintEvent &event); 32 void OnPaint(wxPaintEvent &event);
@@ -40,6 +49,9 @@ class SubwayMap : public wxPanel {
40 49
41 std::unique_ptr<quadtree::Quadtree<int, GetItemBox>> tree_; 50 std::unique_ptr<quadtree::Quadtree<int, GetItemBox>> tree_;
42 std::optional<int> hovered_item_; 51 std::optional<int> hovered_item_;
52
53 NetworkSet networks_;
54 std::set<std::string> checked_paintings_;
43}; 55};
44 56
45#endif /* end of include guard: SUBWAY_MAP_H_BD2D843E */ 57#endif /* end of include guard: SUBWAY_MAP_H_BD2D843E */
diff --git a/src/tracker_frame.cpp b/src/tracker_frame.cpp index 70fee2d..e944704 100644 --- a/src/tracker_frame.cpp +++ b/src/tracker_frame.cpp
@@ -22,6 +22,7 @@ enum TrackerFrameIds {
22 ID_SETTINGS = 3 22 ID_SETTINGS = 3
23}; 23};
24 24
25wxDEFINE_EVENT(STATE_RESET, wxCommandEvent);
25wxDEFINE_EVENT(STATE_CHANGED, wxCommandEvent); 26wxDEFINE_EVENT(STATE_CHANGED, wxCommandEvent);
26wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent); 27wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent);
27 28
@@ -56,6 +57,7 @@ TrackerFrame::TrackerFrame()
56 Bind(wxEVT_MENU, &TrackerFrame::OnSettings, this, ID_SETTINGS); 57 Bind(wxEVT_MENU, &TrackerFrame::OnSettings, this, ID_SETTINGS);
57 Bind(wxEVT_MENU, &TrackerFrame::OnCheckForUpdates, this, 58 Bind(wxEVT_MENU, &TrackerFrame::OnCheckForUpdates, this,
58 ID_CHECK_FOR_UPDATES); 59 ID_CHECK_FOR_UPDATES);
60 Bind(STATE_RESET, &TrackerFrame::OnStateReset, this);
59 Bind(STATE_CHANGED, &TrackerFrame::OnStateChanged, this); 61 Bind(STATE_CHANGED, &TrackerFrame::OnStateChanged, this);
60 Bind(STATUS_CHANGED, &TrackerFrame::OnStatusChanged, this); 62 Bind(STATUS_CHANGED, &TrackerFrame::OnStatusChanged, this);
61 63
@@ -103,6 +105,10 @@ void TrackerFrame::SetStatusMessage(std::string message) {
103 QueueEvent(event); 105 QueueEvent(event);
104} 106}
105 107
108void TrackerFrame::ResetIndicators() {
109 QueueEvent(new wxCommandEvent(STATE_RESET));
110}
111
106void TrackerFrame::UpdateIndicators() { 112void TrackerFrame::UpdateIndicators() {
107 QueueEvent(new wxCommandEvent(STATE_CHANGED)); 113 QueueEvent(new wxCommandEvent(STATE_CHANGED));
108} 114}
@@ -168,6 +174,13 @@ void TrackerFrame::OnCheckForUpdates(wxCommandEvent &event) {
168 CheckForUpdates(/*manual=*/true); 174 CheckForUpdates(/*manual=*/true);
169} 175}
170 176
177void TrackerFrame::OnStateReset(wxCommandEvent& event) {
178 tracker_panel_->UpdateIndicators();
179 achievements_pane_->UpdateIndicators();
180 subway_map_->OnConnect();
181 Refresh();
182}
183
171void TrackerFrame::OnStateChanged(wxCommandEvent &event) { 184void TrackerFrame::OnStateChanged(wxCommandEvent &event) {
172 tracker_panel_->UpdateIndicators(); 185 tracker_panel_->UpdateIndicators();
173 achievements_pane_->UpdateIndicators(); 186 achievements_pane_->UpdateIndicators();
diff --git a/src/tracker_frame.h b/src/tracker_frame.h index c7c6772..f1d7171 100644 --- a/src/tracker_frame.h +++ b/src/tracker_frame.h
@@ -11,6 +11,7 @@ class AchievementsPane;
11class SubwayMap; 11class SubwayMap;
12class TrackerPanel; 12class TrackerPanel;
13 13
14wxDECLARE_EVENT(STATE_RESET, wxCommandEvent);
14wxDECLARE_EVENT(STATE_CHANGED, wxCommandEvent); 15wxDECLARE_EVENT(STATE_CHANGED, wxCommandEvent);
15wxDECLARE_EVENT(STATUS_CHANGED, wxCommandEvent); 16wxDECLARE_EVENT(STATUS_CHANGED, wxCommandEvent);
16 17
@@ -20,6 +21,7 @@ class TrackerFrame : public wxFrame {
20 21
21 void SetStatusMessage(std::string message); 22 void SetStatusMessage(std::string message);
22 23
24 void ResetIndicators();
23 void UpdateIndicators(); 25 void UpdateIndicators();
24 26
25 private: 27 private:
@@ -29,6 +31,7 @@ class TrackerFrame : public wxFrame {
29 void OnSettings(wxCommandEvent &event); 31 void OnSettings(wxCommandEvent &event);
30 void OnCheckForUpdates(wxCommandEvent &event); 32 void OnCheckForUpdates(wxCommandEvent &event);
31 33
34 void OnStateReset(wxCommandEvent &event);
32 void OnStateChanged(wxCommandEvent &event); 35 void OnStateChanged(wxCommandEvent &event);
33 void OnStatusChanged(wxCommandEvent &event); 36 void OnStatusChanged(wxCommandEvent &event);
34 37