diff --git a/ILS_Window_Plugin/ILS_Window_Plugin.vcxproj b/ILS_Window_Plugin/ILS_Window_Plugin.vcxproj
index 180c96f..41f863e 100644
--- a/ILS_Window_Plugin/ILS_Window_Plugin.vcxproj
+++ b/ILS_Window_Plugin/ILS_Window_Plugin.vcxproj
@@ -117,6 +117,7 @@
+
@@ -129,11 +130,13 @@
+
Create
Create
+
@@ -145,6 +148,8 @@
+
+
@@ -158,12 +163,14 @@
+
+
diff --git a/ILS_Window_Plugin/ILS_Window_Plugin.vcxproj.filters b/ILS_Window_Plugin/ILS_Window_Plugin.vcxproj.filters
index ac9e572..314da7b 100644
--- a/ILS_Window_Plugin/ILS_Window_Plugin.vcxproj.filters
+++ b/ILS_Window_Plugin/ILS_Window_Plugin.vcxproj.filters
@@ -81,6 +81,9 @@
Source Files\Theme\X11
+
+ Source Files
+
@@ -163,6 +166,9 @@
Header Files\Theme\X11
+
+ Header Files
+
diff --git a/ILS_Window_Plugin/IWCdeIconifyBtn.cpp b/ILS_Window_Plugin/IWCdeIconifyBtn.cpp
index acb91ef..b98c7bd 100644
--- a/ILS_Window_Plugin/IWCdeIconifyBtn.cpp
+++ b/ILS_Window_Plugin/IWCdeIconifyBtn.cpp
@@ -19,6 +19,6 @@ void IWCdeIconifyBtn::DrawSymbol(CDC* pdc, CRect rect)
icon.top = buttonFrame.top + buttonFrame.Width() * 0.4;
icon.bottom = buttonFrame.bottom - buttonFrame.Width() * 0.4;
- Draw3dRect(pdc, buttonFrame, 1, lightColor, darkColor);
- Draw3dRect(pdc, icon, 1, lightColor, darkColor);
+ DrawThick3dRect(pdc, buttonFrame, 1, lightColor, darkColor);
+ DrawThick3dRect(pdc, icon, 1, lightColor, darkColor);
}
\ No newline at end of file
diff --git a/ILS_Window_Plugin/IWCdeMenuBtn.cpp b/ILS_Window_Plugin/IWCdeMenuBtn.cpp
index 1eb860d..09bc694 100644
--- a/ILS_Window_Plugin/IWCdeMenuBtn.cpp
+++ b/ILS_Window_Plugin/IWCdeMenuBtn.cpp
@@ -16,6 +16,6 @@ void IWCdeMenuBtn::DrawSymbol(CDC* pdc, CRect rect)
barIcon.top = rect.top + rect.Height() / 2 - 2;
barIcon.bottom = barIcon.top + 4;
- Draw3dRect(pdc, rect, 1, lightColor, darkColor);
- Draw3dRect(pdc, barIcon, 1, lightColor, darkColor);
+ DrawThick3dRect(pdc, rect, 1, lightColor, darkColor);
+ DrawThick3dRect(pdc, barIcon, 1, lightColor, darkColor);
}
diff --git a/ILS_Window_Plugin/IWCdeTitleBar.cpp b/ILS_Window_Plugin/IWCdeTitleBar.cpp
index 376cb63..494732a 100644
--- a/ILS_Window_Plugin/IWCdeTitleBar.cpp
+++ b/ILS_Window_Plugin/IWCdeTitleBar.cpp
@@ -14,7 +14,7 @@ IWCdeTitleBar::IWCdeTitleBar(COLORREF backgroundColor, COLORREF textColor, COLOR
this->iconifyButton = new IWCdeIconifyBtn(backgroundColor, lightColor, darkColor);
this->menuButton = new IWCdeMenuBtn(backgroundColor, lightColor, darkColor);
- this->resizeButton = new IWX11ResizeBtn(backgroundColor);
+ this->resizeButton = new IWX11ResizeBtn(backgroundColor, textColor);
}
void IWCdeTitleBar::PositionButtons(const CRect& rect)
@@ -34,9 +34,9 @@ void IWCdeTitleBar::PositionButtons(const CRect& rect)
void IWCdeTitleBar::DrawTitle(CDC* pdc, CRect rect, CString title)
{
- Draw3dRect(pdc, titleArea, 1, lightColor, darkColor);
+ DrawThick3dRect(pdc, titleArea, 1, lightColor, darkColor);
- auto oldFont = pdc->SelectObject(this->font);
+ auto oldFont = pdc->SelectObject(this->mainFont);
pdc->SetTextColor(this->textColor);
pdc->SetBkMode(TRANSPARENT);
pdc->DrawText(_T(title), -1, titleArea, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
diff --git a/ILS_Window_Plugin/IWCdeWindow.cpp b/ILS_Window_Plugin/IWCdeWindow.cpp
index 703ad58..018af53 100644
--- a/ILS_Window_Plugin/IWCdeWindow.cpp
+++ b/ILS_Window_Plugin/IWCdeWindow.cpp
@@ -8,8 +8,8 @@ IWCdeWindow::IWCdeWindow(IWApproachDefinition selectedApproach, IWStyling stylin
, lightColor(AdjustColorBrightness(styling.windowFrameColor, 1.4))
, darkColor(AdjustColorBrightness(styling.windowFrameColor, 0.4))
{
- COLORREF textColor = RGB(styling.windowFrameTextColor.r, styling.windowFrameTextColor.g, styling.windowFrameTextColor.b);
- this->titleBar = new IWCdeTitleBar(windowBorderColor, textColor, lightColor, darkColor, this);
+ this->titleBar = new IWCdeTitleBar(windowBorderColor, styling.windowFrameTextColor, lightColor, darkColor, this);
+ this->extraMenuItemWidth = 20;
}
int IWCdeWindow::GetEdgeCursorPosition(CPoint point)
@@ -76,28 +76,28 @@ void IWCdeWindow::DrawBorder(CDC* pdc, CRect rect)
leftBorderRect.left = leftBorderRect.left + 1;
leftBorderRect.right = leftBorderRect.left + WINDOW_BORDER_THICKNESS - 1;
leftBorderRect.bottom = leftBorderRect.bottom - TITLE_BAR_HEIGHT;
- Draw3dRect(pdc, leftBorderRect, border3dSteps, lightColor, darkColor);
+ DrawThick3dRect(pdc, leftBorderRect, border3dSteps, lightColor, darkColor);
CRect bottomBorderRect = rect;
bottomBorderRect.top = bottomBorderRect.bottom - WINDOW_BORDER_THICKNESS;
bottomBorderRect.left = bottomBorderRect.left + TITLE_BAR_HEIGHT;
bottomBorderRect.right = bottomBorderRect.right - TITLE_BAR_HEIGHT;
bottomBorderRect.bottom = bottomBorderRect.bottom - 1;
- Draw3dRect(pdc, bottomBorderRect, border3dSteps, lightColor, darkColor);
+ DrawThick3dRect(pdc, bottomBorderRect, border3dSteps, lightColor, darkColor);
CRect rightBorderRect = rect;
rightBorderRect.top = rightBorderRect.top + TITLE_BAR_HEIGHT;
rightBorderRect.left = rightBorderRect.right - WINDOW_BORDER_THICKNESS;
rightBorderRect.right = rightBorderRect.right - 1;
rightBorderRect.bottom = rightBorderRect.bottom - TITLE_BAR_HEIGHT;
- Draw3dRect(pdc, rightBorderRect, border3dSteps, lightColor, darkColor);
+ DrawThick3dRect(pdc, rightBorderRect, border3dSteps, lightColor, darkColor);
CRect topBorderRect = rect;
topBorderRect.top = topBorderRect.top + 1;
topBorderRect.left = topBorderRect.left + TITLE_BAR_HEIGHT;
topBorderRect.right = topBorderRect.right - TITLE_BAR_HEIGHT;
topBorderRect.bottom = topBorderRect.top + WINDOW_BORDER_THICKNESS - 1;
- Draw3dRect(pdc, topBorderRect, border3dSteps, lightColor, darkColor);
+ DrawThick3dRect(pdc, topBorderRect, border3dSteps, lightColor, darkColor);
// Corners
@@ -106,36 +106,38 @@ void IWCdeWindow::DrawBorder(CDC* pdc, CRect rect)
topLeftCornerRect.left = topLeftCornerRect.left + 1;
topLeftCornerRect.right = topLeftCornerRect.left + TITLE_BAR_HEIGHT - 2;
topLeftCornerRect.bottom = topLeftCornerRect.top + TITLE_BAR_HEIGHT - 2;
- Draw3dCorner(pdc, topLeftCornerRect, WINDOW_BORDER_THICKNESS, border3dSteps, lightColor, darkColor, true, true);
+ DrawThick3dCorner(pdc, topLeftCornerRect, WINDOW_BORDER_THICKNESS, border3dSteps, lightColor, darkColor, true, true);
CRect topRightCornerRect = rect;
topRightCornerRect.top = topRightCornerRect.top + 1;
topRightCornerRect.left = topRightCornerRect.right - TITLE_BAR_HEIGHT;
topRightCornerRect.right = topRightCornerRect.right - 2;
topRightCornerRect.bottom = topRightCornerRect.top + TITLE_BAR_HEIGHT - 2;
- Draw3dCorner(pdc, topRightCornerRect, WINDOW_BORDER_THICKNESS, border3dSteps, lightColor, darkColor, true, false);
+ DrawThick3dCorner(pdc, topRightCornerRect, WINDOW_BORDER_THICKNESS, border3dSteps, lightColor, darkColor, true, false);
CRect bottomRightCornerRect = rect;
bottomRightCornerRect.top = bottomRightCornerRect.bottom - TITLE_BAR_HEIGHT;
bottomRightCornerRect.left = bottomRightCornerRect.right - TITLE_BAR_HEIGHT;
bottomRightCornerRect.right = bottomRightCornerRect.right - 2;
bottomRightCornerRect.bottom = bottomRightCornerRect.bottom - 2;
- Draw3dCorner(pdc, bottomRightCornerRect, WINDOW_BORDER_THICKNESS, border3dSteps, lightColor, darkColor, false, false);
+ DrawThick3dCorner(pdc, bottomRightCornerRect, WINDOW_BORDER_THICKNESS, border3dSteps, lightColor, darkColor, false, false);
CRect bottomLeftCornerRect = rect;
bottomLeftCornerRect.top = bottomLeftCornerRect.bottom - TITLE_BAR_HEIGHT;
bottomLeftCornerRect.left = bottomLeftCornerRect.left + 1;
bottomLeftCornerRect.right = bottomLeftCornerRect.left + TITLE_BAR_HEIGHT - 2;
bottomLeftCornerRect.bottom = bottomLeftCornerRect.bottom - 2;
- Draw3dCorner(pdc, bottomLeftCornerRect, WINDOW_BORDER_THICKNESS, border3dSteps, lightColor, darkColor, false, true);
+ DrawThick3dCorner(pdc, bottomLeftCornerRect, WINDOW_BORDER_THICKNESS, border3dSteps, lightColor, darkColor, false, true);
}
-COLORREF IWCdeWindow::AdjustColorBrightness(RGB color, double factor)
+COLORREF IWCdeWindow::AdjustColorBrightness(COLORREF color, double factor)
{
+ GetRValue(color);
+
// Adjust each component
- int red = static_cast(color.r * factor);
- int green = static_cast(color.g * factor);
- int blue = static_cast(color.b * factor);
+ int red = GetRValue(color) * factor;
+ int green = GetGValue(color) * factor;
+ int blue = GetBValue(color) * factor;
// Ensure the components are within the valid range
red = max(0, min(255, red));
@@ -145,3 +147,32 @@ COLORREF IWCdeWindow::AdjustColorBrightness(RGB color, double factor)
// Combine them back into a COLORREF
return RGB(red, green, blue);
}
+
+void IWCdeWindow::DrawMenuItem(CDC* pdc, CRect bounds, CString text, bool isHovered, bool isChecked)
+{
+ COLORREF bgColor = isHovered ? RGB(130, 130, 130) : RGB(152, 152, 152);
+ COLORREF textColor = RGB(255, 255, 255); // White text
+
+ std::string fullText = isChecked ? "¤ " : " ";
+ fullText += text;
+
+ CBrush brush(bgColor);
+ pdc->FillRect(&bounds, &brush);
+
+ if (isHovered) {
+ COLORREF darkened = AdjustColorBrightness(bgColor, 0.6);
+ COLORREF lightened = AdjustColorBrightness(bgColor, 1.4);
+ DrawThick3dRect(pdc, bounds, 2, darkened, lightened);
+ }
+
+ // Draw text
+ pdc->SetTextColor(textColor);
+ pdc->SetBkMode(TRANSPARENT);
+
+ CRect textArea = bounds;
+ textArea.left += 10;
+
+ CFont* oldFont = pdc->SelectObject(&mainFont);
+ pdc->DrawText(fullText.c_str(), &textArea, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
+ pdc->SelectObject(&oldFont);
+}
diff --git a/ILS_Window_Plugin/IWCdeWindow.h b/ILS_Window_Plugin/IWCdeWindow.h
index fb8b443..4c2ca1c 100644
--- a/ILS_Window_Plugin/IWCdeWindow.h
+++ b/ILS_Window_Plugin/IWCdeWindow.h
@@ -9,9 +9,11 @@ class IWCdeWindow :
private:
void DrawBorder(CDC* pdc, CRect rect) override;
- COLORREF AdjustColorBrightness(RGB color, double factor);
+ void DrawMenuItem(CDC* pdc, CRect bounds, CString text, bool isHovered, bool isChecked) override;
virtual int GetEdgeCursorPosition(CPoint point) override;
+ COLORREF AdjustColorBrightness(COLORREF color, double factor);
+
const COLORREF lightColor;
const COLORREF darkColor;
};
diff --git a/ILS_Window_Plugin/IWContextMenu.cpp b/ILS_Window_Plugin/IWContextMenu.cpp
new file mode 100644
index 0000000..9e726b2
--- /dev/null
+++ b/ILS_Window_Plugin/IWContextMenu.cpp
@@ -0,0 +1,33 @@
+#include "pch.h"
+#include "IWContextMenu.h"
+
+BEGIN_MESSAGE_MAP(IWContextMenu, CWnd)
+ ON_WM_PAINT()
+END_MESSAGE_MAP()
+
+void IWContextMenu::SubclassMenu(HWND hMenuWnd)
+{
+ // Attach to the existing menu window
+ Attach(hMenuWnd);
+}
+
+void IWContextMenu::OnPaint()
+{
+ CPaintDC dc(this); // Get device context
+
+ // Get the menu window's size
+ CRect rect;
+ GetClientRect(&rect);
+
+ // Draw the default menu first
+ DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, 0);
+
+ // Draw custom border
+ COLORREF borderColor = RGB(255, 0, 0); // Red border
+ int borderWidth = 2;
+
+ CBrush borderBrush(borderColor);
+ dc.FrameRect(&rect, &borderBrush);
+
+ // You can also use dc.DrawEdge() for different styles
+}
diff --git a/ILS_Window_Plugin/IWContextMenu.h b/ILS_Window_Plugin/IWContextMenu.h
new file mode 100644
index 0000000..aeec1ab
--- /dev/null
+++ b/ILS_Window_Plugin/IWContextMenu.h
@@ -0,0 +1,12 @@
+#pragma once
+#include
+
+class IWContextMenu : public CWnd
+{
+public:
+ void SubclassMenu(HWND hMenuWnd);
+
+protected:
+ afx_msg void OnPaint();
+ DECLARE_MESSAGE_MAP()
+};
diff --git a/ILS_Window_Plugin/IWDataTypes.h b/ILS_Window_Plugin/IWDataTypes.h
index 80c8cc0..fa82819 100644
--- a/ILS_Window_Plugin/IWDataTypes.h
+++ b/ILS_Window_Plugin/IWDataTypes.h
@@ -7,10 +7,6 @@
class IWWindow;
-struct RGB {
- int r, g, b;
-};
-
struct IWTargetPosition {
int trueAltitude;
double latitude;
@@ -49,17 +45,22 @@ enum IWTagMode {
Callsign
};
+enum IWTheme {
+ CDE,
+ X11
+};
+
struct IWStyling {
- RGB windowFrameColor;
- RGB windowFrameTextColor;
- RGB windowOuterFrameColor;
- RGB backgroundColor;
- RGB glideslopeColor;
- RGB localizerColor;
- RGB radarTargetColor;
- RGB historyTrailColor;
- RGB targetLabelColor;
- RGB rangeStatusTextColor;
+ COLORREF windowFrameColor;
+ COLORREF windowFrameTextColor;
+ COLORREF windowOuterFrameColor;
+ COLORREF backgroundColor;
+ COLORREF glideslopeColor;
+ COLORREF localizerColor;
+ COLORREF radarTargetColor;
+ COLORREF historyTrailColor;
+ COLORREF targetLabelColor;
+ COLORREF rangeStatusTextColor;
unsigned int fontSize;
bool showTagByDefault;
IWTagMode defaultTagMode;
@@ -68,4 +69,14 @@ struct IWStyling {
struct IWBehaviourSettings {
bool openWindowsBasedOnActiveRunways;
std::string windowStyle;
+};
+
+struct IWConfig {
+ IWStyling styling;
+ IWBehaviourSettings behaviour;
+};
+
+struct IWActiveRunway {
+ std::string airport;
+ std::string runway;
};
\ No newline at end of file
diff --git a/ILS_Window_Plugin/IWPlugin.cpp b/ILS_Window_Plugin/IWPlugin.cpp
index 9de3e29..54f9fd1 100644
--- a/ILS_Window_Plugin/IWPlugin.cpp
+++ b/ILS_Window_Plugin/IWPlugin.cpp
@@ -1,125 +1,24 @@
#include "pch.h"
#include "IWPlugin.h"
-#include
#include
#include "IWUtils.h"
#include
#include "IWCdeWindow.h"
#include "IWX11Window.h"
-using json = nlohmann::json;
-
-IWPlugin::IWPlugin(void) : CPlugIn(EuroScopePlugIn::COMPATIBILITY_CODE, MY_PLUGIN_NAME, MY_PLUGIN_VERSION, MY_PLUGIN_DEVELOPER, MY_PLUGIN_COPYRIGHT) {
-
- AFX_MANAGE_STATE(AfxGetStaticModuleState()); // Manage the module state for MFC
-
- // Read configuration file
- std::string jsonFilePath = GetPluginDirectory() + "\\" + CONFIG_FILE_NAME;
- availableApproaches = ReadApproachDefinitions(jsonFilePath);
- windowStyling = ReadStyling(jsonFilePath);
- behaviourSettings = ReadBehaviourSettings(jsonFilePath);
-
- // Register a custom window class
- WNDCLASS wndClass = { 0 };
- wndClass.lpfnWndProc = ::DefWindowProc;
- wndClass.hInstance = AfxGetInstanceHandle();
- wndClass.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
- wndClass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
- wndClass.lpszClassName = WINDOW_CLASS_NAME;
-
- if (!AfxRegisterClass(&wndClass))
- return;
-
- LoadSavedWindowPositions();
- SyncWithActiveRunways();
-}
-
-IWPlugin::~IWPlugin()
+IWPlugin::IWPlugin(void) :
+ CPlugIn(EuroScopePlugIn::COMPATIBILITY_CODE, MY_PLUGIN_NAME, MY_PLUGIN_VERSION, MY_PLUGIN_DEVELOPER, MY_PLUGIN_COPYRIGHT),
+ settings(this),
+ windowManager(&settings)
{
- for (const auto& window : windows) {
- if (window) {
- delete window;
- }
- }
+ this->windowManager.SyncWithActiveRunways(this->CollectActiveRunways(true));
}
-void IWPlugin::ShowWindow(IWApproachDefinition* approach)
+IWPlugin::~IWPlugin()
{
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- // Check if a window with the same title is already open
- IWWindow* windowWithSameTitle = nullptr;
- for (const auto& window : windows) {
- if (window->GetActiveApproachName() == approach->title) {
- windowWithSameTitle = window;
- break;
- }
- }
-
- if (windowWithSameTitle) {
- // Restore the window and bring it to the front
- windowWithSameTitle->ShowWindow(SW_RESTORE);
- windowWithSameTitle->SetForegroundWindow();
- return;
- }
-
- // Calculate the spawning point for the new window
- CPoint spawningPoint = CPoint(int(windows.size()) * 50, int(windows.size()) * 50 + 100);
- CSize windowSize = CSize(300, 200);
-
- // Use the saved position if there is one
- auto savedPosition = savedWindowPositions.find(approach->title);
- if (savedPosition != savedWindowPositions.end()) {
- windowSize = savedPosition->second.Size();
- spawningPoint = savedPosition->second.TopLeft();
- }
- else {
- // Use the same size as the newest window if there is one.
- IWWindow* newestWindow = windows.size() > 0 ? windows.back() : nullptr;
- if (newestWindow) {
- CRect rect;
- newestWindow->GetWindowRect(&rect);
- windowSize = rect.Size();
- spawningPoint = CPoint(rect.left + 50, rect.top + 50);
- }
- }
-
- IWWindow* newWindow = nullptr;
- if (this->behaviourSettings.windowStyle == "X11") {
- newWindow = new IWX11Window(*approach, windowStyling);
- }
- else {
- newWindow = new IWCdeWindow(*approach, windowStyling);
- }
-
- auto hwndPopup = newWindow->CreateEx(
- WS_EX_TOPMOST | WS_EX_APPWINDOW | WS_EX_NOACTIVATE,
- WINDOW_CLASS_NAME,
- _T(approach->title.c_str()),
- WS_POPUP,
- spawningPoint.x,
- spawningPoint.y,
- windowSize.cx,
- windowSize.cy,
- nullptr,
- nullptr
- );
-
- if (!hwndPopup) {
- delete newWindow;
- return;
- }
-
- newWindow->SetMenu(NULL);
- newWindow->ShowWindow(SW_SHOWNOACTIVATE); // Show but don't steal focus
- newWindow->UpdateWindow();
- newWindow->SetListener(this);
- newWindow->SetAvailableApproaches(availableApproaches);
-
- windows.push_back(newWindow);
+
}
-
void IWPlugin::OnTimer(int seconds)
{
IWLiveData liveData;
@@ -173,14 +72,12 @@ void IWPlugin::OnTimer(int seconds)
}
}
- for (auto& window : windows) {
- window->SendMessage(WM_UPDATE_DATA, reinterpret_cast(&liveData));
- }
+ windowManager.HandleLiveData(liveData);
}
void IWPlugin::OnAirportRunwayActivityChanged()
{
- SyncWithActiveRunways();
+ this->windowManager.SyncWithActiveRunways(CollectActiveRunways(true));
}
void IWPlugin::OnNewMetarReceived(const char* sStation, const char* sFullMetar)
@@ -201,17 +98,9 @@ void IWPlugin::OnNewMetarReceived(const char* sStation, const char* sFullMetar)
}
}
-void IWPlugin::SyncWithActiveRunways()
+std::vector IWPlugin::CollectActiveRunways(bool forArrival)
{
- if (!behaviourSettings.openWindowsBasedOnActiveRunways) {
- return;
- }
-
- AFX_MANAGE_STATE(AfxGetStaticModuleState());
-
- bool forArrival = true;
-
- std::vector approachesThatShouldBeOpen;
+ std::vector activeRunways;
for (auto airport = this->SectorFileElementSelectFirst(EuroScopePlugIn::SECTOR_ELEMENT_AIRPORT); airport.IsValid(); airport = this->SectorFileElementSelectNext(airport, EuroScopePlugIn::SECTOR_ELEMENT_AIRPORT)) {
if (airport.IsElementActive(!forArrival)) {
@@ -222,14 +111,11 @@ void IWPlugin::SyncWithActiveRunways()
for (int runwayDirection = 0; runwayDirection < 2; runwayDirection++) {
if (runway.IsElementActive(!forArrival, runwayDirection) && runwayAirportName == activeAirportIcao) {
auto runwayName = trimString(std::string(runway.GetRunwayName(runwayDirection)));
- auto approach = std::find_if(this->availableApproaches.begin(), this->availableApproaches.end(),
- [&runwayAirportName, runwayName](const IWApproachDefinition& approach) {
- return approach.airport == runwayAirportName && approach.runway == runwayName;
- });
-
- if (approach != this->availableApproaches.end()) {
- approachesThatShouldBeOpen.push_back(&(*approach));
- }
+
+ activeRunways.push_back({
+ runwayAirportName,
+ runwayName
+ });
}
}
}
@@ -237,248 +123,9 @@ void IWPlugin::SyncWithActiveRunways()
}
}
- // Find open windows that should be closed
- for (auto& window : windows) {
- bool shouldBeClosed = true;
- for (auto& approach : approachesThatShouldBeOpen) {
- if (window->GetActiveApproachName() == approach->title) {
- shouldBeClosed = false;
- }
- }
- if (shouldBeClosed) {
- window->DestroyWindow();
- }
- }
-
- // Open windows that should be open
- for (auto& approach : approachesThatShouldBeOpen) {
- bool alreadyOpen = std::any_of(windows.begin(), windows.end(), [&approach](const IWWindow* window) {
- return window->GetActiveApproachName() == approach->title;
- });
-
- if (!alreadyOpen) {
- this->ShowWindow(approach);
- }
- }
+ return activeRunways;
}
-std::vector IWPlugin::ReadApproachDefinitions(const std::string& jsonFilePath) {
- const std::string generalErrorMessage = "Could not load approach definitions";
-
- std::vector approaches;
-
- // Open the JSON file
- std::ifstream file(jsonFilePath);
- if (!file.is_open()) {
- this->ShowErrorMessage(generalErrorMessage, "Unable to open JSON file '" + jsonFilePath + "'");
- return approaches;
- }
-
- // Parse the JSON file
- nlohmann::json jsonData;
- try {
- file >> jsonData;
- }
- catch (const nlohmann::json::parse_error& e) {
- this->ShowErrorMessage(generalErrorMessage, std::string(e.what()));
- return approaches;
- }
-
- // Check if "approaches" key exists
- if (!jsonData.contains("approaches") || !jsonData["approaches"].is_array()) {
- this->ShowErrorMessage(generalErrorMessage, "'approaches' key not found or is not an array.");
- return approaches;
- }
-
- // Iterate over the approaches
- for (const auto& approachJson : jsonData["approaches"]) {
- try {
- IWApproachDefinition approach;
-
- // Parse individual fields
- approach.title = approachJson.at("title").get();
- approach.airport = approachJson.at("airport").get();
- approach.runway = approachJson.at("runway").get();
- approach.localizerCourse = approachJson.at("localizerCourse").get();
- approach.glideslopeAngle = approachJson.at("glideslopeAngle").get();
- approach.defaultRange = approachJson.at("defaultRange").get();
- approach.thresholdAltitude = approachJson.at("thresholdAltitude").get();
- approach.thresholdLatitude = approachJson.at("thresholdLatitude").get();
- approach.thresholdLongitude = approachJson.at("thresholdLongitude").get();
- approach.maxOffsetLeft = approachJson.at("maxOffsetLeft").get();
- approach.maxOffsetRight = approachJson.at("maxOffsetRight").get();
-
-
- // Add to the list
- approaches.push_back(approach);
- }
- catch (const nlohmann::json::exception& e) {
- this->ShowErrorMessage(generalErrorMessage, "Error parsing approach data: " + std::string(e.what()));
- }
- }
-
- return approaches;
-}
-
-IWStyling IWPlugin::ReadStyling(const std::string& jsonFilePath) {
- const std::string generalErrorMessage = "Could not load style settings";
-
- std::ifstream file(jsonFilePath);
- if (!file.is_open()) {
- this->ShowErrorMessage(generalErrorMessage, "Unable to open JSON file: " + jsonFilePath);
- }
-
- nlohmann::json jsonData;
- file >> jsonData;
-
- auto readColor = [&jsonData, &generalErrorMessage, this](const std::string& key) -> RGB {
- if (jsonData.contains("styling") && jsonData["styling"].contains(key)) {
- return HexToRGB(jsonData["styling"][key].get());
- }
- this->ShowErrorMessage(generalErrorMessage, ("'" + key + "' key not found.").c_str());
- };
-
- auto readUnsignedInt = [&jsonData, &generalErrorMessage, this](const std::string& key) -> unsigned int {
- if (jsonData.contains("styling") && jsonData["styling"].contains(key)) {
- return jsonData["styling"][key].get();
- }
- this->ShowErrorMessage(generalErrorMessage, ("'" + key + "' key not found.").c_str());
- return 0; // Default value when key is not found or is not an unsigned integer
- };
-
- auto readUIntWithDefault = [&jsonData, this](const std::string& key, unsigned int defaultValue) -> unsigned int {
- if (jsonData.contains("styling") && jsonData["styling"].contains(key)) {
- return jsonData["styling"][key].get();
- }
- return defaultValue;
- };
-
- auto readStringWithDefault = [&jsonData, this](const std::string& key, const std::string& defaultValue) -> std::string {
- if (jsonData.contains("styling") && jsonData["styling"].contains(key)) {
- return jsonData["styling"][key].get();
- }
- return defaultValue;
- };
-
- auto stringToTagMode = [](const std::string& value) -> IWTagMode {
- if (value == "squawk") {
- return IWTagMode::Squawk;
- }
- return IWTagMode::Callsign;
- };
-
- auto readBoolWithDefault = [&jsonData, this](const std::string& key, bool defaultValue) -> bool {
- if (jsonData.contains("styling") && jsonData["styling"].contains(key)) {
- return jsonData["styling"][key].get();
- }
- return defaultValue;
- };
-
- return IWStyling{
- readColor("windowFrameColor"),
- readColor("windowFrameTextColor"),
- readColor("windowOuterFrameColor"),
- readColor("backgroundColor"),
- readColor("glideslopeColor"),
- readColor("localizerColor"),
- readColor("radarTargetColor"),
- readColor("historyTrailColor"),
- readColor("targetLabelColor"),
- readColor("rangeStatusTextColor"),
- readUIntWithDefault("fontSize", 12),
- readBoolWithDefault("showTagByDefault", true),
- stringToTagMode(readStringWithDefault("defaultTagMode", "callsign"))
- };
-}
-
-IWBehaviourSettings IWPlugin::ReadBehaviourSettings(const std::string& jsonFilePath) {
- std::ifstream file(jsonFilePath);
- if (!file.is_open()) {
- this->ShowErrorMessage("Could not load behaviour options", "Unable to open JSON file '" + jsonFilePath + "'");
- }
-
- nlohmann::json jsonData;
- file >> jsonData;
-
- nlohmann::json jsonObject = jsonData["behaviour"];
-
- auto readStringWithDefault = [&jsonData, this](const std::string& key, const std::string& defaultValue) -> std::string {
- if (jsonData.contains("behaviour") && jsonData["behaviour"].contains(key)) {
- return jsonData["behaviour"][key].get();
- }
- return defaultValue;
- };
-
- return IWBehaviourSettings{
- jsonObject.at("openWindowsBasedOnActiveRunways").get(),
- readStringWithDefault("windowStyle", "X11")
- };
-}
-
-std::string IWPlugin::GetPluginDirectory() {
- char modulePath[MAX_PATH];
- GetModuleFileNameA((HINSTANCE)&__ImageBase, modulePath, sizeof(modulePath));
- std::string pluginDirectory = std::string(modulePath).substr(0, std::string(modulePath).find_last_of("\\/"));
- return pluginDirectory;
-}
-
-void IWPlugin::OnWindowClosed(IWWindow* window)
-{
- auto it = std::find(windows.begin(), windows.end(), window);
- if (it != windows.end()) {
- windows.erase(it);
- }
-}
-
-void IWPlugin::OnWindowMenuOpenNew(std::string approachTitle)
-{
- auto selectedApproach = std::find_if(availableApproaches.begin(), availableApproaches.end(),
- [&approachTitle](const IWApproachDefinition& approach) {
- return approach.title == approachTitle;
- });
-
- if (selectedApproach != availableApproaches.end()) {
- ShowWindow(&(*selectedApproach));
- }
- else {
- ShowWindow(&availableApproaches[0]);
- }
-}
-
-void IWPlugin::OnWindowRectangleChanged(IWWindow* window)
-{
- CRect windowRect;
- window->GetWindowRect(&windowRect);
- std::string name = window->GetActiveApproachName();
- std::string description = name + " pos.";
- std::string rect = std::to_string(windowRect.left) + "," + std::to_string(windowRect.top) + "," + std::to_string(windowRect.right) + "," + std::to_string(windowRect.bottom);
- SaveDataToSettings(name.c_str(), description.c_str(), rect.c_str());
-
- savedWindowPositions[name] = windowRect;
-}
-
-void IWPlugin::LoadSavedWindowPositions()
-{
- // For every available approach, check if there is a saved position
- for (auto& approach : availableApproaches) {
- const char* settings = GetDataFromSettings(approach.title.c_str());
- if (settings) {
- std::string settingsString = std::string(settings);
- std::regex regex("([0-9]+),([0-9]+),([0-9]+),([0-9]+)");
- std::smatch match;
- if (std::regex_search(settingsString, match, regex)) {
- CRect rect;
- rect.left = std::stoi(match[1]);
- rect.top = std::stoi(match[2]);
- rect.right = std::stoi(match[3]);
- rect.bottom = std::stoi(match[4]);
- savedWindowPositions[approach.title] = rect;
- }
- }
- }
-}
-
-
bool IWPlugin::OnCompileCommand(const char* sCommandLine)
{
const std::string generalError = "Could not open ILS window";
@@ -490,28 +137,20 @@ bool IWPlugin::OnCompileCommand(const char* sCommandLine)
}
// Extract the argument after ".ils "
- std::string argument = stringToUpper(trimString(command.substr(prefix.length())));
-
- if (argument.empty()) {
+ std::string approachName = stringToUpper(trimString(command.substr(prefix.length())));
+ if (approachName.empty()) {
this->ShowErrorMessage(generalError, "No approach name specified after '.ils'.");
return false;
}
- // Find the approach by title
- auto it = std::find_if(this->availableApproaches.begin(), this->availableApproaches.end(),
- [&argument](const IWApproachDefinition& approach) {
- return approach.title == argument;
- });
+ bool success = this->windowManager.Open(approachName);
- if (it != this->availableApproaches.end()) {
- // Approach found: Open the approach window
- this->ShowWindow(&(*it));
- return true; // Command handled
+ if (!success) {
+ this->ShowErrorMessage(generalError, "Could not find approach with name '" + approachName + "'.");
+ return false;
}
else {
- // Approach not found
- this->ShowErrorMessage(generalError, "Approach '" + argument + "' not found.");
- return false; // Command not handled
+ return true; // Command was handled
}
}
diff --git a/ILS_Window_Plugin/IWPlugin.h b/ILS_Window_Plugin/IWPlugin.h
index cc1eadd..ce2017e 100644
--- a/ILS_Window_Plugin/IWPlugin.h
+++ b/ILS_Window_Plugin/IWPlugin.h
@@ -2,51 +2,28 @@
#include
#include
-#include "IWWindow.h"
#include "IWDataTypes.h"
#include