From 88869ac1e211741b5b2fd2b9345ea779619f9d01 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Sun, 25 Feb 2024 18:25:42 +0000 Subject: [PATCH] feat: make wake calculator collapsible --- src/plugin/wake/WakeCalculatorDisplay.cpp | 45 +++++++++++++------ src/plugin/wake/WakeCalculatorDisplay.h | 9 ++-- .../plugin/wake/WakeCalculatorDisplayTest.cpp | 38 ++++++++++++++-- 3 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/plugin/wake/WakeCalculatorDisplay.cpp b/src/plugin/wake/WakeCalculatorDisplay.cpp index 30fa8130c..f656a4f01 100644 --- a/src/plugin/wake/WakeCalculatorDisplay.cpp +++ b/src/plugin/wake/WakeCalculatorDisplay.cpp @@ -6,7 +6,7 @@ #include "WakeCalculatorOptions.h" #include "WakeIntervalFormatter.h" #include "components/ClickableArea.h" -#include "components/TitleBar.h" +#include "components/CollapsibleWindowTitleBar.h" #include "euroscope/EuroscopePluginLoopbackInterface.h" #include "euroscope/EuroscopeRadarLoopbackInterface.h" #include "euroscope/UserSetting.h" @@ -27,11 +27,11 @@ namespace UKControllerPlugin::Wake { int screenObjectId) : options(std::move(options)), leadCallsignSelector(std::move(leadCallsignSelector)), followCallsignSelector(std::move(followCallsignSelector)), wakeSchemeSelector(std::move(wakeSchemeSelector)), - plugin(plugin), screenObjectId(screenObjectId), - titleBar(Components::TitleBar::Create(L"Wake Turbulence Calculator", TitleBarArea()) - ->WithDrag(this->screenObjectId) - ->WithDefaultBackgroundBrush() - ->WithDefaultTextBrush()), + plugin(plugin), titleBar(Components::CollapsibleWindowTitleBar::Create( + L"Wake Turbulence Calculator", + TitleBarArea(), + [this]() -> bool { return this->contentCollapsed; }, + screenObjectId)), backgroundBrush(std::make_shared(BACKGROUND_COLOUR)), textBrush(std::make_shared(TEXT_COLOUR)), resultBrush(std::make_shared(RESULT_COLOUR)), @@ -86,6 +86,11 @@ namespace UKControllerPlugin::Wake { options->FollowingAircraft(""); return; } + + if (objectDescription == "collapseButton") { + this->contentCollapsed = !this->contentCollapsed; + return; + } } void WakeCalculatorDisplay::Move(RECT position, std::string objectDescription) @@ -138,14 +143,19 @@ namespace UKControllerPlugin::Wake { Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { graphics.Translated(windowPosition.x, windowPosition.y, [&graphics, &radarScreen, this]() { - graphics.FillRect(this->contentArea, *backgroundBrush); - this->RenderScheme(graphics, radarScreen); - this->RenderIntermediate(graphics, radarScreen); - this->RenderMode(graphics, radarScreen); - this->RenderLead(graphics, radarScreen); - this->RenderFollowing(graphics, radarScreen); - this->RenderDividingLine(graphics); - this->RenderSeparationRequirement(graphics); + // Draw the content if not collapsed + if (!this->contentCollapsed) { + graphics.FillRect(this->contentArea, *backgroundBrush); + this->RenderScheme(graphics, radarScreen); + this->RenderIntermediate(graphics, radarScreen); + this->RenderMode(graphics, radarScreen); + this->RenderLead(graphics, radarScreen); + this->RenderFollowing(graphics, radarScreen); + this->RenderDividingLine(graphics); + this->RenderSeparationRequirement(graphics); + } + + // Do title bar, so it's always on top. titleBar->Draw(graphics, radarScreen); }); } @@ -164,6 +174,7 @@ namespace UKControllerPlugin::Wake { 0}, ""); this->visible = userSetting.GetBooleanEntry(ASR_KEY_VISIBILITY, false); + this->contentCollapsed = userSetting.GetBooleanEntry(ASR_KEY_COLLAPSED, false); } void WakeCalculatorDisplay::AsrClosingEvent(Euroscope::UserSetting& userSetting) @@ -171,6 +182,7 @@ namespace UKControllerPlugin::Wake { userSetting.Save(ASR_KEY_X_POS, ASR_DESCRIPTION_X_POS, windowPosition.x); userSetting.Save(ASR_KEY_Y_POS, ASR_DESCRIPTION_Y_POS, windowPosition.y); userSetting.Save(ASR_KEY_VISIBILITY, ASR_DESCRIPTION_VISIBILITY, visible); + userSetting.Save(ASR_KEY_COLLAPSED, ASR_DESCRIPTION_COLLAPSED, contentCollapsed); } auto WakeCalculatorDisplay::TitleBarArea() -> Gdiplus::Rect @@ -361,4 +373,9 @@ namespace UKControllerPlugin::Wake { { this->visible = !this->visible; } + + auto WakeCalculatorDisplay::IsCollapsed() const -> bool + { + return this->contentCollapsed; + } } // namespace UKControllerPlugin::Wake diff --git a/src/plugin/wake/WakeCalculatorDisplay.h b/src/plugin/wake/WakeCalculatorDisplay.h index 138df6faa..210df9e24 100644 --- a/src/plugin/wake/WakeCalculatorDisplay.h +++ b/src/plugin/wake/WakeCalculatorDisplay.h @@ -34,6 +34,7 @@ namespace UKControllerPlugin::Wake { Euroscope::EuroscopePluginLoopbackInterface& plugin, int screenObjectId); [[nodiscard]] auto IsVisible() const -> bool override; + [[nodiscard]] auto IsCollapsed() const -> bool; void LeftClick( Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, int objectId, @@ -91,9 +92,6 @@ namespace UKControllerPlugin::Wake { // For getting flightplans Euroscope::EuroscopePluginLoopbackInterface& plugin; - // The screen object id for click - const int screenObjectId; - // The titlebar std::shared_ptr titleBar; @@ -137,8 +135,13 @@ namespace UKControllerPlugin::Wake { const std::string ASR_DESCRIPTION_X_POS = "Wake Calculator X Position"; const std::string ASR_KEY_Y_POS = "wakeCalculatorYPosition"; const std::string ASR_DESCRIPTION_Y_POS = "Wake Calculator Y Position"; + const std::string ASR_KEY_COLLAPSED = "wakeCalculatorCollapsed"; + const std::string ASR_DESCRIPTION_COLLAPSED = "Wake Calculator Collapsed"; // Visibility bool visible = false; + + // Content collapsed + bool contentCollapsed = false; }; } // namespace UKControllerPlugin::Wake diff --git a/test/plugin/wake/WakeCalculatorDisplayTest.cpp b/test/plugin/wake/WakeCalculatorDisplayTest.cpp index 2ba57ec78..8bb5df8ae 100644 --- a/test/plugin/wake/WakeCalculatorDisplayTest.cpp +++ b/test/plugin/wake/WakeCalculatorDisplayTest.cpp @@ -45,6 +45,15 @@ namespace UKControllerPluginTest::Wake { EXPECT_FALSE(display.IsVisible()); } + TEST_F(WakeCalculatorDisplayTest, ItCanBeCollapsedByClickButton) + { + EXPECT_FALSE(display.IsCollapsed()); + display.LeftClick(radarScreen, 1, "collapseButton", {1, 2}, {}); + EXPECT_TRUE(display.IsCollapsed()); + display.LeftClick(radarScreen, 1, "collapseButton", {1, 2}, {}); + EXPECT_FALSE(display.IsCollapsed()); + } + TEST_F(WakeCalculatorDisplayTest, ItHasADefaultPosition) { const auto position = display.Position(); @@ -71,7 +80,7 @@ namespace UKControllerPluginTest::Wake { TEST_F(WakeCalculatorDisplayTest, AsrLoadingLoadsPosition) { - EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(1).WillRepeatedly(testing::Return("")); + EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(2).WillRepeatedly(testing::Return("")); EXPECT_CALL(mockAsrProvider, GetKey("wakeCalculatorXPosition")).Times(1).WillOnce(testing::Return("250")); @@ -85,7 +94,7 @@ namespace UKControllerPluginTest::Wake { TEST_F(WakeCalculatorDisplayTest, AsrLoadingLoadsVisibility) { - EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(2).WillRepeatedly(testing::Return("")); + EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(3).WillRepeatedly(testing::Return("")); EXPECT_CALL(mockAsrProvider, GetKey("wakeCalculatorVisibility")).Times(1).WillOnce(testing::Return("1")); @@ -93,10 +102,20 @@ namespace UKControllerPluginTest::Wake { EXPECT_TRUE(display.IsVisible()); } + TEST_F(WakeCalculatorDisplayTest, AsrLoadingLoadsCollapsed) + { + EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(3).WillRepeatedly(testing::Return("")); + + EXPECT_CALL(mockAsrProvider, GetKey("wakeCalculatorCollapsed")).Times(1).WillOnce(testing::Return("1")); + + display.AsrLoadedEvent(userSettings); + EXPECT_TRUE(display.IsCollapsed()); + } + TEST_F(WakeCalculatorDisplayTest, AsrLoadingLoadsDefaultPosition) { display.Move({300, 400, 500, 600}, ""); - EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(1).WillRepeatedly(testing::Return("")); + EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(2).WillRepeatedly(testing::Return("")); EXPECT_CALL(mockAsrProvider, GetKey("wakeCalculatorXPosition")).Times(1).WillOnce(testing::Return("")); EXPECT_CALL(mockAsrProvider, GetKey("wakeCalculatorYPosition")).Times(1).WillOnce(testing::Return("")); @@ -109,13 +128,23 @@ namespace UKControllerPluginTest::Wake { TEST_F(WakeCalculatorDisplayTest, AsrLoadingLoadsDefaultVisibility) { display.Toggle(); - EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(2).WillRepeatedly(testing::Return("")); + EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(3).WillRepeatedly(testing::Return("")); EXPECT_CALL(mockAsrProvider, GetKey("wakeCalculatorVisibility")).Times(1).WillOnce(testing::Return("")); display.AsrLoadedEvent(userSettings); EXPECT_FALSE(display.IsVisible()); } + TEST_F(WakeCalculatorDisplayTest, AsrLoadingLoadsDefaultCollapsed) + { + display.Toggle(); + EXPECT_CALL(mockAsrProvider, GetKey(testing::_)).Times(3).WillRepeatedly(testing::Return("")); + EXPECT_CALL(mockAsrProvider, GetKey("wakeCalculatorCollapsed")).Times(1).WillOnce(testing::Return("")); + + display.AsrLoadedEvent(userSettings); + EXPECT_FALSE(display.IsCollapsed()); + } + TEST_F(WakeCalculatorDisplayTest, AsrClosingSavesFields) { display.Toggle(); @@ -123,6 +152,7 @@ namespace UKControllerPluginTest::Wake { EXPECT_CALL(mockAsrProvider, SetKey("wakeCalculatorVisibility", "Wake Calculator Visibility", "1")).Times(1); EXPECT_CALL(mockAsrProvider, SetKey("wakeCalculatorXPosition", "Wake Calculator X Position", "300")).Times(1); EXPECT_CALL(mockAsrProvider, SetKey("wakeCalculatorYPosition", "Wake Calculator Y Position", "400")).Times(1); + EXPECT_CALL(mockAsrProvider, SetKey("wakeCalculatorCollapsed", "Wake Calculator Collapsed", "0")).Times(1); display.AsrClosingEvent(userSettings); }