From a9bc708c7eeeada4c59952ce71aa071175f8f27d Mon Sep 17 00:00:00 2001
From: Star Rauchenberger <fefferburbia@gmail.com>
Date: Fri, 17 Nov 2023 10:11:41 -0500
Subject: Added hybrid areas and settings dialog

---
 src/settings_dialog.cpp | 29 +++++++++++++++++++++++++
 src/settings_dialog.h   | 24 ++++++++++++++++++++
 src/tracker_config.cpp  |  2 ++
 src/tracker_config.h    |  1 +
 src/tracker_frame.cpp   | 22 ++++++++++++++++++-
 src/tracker_frame.h     |  1 +
 src/tracker_panel.cpp   | 58 ++++++++++++++++++++++++++++++++++---------------
 7 files changed, 118 insertions(+), 19 deletions(-)
 create mode 100644 src/settings_dialog.cpp
 create mode 100644 src/settings_dialog.h

(limited to 'src')

diff --git a/src/settings_dialog.cpp b/src/settings_dialog.cpp
new file mode 100644
index 0000000..58e5988
--- /dev/null
+++ b/src/settings_dialog.cpp
@@ -0,0 +1,29 @@
+#include "settings_dialog.h"
+
+#include "tracker_config.h"
+
+SettingsDialog::SettingsDialog() : wxDialog(nullptr, wxID_ANY, "Settings") {
+  should_check_for_updates_box_ = new wxCheckBox(
+      this, wxID_ANY, "Check for updates when the tracker opens");
+  hybrid_areas_box_ = new wxCheckBox(
+      this, wxID_ANY,
+      "Use two colors to show that an area has partial availability");
+
+  should_check_for_updates_box_->SetValue(
+      GetTrackerConfig().should_check_for_updates);
+  hybrid_areas_box_->SetValue(GetTrackerConfig().hybrid_areas);
+
+  wxBoxSizer* form_sizer = new wxBoxSizer(wxVERTICAL);
+
+  form_sizer->Add(should_check_for_updates_box_, wxSizerFlags().HorzBorder());
+  form_sizer->AddSpacer(2);
+
+  form_sizer->Add(hybrid_areas_box_, wxSizerFlags().HorzBorder());
+  form_sizer->AddSpacer(2);
+
+  form_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL), wxSizerFlags().Center());
+
+  SetSizerAndFit(form_sizer);
+
+  Center();
+}
diff --git a/src/settings_dialog.h b/src/settings_dialog.h
new file mode 100644
index 0000000..150a7a8
--- /dev/null
+++ b/src/settings_dialog.h
@@ -0,0 +1,24 @@
+#ifndef SETTINGS_DIALOG_H_D8635719
+#define SETTINGS_DIALOG_H_D8635719
+
+#include <wx/wxprec.h>
+
+#ifndef WX_PRECOMP
+#include <wx/wx.h>
+#endif
+
+class SettingsDialog : public wxDialog {
+ public:
+  SettingsDialog();
+
+  bool GetShouldCheckForUpdates() const {
+    return should_check_for_updates_box_->GetValue();
+  }
+  bool GetHybridAreas() const { return hybrid_areas_box_->GetValue(); }
+
+ private:
+  wxCheckBox* should_check_for_updates_box_;
+  wxCheckBox* hybrid_areas_box_;
+};
+
+#endif /* end of include guard: SETTINGS_DIALOG_H_D8635719 */
diff --git a/src/tracker_config.cpp b/src/tracker_config.cpp
index c09d241..9318091 100644
--- a/src/tracker_config.cpp
+++ b/src/tracker_config.cpp
@@ -14,6 +14,7 @@ void TrackerConfig::Load() {
     ap_password = file["ap_password"].as<std::string>();
     asked_to_check_for_updates = file["asked_to_check_for_updates"].as<bool>();
     should_check_for_updates = file["should_check_for_updates"].as<bool>();
+    hybrid_areas = file["hybrid_areas"].as<bool>();
   } catch (const std::exception&) {
     // It's fine if the file can't be loaded.
   }
@@ -26,6 +27,7 @@ void TrackerConfig::Save() {
   output["ap_password"] = ap_password;
   output["asked_to_check_for_updates"] = asked_to_check_for_updates;
   output["should_check_for_updates"] = should_check_for_updates;
+  output["hybrid_areas"] = hybrid_areas;
 
   std::ofstream filewriter(CONFIG_FILE_NAME);
   filewriter << output;
diff --git a/src/tracker_config.h b/src/tracker_config.h
index b9460d2..6c94e1b 100644
--- a/src/tracker_config.h
+++ b/src/tracker_config.h
@@ -14,6 +14,7 @@ class TrackerConfig {
   std::string ap_password;
   bool asked_to_check_for_updates = false;
   bool should_check_for_updates = false;
+  bool hybrid_areas = false;
 };
 
 TrackerConfig& GetTrackerConfig();
diff --git a/src/tracker_frame.cpp b/src/tracker_frame.cpp
index a74e81e..5341fa6 100644
--- a/src/tracker_frame.cpp
+++ b/src/tracker_frame.cpp
@@ -9,11 +9,16 @@
 #include "achievements_pane.h"
 #include "ap_state.h"
 #include "connection_dialog.h"
+#include "settings_dialog.h"
 #include "tracker_config.h"
 #include "tracker_panel.h"
 #include "version.h"
 
-enum TrackerFrameIds { ID_CONNECT = 1, ID_CHECK_FOR_UPDATES = 2 };
+enum TrackerFrameIds {
+  ID_CONNECT = 1,
+  ID_CHECK_FOR_UPDATES = 2,
+  ID_SETTINGS = 3
+};
 
 wxDEFINE_EVENT(STATE_CHANGED, wxCommandEvent);
 wxDEFINE_EVENT(STATUS_CHANGED, wxCommandEvent);
@@ -29,6 +34,7 @@ TrackerFrame::TrackerFrame()
 
   wxMenu *menuFile = new wxMenu();
   menuFile->Append(ID_CONNECT, "&Connect");
+  menuFile->Append(ID_SETTINGS, "&Settings");
   menuFile->Append(wxID_EXIT);
 
   wxMenu *menuHelp = new wxMenu();
@@ -47,6 +53,7 @@ TrackerFrame::TrackerFrame()
   Bind(wxEVT_MENU, &TrackerFrame::OnAbout, this, wxID_ABOUT);
   Bind(wxEVT_MENU, &TrackerFrame::OnExit, this, wxID_EXIT);
   Bind(wxEVT_MENU, &TrackerFrame::OnConnect, this, ID_CONNECT);
+  Bind(wxEVT_MENU, &TrackerFrame::OnSettings, this, ID_SETTINGS);
   Bind(wxEVT_MENU, &TrackerFrame::OnCheckForUpdates, this,
        ID_CHECK_FOR_UPDATES);
   Bind(STATE_CHANGED, &TrackerFrame::OnStateChanged, this);
@@ -119,6 +126,19 @@ void TrackerFrame::OnConnect(wxCommandEvent &event) {
   }
 }
 
+void TrackerFrame::OnSettings(wxCommandEvent &event) {
+  SettingsDialog dlg;
+
+  if (dlg.ShowModal() == wxID_OK) {
+    GetTrackerConfig().should_check_for_updates =
+        dlg.GetShouldCheckForUpdates();
+    GetTrackerConfig().hybrid_areas = dlg.GetHybridAreas();
+    GetTrackerConfig().Save();
+
+    UpdateIndicators();
+  }
+}
+
 void TrackerFrame::OnCheckForUpdates(wxCommandEvent &event) {
   CheckForUpdates(/*manual=*/true);
 }
diff --git a/src/tracker_frame.h b/src/tracker_frame.h
index 85cc7c3..e5bf97e 100644
--- a/src/tracker_frame.h
+++ b/src/tracker_frame.h
@@ -25,6 +25,7 @@ class TrackerFrame : public wxFrame {
   void OnExit(wxCommandEvent &event);
   void OnAbout(wxCommandEvent &event);
   void OnConnect(wxCommandEvent &event);
+  void OnSettings(wxCommandEvent &event);
   void OnCheckForUpdates(wxCommandEvent &event);
 
   void OnStateChanged(wxCommandEvent &event);
diff --git a/src/tracker_panel.cpp b/src/tracker_panel.cpp
index 5580068..466440f 100644
--- a/src/tracker_panel.cpp
+++ b/src/tracker_panel.cpp
@@ -3,6 +3,7 @@
 #include "ap_state.h"
 #include "area_popup.h"
 #include "game_data.h"
+#include "tracker_config.h"
 #include "tracker_state.h"
 
 constexpr int AREA_ACTUAL_SIZE = 64;
@@ -91,9 +92,17 @@ void TrackerPanel::Redraw() {
   wxMemoryDC dc;
   dc.SelectObject(rendered_);
 
-  for (AreaIndicator &area : areas_) {
-    const wxBrush *brush_color = wxGREY_BRUSH;
+  int real_area_size =
+      final_width * AREA_EFFECTIVE_SIZE / image_size.GetWidth();
+  int actual_border_size =
+      real_area_size * AREA_BORDER_SIZE / AREA_EFFECTIVE_SIZE;
+  const wxPoint upper_left_triangle[] = {
+      {0, 0}, {0, real_area_size}, {real_area_size, 0}};
+  const wxPoint lower_right_triangle[] = {{0, real_area_size - 1},
+                                          {real_area_size - 1, 0},
+                                          {real_area_size, real_area_size}};
 
+  for (AreaIndicator &area : areas_) {
     const MapArea &map_area = GD_GetMapArea(area.area_id);
     if (!AP_IsLocationVisible(map_area.classification)) {
       area.active = false;
@@ -115,27 +124,40 @@ void TrackerPanel::Redraw() {
       }
     }
 
-    if (has_reachable_unchecked && has_unreachable_unchecked) {
-      brush_color = wxYELLOW_BRUSH;
-    } else if (has_reachable_unchecked) {
-      brush_color = wxGREEN_BRUSH;
-    } else if (has_unreachable_unchecked) {
-      brush_color = wxRED_BRUSH;
-    }
-
-    int real_area_size =
-        final_width * AREA_EFFECTIVE_SIZE / image_size.GetWidth();
-    int actual_border_size =
-        real_area_size * AREA_BORDER_SIZE / AREA_EFFECTIVE_SIZE;
     int real_area_x = final_x + (map_area.map_x - (AREA_EFFECTIVE_SIZE / 2)) *
                                     final_width / image_size.GetWidth();
     int real_area_y = final_y + (map_area.map_y - (AREA_EFFECTIVE_SIZE / 2)) *
                                     final_width / image_size.GetWidth();
 
-    dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size));
-    dc.SetBrush(*brush_color);
-    dc.DrawRectangle({real_area_x, real_area_y},
-                     {real_area_size, real_area_size});
+    if (has_reachable_unchecked && has_unreachable_unchecked &&
+        GetTrackerConfig().hybrid_areas) {
+      dc.SetPen(*wxTRANSPARENT_PEN);
+      dc.SetBrush(*wxGREEN_BRUSH);
+      dc.DrawPolygon(3, upper_left_triangle, real_area_x, real_area_y);
+
+      dc.SetBrush(*wxRED_BRUSH);
+      dc.DrawPolygon(3, lower_right_triangle, real_area_x, real_area_y);
+
+      dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size));
+      dc.SetBrush(*wxTRANSPARENT_BRUSH);
+      dc.DrawRectangle({real_area_x, real_area_y},
+                       {real_area_size, real_area_size});
+
+    } else {
+      const wxBrush *brush_color = wxGREY_BRUSH;
+      if (has_reachable_unchecked && has_unreachable_unchecked) {
+        brush_color = wxYELLOW_BRUSH;
+      } else if (has_reachable_unchecked) {
+        brush_color = wxGREEN_BRUSH;
+      } else if (has_unreachable_unchecked) {
+        brush_color = wxRED_BRUSH;
+      }
+
+      dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, actual_border_size));
+      dc.SetBrush(*brush_color);
+      dc.DrawRectangle({real_area_x, real_area_y},
+                       {real_area_size, real_area_size});
+    }
 
     area.real_x1 = real_area_x;
     area.real_x2 = real_area_x + real_area_size;
-- 
cgit 1.4.1