From 49dbf1656a1203f7981b988c8393c53a72172904 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Tue, 22 Mar 2022 16:37:15 +0000 Subject: [PATCH 01/18] Mapping element --- src/plugin/CMakeLists.txt | 5 ++ src/plugin/mapping/DisplayRule.h | 18 +++++ src/plugin/mapping/MappingElement.cpp | 54 ++++++++++++++ src/plugin/mapping/MappingElement.h | 48 +++++++++++++ src/plugin/mapping/MappingElementDrawer.h | 22 ++++++ src/plugin/mapping/MappingElementInterface.h | 47 ++++++++++++ test/plugin/CMakeLists.txt | 7 +- test/plugin/mapping/MappingElementTest.cpp | 75 ++++++++++++++++++++ test/plugin/mock/MockDisplayRule.h | 10 +++ test/plugin/mock/MockMappingElementDrawer.h | 13 ++++ test/plugin/pch/pch.h | 2 + 11 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 src/plugin/mapping/DisplayRule.h create mode 100644 src/plugin/mapping/MappingElement.cpp create mode 100644 src/plugin/mapping/MappingElement.h create mode 100644 src/plugin/mapping/MappingElementDrawer.h create mode 100644 src/plugin/mapping/MappingElementInterface.h create mode 100644 test/plugin/mapping/MappingElementTest.cpp create mode 100644 test/plugin/mock/MockDisplayRule.h create mode 100644 test/plugin/mock/MockMappingElementDrawer.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 78f0b4aa0..94add81f6 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -487,6 +487,10 @@ set(src__login ) source_group("src\\login" FILES ${src__login}) +set(src__mapping + mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h) +source_group("src\\mapping" FILES ${src__mapping}) + set(src__message "message/MessageSerializableInterface.h" "message/UserMessager.cpp" @@ -965,6 +969,7 @@ set(ALL_FILES ${src__intention} ${src__list} ${src__login} + ${src__mapping} ${src__message} ${src__metar} ${src__minstack} diff --git a/src/plugin/mapping/DisplayRule.h b/src/plugin/mapping/DisplayRule.h new file mode 100644 index 000000000..683d847bf --- /dev/null +++ b/src/plugin/mapping/DisplayRule.h @@ -0,0 +1,18 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + /** + * A rule as to whether a particular mapping element should be displayed. + */ + class DisplayRule + { + public: + virtual ~DisplayRule() = default; + + /** + * Returns true if the rule passes and thus the element should + * be rendered. + */ + [[nodiscard]] virtual auto Passes() -> bool = 0; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElement.cpp b/src/plugin/mapping/MappingElement.cpp new file mode 100644 index 000000000..31e476ec8 --- /dev/null +++ b/src/plugin/mapping/MappingElement.cpp @@ -0,0 +1,54 @@ +#include "DisplayRule.h" +#include "MappingElement.h" +#include "MappingElementDrawer.h" + +namespace UKControllerPlugin::Mapping { + + MappingElement::MappingElement( + int id, + std::string type, + std::string label, + EuroScopePlugIn::CPosition position, + std::set> displayRules, + std::shared_ptr drawer) + : id(id), type(std::move(type)), label(std::move(label)), position(std::move(position)), + displayRules(std::move(displayRules)), drawer(std::move(drawer)) + { + } + + auto MappingElement::Id() const -> int + { + return id; + } + + auto MappingElement::Type() const -> const std::string& + { + return type; + } + + auto MappingElement::Label() const -> const std::string& + { + return label; + } + + auto MappingElement::ShouldDisplay() const -> bool + { + for (const auto& rule : displayRules) { + if (!rule->Passes()) { + return false; + } + } + + return true; + } + + auto MappingElement::Position() const -> const EuroScopePlugIn::CPosition& + { + return position; + } + + void MappingElement::Draw(Graphics::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) + { + this->drawer->Draw(graphics, area); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElement.h b/src/plugin/mapping/MappingElement.h new file mode 100644 index 000000000..646680ca3 --- /dev/null +++ b/src/plugin/mapping/MappingElement.h @@ -0,0 +1,48 @@ +#pragma once +#include "MappingElementInterface.h" + +namespace UKControllerPlugin::Mapping { + class DisplayRule; + class MappingElementDrawer; + + /** + * Represents something that can be drawn onto the map. + */ + class MappingElement : public MappingElementInterface + { + public: + MappingElement( + int id, + std::string type, + std::string label, + EuroScopePlugIn::CPosition position, + std::set> displayRules, + std::shared_ptr drawer + ); + [[nodiscard]] auto Id() const -> int override; + [[nodiscard]] auto Type() const -> const std::string& override; + [[nodiscard]] auto Label() const -> const std::string& override; + [[nodiscard]] auto ShouldDisplay() const -> bool override; + [[nodiscard]] auto Position() const -> const EuroScopePlugIn::CPosition& override; + void Draw(Graphics::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) override; + + private: + // The id of the element, is only unique within a type + int id; + + // The type of the element, e.g. visual_reference_point + std::string type; + + // The label that accompanies the element. + std::string label; + + // The position of the element + EuroScopePlugIn::CPosition position; + + // Display rules + std::set> displayRules; + + // Draws the element + std::shared_ptr drawer; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementDrawer.h b/src/plugin/mapping/MappingElementDrawer.h new file mode 100644 index 000000000..8d5bf2d97 --- /dev/null +++ b/src/plugin/mapping/MappingElementDrawer.h @@ -0,0 +1,22 @@ +#pragma once + +namespace UKControllerPlugin::Graphics { + class GdiGraphicsInterface; +} // namespace UKControllerPlugin::Graphics + +namespace UKControllerPlugin::Mapping { + + /** + * A class that knows how to draw a mapping element. + */ + class MappingElementDrawer + { + public: + virtual ~MappingElementDrawer() = default; + + /** + * Draw the mapping element. The area is centered on the centre of the element. + */ + virtual void Draw(Graphics::GdiGraphicsInterface& graphics, const Gdiplus::Rect& area) = 0; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementInterface.h b/src/plugin/mapping/MappingElementInterface.h new file mode 100644 index 000000000..3ab014b68 --- /dev/null +++ b/src/plugin/mapping/MappingElementInterface.h @@ -0,0 +1,47 @@ +#pragma once + +namespace UKControllerPlugin::Graphics { + class GdiGraphicsInterface; +} // namespace UKControllerPlugin::Graphics + +namespace UKControllerPlugin::Mapping { + /** + * An element that can be drawn or otherwise represented on the + * map. + */ + class MappingElementInterface + { + public: + virtual ~MappingElementInterface() = default; + + /** + * The id of the element. + */ + [[nodiscard]] virtual auto Id() const -> int = 0; + + /** + * The type of the element to be drawn. + */ + [[nodiscard]] virtual auto Type() const -> const std::string& = 0; + + /** + * The label associated with the element. + */ + [[nodiscard]] virtual auto Label() const -> const std::string& = 0; + + /** + * The label associated with the element. + */ + [[nodiscard]] virtual auto Position() const -> const EuroScopePlugIn::CPosition& = 0; + + /** + * Should we be displaying the mapping element + */ + [[nodiscard]] virtual auto ShouldDisplay() const -> bool = 0; + + /** + * Draw the mapping element. The area is centered on the centre of the element. + */ + virtual void Draw(Graphics::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) = 0; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/test/plugin/CMakeLists.txt b/test/plugin/CMakeLists.txt index 1c4f8d81d..f79ba3d3a 100644 --- a/test/plugin/CMakeLists.txt +++ b/test/plugin/CMakeLists.txt @@ -260,6 +260,10 @@ set(test__login ) source_group("test\\login" FILES ${test__login}) +set(test__mapping + mapping/MappingElementTest.cpp) +source_group("test\\mapping" FILES ${test__mapping}) + set(test__message "message/UserMessagerBootstrapTest.cpp" "message/UserMessagerTest.cpp" @@ -356,7 +360,7 @@ set(test__mock mock/MockCallsignSelectionProvider.h mock/MockAircraftTypeMapper.h mock/MockWakeCategoryMapper.h - mock/MockListItemProvider.h mock/MockPopupList.h mock/MockBootstrapProvider.h mock/MockPluginSettingsProvider.h) + mock/MockListItemProvider.h mock/MockPopupList.h mock/MockBootstrapProvider.h mock/MockPluginSettingsProvider.h mock/MockDisplayRule.h mock/MockMappingElementDrawer.h) source_group("test\\mock" FILES ${test__mock}) set(test__navaids @@ -607,6 +611,7 @@ set(ALL_FILES ${test__intention} ${test__list} ${test__login} + ${test__mapping} ${test__message} ${test__metar} ${test__minstack} diff --git a/test/plugin/mapping/MappingElementTest.cpp b/test/plugin/mapping/MappingElementTest.cpp new file mode 100644 index 000000000..46392e0f0 --- /dev/null +++ b/test/plugin/mapping/MappingElementTest.cpp @@ -0,0 +1,75 @@ +#include "mapping/MappingElement.h" + +using UKControllerPlugin::Mapping::DisplayRule; +using UKControllerPlugin::Mapping::MappingElement; + +namespace UKControllerPluginTest::Mapping { + class MappingElementTest : public testing::Test + { + public: + MappingElementTest() + : displayRule1(std::make_shared>()), + displayRule2(std::make_shared>()), + displayRules({displayRule1, displayRule2}), + drawer(std::make_shared>()), + element(1, "visual_reference_point", "M5 Avon Bridge", Position(), displayRules, drawer) + { + } + + [[nodiscard]] static auto Position() -> EuroScopePlugIn::CPosition + { + EuroScopePlugIn::CPosition position; + position.m_Latitude = 1; + position.m_Longitude = 2; + + return position; + } + + testing::NiceMock graphics; + std::shared_ptr> displayRule1; + std::shared_ptr> displayRule2; + std::set> displayRules; + std::shared_ptr> drawer; + MappingElement element; + }; + + TEST_F(MappingElementTest, ItHasAnId) + { + EXPECT_EQ(1, element.Id()); + } + + TEST_F(MappingElementTest, ItHasAType) + { + EXPECT_EQ("visual_reference_point", element.Type()); + } + + TEST_F(MappingElementTest, ItHasALabel) + { + EXPECT_EQ("M5 Avon Bridge", element.Label()); + } + + TEST_F(MappingElementTest, ItHasAPosition) + { + const auto position = element.Position(); + EXPECT_EQ(1, position.m_Latitude); + EXPECT_EQ(2, position.m_Longitude); + } + + TEST_F(MappingElementTest, ItShouldDisplayIfAllRulesPass) + { + ON_CALL(*displayRule1, Passes()).WillByDefault(testing::Return(true)); + + ON_CALL(*displayRule2, Passes()).WillByDefault(testing::Return(true)); + + EXPECT_TRUE(element.ShouldDisplay()); + } + + TEST_F(MappingElementTest, ItShouldNotDisplayIfARuleDoesNotPass) + { + ON_CALL(*displayRule1, Passes()).WillByDefault(testing::Return(true)); + + ON_CALL(*displayRule2, Passes()).WillByDefault(testing::Return(false)); + + EXPECT_FALSE(element.ShouldDisplay()); + } +} // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/mock/MockDisplayRule.h b/test/plugin/mock/MockDisplayRule.h new file mode 100644 index 000000000..b3f605aa5 --- /dev/null +++ b/test/plugin/mock/MockDisplayRule.h @@ -0,0 +1,10 @@ +#pragma once +#include "mapping/DisplayRule.h" + +namespace UKControllerPluginTest::Mapping { + class MockDisplayRule : public UKControllerPlugin::Mapping::DisplayRule + { + public: + MOCK_METHOD(bool, Passes, (), (override)); + }; +} // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/mock/MockMappingElementDrawer.h b/test/plugin/mock/MockMappingElementDrawer.h new file mode 100644 index 000000000..f6a11e6ef --- /dev/null +++ b/test/plugin/mock/MockMappingElementDrawer.h @@ -0,0 +1,13 @@ +#pragma once +#include "mapping/MappingElementDrawer.h" + +using UKControllerPlugin::Graphics::GdiGraphicsInterface; +using UKControllerPlugin::Mapping::MappingElementDrawer; + +namespace UKControllerPluginTest::Mapping { + class MockMappingElementDrawer : public MappingElementDrawer + { + public: + MOCK_METHOD(void, Draw, (GdiGraphicsInterface&, const Gdiplus::Rect&), (override)); + }; +} // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/pch/pch.h b/test/plugin/pch/pch.h index 20a38324f..fca1f6a56 100644 --- a/test/plugin/pch/pch.h +++ b/test/plugin/pch/pch.h @@ -36,6 +36,7 @@ #include "../mock/MockConnection.h" #include "../mock/MockControllerStatusEventHandlerInterface.h" #include "../mock/MockDependencyLoader.h" +#include "../mock/MockDisplayRule.h" #include "../mock/MockEuroScopeCControllerInterface.h" #include "../mock/MockEuroScopeCFlightplanInterface.h" #include "../mock/MockEuroScopeCRadarTargetInterface.h" @@ -52,6 +53,7 @@ #include "../mock/MockHistoryTrailRepository.h" #include "../mock/MockIntegrationActionProcessor.h" #include "../mock/MockListItemProvider.h" +#include "../mock/MockMappingElementDrawer.h" #include "../mock/MockMenuToggleableDisplay.h" #include "../mock/MockMetarEventHandler.h" #include "../mock/MockOutboundIntegrationEventHandler.h" From 8dc09ab7e2c093548b96140afcb7b1e00a0c7e83 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Tue, 22 Mar 2022 16:55:31 +0000 Subject: [PATCH 02/18] Draw VRP --- src/plugin/CMakeLists.txt | 2 +- src/plugin/mapping/MappingElement.cpp | 2 +- src/plugin/mapping/MappingElement.h | 7 +++---- src/plugin/mapping/MappingElementDrawer.h | 6 +++--- src/plugin/mapping/MappingElementInterface.h | 6 +++--- src/plugin/mapping/VisualReferencePoint.cpp | 22 ++++++++++++++++++++ src/plugin/mapping/VisualReferencePoint.h | 17 +++++++++++++++ test/plugin/mapping/MappingElementTest.cpp | 8 +++++++ 8 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 src/plugin/mapping/VisualReferencePoint.cpp create mode 100644 src/plugin/mapping/VisualReferencePoint.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 94add81f6..64c7e95ce 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -488,7 +488,7 @@ set(src__login source_group("src\\login" FILES ${src__login}) set(src__mapping - mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h) + mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h) source_group("src\\mapping" FILES ${src__mapping}) set(src__message diff --git a/src/plugin/mapping/MappingElement.cpp b/src/plugin/mapping/MappingElement.cpp index 31e476ec8..7f9b48aaa 100644 --- a/src/plugin/mapping/MappingElement.cpp +++ b/src/plugin/mapping/MappingElement.cpp @@ -47,7 +47,7 @@ namespace UKControllerPlugin::Mapping { return position; } - void MappingElement::Draw(Graphics::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) + void MappingElement::Draw(Windows::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) { this->drawer->Draw(graphics, area); } diff --git a/src/plugin/mapping/MappingElement.h b/src/plugin/mapping/MappingElement.h index 646680ca3..1264265d4 100644 --- a/src/plugin/mapping/MappingElement.h +++ b/src/plugin/mapping/MappingElement.h @@ -17,14 +17,13 @@ namespace UKControllerPlugin::Mapping { std::string label, EuroScopePlugIn::CPosition position, std::set> displayRules, - std::shared_ptr drawer - ); + std::shared_ptr drawer); [[nodiscard]] auto Id() const -> int override; [[nodiscard]] auto Type() const -> const std::string& override; [[nodiscard]] auto Label() const -> const std::string& override; [[nodiscard]] auto ShouldDisplay() const -> bool override; [[nodiscard]] auto Position() const -> const EuroScopePlugIn::CPosition& override; - void Draw(Graphics::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) override; + void Draw(Windows::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) override; private: // The id of the element, is only unique within a type @@ -41,7 +40,7 @@ namespace UKControllerPlugin::Mapping { // Display rules std::set> displayRules; - + // Draws the element std::shared_ptr drawer; }; diff --git a/src/plugin/mapping/MappingElementDrawer.h b/src/plugin/mapping/MappingElementDrawer.h index 8d5bf2d97..eb68ac86d 100644 --- a/src/plugin/mapping/MappingElementDrawer.h +++ b/src/plugin/mapping/MappingElementDrawer.h @@ -1,8 +1,8 @@ #pragma once -namespace UKControllerPlugin::Graphics { +namespace UKControllerPlugin::Windows { class GdiGraphicsInterface; -} // namespace UKControllerPlugin::Graphics +} // namespace UKControllerPlugin::Windows namespace UKControllerPlugin::Mapping { @@ -17,6 +17,6 @@ namespace UKControllerPlugin::Mapping { /** * Draw the mapping element. The area is centered on the centre of the element. */ - virtual void Draw(Graphics::GdiGraphicsInterface& graphics, const Gdiplus::Rect& area) = 0; + virtual void Draw(Windows::GdiGraphicsInterface& graphics, const Gdiplus::Rect& area) = 0; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementInterface.h b/src/plugin/mapping/MappingElementInterface.h index 3ab014b68..dcafa56c1 100644 --- a/src/plugin/mapping/MappingElementInterface.h +++ b/src/plugin/mapping/MappingElementInterface.h @@ -1,8 +1,8 @@ #pragma once -namespace UKControllerPlugin::Graphics { +namespace UKControllerPlugin::Windows { class GdiGraphicsInterface; -} // namespace UKControllerPlugin::Graphics +} // namespace UKControllerPlugin::Windows namespace UKControllerPlugin::Mapping { /** @@ -42,6 +42,6 @@ namespace UKControllerPlugin::Mapping { /** * Draw the mapping element. The area is centered on the centre of the element. */ - virtual void Draw(Graphics::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) = 0; + virtual void Draw(Windows::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) = 0; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePoint.cpp b/src/plugin/mapping/VisualReferencePoint.cpp new file mode 100644 index 000000000..35b3a1d83 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePoint.cpp @@ -0,0 +1,22 @@ +#include "VisualReferencePoint.h" +#include "graphics/GdiGraphicsInterface.h" + +namespace UKControllerPlugin::Mapping { + + VisualReferencePoint::VisualReferencePoint() : pen(std::make_shared(Gdiplus::Color(50, 127, 168))) + { + } + + void VisualReferencePoint::Draw(Windows::GdiGraphicsInterface& graphics, const Gdiplus::Rect& area) + { + graphics.DrawCircle(area, *pen); + graphics.DrawLine( + *pen, + Gdiplus::PointF{static_cast(area.Width / 2), 0}, + Gdiplus::PointF{static_cast(area.Width / 2), static_cast(area.Height)}); + graphics.DrawLine( + *pen, + Gdiplus::PointF{0, static_cast(area.Height / 2)}, + Gdiplus::PointF{static_cast(area.Width), static_cast(area.Height / 2)}); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePoint.h b/src/plugin/mapping/VisualReferencePoint.h new file mode 100644 index 000000000..ad8bc4c86 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePoint.h @@ -0,0 +1,17 @@ +#pragma once +#include "MappingElementDrawer.h" + +namespace UKControllerPlugin::Mapping { + /** + * Draws a visual reference point. + */ + class VisualReferencePoint : public MappingElementDrawer + { + public: + VisualReferencePoint(); + void Draw(Windows::GdiGraphicsInterface& graphics, const Gdiplus::Rect& area) override; + + private: + std::shared_ptr pen; + }; +} // diff --git a/test/plugin/mapping/MappingElementTest.cpp b/test/plugin/mapping/MappingElementTest.cpp index 46392e0f0..13b2f32c4 100644 --- a/test/plugin/mapping/MappingElementTest.cpp +++ b/test/plugin/mapping/MappingElementTest.cpp @@ -72,4 +72,12 @@ namespace UKControllerPluginTest::Mapping { EXPECT_FALSE(element.ShouldDisplay()); } + + TEST_F(MappingElementTest, ItDraws) + { + EXPECT_CALL(*drawer, Draw(testing::_, testing::_)).Times(1); + + Gdiplus::Rect rect{1, 2, 3, 4}; + element.Draw(graphics, rect); + } } // namespace UKControllerPluginTest::Mapping From f6920ef9ed1469b21cb0f31f4c6d83333112df27 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Thu, 24 Mar 2022 17:32:38 +0000 Subject: [PATCH 03/18] Elements and collection --- src/plugin/CMakeLists.txt | 2 +- .../BootstrapProviderCollectionFactory.cpp | 2 + src/plugin/bootstrap/ModuleFactories.cpp | 11 ++ src/plugin/bootstrap/ModuleFactories.h | 8 + .../mapping/MappingBootstrapProvider.cpp | 23 +++ src/plugin/mapping/MappingBootstrapProvider.h | 19 ++ src/plugin/mapping/MappingElement.cpp | 14 +- src/plugin/mapping/MappingElement.h | 9 +- src/plugin/mapping/MappingElementDrawer.h | 14 +- src/plugin/mapping/MappingElementInterface.h | 19 +- src/plugin/mapping/MappingElementManager.cpp | 26 +++ src/plugin/mapping/MappingElementManager.h | 22 +++ .../mapping/MappingElementManagerFactory.cpp | 50 +++++ .../mapping/MappingElementManagerFactory.h | 15 ++ src/plugin/mapping/MappingModuleFactory.cpp | 26 +++ src/plugin/mapping/MappingModuleFactory.h | 28 +++ src/plugin/mapping/VisualReferencePoint.cpp | 20 +- src/plugin/mapping/VisualReferencePoint.h | 20 +- test/plugin/CMakeLists.txt | 2 +- ...BootstrapProviderCollectionFactoryTest.cpp | 7 + test/plugin/bootstrap/ModuleFactoriesTest.cpp | 7 + .../MappingElementManagerFactoryTest.cpp | 174 ++++++++++++++++++ .../mapping/MappingElementManagerTest.cpp | 77 ++++++++ test/plugin/mapping/MappingElementTest.cpp | 21 +-- .../mapping/MappingModuleFactoryTest.cpp | 32 ++++ test/plugin/mock/MockMappingElementDrawer.h | 5 +- 26 files changed, 600 insertions(+), 53 deletions(-) create mode 100644 src/plugin/mapping/MappingBootstrapProvider.cpp create mode 100644 src/plugin/mapping/MappingBootstrapProvider.h create mode 100644 src/plugin/mapping/MappingElementManager.cpp create mode 100644 src/plugin/mapping/MappingElementManager.h create mode 100644 src/plugin/mapping/MappingElementManagerFactory.cpp create mode 100644 src/plugin/mapping/MappingElementManagerFactory.h create mode 100644 src/plugin/mapping/MappingModuleFactory.cpp create mode 100644 src/plugin/mapping/MappingModuleFactory.h create mode 100644 test/plugin/mapping/MappingElementManagerFactoryTest.cpp create mode 100644 test/plugin/mapping/MappingElementManagerTest.cpp create mode 100644 test/plugin/mapping/MappingModuleFactoryTest.cpp diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 64c7e95ce..e7c941f73 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -488,7 +488,7 @@ set(src__login source_group("src\\login" FILES ${src__login}) set(src__mapping - mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h) + mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h mapping/MappingElementManager.cpp mapping/MappingElementManager.h mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h) source_group("src\\mapping" FILES ${src__mapping}) set(src__message diff --git a/src/plugin/bootstrap/BootstrapProviderCollectionFactory.cpp b/src/plugin/bootstrap/BootstrapProviderCollectionFactory.cpp index 48c0248ea..d7634ca98 100644 --- a/src/plugin/bootstrap/BootstrapProviderCollectionFactory.cpp +++ b/src/plugin/bootstrap/BootstrapProviderCollectionFactory.cpp @@ -1,12 +1,14 @@ #include "BootstrapProviderCollection.h" #include "BootstrapProviderCollectionFactory.h" #include "approach/ApproachBootstrapProvider.h" +#include "mapping/MappingBootstrapProvider.h" namespace UKControllerPlugin::Bootstrap { auto Make() -> std::unique_ptr { auto collection = std::make_unique(); collection->AddProvider(std::make_unique()); + collection->AddProvider(std::make_unique()); return collection; } diff --git a/src/plugin/bootstrap/ModuleFactories.cpp b/src/plugin/bootstrap/ModuleFactories.cpp index 06bfc31a4..4690e7475 100644 --- a/src/plugin/bootstrap/ModuleFactories.cpp +++ b/src/plugin/bootstrap/ModuleFactories.cpp @@ -1,8 +1,10 @@ #include "ModuleFactories.h" #include "approach/ApproachModuleFactory.h" +#include "mapping/MappingModuleFactory.h" namespace UKControllerPlugin::Bootstrap { + ModuleFactories::ModuleFactories() = default; ModuleFactories::~ModuleFactories() = default; auto ModuleFactories::Approach() -> Approach::ApproachModuleFactory& @@ -13,4 +15,13 @@ namespace UKControllerPlugin::Bootstrap { return *approach; } + + auto ModuleFactories::Mapping() -> Mapping::MappingModuleFactory& + { + if (!mapping) { + mapping = std::make_unique(); + } + + return *mapping; + } } // namespace UKControllerPlugin::Bootstrap diff --git a/src/plugin/bootstrap/ModuleFactories.h b/src/plugin/bootstrap/ModuleFactories.h index e5f744639..7dee4d0aa 100644 --- a/src/plugin/bootstrap/ModuleFactories.h +++ b/src/plugin/bootstrap/ModuleFactories.h @@ -4,6 +4,9 @@ namespace UKControllerPlugin { namespace Approach { class ApproachModuleFactory; } // namespace Approach + namespace Mapping { + class MappingModuleFactory; + } // namespace Mapping } // namespace UKControllerPlugin namespace UKControllerPlugin::Bootstrap { @@ -17,11 +20,16 @@ namespace UKControllerPlugin::Bootstrap { class ModuleFactories { public: + ModuleFactories(); ~ModuleFactories(); [[nodiscard]] auto Approach() -> Approach::ApproachModuleFactory&; + [[nodiscard]] auto Mapping() -> Mapping::MappingModuleFactory&; private: // The approach module std::unique_ptr approach; + + // The mapping module + std::unique_ptr mapping; }; } // namespace UKControllerPlugin::Bootstrap diff --git a/src/plugin/mapping/MappingBootstrapProvider.cpp b/src/plugin/mapping/MappingBootstrapProvider.cpp new file mode 100644 index 000000000..113a45679 --- /dev/null +++ b/src/plugin/mapping/MappingBootstrapProvider.cpp @@ -0,0 +1,23 @@ +#include "MappingBootstrapProvider.h" +#include "MappingModuleFactory.h" +#include "bootstrap/PersistenceContainer.h" +#include "bootstrap/ModuleFactories.h" + +namespace UKControllerPlugin::Mapping { + + void MappingBootstrapProvider::BootstrapPlugin(Bootstrap::PersistenceContainer& container) + { + static_cast(container.moduleFactories->Mapping().ElementManager(*container.dependencyLoader)); + } + + void MappingBootstrapProvider::BootstrapRadarScreen( + const Bootstrap::PersistenceContainer& container, + RadarScreen::RadarRenderableCollection& radarRenderables, + RadarScreen::ConfigurableDisplayCollection& configurables, + Euroscope::AsrEventHandlerCollection& asrHandlers, + const RadarScreen::MenuToggleableDisplayFactory& toggleableDisplayFactory) + { + BootstrapProviderInterface::BootstrapRadarScreen( + container, radarRenderables, configurables, asrHandlers, toggleableDisplayFactory); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingBootstrapProvider.h b/src/plugin/mapping/MappingBootstrapProvider.h new file mode 100644 index 000000000..399c197eb --- /dev/null +++ b/src/plugin/mapping/MappingBootstrapProvider.h @@ -0,0 +1,19 @@ +#pragma once +#include "bootstrap/BootstrapProviderInterface.h" + +namespace UKControllerPlugin::Mapping { + /** + * Bootstraps the mapping module + */ + class MappingBootstrapProvider : public Bootstrap::BootstrapProviderInterface + { + public: + void BootstrapPlugin(Bootstrap::PersistenceContainer& container) override; + void BootstrapRadarScreen( + const Bootstrap::PersistenceContainer& container, + RadarScreen::RadarRenderableCollection& radarRenderables, + RadarScreen::ConfigurableDisplayCollection& configurables, + Euroscope::AsrEventHandlerCollection& asrHandlers, + const RadarScreen::MenuToggleableDisplayFactory& toggleableDisplayFactory) override; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElement.cpp b/src/plugin/mapping/MappingElement.cpp index 7f9b48aaa..35188f48b 100644 --- a/src/plugin/mapping/MappingElement.cpp +++ b/src/plugin/mapping/MappingElement.cpp @@ -8,11 +8,10 @@ namespace UKControllerPlugin::Mapping { int id, std::string type, std::string label, - EuroScopePlugIn::CPosition position, std::set> displayRules, std::shared_ptr drawer) - : id(id), type(std::move(type)), label(std::move(label)), position(std::move(position)), - displayRules(std::move(displayRules)), drawer(std::move(drawer)) + : id(id), type(std::move(type)), label(std::move(label)), displayRules(std::move(displayRules)), + drawer(std::move(drawer)) { } @@ -42,13 +41,14 @@ namespace UKControllerPlugin::Mapping { return true; } - auto MappingElement::Position() const -> const EuroScopePlugIn::CPosition& + void MappingElement::Draw( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { - return position; + this->drawer->Draw(graphics, radarScreen); } - void MappingElement::Draw(Windows::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) + auto MappingElement::Drawer() const -> std::shared_ptr { - this->drawer->Draw(graphics, area); + return drawer; } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElement.h b/src/plugin/mapping/MappingElement.h index 1264265d4..633b43bdd 100644 --- a/src/plugin/mapping/MappingElement.h +++ b/src/plugin/mapping/MappingElement.h @@ -15,15 +15,15 @@ namespace UKControllerPlugin::Mapping { int id, std::string type, std::string label, - EuroScopePlugIn::CPosition position, std::set> displayRules, std::shared_ptr drawer); [[nodiscard]] auto Id() const -> int override; [[nodiscard]] auto Type() const -> const std::string& override; [[nodiscard]] auto Label() const -> const std::string& override; [[nodiscard]] auto ShouldDisplay() const -> bool override; - [[nodiscard]] auto Position() const -> const EuroScopePlugIn::CPosition& override; - void Draw(Windows::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) override; + [[nodiscard]] auto Drawer() const -> std::shared_ptr; + void Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) + override; private: // The id of the element, is only unique within a type @@ -35,9 +35,6 @@ namespace UKControllerPlugin::Mapping { // The label that accompanies the element. std::string label; - // The position of the element - EuroScopePlugIn::CPosition position; - // Display rules std::set> displayRules; diff --git a/src/plugin/mapping/MappingElementDrawer.h b/src/plugin/mapping/MappingElementDrawer.h index eb68ac86d..0714fa49a 100644 --- a/src/plugin/mapping/MappingElementDrawer.h +++ b/src/plugin/mapping/MappingElementDrawer.h @@ -1,8 +1,13 @@ #pragma once -namespace UKControllerPlugin::Windows { - class GdiGraphicsInterface; -} // namespace UKControllerPlugin::Windows +namespace UKControllerPlugin { + namespace Euroscope { + class EuroscopeRadarLoopbackInterface; + } // namespace Euroscope + namespace Windows { + class GdiGraphicsInterface; + } // namespace Windows +} // namespace UKControllerPlugin namespace UKControllerPlugin::Mapping { @@ -17,6 +22,7 @@ namespace UKControllerPlugin::Mapping { /** * Draw the mapping element. The area is centered on the centre of the element. */ - virtual void Draw(Windows::GdiGraphicsInterface& graphics, const Gdiplus::Rect& area) = 0; + virtual void + Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) = 0; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementInterface.h b/src/plugin/mapping/MappingElementInterface.h index dcafa56c1..a9693c64f 100644 --- a/src/plugin/mapping/MappingElementInterface.h +++ b/src/plugin/mapping/MappingElementInterface.h @@ -1,8 +1,13 @@ #pragma once -namespace UKControllerPlugin::Windows { - class GdiGraphicsInterface; -} // namespace UKControllerPlugin::Windows +namespace UKControllerPlugin { + namespace Euroscope { + class EuroscopeRadarLoopbackInterface; + } // namespace Euroscope + namespace Windows { + class GdiGraphicsInterface; + } // namespace Windows +} // namespace UKControllerPlugin namespace UKControllerPlugin::Mapping { /** @@ -29,11 +34,6 @@ namespace UKControllerPlugin::Mapping { */ [[nodiscard]] virtual auto Label() const -> const std::string& = 0; - /** - * The label associated with the element. - */ - [[nodiscard]] virtual auto Position() const -> const EuroScopePlugIn::CPosition& = 0; - /** * Should we be displaying the mapping element */ @@ -42,6 +42,7 @@ namespace UKControllerPlugin::Mapping { /** * Draw the mapping element. The area is centered on the centre of the element. */ - virtual void Draw(Windows::GdiGraphicsInterface& graphics, Gdiplus::Rect& area) = 0; + virtual void + Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) = 0; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManager.cpp b/src/plugin/mapping/MappingElementManager.cpp new file mode 100644 index 000000000..7a6f28ebd --- /dev/null +++ b/src/plugin/mapping/MappingElementManager.cpp @@ -0,0 +1,26 @@ +#include "MappingElement.h" +#include "MappingElementManager.h" + +namespace UKControllerPlugin::Mapping { + + void MappingElementManager::Add(std::shared_ptr element) + { + allElements.insert(element); + activeElements.insert(element); + } + + auto MappingElementManager::Count() const -> size_t + { + return allElements.size(); + } + + auto MappingElementManager::GetByTypeAndId(const std::string& type, int id) const -> std::shared_ptr + { + auto element = std::find_if( + allElements.cbegin(), allElements.cend(), [&type, &id](const std::shared_ptr& element) { + return element->Type() == type && element->Id() == id; + }); + + return element == allElements.cend() ? nullptr : *element; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManager.h b/src/plugin/mapping/MappingElementManager.h new file mode 100644 index 000000000..9e8852ddc --- /dev/null +++ b/src/plugin/mapping/MappingElementManager.h @@ -0,0 +1,22 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + class MappingElement; + + /** + * Looks after all the mapping elements. + */ + class MappingElementManager + { + public: + void Add(std::shared_ptr element); + [[nodiscard]] auto Count() const -> size_t; + [[nodiscard]] auto GetByTypeAndId(const std::string& type, int id) const -> std::shared_ptr; + + private: + // Active elements - those being drawn + std::set> activeElements; + + std::set> allElements; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManagerFactory.cpp b/src/plugin/mapping/MappingElementManagerFactory.cpp new file mode 100644 index 000000000..f3f42e7f6 --- /dev/null +++ b/src/plugin/mapping/MappingElementManagerFactory.cpp @@ -0,0 +1,50 @@ +#include "MappingElement.h" +#include "MappingElementManager.h" +#include "MappingElementManagerFactory.h" +#include "MappingModuleFactory.h" +#include "VisualReferencePoint.h" +#include "dependency/DependencyLoaderInterface.h" + +namespace UKControllerPlugin::Mapping { + + auto + MakeMappingElementManager(MappingModuleFactory& module, Dependency::DependencyLoaderInterface& dependencyLoader) + -> std::unique_ptr + { + auto mapper = std::make_unique(); + const auto& dependency = + dependencyLoader.LoadDependency("DEPENDENCY_MAPPING_ELEMENTS", nlohmann::json::array()); + if (!dependency.is_array()) { + LogError("Mapping elements dependency is not an array"); + return mapper; + } + + for (const auto& element : dependency) { + if (!ElementValid(element)) { + LogError("Invalid mapping element " + element.dump()); + continue; + } + + EuroScopePlugIn::CPosition position; + position.m_Latitude = element.at("latitude").get(); + position.m_Longitude = element.at("longitude").get(); + mapper->Add(std::make_shared( + element.at("id").get(), + element.at("type").get(), + element.at("name").get(), + std::set>{}, + module.VrpDrawer(element.at("name").get(), position))); + } + + LogInfo("Loaded " + std::to_string(mapper->Count()) + " mapping elements"); + return mapper; + } + + auto ElementValid(const nlohmann::json& data) -> bool + { + return data.is_object() && data.contains("id") && data.at("id").is_number_integer() && data.contains("type") && + data.at("type").is_string() && data.at("type").get() == "visual_reference_point" && + data.contains("latitude") && data.at("latitude").is_number() && data.contains("longitude") && + data.at("longitude").is_number() && data.contains("name") && data.at("name").is_string(); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManagerFactory.h b/src/plugin/mapping/MappingElementManagerFactory.h new file mode 100644 index 000000000..f4aedd290 --- /dev/null +++ b/src/plugin/mapping/MappingElementManagerFactory.h @@ -0,0 +1,15 @@ +#pragma once + +namespace UKControllerPlugin::Dependency { + class DependencyLoaderInterface; +} // namespace UKControllerPlugin::Dependency + +namespace UKControllerPlugin::Mapping { + class MappingElementManager; + class MappingModuleFactory; + + [[nodiscard]] auto MakeMappingElementManager(MappingModuleFactory& module, Dependency::DependencyLoaderInterface& + dependencyLoader) -> + std::unique_ptr; + [[nodiscard]] auto ElementValid(const nlohmann::json& data) -> bool; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingModuleFactory.cpp b/src/plugin/mapping/MappingModuleFactory.cpp new file mode 100644 index 000000000..09cdea438 --- /dev/null +++ b/src/plugin/mapping/MappingModuleFactory.cpp @@ -0,0 +1,26 @@ +#include "MappingElementManager.h" +#include "MappingElementManagerFactory.h" +#include "MappingModuleFactory.h" +#include "VisualReferencePoint.h" + +namespace UKControllerPlugin::Mapping { + + MappingModuleFactory::MappingModuleFactory() = default; + MappingModuleFactory::~MappingModuleFactory() = default; + + auto MappingModuleFactory::VrpDrawer(std::string label, EuroScopePlugIn::CPosition position) + -> std::shared_ptr + { + return std::make_shared(label, position); + } + + auto MappingModuleFactory::ElementManager(Dependency::DependencyLoaderInterface& dependencyLoader) + -> MappingElementManager& + { + if (!elementManager) { + elementManager = MakeMappingElementManager(*this, dependencyLoader); + } + + return *elementManager; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingModuleFactory.h b/src/plugin/mapping/MappingModuleFactory.h new file mode 100644 index 000000000..59d15908d --- /dev/null +++ b/src/plugin/mapping/MappingModuleFactory.h @@ -0,0 +1,28 @@ +#pragma once + +namespace UKControllerPlugin::Dependency { + class DependencyLoaderInterface; +} // namespace UKControllerPlugin::Dependency + +namespace UKControllerPlugin::Mapping { + class MappingElementManager; + class VisualReferencePoint; + + /** + * Bootstraps up the mapping module + */ + class MappingModuleFactory + { + public: + MappingModuleFactory(); + ~MappingModuleFactory(); + [[nodiscard]] auto VrpDrawer(std::string label, EuroScopePlugIn::CPosition position) -> + std::shared_ptr; + [[nodiscard]] auto ElementManager(Dependency::DependencyLoaderInterface& dependencyLoader) -> + MappingElementManager&; + + private: + // Manages mapping elements + std::unique_ptr elementManager; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePoint.cpp b/src/plugin/mapping/VisualReferencePoint.cpp index 35b3a1d83..d91199153 100644 --- a/src/plugin/mapping/VisualReferencePoint.cpp +++ b/src/plugin/mapping/VisualReferencePoint.cpp @@ -1,14 +1,20 @@ #include "VisualReferencePoint.h" +#include "euroscope/EuroscopeRadarLoopbackInterface.h" #include "graphics/GdiGraphicsInterface.h" namespace UKControllerPlugin::Mapping { - VisualReferencePoint::VisualReferencePoint() : pen(std::make_shared(Gdiplus::Color(50, 127, 168))) + VisualReferencePoint::VisualReferencePoint(std::string label, EuroScopePlugIn::CPosition position) + : label(label), position(std::move(position)), pen(std::make_shared(Gdiplus::Color(50, 127, 168))) { } - void VisualReferencePoint::Draw(Windows::GdiGraphicsInterface& graphics, const Gdiplus::Rect& area) + void VisualReferencePoint::Draw( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { + const auto screenPosition = radarScreen.ConvertCoordinateToScreenPoint(position); + Gdiplus::Rect area{screenPosition.x - 20, screenPosition.y - 20, 20, 20}; + graphics.DrawCircle(area, *pen); graphics.DrawLine( *pen, @@ -19,4 +25,14 @@ namespace UKControllerPlugin::Mapping { Gdiplus::PointF{0, static_cast(area.Height / 2)}, Gdiplus::PointF{static_cast(area.Width), static_cast(area.Height / 2)}); } + + auto VisualReferencePoint::Position() const -> const EuroScopePlugIn::CPosition& + { + return position; + } + + auto VisualReferencePoint::Label() const -> const std::string& + { + return label; + } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePoint.h b/src/plugin/mapping/VisualReferencePoint.h index ad8bc4c86..23e00e749 100644 --- a/src/plugin/mapping/VisualReferencePoint.h +++ b/src/plugin/mapping/VisualReferencePoint.h @@ -8,10 +8,20 @@ namespace UKControllerPlugin::Mapping { class VisualReferencePoint : public MappingElementDrawer { public: - VisualReferencePoint(); - void Draw(Windows::GdiGraphicsInterface& graphics, const Gdiplus::Rect& area) override; - + VisualReferencePoint(std::string label, EuroScopePlugIn::CPosition position); + void + Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) override; + [[nodiscard]] auto Label() const -> const std::string&; + [[nodiscard]] auto Position() const -> const EuroScopePlugIn::CPosition&; + private: - std::shared_ptr pen; + // The label for the VRP + std::string label; + + // Where on the map to draw + EuroScopePlugIn::CPosition position; + + // A pen for drawing + std::shared_ptr pen; }; -} // +} // namespace UKControllerPlugin::Mapping diff --git a/test/plugin/CMakeLists.txt b/test/plugin/CMakeLists.txt index f79ba3d3a..cc874f35e 100644 --- a/test/plugin/CMakeLists.txt +++ b/test/plugin/CMakeLists.txt @@ -261,7 +261,7 @@ set(test__login source_group("test\\login" FILES ${test__login}) set(test__mapping - mapping/MappingElementTest.cpp) + mapping/MappingElementTest.cpp mapping/MappingModuleFactoryTest.cpp mapping/MappingElementManagerTest.cpp mapping/MappingElementManagerFactoryTest.cpp) source_group("test\\mapping" FILES ${test__mapping}) set(test__message diff --git a/test/plugin/bootstrap/BootstrapProviderCollectionFactoryTest.cpp b/test/plugin/bootstrap/BootstrapProviderCollectionFactoryTest.cpp index 2fea6ab20..f5c81a7c3 100644 --- a/test/plugin/bootstrap/BootstrapProviderCollectionFactoryTest.cpp +++ b/test/plugin/bootstrap/BootstrapProviderCollectionFactoryTest.cpp @@ -1,9 +1,11 @@ #include "approach/ApproachBootstrapProvider.h" #include "bootstrap/BootstrapProviderCollection.h" #include "bootstrap/BootstrapProviderCollectionFactory.h" +#include "mapping/MappingBootstrapProvider.h" using UKControllerPlugin::Approach::ApproachBootstrapProvider; using UKControllerPlugin::Bootstrap::Make; +using UKControllerPlugin::Mapping::MappingBootstrapProvider; namespace UKControllerPluginTest::Bootstrap { class BootstrapProviderCollectionFactoryTest : public testing::Test @@ -26,4 +28,9 @@ namespace UKControllerPluginTest::Bootstrap { { AssertHasProvider(); } + + TEST_F(BootstrapProviderCollectionFactoryTest, TestItHasMappingModule) + { + AssertHasProvider(); + } } // namespace UKControllerPluginTest::Bootstrap diff --git a/test/plugin/bootstrap/ModuleFactoriesTest.cpp b/test/plugin/bootstrap/ModuleFactoriesTest.cpp index 65be5188d..86a03f918 100644 --- a/test/plugin/bootstrap/ModuleFactoriesTest.cpp +++ b/test/plugin/bootstrap/ModuleFactoriesTest.cpp @@ -1,5 +1,6 @@ #include "approach/ApproachModuleFactory.h" #include "bootstrap/ModuleFactories.h" +#include "mapping/MappingModuleFactory.h" using UKControllerPlugin::Bootstrap::ModuleFactories; @@ -15,4 +16,10 @@ namespace UKControllerPluginTest::Bootstrap { EXPECT_NE(nullptr, &factories.Approach()); EXPECT_EQ(&factories.Approach(), &factories.Approach()); } + + TEST_F(ModuleFactoriesTest, ItReturnsMappingFactoryAsSingleton) + { + EXPECT_NE(nullptr, &factories.Mapping()); + EXPECT_EQ(&factories.Mapping(), &factories.Mapping()); + } } // namespace UKControllerPluginTest::Bootstrap diff --git a/test/plugin/mapping/MappingElementManagerFactoryTest.cpp b/test/plugin/mapping/MappingElementManagerFactoryTest.cpp new file mode 100644 index 000000000..02ab01710 --- /dev/null +++ b/test/plugin/mapping/MappingElementManagerFactoryTest.cpp @@ -0,0 +1,174 @@ +#include "mapping/MappingModuleFactory.h" +#include "mapping/MappingElement.h" +#include "mapping/MappingElementDrawer.h" +#include "mapping/MappingElementManager.h" +#include "mapping/MappingElementManagerFactory.h" +#include "mapping/VisualReferencePoint.h" + +using UKControllerPlugin::Mapping::ElementValid; +using UKControllerPlugin::Mapping::MakeMappingElementManager; +using UKControllerPlugin::Mapping::MappingElementDrawer; +using UKControllerPlugin::Mapping::MappingModuleFactory; +using UKControllerPlugin::Mapping::VisualReferencePoint; + +namespace UKControllerPluginTest::Mapping { + class MappingElementManagerFactoryTest : public testing::Test + { + public: + MappingElementManagerFactoryTest() + { + ON_CALL(dependencyLoader, LoadDependency("DEPENDENCY_MAPPING_ELEMENTS", nlohmann::json::array())) + .WillByDefault(testing::Return(nlohmann::json::array())); + } + + [[nodiscard]] static auto + GetJson(const nlohmann::json& overridingData = nlohmann::json::object(), const std::string& keyToRemove = "") + -> nlohmann::json + { + nlohmann::json json{ + {"id", 1}, + {"type", "visual_reference_point"}, + {"latitude", 1.1}, + {"longitude", 2.2}, + {"name", "M5 Avon Bridge"}}; + + if (overridingData.is_object()) { + json.update(overridingData); + } else { + json = overridingData; + } + + if (!keyToRemove.empty()) { + json.erase(json.find(keyToRemove)); + } + + return json; + } + + testing::NiceMock dependencyLoader; + MappingModuleFactory moduleFactory; + }; + + TEST_F(MappingElementManagerFactoryTest, ElementIsValid) + { + EXPECT_TRUE(ElementValid(GetJson())); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfNotObject) + { + EXPECT_FALSE(ElementValid(nlohmann::json::array())); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfIdMissing) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object(), "id"))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfIdNotInteger) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object({{"id", "abc"}})))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfTypeMissing) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object(), "type"))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfTypeNotString) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object({{"type", 123}})))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfTypeNotValid) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object({{"type", "not_visual_reference_point"}})))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfLatitudeMissing) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object(), "latitude"))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfLatitudeNotNumber) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object({{"latitude", "abc"}})))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfLongitudeMissing) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object(), "longitude"))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfLongitudeNotNumber) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object({{"longitude", "abc"}})))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfNameMissing) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object(), "name"))); + } + + TEST_F(MappingElementManagerFactoryTest, ElementIsNotValidIfNameNotString) + { + EXPECT_FALSE(ElementValid(GetJson(nlohmann::json::object({{"name", 123}})))); + } + + TEST_F(MappingElementManagerFactoryTest, ItBuildsDefaultEmptyCollection) + { + EXPECT_EQ(0, MakeMappingElementManager(moduleFactory, dependencyLoader)->Count()); + } + + TEST_F(MappingElementManagerFactoryTest, ItReturnsEmptyCollectionIfDependencyNotArray) + { + ON_CALL(dependencyLoader, LoadDependency("DEPENDENCY_MAPPING_ELEMENTS", nlohmann::json::array())) + .WillByDefault(testing::Return(nlohmann::json::object())); + + EXPECT_EQ(0, MakeMappingElementManager(moduleFactory, dependencyLoader)->Count()); + } + + TEST_F(MappingElementManagerFactoryTest, ItBuildsCollection) + { + nlohmann::json dependency = nlohmann::json::array(); + dependency.push_back(GetJson()); + dependency.push_back(GetJson(nlohmann::json::object({{"id", 2}, {"name", "VRP Two"}}))); + + ON_CALL(dependencyLoader, LoadDependency("DEPENDENCY_MAPPING_ELEMENTS", nlohmann::json::array())) + .WillByDefault(testing::Return(dependency)); + + const auto manager = MakeMappingElementManager(moduleFactory, dependencyLoader); + EXPECT_EQ(2, manager->Count()); + const auto element1 = manager->GetByTypeAndId("visual_reference_point", 1); + EXPECT_NE(nullptr, element1); + EXPECT_EQ(1, element1->Id()); + EXPECT_EQ("visual_reference_point", element1->Type()); + EXPECT_EQ("M5 Avon Bridge", element1->Label()); + auto drawer1 = static_cast(element1->Drawer().get()); + EXPECT_DOUBLE_EQ(1.1, drawer1->Position().m_Latitude); + EXPECT_DOUBLE_EQ(2.2, drawer1->Position().m_Longitude); + EXPECT_EQ("M5 Avon Bridge", drawer1->Label()); + + const auto element2 = manager->GetByTypeAndId("visual_reference_point", 2); + EXPECT_NE(nullptr, element2); + EXPECT_EQ(2, element2->Id()); + EXPECT_EQ("visual_reference_point", element2->Type()); + EXPECT_EQ("VRP Two", element2->Label()); + auto drawer2 = static_cast(element2->Drawer().get()); + EXPECT_DOUBLE_EQ(1.1, drawer2->Position().m_Latitude); + EXPECT_DOUBLE_EQ(2.2, drawer2->Position().m_Longitude); + EXPECT_EQ("VRP Two", drawer2->Label()); + } + + TEST_F(MappingElementManagerFactoryTest, ItIgnoresBadElementsInDependency) + { + nlohmann::json dependency = nlohmann::json::array(); + dependency.push_back(GetJson(nlohmann::json::object({{"id", "abc"}, {"name", "VRP Two"}}))); + dependency.push_back(GetJson(nlohmann::json::object({{"name", 123}}))); + + ON_CALL(dependencyLoader, LoadDependency("DEPENDENCY_MAPPING_ELEMENTS", nlohmann::json::array())) + .WillByDefault(testing::Return(dependency)); + + const auto manager = MakeMappingElementManager(moduleFactory, dependencyLoader); + EXPECT_EQ(0, manager->Count()); + } +} // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/mapping/MappingElementManagerTest.cpp b/test/plugin/mapping/MappingElementManagerTest.cpp new file mode 100644 index 000000000..aa3433471 --- /dev/null +++ b/test/plugin/mapping/MappingElementManagerTest.cpp @@ -0,0 +1,77 @@ +#include "mapping/MappingElement.h" +#include "mapping/MappingElementManager.h" + +using UKControllerPlugin::Mapping::DisplayRule; +using UKControllerPlugin::Mapping::MappingElement; +using UKControllerPlugin::Mapping::MappingElementManager; + +namespace UKControllerPLuginTest::Mapping { + class MappingElementManagerTest : public testing::Test + { + public: + MappingElementManagerTest() + { + element1 = std::make_shared( + 1, "vrp", "VRP One", std::set>{}, nullptr); + element2 = std::make_shared( + 2, "not_vrp", "Not VRP One", std::set>{}, nullptr); + element3 = std::make_shared( + 3, "vrp", "VRP Two", std::set>{}, nullptr); + } + + std::shared_ptr element1; + std::shared_ptr element2; + std::shared_ptr element3; + MappingElementManager manager; + }; + + TEST_F(MappingElementManagerTest, ItStartsEmpty) + { + EXPECT_EQ(0, manager.Count()); + } + + TEST_F(MappingElementManagerTest, ItAddsElements) + { + manager.Add(element1); + manager.Add(element2); + EXPECT_EQ(2, manager.Count()); + } + + TEST_F(MappingElementManagerTest, ItDoesntAddDuplicateElements) + { + manager.Add(element1); + manager.Add(element1); + manager.Add(element1); + manager.Add(element2); + manager.Add(element2); + manager.Add(element2); + EXPECT_EQ(2, manager.Count()); + } + + TEST_F(MappingElementManagerTest, ItReturnsElementByTypeAndId) + { + manager.Add(element1); + manager.Add(element2); + manager.Add(element3); + + EXPECT_EQ(element1, manager.GetByTypeAndId("vrp", 1)); + } + + TEST_F(MappingElementManagerTest, ItReturnsNullptrIfWrongId) + { + manager.Add(element1); + manager.Add(element2); + manager.Add(element3); + + EXPECT_EQ(nullptr, manager.GetByTypeAndId("not_vrp", 1)); + } + + TEST_F(MappingElementManagerTest, ItReturnsNullptrIfWrongType) + { + manager.Add(element1); + manager.Add(element2); + manager.Add(element3); + + EXPECT_EQ(nullptr, manager.GetByTypeAndId("vrp", 2)); + } +} // namespace UKControllerPLuginTest::Mapping diff --git a/test/plugin/mapping/MappingElementTest.cpp b/test/plugin/mapping/MappingElementTest.cpp index 13b2f32c4..8ff29d907 100644 --- a/test/plugin/mapping/MappingElementTest.cpp +++ b/test/plugin/mapping/MappingElementTest.cpp @@ -12,19 +12,11 @@ namespace UKControllerPluginTest::Mapping { displayRule2(std::make_shared>()), displayRules({displayRule1, displayRule2}), drawer(std::make_shared>()), - element(1, "visual_reference_point", "M5 Avon Bridge", Position(), displayRules, drawer) + element(1, "visual_reference_point", "M5 Avon Bridge", displayRules, drawer) { } - [[nodiscard]] static auto Position() -> EuroScopePlugIn::CPosition - { - EuroScopePlugIn::CPosition position; - position.m_Latitude = 1; - position.m_Longitude = 2; - - return position; - } - + testing::NiceMock radarScreen; testing::NiceMock graphics; std::shared_ptr> displayRule1; std::shared_ptr> displayRule2; @@ -48,11 +40,9 @@ namespace UKControllerPluginTest::Mapping { EXPECT_EQ("M5 Avon Bridge", element.Label()); } - TEST_F(MappingElementTest, ItHasAPosition) + TEST_F(MappingElementTest, ItHasADrawer) { - const auto position = element.Position(); - EXPECT_EQ(1, position.m_Latitude); - EXPECT_EQ(2, position.m_Longitude); + EXPECT_EQ(drawer, element.Drawer()); } TEST_F(MappingElementTest, ItShouldDisplayIfAllRulesPass) @@ -77,7 +67,6 @@ namespace UKControllerPluginTest::Mapping { { EXPECT_CALL(*drawer, Draw(testing::_, testing::_)).Times(1); - Gdiplus::Rect rect{1, 2, 3, 4}; - element.Draw(graphics, rect); + element.Draw(graphics, radarScreen); } } // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/mapping/MappingModuleFactoryTest.cpp b/test/plugin/mapping/MappingModuleFactoryTest.cpp new file mode 100644 index 000000000..7392bcb26 --- /dev/null +++ b/test/plugin/mapping/MappingModuleFactoryTest.cpp @@ -0,0 +1,32 @@ +#include "mapping/MappingModuleFactory.h" + +using UKControllerPlugin::Mapping::MappingModuleFactory; + +namespace UKControllerPluginTest::Mapping { + class MappingModuleFactoryTest : public testing::Test + { + public: + MappingModuleFactoryTest() + { + ON_CALL(dependencyLoader, LoadDependency).WillByDefault(testing::Return(nlohmann::json::array())); + } + + testing::NiceMock dependencyLoader; + MappingModuleFactory factory; + }; + + TEST_F(MappingModuleFactoryTest, ItReturnsAVrpDrawer) + { + EXPECT_NE(nullptr, factory.VrpDrawer("foo", EuroScopePlugIn::CPosition())); + } + + TEST_F(MappingModuleFactoryTest, ItReturnsTheElementManager) + { + EXPECT_NE(nullptr, &factory.ElementManager(dependencyLoader)); + } + + TEST_F(MappingModuleFactoryTest, ItReturnsTheElementManagerAsASingleton) + { + EXPECT_EQ(&factory.ElementManager(dependencyLoader), &factory.ElementManager(dependencyLoader)); + } +} // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/mock/MockMappingElementDrawer.h b/test/plugin/mock/MockMappingElementDrawer.h index f6a11e6ef..2ec816951 100644 --- a/test/plugin/mock/MockMappingElementDrawer.h +++ b/test/plugin/mock/MockMappingElementDrawer.h @@ -1,13 +1,14 @@ #pragma once #include "mapping/MappingElementDrawer.h" -using UKControllerPlugin::Graphics::GdiGraphicsInterface; +using UKControllerPlugin::Euroscope::EuroscopeRadarLoopbackInterface; using UKControllerPlugin::Mapping::MappingElementDrawer; +using UKControllerPlugin::Windows::GdiGraphicsInterface; namespace UKControllerPluginTest::Mapping { class MockMappingElementDrawer : public MappingElementDrawer { public: - MOCK_METHOD(void, Draw, (GdiGraphicsInterface&, const Gdiplus::Rect&), (override)); + MOCK_METHOD(void, Draw, (GdiGraphicsInterface&, EuroscopeRadarLoopbackInterface&), (override)); }; } // namespace UKControllerPluginTest::Mapping From 1761584b82bf0675e813bdc8aeda756c522b2624 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Thu, 24 Mar 2022 17:36:25 +0000 Subject: [PATCH 04/18] Label --- src/plugin/mapping/VisualReferencePoint.cpp | 7 ++++++- src/plugin/mapping/VisualReferencePoint.h | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/plugin/mapping/VisualReferencePoint.cpp b/src/plugin/mapping/VisualReferencePoint.cpp index d91199153..dd2fcb632 100644 --- a/src/plugin/mapping/VisualReferencePoint.cpp +++ b/src/plugin/mapping/VisualReferencePoint.cpp @@ -1,11 +1,14 @@ #include "VisualReferencePoint.h" #include "euroscope/EuroscopeRadarLoopbackInterface.h" +#include "helper/HelperFunctions.h" #include "graphics/GdiGraphicsInterface.h" namespace UKControllerPlugin::Mapping { VisualReferencePoint::VisualReferencePoint(std::string label, EuroScopePlugIn::CPosition position) - : label(label), position(std::move(position)), pen(std::make_shared(Gdiplus::Color(50, 127, 168))) + : label(label), position(std::move(position)), + pen(std::make_shared(Gdiplus::Color(50, 127, 168))), + textBrush(std::make_shared(Gdiplus::Color(255, 255, 255))) { } @@ -24,6 +27,8 @@ namespace UKControllerPlugin::Mapping { *pen, Gdiplus::PointF{0, static_cast(area.Height / 2)}, Gdiplus::PointF{static_cast(area.Width), static_cast(area.Height / 2)}); + Gdiplus::Rect labelArea{screenPosition.x - 80, area.GetBottom() + 10, 160, 20}; + graphics.DrawString(HelperFunctions::ConvertToWideString(label), labelArea, *textBrush); } auto VisualReferencePoint::Position() const -> const EuroScopePlugIn::CPosition& diff --git a/src/plugin/mapping/VisualReferencePoint.h b/src/plugin/mapping/VisualReferencePoint.h index 23e00e749..3881525af 100644 --- a/src/plugin/mapping/VisualReferencePoint.h +++ b/src/plugin/mapping/VisualReferencePoint.h @@ -23,5 +23,8 @@ namespace UKControllerPlugin::Mapping { // A pen for drawing std::shared_ptr pen; + + // Text brush + std::shared_ptr textBrush; }; } // namespace UKControllerPlugin::Mapping From 204fdba4638ea57b0da515526eddd1a8980a6c26 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Wed, 6 Apr 2022 21:11:29 +0100 Subject: [PATCH 05/18] Make things render --- src/plugin/CMakeLists.txt | 2 +- .../mapping/MappingBootstrapProvider.cpp | 11 ++++++--- src/plugin/mapping/MappingElementManager.cpp | 7 ++++++ src/plugin/mapping/MappingElementManager.h | 2 ++ src/plugin/mapping/MappingRenderer.cpp | 23 +++++++++++++++++++ src/plugin/mapping/MappingRenderer.h | 22 ++++++++++++++++++ src/plugin/mapping/VisualReferencePoint.cpp | 22 ++++++++---------- test/plugin/CMakeLists.txt | 2 +- .../mapping/MappingBootstrapProviderTest.cpp | 18 +++++++++++++++ .../mapping/MappingElementManagerTest.cpp | 13 +++++++++++ .../plugin/test/BootstrapProviderTestCase.cpp | 1 + 11 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 src/plugin/mapping/MappingRenderer.cpp create mode 100644 src/plugin/mapping/MappingRenderer.h create mode 100644 test/plugin/mapping/MappingBootstrapProviderTest.cpp diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index e7c941f73..6a91fc7d7 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -488,7 +488,7 @@ set(src__login source_group("src\\login" FILES ${src__login}) set(src__mapping - mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h mapping/MappingElementManager.cpp mapping/MappingElementManager.h mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h) + mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h mapping/MappingElementManager.cpp mapping/MappingElementManager.h mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h mapping/MappingRenderer.cpp mapping/MappingRenderer.h) source_group("src\\mapping" FILES ${src__mapping}) set(src__message diff --git a/src/plugin/mapping/MappingBootstrapProvider.cpp b/src/plugin/mapping/MappingBootstrapProvider.cpp index 113a45679..6b0de492c 100644 --- a/src/plugin/mapping/MappingBootstrapProvider.cpp +++ b/src/plugin/mapping/MappingBootstrapProvider.cpp @@ -1,7 +1,9 @@ #include "MappingBootstrapProvider.h" #include "MappingModuleFactory.h" -#include "bootstrap/PersistenceContainer.h" +#include "MappingRenderer.h" #include "bootstrap/ModuleFactories.h" +#include "bootstrap/PersistenceContainer.h" +#include "radarscreen/RadarRenderableCollection.h" namespace UKControllerPlugin::Mapping { @@ -17,7 +19,10 @@ namespace UKControllerPlugin::Mapping { Euroscope::AsrEventHandlerCollection& asrHandlers, const RadarScreen::MenuToggleableDisplayFactory& toggleableDisplayFactory) { - BootstrapProviderInterface::BootstrapRadarScreen( - container, radarRenderables, configurables, asrHandlers, toggleableDisplayFactory); + radarRenderables.RegisterRenderer( + radarRenderables.ReserveRendererIdentifier(), + std::make_shared( + container.moduleFactories->Mapping().ElementManager(*container.dependencyLoader)), + RadarScreen::RadarRenderableCollection::beforeTags); } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManager.cpp b/src/plugin/mapping/MappingElementManager.cpp index 7a6f28ebd..064628944 100644 --- a/src/plugin/mapping/MappingElementManager.cpp +++ b/src/plugin/mapping/MappingElementManager.cpp @@ -23,4 +23,11 @@ namespace UKControllerPlugin::Mapping { return element == allElements.cend() ? nullptr : *element; } + + void MappingElementManager::ForEachActiveElement(const std::function& function) const + { + for (const auto& element : activeElements) { + function(*element); + } + } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManager.h b/src/plugin/mapping/MappingElementManager.h index 9e8852ddc..187dd54e5 100644 --- a/src/plugin/mapping/MappingElementManager.h +++ b/src/plugin/mapping/MappingElementManager.h @@ -2,6 +2,7 @@ namespace UKControllerPlugin::Mapping { class MappingElement; + class MappingElementInterface; /** * Looks after all the mapping elements. @@ -12,6 +13,7 @@ namespace UKControllerPlugin::Mapping { void Add(std::shared_ptr element); [[nodiscard]] auto Count() const -> size_t; [[nodiscard]] auto GetByTypeAndId(const std::string& type, int id) const -> std::shared_ptr; + void ForEachActiveElement(const std::function& function) const; private: // Active elements - those being drawn diff --git a/src/plugin/mapping/MappingRenderer.cpp b/src/plugin/mapping/MappingRenderer.cpp new file mode 100644 index 000000000..3d98482e1 --- /dev/null +++ b/src/plugin/mapping/MappingRenderer.cpp @@ -0,0 +1,23 @@ +#include "MappingElementInterface.h" +#include "MappingElementManager.h" +#include "MappingRenderer.h" +#include "euroscope/EuroscopeRadarLoopbackInterface.h" +#include "graphics/GdiGraphicsInterface.h" + +namespace UKControllerPlugin::Mapping { + MappingRenderer::MappingRenderer(const MappingElementManager& elementManager) : elementManager(elementManager) + { + } + + bool MappingRenderer::IsVisible() const + { + return true; + } + + void MappingRenderer::Render( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) + { + elementManager.ForEachActiveElement( + [&graphics, &radarScreen](MappingElementInterface& element) { element.Draw(graphics, radarScreen); }); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderer.h b/src/plugin/mapping/MappingRenderer.h new file mode 100644 index 000000000..328d9aad8 --- /dev/null +++ b/src/plugin/mapping/MappingRenderer.h @@ -0,0 +1,22 @@ +#pragma once +#include "radarscreen/RadarRenderableInterface.h" + +namespace UKControllerPlugin::Mapping { + class MappingElementManager; + + /** + * Renders everything mapping. + */ + class MappingRenderer : public RadarScreen::RadarRenderableInterface + { + public: + MappingRenderer(const MappingElementManager& elementManager); + auto IsVisible() const -> bool override; + void Render( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) override; + + private: + // All the mapping elements + const MappingElementManager& elementManager; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePoint.cpp b/src/plugin/mapping/VisualReferencePoint.cpp index dd2fcb632..e6da88a26 100644 --- a/src/plugin/mapping/VisualReferencePoint.cpp +++ b/src/plugin/mapping/VisualReferencePoint.cpp @@ -16,19 +16,17 @@ namespace UKControllerPlugin::Mapping { Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { const auto screenPosition = radarScreen.ConvertCoordinateToScreenPoint(position); - Gdiplus::Rect area{screenPosition.x - 20, screenPosition.y - 20, 20, 20}; + graphics.Translated(screenPosition.x, screenPosition.y, [&graphics, this]() { + Gdiplus::Rect area{-10, -10, 20, 20}; - graphics.DrawCircle(area, *pen); - graphics.DrawLine( - *pen, - Gdiplus::PointF{static_cast(area.Width / 2), 0}, - Gdiplus::PointF{static_cast(area.Width / 2), static_cast(area.Height)}); - graphics.DrawLine( - *pen, - Gdiplus::PointF{0, static_cast(area.Height / 2)}, - Gdiplus::PointF{static_cast(area.Width), static_cast(area.Height / 2)}); - Gdiplus::Rect labelArea{screenPosition.x - 80, area.GetBottom() + 10, 160, 20}; - graphics.DrawString(HelperFunctions::ConvertToWideString(label), labelArea, *textBrush); + graphics.DrawCircle(area, *pen); + graphics.DrawLine(*pen, Gdiplus::PointF{0, -10}, Gdiplus::PointF{0, 10}); + graphics.DrawLine(*pen, Gdiplus::PointF{-10, 0}, Gdiplus::PointF{10, 0}); + graphics.DrawString( + HelperFunctions::ConvertToWideString(label), + Gdiplus::Rect{-90, area.GetBottom() + 5, 180, 20}, + *textBrush); + }); } auto VisualReferencePoint::Position() const -> const EuroScopePlugIn::CPosition& diff --git a/test/plugin/CMakeLists.txt b/test/plugin/CMakeLists.txt index cc874f35e..4ba6463a6 100644 --- a/test/plugin/CMakeLists.txt +++ b/test/plugin/CMakeLists.txt @@ -261,7 +261,7 @@ set(test__login source_group("test\\login" FILES ${test__login}) set(test__mapping - mapping/MappingElementTest.cpp mapping/MappingModuleFactoryTest.cpp mapping/MappingElementManagerTest.cpp mapping/MappingElementManagerFactoryTest.cpp) + mapping/MappingElementTest.cpp mapping/MappingModuleFactoryTest.cpp mapping/MappingElementManagerTest.cpp mapping/MappingElementManagerFactoryTest.cpp mapping/MappingBootstrapProviderTest.cpp) source_group("test\\mapping" FILES ${test__mapping}) set(test__message diff --git a/test/plugin/mapping/MappingBootstrapProviderTest.cpp b/test/plugin/mapping/MappingBootstrapProviderTest.cpp new file mode 100644 index 000000000..b5b9631ac --- /dev/null +++ b/test/plugin/mapping/MappingBootstrapProviderTest.cpp @@ -0,0 +1,18 @@ +#include "mapping/MappingBootstrapProvider.h" + +using UKControllerPlugin::Mapping::MappingBootstrapProvider; + +namespace UKControllerPluginTest::Mapping { + class MappingBootstrapProviderTest : public BootstrapProviderTestCase + { + public:\ + MappingBootstrapProvider provider; + }; + + TEST_F(MappingBootstrapProviderTest, ItBootstrapsRendererToRadarScreen) + { + this->RunBootstrapRadarScreen(provider); + EXPECT_EQ(1, renderers.CountRenderers()); + EXPECT_EQ(1, renderers.CountRenderersInPhase(renderers.beforeTags)); + } +} // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/mapping/MappingElementManagerTest.cpp b/test/plugin/mapping/MappingElementManagerTest.cpp index aa3433471..1ae90dbc1 100644 --- a/test/plugin/mapping/MappingElementManagerTest.cpp +++ b/test/plugin/mapping/MappingElementManagerTest.cpp @@ -3,6 +3,7 @@ using UKControllerPlugin::Mapping::DisplayRule; using UKControllerPlugin::Mapping::MappingElement; +using UKControllerPlugin::Mapping::MappingElementInterface; using UKControllerPlugin::Mapping::MappingElementManager; namespace UKControllerPLuginTest::Mapping { @@ -74,4 +75,16 @@ namespace UKControllerPLuginTest::Mapping { EXPECT_EQ(nullptr, manager.GetByTypeAndId("vrp", 2)); } + + TEST_F(MappingElementManagerTest, ItIteratesActiveElements) + { + manager.Add(element1); + manager.Add(element2); + + std::set expected{element1.get(), element2.get()}; + std::set actual; + manager.ForEachActiveElement([&actual](MappingElementInterface& element) { actual.insert(&element); }); + + EXPECT_EQ(expected, actual); + } } // namespace UKControllerPLuginTest::Mapping diff --git a/test/plugin/test/BootstrapProviderTestCase.cpp b/test/plugin/test/BootstrapProviderTestCase.cpp index a30be2c72..591d6f060 100644 --- a/test/plugin/test/BootstrapProviderTestCase.cpp +++ b/test/plugin/test/BootstrapProviderTestCase.cpp @@ -33,6 +33,7 @@ namespace UKControllerPluginTest { { PersistenceContainer container; ModuleBootstrap(container); + container.dependencyLoader = std::make_shared(); container.pluginFunctionHandlers = std::make_unique(); container.popupListFactory = std::make_unique(*container.pluginFunctionHandlers, *container.plugin); From 3e74ea556ac324a8d0dd840c7a297b0be82a09a5 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Sun, 10 Apr 2022 17:14:26 +0100 Subject: [PATCH 06/18] Rendering the mapping options --- src/plugin/CMakeLists.txt | 2 +- .../mapping/MappingBootstrapProvider.cpp | 23 +++++++++ src/plugin/mapping/MappingOptionsRenderer.cpp | 41 ++++++++++++++++ src/plugin/mapping/MappingOptionsRenderer.h | 35 ++++++++++++++ src/plugin/mapping/MappingRenderOptions.cpp | 24 ++++++++++ src/plugin/mapping/MappingRenderOptions.h | 22 +++++++++ src/plugin/mapping/MappingRenderer.cpp | 2 +- .../mapping/ToggleMappingOptionsRender.cpp | 45 +++++++++++++++++ .../mapping/ToggleMappingOptionsRender.h | 48 +++++++++++++++++++ test/plugin/CMakeLists.txt | 2 +- .../mapping/MappingBootstrapProviderTest.cpp | 11 +++-- .../mapping/MappingRenderOptionsTest.cpp | 37 ++++++++++++++ .../ToggleMappingOptionsRenderTest.cpp | 28 +++++++++++ 13 files changed, 314 insertions(+), 6 deletions(-) create mode 100644 src/plugin/mapping/MappingOptionsRenderer.cpp create mode 100644 src/plugin/mapping/MappingOptionsRenderer.h create mode 100644 src/plugin/mapping/MappingRenderOptions.cpp create mode 100644 src/plugin/mapping/MappingRenderOptions.h create mode 100644 src/plugin/mapping/ToggleMappingOptionsRender.cpp create mode 100644 src/plugin/mapping/ToggleMappingOptionsRender.h create mode 100644 test/plugin/mapping/MappingRenderOptionsTest.cpp create mode 100644 test/plugin/mapping/ToggleMappingOptionsRenderTest.cpp diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 6a91fc7d7..e6aafbac4 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -488,7 +488,7 @@ set(src__login source_group("src\\login" FILES ${src__login}) set(src__mapping - mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h mapping/MappingElementManager.cpp mapping/MappingElementManager.h mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h mapping/MappingRenderer.cpp mapping/MappingRenderer.h) + mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h mapping/MappingElementManager.cpp mapping/MappingElementManager.h mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h mapping/MappingRenderer.cpp mapping/MappingRenderer.h mapping/MappingOptionsRenderer.cpp mapping/MappingOptionsRenderer.h mapping/MappingRenderOptions.cpp mapping/MappingRenderOptions.h mapping/ToggleMappingOptionsRender.cpp mapping/ToggleMappingOptionsRender.h) source_group("src\\mapping" FILES ${src__mapping}) set(src__message diff --git a/src/plugin/mapping/MappingBootstrapProvider.cpp b/src/plugin/mapping/MappingBootstrapProvider.cpp index 6b0de492c..bea4e878b 100644 --- a/src/plugin/mapping/MappingBootstrapProvider.cpp +++ b/src/plugin/mapping/MappingBootstrapProvider.cpp @@ -1,6 +1,9 @@ #include "MappingBootstrapProvider.h" #include "MappingModuleFactory.h" +#include "MappingOptionsRenderer.h" #include "MappingRenderer.h" +#include "MappingRenderOptions.h" +#include "ToggleMappingOptionsRender.h" #include "bootstrap/ModuleFactories.h" #include "bootstrap/PersistenceContainer.h" #include "radarscreen/RadarRenderableCollection.h" @@ -19,10 +22,30 @@ namespace UKControllerPlugin::Mapping { Euroscope::AsrEventHandlerCollection& asrHandlers, const RadarScreen::MenuToggleableDisplayFactory& toggleableDisplayFactory) { + // Renders the mapping elements radarRenderables.RegisterRenderer( radarRenderables.ReserveRendererIdentifier(), std::make_shared( container.moduleFactories->Mapping().ElementManager(*container.dependencyLoader)), RadarScreen::RadarRenderableCollection::beforeTags); + + // The rendering options + auto renderOptions = std::make_shared(); + + // Renders the options + auto optionsRendererId = radarRenderables.ReserveRendererIdentifier(); + radarRenderables.RegisterRenderer( + optionsRendererId, + std::make_shared( + renderOptions, radarRenderables.ReserveScreenObjectIdentifier(optionsRendererId)), + RadarScreen::RadarRenderableCollection::afterLists); + + // Toggles the options + auto toggleOptionsRendererId = radarRenderables.ReserveRendererIdentifier(); + radarRenderables.RegisterRenderer( + toggleOptionsRendererId, + std::make_shared( + renderOptions, radarRenderables.ReserveScreenObjectIdentifier(toggleOptionsRendererId)), + RadarScreen::RadarRenderableCollection::afterLists); } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingOptionsRenderer.cpp b/src/plugin/mapping/MappingOptionsRenderer.cpp new file mode 100644 index 000000000..0b1b8339d --- /dev/null +++ b/src/plugin/mapping/MappingOptionsRenderer.cpp @@ -0,0 +1,41 @@ +#include "MappingOptionsRenderer.h" +#include "MappingRenderOptions.h" +#include "euroscope/EuroscopeRadarLoopbackInterface.h" +#include "graphics/GdiGraphicsInterface.h" + +namespace UKControllerPlugin::Mapping { + + MappingOptionsRenderer::MappingOptionsRenderer( + std::shared_ptr mappingOptions, int screenObjectId) + : mappingOptions(mappingOptions), screenObjectId(screenObjectId), + backgroundBrush(std::make_shared(Gdiplus::Color(170, 64, 64, 64))) + { + int i = this->screenObjectId == 1 ? 1 : 2; + i++; + assert(mappingOptions && "Mapping render options not set"); + } + + auto MappingOptionsRenderer::IsVisible() const -> bool + { + return mappingOptions->ShowOptions(); + } + + void MappingOptionsRenderer::LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, + int objectId, + const std::string& objectDescription, + POINT mousePos, + RECT itemArea) + { + RadarRenderableInterface::LeftClick(radarScreen, objectId, objectDescription, mousePos, itemArea); + } + + void MappingOptionsRenderer::Render( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) + { + const auto viewport = radarScreen.GetRadarViewport(); + graphics.FillRect( + Gdiplus::Rect{50, 50, viewport.right - viewport.left - 100, viewport.bottom - viewport.top - 100}, + *backgroundBrush); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingOptionsRenderer.h b/src/plugin/mapping/MappingOptionsRenderer.h new file mode 100644 index 000000000..aaa206967 --- /dev/null +++ b/src/plugin/mapping/MappingOptionsRenderer.h @@ -0,0 +1,35 @@ +#pragma once +#include "radarscreen/RadarRenderableInterface.h" + +namespace UKControllerPlugin::Mapping { + class MappingRenderOptions; + + /** + * Renders the mapping options to the screen + */ + class MappingOptionsRenderer : public RadarScreen::RadarRenderableInterface + { + public: + MappingOptionsRenderer(std::shared_ptr mappingOptions, int screenObjectId); + [[nodiscard]] auto IsVisible() const -> bool override; + void LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, + int objectId, + const std::string& objectDescription, + POINT mousePos, + RECT itemArea) override; + void Render( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) override; + + private: + + // The options + std::shared_ptr mappingOptions; + + // For clickspots + const int screenObjectId; + + // Brushes + std::shared_ptr backgroundBrush; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderOptions.cpp b/src/plugin/mapping/MappingRenderOptions.cpp new file mode 100644 index 000000000..18507e943 --- /dev/null +++ b/src/plugin/mapping/MappingRenderOptions.cpp @@ -0,0 +1,24 @@ +#include "MappingRenderOptions.h" + +namespace UKControllerPlugin::Mapping { + + void MappingRenderOptions::ShowVisualReferencePoints(bool show) + { + this->showVisualReferencePoints = show; + } + + auto MappingRenderOptions::ShowVisualReferencePoints() const -> bool + { + return this->showVisualReferencePoints; + } + + void MappingRenderOptions::ShowOptions(bool show) + { + this->showOptions = show; + } + + auto MappingRenderOptions::ShowOptions() const -> bool + { + return this->showOptions; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderOptions.h b/src/plugin/mapping/MappingRenderOptions.h new file mode 100644 index 000000000..da5d00fea --- /dev/null +++ b/src/plugin/mapping/MappingRenderOptions.h @@ -0,0 +1,22 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + /** + * Has all the options for rendering mapping elements. + */ + class MappingRenderOptions + { + public: + void ShowOptions(bool show); + [[nodiscard]] auto ShowOptions() const -> bool; + void ShowVisualReferencePoints(bool show); + [[nodiscard]] auto ShowVisualReferencePoints() const -> bool; + + private: + // Do we display the options + bool showOptions = false; + + // Do we display VRPs + bool showVisualReferencePoints = false; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderer.cpp b/src/plugin/mapping/MappingRenderer.cpp index 3d98482e1..8461f68db 100644 --- a/src/plugin/mapping/MappingRenderer.cpp +++ b/src/plugin/mapping/MappingRenderer.cpp @@ -9,7 +9,7 @@ namespace UKControllerPlugin::Mapping { { } - bool MappingRenderer::IsVisible() const + auto MappingRenderer::IsVisible() const -> bool { return true; } diff --git a/src/plugin/mapping/ToggleMappingOptionsRender.cpp b/src/plugin/mapping/ToggleMappingOptionsRender.cpp new file mode 100644 index 000000000..fa1b19fa2 --- /dev/null +++ b/src/plugin/mapping/ToggleMappingOptionsRender.cpp @@ -0,0 +1,45 @@ +#include "ToggleMappingOptionsRender.h" +#include "MappingRenderOptions.h" +#include "components/ClickableArea.h" +#include "euroscope/EuroscopeRadarLoopbackInterface.h" +#include "graphics/GdiGraphicsInterface.h" + +namespace UKControllerPlugin::Mapping { + + ToggleMappingOptionsRender::ToggleMappingOptionsRender( + std::shared_ptr mappingOptions, int screenObjectId) + : mappingOptions(mappingOptions), screenObjectId(screenObjectId), renderArea(0, 0, WIDTH, HEIGHT), + backgroundBrush(std::make_shared(Gdiplus::Color(11, 65, 54))), + textBrush(std::make_shared(Gdiplus::Color(0, 255, 0))), + clickspot(Components::ClickableArea::Create(renderArea, this->screenObjectId, "mapToggle", false)) + { + assert(mappingOptions && "Mapping options not set in ToggleMappingOptionsRender"); + } + + bool ToggleMappingOptionsRender::IsVisible() const + { + return true; + } + + void ToggleMappingOptionsRender::LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, + int objectId, + const std::string& objectDescription, + POINT mousePos, + RECT itemArea) + { + mappingOptions->ShowOptions(!mappingOptions->ShowOptions()); + } + + void ToggleMappingOptionsRender::Render( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) + { + // Translate it next to the OP button + const auto viewport = radarScreen.GetRadarViewport(); + graphics.Translated(viewport.right - 25 - WIDTH, viewport.bottom - HEIGHT, [this, &graphics, &radarScreen]() { + graphics.FillRect(renderArea, *backgroundBrush); + graphics.DrawString(L"MAP", renderArea, *this->textBrush); + clickspot->Apply(graphics, radarScreen); + }); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/ToggleMappingOptionsRender.h b/src/plugin/mapping/ToggleMappingOptionsRender.h new file mode 100644 index 000000000..55b052065 --- /dev/null +++ b/src/plugin/mapping/ToggleMappingOptionsRender.h @@ -0,0 +1,48 @@ +#pragma once +#include "radarscreen/RadarRenderableInterface.h" + +namespace UKControllerPlugin::Components { + class ClickableArea; +} // namespace UKControllerPlugin::Components + +namespace UKControllerPlugin::Mapping { + class MappingRenderOptions; + + class ToggleMappingOptionsRender : public RadarScreen::RadarRenderableInterface + { + public: + ToggleMappingOptionsRender(std::shared_ptr mappingOptions, int screenObjectId); + auto IsVisible() const -> bool override; + void LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, + int objectId, + const std::string& objectDescription, + POINT mousePos, + RECT itemArea) override; + void Render( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) override; + + private: + // Rendering constants + inline static const int WIDTH = 35; + inline static const int HEIGHT = 25; + + // The options + std::shared_ptr mappingOptions; + + // For clickspots + const int screenObjectId; + + // The rendering area + const Gdiplus::Rect renderArea; + + // Background brush + std::shared_ptr backgroundBrush; + + // Text brush + std::shared_ptr textBrush; + + // For clicking + std::shared_ptr clickspot; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/test/plugin/CMakeLists.txt b/test/plugin/CMakeLists.txt index 4ba6463a6..b087c2ec7 100644 --- a/test/plugin/CMakeLists.txt +++ b/test/plugin/CMakeLists.txt @@ -261,7 +261,7 @@ set(test__login source_group("test\\login" FILES ${test__login}) set(test__mapping - mapping/MappingElementTest.cpp mapping/MappingModuleFactoryTest.cpp mapping/MappingElementManagerTest.cpp mapping/MappingElementManagerFactoryTest.cpp mapping/MappingBootstrapProviderTest.cpp) + mapping/MappingElementTest.cpp mapping/MappingModuleFactoryTest.cpp mapping/MappingElementManagerTest.cpp mapping/MappingElementManagerFactoryTest.cpp mapping/MappingBootstrapProviderTest.cpp mapping/MappingRenderOptionsTest.cpp mapping/ToggleMappingOptionsRenderTest.cpp) source_group("test\\mapping" FILES ${test__mapping}) set(test__message diff --git a/test/plugin/mapping/MappingBootstrapProviderTest.cpp b/test/plugin/mapping/MappingBootstrapProviderTest.cpp index b5b9631ac..d08626773 100644 --- a/test/plugin/mapping/MappingBootstrapProviderTest.cpp +++ b/test/plugin/mapping/MappingBootstrapProviderTest.cpp @@ -5,14 +5,19 @@ using UKControllerPlugin::Mapping::MappingBootstrapProvider; namespace UKControllerPluginTest::Mapping { class MappingBootstrapProviderTest : public BootstrapProviderTestCase { - public:\ + public: MappingBootstrapProvider provider; }; - TEST_F(MappingBootstrapProviderTest, ItBootstrapsRendererToRadarScreen) + TEST_F(MappingBootstrapProviderTest, ItBootstrapsElementRendererToRadarScreen) { this->RunBootstrapRadarScreen(provider); - EXPECT_EQ(1, renderers.CountRenderers()); EXPECT_EQ(1, renderers.CountRenderersInPhase(renderers.beforeTags)); } + + TEST_F(MappingBootstrapProviderTest, ItBootstrapsOptionsRenderersToRadarScreen) + { + this->RunBootstrapRadarScreen(provider); + EXPECT_EQ(2, renderers.CountRenderersInPhase(renderers.afterLists)); + } } // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/mapping/MappingRenderOptionsTest.cpp b/test/plugin/mapping/MappingRenderOptionsTest.cpp new file mode 100644 index 000000000..7cfae1bf7 --- /dev/null +++ b/test/plugin/mapping/MappingRenderOptionsTest.cpp @@ -0,0 +1,37 @@ +#include "mapping/MappingRenderOptions.h" + +using UKControllerPlugin::Mapping::MappingRenderOptions; + +namespace UKControllerPluginTest::Mapping { + class MappingRenderOptionsTest : public testing::Test + { + public: + MappingRenderOptions renderOptions; + }; + + TEST_F(MappingRenderOptionsTest, ItDoesntShowOptionsByDefault) + { + EXPECT_FALSE(renderOptions.ShowOptions()); + } + + TEST_F(MappingRenderOptionsTest, ItCanShowOptions) + { + renderOptions.ShowOptions(true); + EXPECT_TRUE(renderOptions.ShowOptions()); + renderOptions.ShowOptions(false); + EXPECT_FALSE(renderOptions.ShowOptions()); + } + + TEST_F(MappingRenderOptionsTest, ItDoesntShowVisualReferencePointsByDefault) + { + EXPECT_FALSE(renderOptions.ShowVisualReferencePoints()); + } + + TEST_F(MappingRenderOptionsTest, ItCanShowVisualReferencePoints) + { + renderOptions.ShowVisualReferencePoints(true); + EXPECT_TRUE(renderOptions.ShowVisualReferencePoints()); + renderOptions.ShowVisualReferencePoints(false); + EXPECT_FALSE(renderOptions.ShowVisualReferencePoints()); + } +} // namespace UKControllerPluginTest::Mapping diff --git a/test/plugin/mapping/ToggleMappingOptionsRenderTest.cpp b/test/plugin/mapping/ToggleMappingOptionsRenderTest.cpp new file mode 100644 index 000000000..dcedc5e66 --- /dev/null +++ b/test/plugin/mapping/ToggleMappingOptionsRenderTest.cpp @@ -0,0 +1,28 @@ +#include "mapping/MappingRenderOptions.h" +#include "mapping/ToggleMappingOptionsRender.h" + +using UKControllerPlugin::Mapping::MappingRenderOptions; +using UKControllerPlugin::Mapping::ToggleMappingOptionsRender; + +namespace UKControllerPluginTest::Mapping { + class ToggleMappingOptionsRenderTest : public testing::Test + { + public: + ToggleMappingOptionsRenderTest() : options(std::make_shared()), toggle(options, 123) + { + } + + testing::NiceMock radarScreen; + std::shared_ptr options; + ToggleMappingOptionsRender toggle; + }; + + TEST_F(ToggleMappingOptionsRenderTest, LeftClickTogglesShowOptions) + { + EXPECT_FALSE(options->ShowOptions()); + toggle.LeftClick(radarScreen, 123, "", {}, {}); + EXPECT_TRUE(options->ShowOptions()); + toggle.LeftClick(radarScreen, 123, "", {}, {}); + EXPECT_FALSE(options->ShowOptions()); + } +} // namespace UKControllerPluginTest::Mapping From 2e7b07fb3509c09363bf57b8ce2aefb12d0dbb83 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Sun, 10 Apr 2022 17:23:46 +0100 Subject: [PATCH 07/18] Titlebar on mapping options --- src/plugin/mapping/MappingOptionsRenderer.cpp | 17 +++++++++++++---- src/plugin/mapping/MappingOptionsRenderer.h | 7 +++---- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/plugin/mapping/MappingOptionsRenderer.cpp b/src/plugin/mapping/MappingOptionsRenderer.cpp index 0b1b8339d..df0ceea4a 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.cpp +++ b/src/plugin/mapping/MappingOptionsRenderer.cpp @@ -1,5 +1,6 @@ #include "MappingOptionsRenderer.h" #include "MappingRenderOptions.h" +#include "components/TitleBar.h" #include "euroscope/EuroscopeRadarLoopbackInterface.h" #include "graphics/GdiGraphicsInterface.h" @@ -33,9 +34,17 @@ namespace UKControllerPlugin::Mapping { void MappingOptionsRenderer::Render( Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { - const auto viewport = radarScreen.GetRadarViewport(); - graphics.FillRect( - Gdiplus::Rect{50, 50, viewport.right - viewport.left - 100, viewport.bottom - viewport.top - 100}, - *backgroundBrush); + graphics.Translated(50, 50, [&graphics, &radarScreen, this]() { + const auto viewport = radarScreen.GetRadarViewport(); + // Background + const auto width = viewport.right - viewport.left - 100; + graphics.FillRect(Gdiplus::Rect{0, 0, width, viewport.bottom - viewport.top - 100}, *backgroundBrush); + + // Titlebar + Components::TitleBar::Create(L"Mapping Options", Gdiplus::Rect{0, 0, width, 25}) + ->WithDefaultBackgroundBrush() + ->WithDefaultTextBrush() + ->Draw(graphics, radarScreen); + }); } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingOptionsRenderer.h b/src/plugin/mapping/MappingOptionsRenderer.h index aaa206967..386edc818 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.h +++ b/src/plugin/mapping/MappingOptionsRenderer.h @@ -3,7 +3,7 @@ namespace UKControllerPlugin::Mapping { class MappingRenderOptions; - + /** * Renders the mapping options to the screen */ @@ -22,13 +22,12 @@ namespace UKControllerPlugin::Mapping { Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) override; private: - // The options std::shared_ptr mappingOptions; - + // For clickspots const int screenObjectId; - + // Brushes std::shared_ptr backgroundBrush; }; From c460f58a48750b25a6c568617a43dff98cdf2aef Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Sun, 10 Apr 2022 17:42:46 +0100 Subject: [PATCH 08/18] Only render VRPs on screen --- src/plugin/CMakeLists.txt | 2 +- src/plugin/geometry/RectangleFunctions.cpp | 8 +++ src/plugin/geometry/RectangleFunctions.h | 5 ++ src/plugin/mapping/VisualReferencePoint.cpp | 7 ++ test/plugin/CMakeLists.txt | 2 +- .../geometry/RectangleFunctionsTest.cpp | 71 +++++++++++++++++++ 6 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 src/plugin/geometry/RectangleFunctions.cpp create mode 100644 src/plugin/geometry/RectangleFunctions.h create mode 100644 test/plugin/geometry/RectangleFunctionsTest.cpp diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index e6aafbac4..8c65b32d3 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -256,7 +256,7 @@ set(src__flightrule source_group("src\\flightrule" FILES ${src__flightrule}) set(src__geometry - geometry/Line.cpp geometry/Line.h geometry/DistanceRadiusToScreenRadius.cpp geometry/DistanceRadiusToScreenRadius.h) + geometry/Line.cpp geometry/Line.h geometry/DistanceRadiusToScreenRadius.cpp geometry/DistanceRadiusToScreenRadius.h geometry/RectangleFunctions.cpp geometry/RectangleFunctions.h) source_group("src\\geometry" FILES ${src__geometry}) set(src__graphics diff --git a/src/plugin/geometry/RectangleFunctions.cpp b/src/plugin/geometry/RectangleFunctions.cpp new file mode 100644 index 000000000..9733603c6 --- /dev/null +++ b/src/plugin/geometry/RectangleFunctions.cpp @@ -0,0 +1,8 @@ +#include "RectangleFunctions.h" + +namespace UKControllerPlugin::Geometry { + auto PointInRect(POINT point, RECT rect) -> bool + { + return point.x >= rect.left && point.x <= rect.right && point.y >= rect.top && point.y <= rect.bottom; + } +} // namespace UKControllerPlugin::Geometry diff --git a/src/plugin/geometry/RectangleFunctions.h b/src/plugin/geometry/RectangleFunctions.h new file mode 100644 index 000000000..e40fb4f6a --- /dev/null +++ b/src/plugin/geometry/RectangleFunctions.h @@ -0,0 +1,5 @@ +#pragma once + +namespace UKControllerPlugin::Geometry { + [[nodiscard]] auto PointInRect(POINT point, RECT rect) -> bool; +} diff --git a/src/plugin/mapping/VisualReferencePoint.cpp b/src/plugin/mapping/VisualReferencePoint.cpp index e6da88a26..d99cd5b11 100644 --- a/src/plugin/mapping/VisualReferencePoint.cpp +++ b/src/plugin/mapping/VisualReferencePoint.cpp @@ -1,6 +1,7 @@ #include "VisualReferencePoint.h" #include "euroscope/EuroscopeRadarLoopbackInterface.h" #include "helper/HelperFunctions.h" +#include "geometry/RectangleFunctions.h" #include "graphics/GdiGraphicsInterface.h" namespace UKControllerPlugin::Mapping { @@ -15,7 +16,13 @@ namespace UKControllerPlugin::Mapping { void VisualReferencePoint::Draw( Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { + const auto viewport = radarScreen.GetRadarViewport(); const auto screenPosition = radarScreen.ConvertCoordinateToScreenPoint(position); + + if (!Geometry::PointInRect(screenPosition, viewport)) { + return; + } + graphics.Translated(screenPosition.x, screenPosition.y, [&graphics, this]() { Gdiplus::Rect area{-10, -10, 20, 20}; diff --git a/test/plugin/CMakeLists.txt b/test/plugin/CMakeLists.txt index b087c2ec7..a79cb40a3 100644 --- a/test/plugin/CMakeLists.txt +++ b/test/plugin/CMakeLists.txt @@ -143,7 +143,7 @@ set(test__flightrule source_group("test\\flightrule" FILES ${test__flightrule}) set(test__geometry - geometry/LineTest.cpp geometry/DistanceRadiusToScreenRadiusTest.cpp) + geometry/LineTest.cpp geometry/DistanceRadiusToScreenRadiusTest.cpp geometry/RectangleFunctionsTest.cpp) source_group("test\\geometry" FILES ${test__geometry}) set(test__handoff diff --git a/test/plugin/geometry/RectangleFunctionsTest.cpp b/test/plugin/geometry/RectangleFunctionsTest.cpp new file mode 100644 index 000000000..83cdfe4b5 --- /dev/null +++ b/test/plugin/geometry/RectangleFunctionsTest.cpp @@ -0,0 +1,71 @@ +#include "geometry/RectangleFunctions.h" + +using UKControllerPlugin::Geometry::PointInRect; + +namespace UKControllerPluginTest::Geometry { + class RectangleFunctionsTest : public testing::Test + { + public: + RECT rect{10, 10, 50, 50}; + }; + + TEST_F(RectangleFunctionsTest, PointIsInRectangleTopLeftCorner) + { + EXPECT_TRUE(PointInRect(POINT{10, 10}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInRectangleTopBoundary) + { + EXPECT_TRUE(PointInRect(POINT{20, 10}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInRectangleTopRightCorner) + { + EXPECT_TRUE(PointInRect(POINT{50, 10}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInRectangleRightBoundary) + { + EXPECT_TRUE(PointInRect(POINT{50, 30}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInRectangleBottomRightCorner) + { + EXPECT_TRUE(PointInRect(POINT{50, 50}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInRectangleBottomBoundary) + { + EXPECT_TRUE(PointInRect(POINT{25, 50}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInRectangleBottomLeftCorner) + { + EXPECT_TRUE(PointInRect(POINT{10, 50}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInRectangleLeftBoundary) + { + EXPECT_TRUE(PointInRect(POINT{10, 30}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInNotInRectangleAboveTopBoundary) + { + EXPECT_FALSE(PointInRect(POINT{25, 5}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInNotInRectangleRightOfRightBoundary) + { + EXPECT_FALSE(PointInRect(POINT{55, 25}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInNotInRectangleBelowBottomBoundary) + { + EXPECT_FALSE(PointInRect(POINT{25, 55}, rect)); + } + + TEST_F(RectangleFunctionsTest, PointIsInNotInRectangleLeftOfLeftBoundary) + { + EXPECT_FALSE(PointInRect(POINT{5, 25}, rect)); + } +} // namespace UKControllerPluginTest::Geometry From d4453bc226627ae45a7f9caacc4532d34179fd94 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Wed, 11 May 2022 22:05:02 +0100 Subject: [PATCH 09/18] Commit some stuff --- src/plugin/CMakeLists.txt | 2 +- .../mapping/MappingBootstrapProvider.cpp | 6 --- src/plugin/mapping/MappingBootstrapProvider.h | 1 - .../mapping/MappingElementDrawerFactory.h | 12 +++++ .../MappingElementDrawerFactoryDelegator.cpp | 21 +++++++++ .../MappingElementDrawerFactoryDelegator.h | 20 +++++++++ src/plugin/mapping/MappingElementFactory.cpp | 45 +++++++++++++++++++ src/plugin/mapping/MappingElementFactory.h | 20 +++++++++ src/plugin/mapping/MappingRenderOptions.cpp | 14 +++++- src/plugin/mapping/MappingRenderOptions.h | 7 ++- src/plugin/mapping/RelatedAirfield.cpp | 22 +++++++++ src/plugin/mapping/RelatedAirfield.h | 23 ++++++++++ src/plugin/mapping/RelatedAirfieldProvider.h | 13 ++++++ .../RelatedAirfieldProviderFactory.cpp | 1 + .../mapping/RelatedAirfieldProviderFactory.h | 5 +++ .../mapping/ShowsVisualReferencePoints.cpp | 14 ++++++ .../mapping/ShowsVisualReferencePoints.h | 21 +++++++++ .../mapping/TypeSpecificDisplayRuleFactory.h | 15 +++++++ .../VisualReferencePointDrawerFactory.cpp | 25 +++++++++++ .../VisualReferencePointDrawerFactory.h | 16 +++++++ ...lReferencePointRelatedAirfieldProvider.cpp | 16 +++++++ ...ualReferencePointRelatedAirfieldProvider.h | 20 +++++++++ .../VisualReferencePointShouldRender.cpp | 17 +++++++ .../VisualReferencePointShouldRender.h | 20 +++++++++ .../mapping/MappingRenderOptionsTest.cpp | 12 +++++ 25 files changed, 377 insertions(+), 11 deletions(-) create mode 100644 src/plugin/mapping/MappingElementDrawerFactory.h create mode 100644 src/plugin/mapping/MappingElementDrawerFactoryDelegator.cpp create mode 100644 src/plugin/mapping/MappingElementDrawerFactoryDelegator.h create mode 100644 src/plugin/mapping/MappingElementFactory.cpp create mode 100644 src/plugin/mapping/MappingElementFactory.h create mode 100644 src/plugin/mapping/RelatedAirfield.cpp create mode 100644 src/plugin/mapping/RelatedAirfield.h create mode 100644 src/plugin/mapping/RelatedAirfieldProvider.h create mode 100644 src/plugin/mapping/RelatedAirfieldProviderFactory.cpp create mode 100644 src/plugin/mapping/RelatedAirfieldProviderFactory.h create mode 100644 src/plugin/mapping/ShowsVisualReferencePoints.cpp create mode 100644 src/plugin/mapping/ShowsVisualReferencePoints.h create mode 100644 src/plugin/mapping/TypeSpecificDisplayRuleFactory.h create mode 100644 src/plugin/mapping/VisualReferencePointDrawerFactory.cpp create mode 100644 src/plugin/mapping/VisualReferencePointDrawerFactory.h create mode 100644 src/plugin/mapping/VisualReferencePointRelatedAirfieldProvider.cpp create mode 100644 src/plugin/mapping/VisualReferencePointRelatedAirfieldProvider.h create mode 100644 src/plugin/mapping/VisualReferencePointShouldRender.cpp create mode 100644 src/plugin/mapping/VisualReferencePointShouldRender.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 8c65b32d3..48ade7e42 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -488,7 +488,7 @@ set(src__login source_group("src\\login" FILES ${src__login}) set(src__mapping - mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h mapping/MappingElementManager.cpp mapping/MappingElementManager.h mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h mapping/MappingRenderer.cpp mapping/MappingRenderer.h mapping/MappingOptionsRenderer.cpp mapping/MappingOptionsRenderer.h mapping/MappingRenderOptions.cpp mapping/MappingRenderOptions.h mapping/ToggleMappingOptionsRender.cpp mapping/ToggleMappingOptionsRender.h) + mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h mapping/MappingElementManager.cpp mapping/MappingElementManager.h mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h mapping/MappingRenderer.cpp mapping/MappingRenderer.h mapping/MappingOptionsRenderer.cpp mapping/MappingOptionsRenderer.h mapping/MappingRenderOptions.cpp mapping/MappingRenderOptions.h mapping/ToggleMappingOptionsRender.cpp mapping/ToggleMappingOptionsRender.h mapping/VisualReferencePointShouldRender.cpp mapping/VisualReferencePointShouldRender.h mapping/RelatedAirfieldProvider.h mapping/RelatedAirfield.cpp mapping/RelatedAirfield.h mapping/VisualReferencePointRelatedAirfieldProvider.cpp mapping/VisualReferencePointRelatedAirfieldProvider.h mapping/MappingElementDrawerFactoryDelegator.cpp mapping/MappingElementDrawerFactoryDelegator.h mapping/MappingElementFactory.h mapping/MappingElementDrawerFactory.h mapping/VisualReferencePointDrawerFactory.cpp mapping/VisualReferencePointDrawerFactory.h mapping/TypeSpecificDisplayRuleFactory.h mapping/ShowsVisualReferencePoints.cpp mapping/ShowsVisualReferencePoints.h mapping/RelatedAirfieldProviderFactory.cpp mapping/RelatedAirfieldProviderFactory.h mapping/MappingElementFactory.cpp) source_group("src\\mapping" FILES ${src__mapping}) set(src__message diff --git a/src/plugin/mapping/MappingBootstrapProvider.cpp b/src/plugin/mapping/MappingBootstrapProvider.cpp index bea4e878b..ce4b57522 100644 --- a/src/plugin/mapping/MappingBootstrapProvider.cpp +++ b/src/plugin/mapping/MappingBootstrapProvider.cpp @@ -9,12 +9,6 @@ #include "radarscreen/RadarRenderableCollection.h" namespace UKControllerPlugin::Mapping { - - void MappingBootstrapProvider::BootstrapPlugin(Bootstrap::PersistenceContainer& container) - { - static_cast(container.moduleFactories->Mapping().ElementManager(*container.dependencyLoader)); - } - void MappingBootstrapProvider::BootstrapRadarScreen( const Bootstrap::PersistenceContainer& container, RadarScreen::RadarRenderableCollection& radarRenderables, diff --git a/src/plugin/mapping/MappingBootstrapProvider.h b/src/plugin/mapping/MappingBootstrapProvider.h index 399c197eb..188b9596a 100644 --- a/src/plugin/mapping/MappingBootstrapProvider.h +++ b/src/plugin/mapping/MappingBootstrapProvider.h @@ -8,7 +8,6 @@ namespace UKControllerPlugin::Mapping { class MappingBootstrapProvider : public Bootstrap::BootstrapProviderInterface { public: - void BootstrapPlugin(Bootstrap::PersistenceContainer& container) override; void BootstrapRadarScreen( const Bootstrap::PersistenceContainer& container, RadarScreen::RadarRenderableCollection& radarRenderables, diff --git a/src/plugin/mapping/MappingElementDrawerFactory.h b/src/plugin/mapping/MappingElementDrawerFactory.h new file mode 100644 index 000000000..08457020e --- /dev/null +++ b/src/plugin/mapping/MappingElementDrawerFactory.h @@ -0,0 +1,12 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + class MappingElementDrawer; + + class MappingElementDrawerFactory + { + public: + virtual ~MappingElementDrawerFactory() = default; + [[nodiscard]] virtual auto Make(const nlohmann::json& data) const -> std::shared_ptr = 0; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementDrawerFactoryDelegator.cpp b/src/plugin/mapping/MappingElementDrawerFactoryDelegator.cpp new file mode 100644 index 000000000..b3443e3fa --- /dev/null +++ b/src/plugin/mapping/MappingElementDrawerFactoryDelegator.cpp @@ -0,0 +1,21 @@ +#include "MappingElementDrawerFactoryDelegator.h" + +namespace UKControllerPlugin::Mapping { + + MappingElementDrawerFactoryDelegator::MappingElementDrawerFactoryDelegator( + std::map> factories) + : factories(std::move(factories)) + { + } + + auto MappingElementDrawerFactoryDelegator::Make(const nlohmann::json& data) const + -> std::shared_ptr + { + const auto type = data.contains("type") ? data.at("type").get() : std::string(); + if (!factories.contains(type)) { + throw std::exception(std::string("Unknown mapping element type, cannot make drawer: " + type).c_str()); + } + + return factories.at(type)->Make(data); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementDrawerFactoryDelegator.h b/src/plugin/mapping/MappingElementDrawerFactoryDelegator.h new file mode 100644 index 000000000..4b432b775 --- /dev/null +++ b/src/plugin/mapping/MappingElementDrawerFactoryDelegator.h @@ -0,0 +1,20 @@ +#pragma once +#include "MappingElementDrawerFactory.h" + +namespace UKControllerPlugin::Mapping { + + /** + * Delegates the responsibility for creating drawers to other factories. + */ + class MappingElementDrawerFactoryDelegator : public MappingElementDrawerFactory + { + public: + MappingElementDrawerFactoryDelegator( + std::map> factories); + [[nodiscard]] auto Make(const nlohmann::json& data) const -> std::shared_ptr; + + private: + // All the factories + const std::map> factories; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementFactory.cpp b/src/plugin/mapping/MappingElementFactory.cpp new file mode 100644 index 000000000..169adabcc --- /dev/null +++ b/src/plugin/mapping/MappingElementFactory.cpp @@ -0,0 +1,45 @@ +#include "MappingElement.h" +#include "MappingElementDrawerFactory.h" +#include "MappingElementFactory.h" + +namespace UKControllerPlugin::Mapping { + + MappingElementFactory::MappingElementFactory(const MappingElementDrawerFactory& drawerFactory) + : drawerFactory(drawerFactory) + { + } + + auto MappingElementFactory::Make(const nlohmann::json& data) -> std::shared_ptr + { + if (!DataIsValid(data)) { + return nullptr; + } + + const auto type = data.at("type").get(); + if (!IsKnownType(type)) { + LogWarning("Detected mapping element of unknown type, ignoring"); + return nullptr; + } + + return std::make_shared( + data.at("id").get(), + data.at("type").get(), + data.at("name").get(), + std::set>{}, + drawerFactory.Make(data)); + } + + /** + * Checks that we have the minimum necessary data to build a mapping element. + */ + auto MappingElementFactory::DataIsValid(const nlohmann::json& data) -> bool + { + return data.is_object() && data.contains("id") && data.at("id").is_number_integer() && data.contains("type") && + data.at("type").is_string() && data.contains("name") && data.at("name").is_string(); + } + + auto MappingElementFactory::IsKnownType(const std::string& type) -> bool + { + return type == "visual_reference_point"; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementFactory.h b/src/plugin/mapping/MappingElementFactory.h new file mode 100644 index 000000000..27df9dd8b --- /dev/null +++ b/src/plugin/mapping/MappingElementFactory.h @@ -0,0 +1,20 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + class MappingElementDrawerFactory; + class MappingElement; + + class MappingElementFactory + { + public: + MappingElementFactory(const MappingElementDrawerFactory& drawerFactory); + [[nodiscard]] auto Make(const nlohmann::json& data) -> std::shared_ptr; + + private: + [[nodiscard]] static auto DataIsValid(const nlohmann::json& data) -> bool; + [[nodiscard]] static auto IsKnownType(const std::string& type) -> bool; + + // Builds drawers + const MappingElementDrawerFactory& drawerFactory; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderOptions.cpp b/src/plugin/mapping/MappingRenderOptions.cpp index 18507e943..eb4bbfdf3 100644 --- a/src/plugin/mapping/MappingRenderOptions.cpp +++ b/src/plugin/mapping/MappingRenderOptions.cpp @@ -11,14 +11,24 @@ namespace UKControllerPlugin::Mapping { { return this->showVisualReferencePoints; } - + void MappingRenderOptions::ShowOptions(bool show) { this->showOptions = show; } - + auto MappingRenderOptions::ShowOptions() const -> bool { return this->showOptions; } + + auto MappingRenderOptions::VisualReferencePointAirfields() const -> const std::set& + { + return this->visualReferencePointAirfields; + } + + void MappingRenderOptions::VisualReferencePointAirfields(const std::set airfields) + { + this->visualReferencePointAirfields = airfields; + } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderOptions.h b/src/plugin/mapping/MappingRenderOptions.h index da5d00fea..e84c2bb9d 100644 --- a/src/plugin/mapping/MappingRenderOptions.h +++ b/src/plugin/mapping/MappingRenderOptions.h @@ -11,12 +11,17 @@ namespace UKControllerPlugin::Mapping { [[nodiscard]] auto ShowOptions() const -> bool; void ShowVisualReferencePoints(bool show); [[nodiscard]] auto ShowVisualReferencePoints() const -> bool; + void VisualReferencePointAirfields(const std::set airfields); + [[nodiscard]] auto VisualReferencePointAirfields() const -> const std::set&; private: // Do we display the options bool showOptions = false; - + // Do we display VRPs bool showVisualReferencePoints = false; + + // The airfields to render + std::set visualReferencePointAirfields; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/RelatedAirfield.cpp b/src/plugin/mapping/RelatedAirfield.cpp new file mode 100644 index 000000000..da605b523 --- /dev/null +++ b/src/plugin/mapping/RelatedAirfield.cpp @@ -0,0 +1,22 @@ +#include "RelatedAirfield.h" +#include "RelatedAirfieldProvider.h" + +namespace UKControllerPlugin::Mapping { + + RelatedAirfield::RelatedAirfield(std::shared_ptr provider, std::set airfields) + : provider(std::move(provider)), airfields(std::move(airfields)) + { + } + + auto RelatedAirfield::Passes() -> bool + { + const auto& selectedAirfields = provider->Airfields(); + for (const auto& airfield : airfields) { + if (selectedAirfields.find(airfield) != selectedAirfields.cend()) { + return true; + } + } + + return false; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/RelatedAirfield.h b/src/plugin/mapping/RelatedAirfield.h new file mode 100644 index 000000000..968cc6281 --- /dev/null +++ b/src/plugin/mapping/RelatedAirfield.h @@ -0,0 +1,23 @@ +#pragma once +#include "DisplayRule.h" + +namespace UKControllerPlugin::Mapping { + class RelatedAirfieldProvider; + + /** + * Checks if related airfields are selected for the mapping element. + */ + class RelatedAirfield : public DisplayRule + { + public: + RelatedAirfield(std::shared_ptr provider, std::set airfields); + auto Passes() -> bool override; + + private: + // Provides the airfields to compare against + std::shared_ptr provider; + + // The airfields that are related + std::set airfields; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/RelatedAirfieldProvider.h b/src/plugin/mapping/RelatedAirfieldProvider.h new file mode 100644 index 000000000..3985a107a --- /dev/null +++ b/src/plugin/mapping/RelatedAirfieldProvider.h @@ -0,0 +1,13 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + /** + * Provides airfield to compare against related airfields. + */ + class RelatedAirfieldProvider + { + public: + virtual ~RelatedAirfieldProvider() = default; + [[nodiscard]] virtual auto Airfields() const -> const std::set& = 0; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/RelatedAirfieldProviderFactory.cpp b/src/plugin/mapping/RelatedAirfieldProviderFactory.cpp new file mode 100644 index 000000000..0e10bbd78 --- /dev/null +++ b/src/plugin/mapping/RelatedAirfieldProviderFactory.cpp @@ -0,0 +1 @@ +#include "RelatedAirfieldProviderFactory.h" diff --git a/src/plugin/mapping/RelatedAirfieldProviderFactory.h b/src/plugin/mapping/RelatedAirfieldProviderFactory.h new file mode 100644 index 000000000..8bf90b8fa --- /dev/null +++ b/src/plugin/mapping/RelatedAirfieldProviderFactory.h @@ -0,0 +1,5 @@ +#pragma once + +class RelatedAirfieldProviderFactory +{ +}; diff --git a/src/plugin/mapping/ShowsVisualReferencePoints.cpp b/src/plugin/mapping/ShowsVisualReferencePoints.cpp new file mode 100644 index 000000000..54347c5fb --- /dev/null +++ b/src/plugin/mapping/ShowsVisualReferencePoints.cpp @@ -0,0 +1,14 @@ +#include "MappingRenderOptions.h" +#include "ShowsVisualReferencePoints.h" + +namespace UKControllerPlugin::Mapping { + ShowsVisualReferencePoints::ShowsVisualReferencePoints(std::shared_ptr renderOptions) + : renderOptions(std::move(renderOptions)) + { + } + + auto ShowsVisualReferencePoints::Passes() -> bool + { + return renderOptions->ShowVisualReferencePoints(); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/ShowsVisualReferencePoints.h b/src/plugin/mapping/ShowsVisualReferencePoints.h new file mode 100644 index 000000000..3eb50563f --- /dev/null +++ b/src/plugin/mapping/ShowsVisualReferencePoints.h @@ -0,0 +1,21 @@ +#pragma once +#include "DisplayRule.h" + +namespace UKControllerPlugin::Mapping { + class MappingRenderOptions; + + /** + * Should visual reference points be displayed. + */ + class ShowsVisualReferencePoints : public DisplayRule + { + public: + ShowsVisualReferencePoints(std::shared_ptr renderOptions); + auto Passes() -> bool override; + + private: + + // Options for rendering + std::shared_ptr renderOptions; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/TypeSpecificDisplayRuleFactory.h b/src/plugin/mapping/TypeSpecificDisplayRuleFactory.h new file mode 100644 index 000000000..b582ab0f9 --- /dev/null +++ b/src/plugin/mapping/TypeSpecificDisplayRuleFactory.h @@ -0,0 +1,15 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + class DisplayRule; + + /** + * Builds display rules associated with mapping elements + */ + class TypeSpecificDisplayRuleFactory + { + public: + virtual ~TypeSpecificDisplayRuleFactory() = default; + [[nodiscard]] virtual auto Make(const nlohmann::json& data) -> std::set> = 0; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointDrawerFactory.cpp b/src/plugin/mapping/VisualReferencePointDrawerFactory.cpp new file mode 100644 index 000000000..43fdf2dd5 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointDrawerFactory.cpp @@ -0,0 +1,25 @@ +#include "VisualReferencePoint.h" +#include "VisualReferencePointDrawerFactory.h" + +namespace UKControllerPlugin::Mapping { + + auto VisualReferencePointDrawerFactory::Make(const nlohmann::json& data) const + -> std::shared_ptr + { + if (!DataValid(data)) { + throw std::exception("Invalid VRP data for drawer creation"); + } + + EuroScopePlugIn::CPosition position; + position.m_Latitude = data.at("latitude").get(); + position.m_Longitude = data.at("longitude").get(); + + return std::make_shared(data.at("name").get(), position); + } + + auto VisualReferencePointDrawerFactory::DataValid(const nlohmann::json& data) const -> bool + { + return data.contains("name") && data.at("name").is_string() && data.contains("latitude") && + data.at("latitude").is_number() && data.contains("longitude") && data.at("longitude").is_number(); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointDrawerFactory.h b/src/plugin/mapping/VisualReferencePointDrawerFactory.h new file mode 100644 index 000000000..df6e97e1e --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointDrawerFactory.h @@ -0,0 +1,16 @@ +#pragma once +#include "mapping/MappingElementDrawerFactory.h" + +namespace UKControllerPlugin::Mapping { + /** + * Builds visual reference point drawers. + */ + class VisualReferencePointDrawerFactory : public MappingElementDrawerFactory + { + public: + [[nodiscard]] auto Make(const nlohmann::json& data) const -> std::shared_ptr override; + + private: + [[nodiscard]] auto DataValid(const nlohmann::json& data) const -> bool; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointRelatedAirfieldProvider.cpp b/src/plugin/mapping/VisualReferencePointRelatedAirfieldProvider.cpp new file mode 100644 index 000000000..0683dd118 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointRelatedAirfieldProvider.cpp @@ -0,0 +1,16 @@ +#include "MappingRenderOptions.h" +#include "VisualReferencePointRelatedAirfieldProvider.h" + +namespace UKControllerPlugin::Mapping { + + VisualReferencePointRelatedAirfieldProvider::VisualReferencePointRelatedAirfieldProvider( + std::shared_ptr renderOptions) + : renderOptions(std::move(renderOptions)) + { + } + + auto VisualReferencePointRelatedAirfieldProvider::Airfields() const -> const std::set& + { + return renderOptions->VisualReferencePointAirfields(); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointRelatedAirfieldProvider.h b/src/plugin/mapping/VisualReferencePointRelatedAirfieldProvider.h new file mode 100644 index 000000000..a6274916d --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointRelatedAirfieldProvider.h @@ -0,0 +1,20 @@ +#pragma once +#include "RelatedAirfieldProvider.h" + +namespace UKControllerPlugin::Mapping { + class MappingRenderOptions; + + /** + * Provides airfields related to visual reference points + */ + class VisualReferencePointRelatedAirfieldProvider : public RelatedAirfieldProvider + { + public: + VisualReferencePointRelatedAirfieldProvider(std::shared_ptr renderOptions); + [[nodiscard]] auto Airfields() const -> const std::set& override; + + private: + // Rendering options + std::shared_ptr renderOptions; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointShouldRender.cpp b/src/plugin/mapping/VisualReferencePointShouldRender.cpp new file mode 100644 index 000000000..780086934 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointShouldRender.cpp @@ -0,0 +1,17 @@ +#include "MappingRenderOptions.h" +#include "VisualReferencePointShouldRender.h" + +namespace UKControllerPlugin::Mapping { + + VisualReferencePointShouldRender::VisualReferencePointShouldRender( + std::shared_ptr renderOptions) + : renderOptions(renderOptions) + { + assert(renderOptions && "Render options not set in VisualReferencePointShouldRender"); + } + + auto VisualReferencePointShouldRender::Passes() -> bool + { + return renderOptions->ShowVisualReferencePoints(); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointShouldRender.h b/src/plugin/mapping/VisualReferencePointShouldRender.h new file mode 100644 index 000000000..8830a9323 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointShouldRender.h @@ -0,0 +1,20 @@ +#pragma once +#include "DisplayRule.h" + +namespace UKControllerPlugin::Mapping { + class MappingRenderOptions; + + /** + * Determines whether a VRP should render. + */ + class VisualReferencePointShouldRender : public DisplayRule + { + public: + VisualReferencePointShouldRender(std::shared_ptr renderOptions); + [[nodiscard]] auto Passes() -> bool override; + + private: + // Render options + std::shared_ptr renderOptions; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/test/plugin/mapping/MappingRenderOptionsTest.cpp b/test/plugin/mapping/MappingRenderOptionsTest.cpp index 7cfae1bf7..b71667d9b 100644 --- a/test/plugin/mapping/MappingRenderOptionsTest.cpp +++ b/test/plugin/mapping/MappingRenderOptionsTest.cpp @@ -34,4 +34,16 @@ namespace UKControllerPluginTest::Mapping { renderOptions.ShowVisualReferencePoints(false); EXPECT_FALSE(renderOptions.ShowVisualReferencePoints()); } + + TEST_F(MappingRenderOptionsTest, ItDoesntHaveAnyVisualReferencePointAirfields) + { + EXPECT_TRUE(renderOptions.VisualReferencePointAirfields().empty()); + } + + TEST_F(MappingRenderOptionsTest, ItHasVisualReferencePointAirfields) + { + std::set expected{1, 2, 3}; + renderOptions.VisualReferencePointAirfields({1, 2, 3}); + EXPECT_EQ(expected, renderOptions.VisualReferencePointAirfields()); + } } // namespace UKControllerPluginTest::Mapping From 33c448124951da72a8656ebc0738e9c98ace5e12 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Sat, 14 May 2022 17:03:04 +0100 Subject: [PATCH 10/18] More rulesets --- src/plugin/CMakeLists.txt | 39 ++++++++++++++++++- .../DefaultDisplayRulesetDelegatorFactory.cpp | 20 ++++++++++ .../DefaultDisplayRulesetDelegatorFactory.h | 17 ++++++++ ...DisplayRuleElementTypeDelegatorFactory.cpp | 19 +++++++++ .../DisplayRuleElementTypeDelegatorFactory.h | 19 +++++++++ .../mapping/DisplayRuleFactoryFactory.cpp | 27 +++++++++++++ .../mapping/DisplayRuleFactoryFactory.h | 22 +++++++++++ .../mapping/DisplayRuleFactoryInterface.h | 16 ++++++++ .../DisplayRuleTypeDelegatorFactory.cpp | 20 ++++++++++ .../mapping/DisplayRuleTypeDelegatorFactory.h | 18 +++++++++ .../DisplayRulesetAggregatorFactory.cpp | 23 +++++++++++ .../mapping/DisplayRulesetAggregatorFactory.h | 24 ++++++++++++ src/plugin/mapping/DisplayRulesetFactory.cpp | 9 +++++ src/plugin/mapping/DisplayRulesetFactory.h | 17 ++++++++ .../mapping/DisplayRulesetFactoryFactory.cpp | 7 ++++ .../mapping/DisplayRulesetFactoryFactory.h | 11 ++++++ .../mapping/DisplayRulesetFactoryInterface.h | 15 +++++++ .../mapping/TypeSpecificDisplayRuleFactory.h | 15 ------- ...rencePointDefaultDisplayRulesetFactory.cpp | 10 +++++ ...ferencePointDefaultDisplayRulesetFactory.h | 14 +++++++ ...alReferencePointRelatedAirfieldFactory.cpp | 30 ++++++++++++++ ...sualReferencePointRelatedAirfieldFactory.h | 21 ++++++++++ 22 files changed, 397 insertions(+), 16 deletions(-) create mode 100644 src/plugin/mapping/DefaultDisplayRulesetDelegatorFactory.cpp create mode 100644 src/plugin/mapping/DefaultDisplayRulesetDelegatorFactory.h create mode 100644 src/plugin/mapping/DisplayRuleElementTypeDelegatorFactory.cpp create mode 100644 src/plugin/mapping/DisplayRuleElementTypeDelegatorFactory.h create mode 100644 src/plugin/mapping/DisplayRuleFactoryFactory.cpp create mode 100644 src/plugin/mapping/DisplayRuleFactoryFactory.h create mode 100644 src/plugin/mapping/DisplayRuleFactoryInterface.h create mode 100644 src/plugin/mapping/DisplayRuleTypeDelegatorFactory.cpp create mode 100644 src/plugin/mapping/DisplayRuleTypeDelegatorFactory.h create mode 100644 src/plugin/mapping/DisplayRulesetAggregatorFactory.cpp create mode 100644 src/plugin/mapping/DisplayRulesetAggregatorFactory.h create mode 100644 src/plugin/mapping/DisplayRulesetFactory.cpp create mode 100644 src/plugin/mapping/DisplayRulesetFactory.h create mode 100644 src/plugin/mapping/DisplayRulesetFactoryFactory.cpp create mode 100644 src/plugin/mapping/DisplayRulesetFactoryFactory.h create mode 100644 src/plugin/mapping/DisplayRulesetFactoryInterface.h delete mode 100644 src/plugin/mapping/TypeSpecificDisplayRuleFactory.h create mode 100644 src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp create mode 100644 src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.h create mode 100644 src/plugin/mapping/VisualReferencePointRelatedAirfieldFactory.cpp create mode 100644 src/plugin/mapping/VisualReferencePointRelatedAirfieldFactory.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 48ade7e42..4a9d58de9 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -488,7 +488,39 @@ set(src__login source_group("src\\login" FILES ${src__login}) set(src__mapping - mapping/MappingElement.cpp mapping/MappingElement.h mapping/MappingElementInterface.h mapping/MappingElementDrawer.h mapping/DisplayRule.h mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h mapping/MappingElementManager.cpp mapping/MappingElementManager.h mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h mapping/MappingRenderer.cpp mapping/MappingRenderer.h mapping/MappingOptionsRenderer.cpp mapping/MappingOptionsRenderer.h mapping/MappingRenderOptions.cpp mapping/MappingRenderOptions.h mapping/ToggleMappingOptionsRender.cpp mapping/ToggleMappingOptionsRender.h mapping/VisualReferencePointShouldRender.cpp mapping/VisualReferencePointShouldRender.h mapping/RelatedAirfieldProvider.h mapping/RelatedAirfield.cpp mapping/RelatedAirfield.h mapping/VisualReferencePointRelatedAirfieldProvider.cpp mapping/VisualReferencePointRelatedAirfieldProvider.h mapping/MappingElementDrawerFactoryDelegator.cpp mapping/MappingElementDrawerFactoryDelegator.h mapping/MappingElementFactory.h mapping/MappingElementDrawerFactory.h mapping/VisualReferencePointDrawerFactory.cpp mapping/VisualReferencePointDrawerFactory.h mapping/TypeSpecificDisplayRuleFactory.h mapping/ShowsVisualReferencePoints.cpp mapping/ShowsVisualReferencePoints.h mapping/RelatedAirfieldProviderFactory.cpp mapping/RelatedAirfieldProviderFactory.h mapping/MappingElementFactory.cpp) + mapping/MappingElement.cpp mapping/MappingElement.h + mapping/MappingElementInterface.h + mapping/MappingElementDrawer.h + mapping/DisplayRule.h + mapping/VisualReferencePoint.cpp mapping/VisualReferencePoint.h + mapping/MappingElementManager.cpp mapping/MappingElementManager.h + mapping/MappingElementManagerFactory.cpp mapping/MappingElementManagerFactory.h + mapping/MappingModuleFactory.cpp mapping/MappingModuleFactory.h + mapping/MappingBootstrapProvider.cpp mapping/MappingBootstrapProvider.h + mapping/MappingRenderer.cpp mapping/MappingRenderer.h + mapping/MappingOptionsRenderer.cpp mapping/MappingOptionsRenderer.h + mapping/MappingRenderOptions.cpp mapping/MappingRenderOptions.h + mapping/ToggleMappingOptionsRender.cpp mapping/ToggleMappingOptionsRender.h + mapping/VisualReferencePointShouldRender.cpp mapping/VisualReferencePointShouldRender.h + mapping/RelatedAirfieldProvider.h + mapping/RelatedAirfield.cpp mapping/RelatedAirfield.h + mapping/VisualReferencePointRelatedAirfieldProvider.cpp mapping/VisualReferencePointRelatedAirfieldProvider.h + mapping/MappingElementDrawerFactoryDelegator.cpp mapping/MappingElementDrawerFactoryDelegator.h + mapping/MappingElementFactory.h + mapping/MappingElementDrawerFactory.h + mapping/VisualReferencePointDrawerFactory.cpp mapping/VisualReferencePointDrawerFactory.h + mapping/ShowsVisualReferencePoints.cpp mapping/ShowsVisualReferencePoints.h + mapping/RelatedAirfieldProviderFactory.cpp mapping/RelatedAirfieldProviderFactory.h + mapping/MappingElementFactory.cpp + mapping/DisplayRuleFactoryInterface.h + mapping/DisplayRuleTypeDelegatorFactory.cpp mapping/DisplayRuleTypeDelegatorFactory.h + mapping/DisplayRuleElementTypeDelegatorFactory.cpp mapping/DisplayRuleElementTypeDelegatorFactory.h + mapping/DisplayRuleFactoryFactory.cpp mapping/DisplayRuleFactoryFactory.h + mapping/VisualReferencePointRelatedAirfieldFactory.cpp mapping/VisualReferencePointRelatedAirfieldFactory.h + mapping/DisplayRulesetFactory.cpp mapping/DisplayRulesetFactory.h + mapping/DisplayRulesetFactoryInterface.h + mapping/DisplayRulesetAggregatorFactory.cpp mapping/DisplayRulesetAggregatorFactory.h + mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp mapping/VisualReferencePointDefaultDisplayRulesetFactory.h mapping/DefaultDisplayRulesetDelegatorFactory.cpp mapping/DefaultDisplayRulesetDelegatorFactory.h mapping/DisplayRulesetFactoryFactory.cpp mapping/DisplayRulesetFactoryFactory.h) source_group("src\\mapping" FILES ${src__mapping}) set(src__message @@ -999,6 +1031,11 @@ set(ALL_FILES ${src__timer} ${src__wake}) +################################################################################ +# Source Files +################################################################################ +set_source_files_properties(ALL_FILES PROPERTIES COMPILE_FLAGS "-include pch/pch.h") + ################################################################################ # Target ################################################################################ diff --git a/src/plugin/mapping/DefaultDisplayRulesetDelegatorFactory.cpp b/src/plugin/mapping/DefaultDisplayRulesetDelegatorFactory.cpp new file mode 100644 index 000000000..85cebb047 --- /dev/null +++ b/src/plugin/mapping/DefaultDisplayRulesetDelegatorFactory.cpp @@ -0,0 +1,20 @@ +#include "DefaultDisplayRulesetDelegatorFactory.h" + +namespace UKControllerPlugin::Mapping { + + DefaultDisplayRulesetDelegatorFactory::DefaultDisplayRulesetDelegatorFactory( + const std::map> factories) + : factories(std::move(factories)) + { + } + + auto DefaultDisplayRulesetDelegatorFactory::Make(const std::string& elementType, const nlohmann::json& data) const + -> std::set> + { + if (!factories.contains(elementType)) { + throw std::invalid_argument("No default display ruleset factory for element type " + elementType); + } + + return factories.at(elementType)->Make(elementType, data); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DefaultDisplayRulesetDelegatorFactory.h b/src/plugin/mapping/DefaultDisplayRulesetDelegatorFactory.h new file mode 100644 index 000000000..1507bf94f --- /dev/null +++ b/src/plugin/mapping/DefaultDisplayRulesetDelegatorFactory.h @@ -0,0 +1,17 @@ +#pragma once +#include "DisplayRulesetFactoryInterface.h" + +namespace UKControllerPlugin::Mapping { + class DefaultDisplayRulesetDelegatorFactory : public DisplayRulesetFactoryInterface + { + public: + DefaultDisplayRulesetDelegatorFactory( + const std::map> factories); + auto Make(const std::string& elementType, const nlohmann::json& data) const + -> std::set> override; + + private: + // Factories for delegation + const std::map> factories; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRuleElementTypeDelegatorFactory.cpp b/src/plugin/mapping/DisplayRuleElementTypeDelegatorFactory.cpp new file mode 100644 index 000000000..475367b6d --- /dev/null +++ b/src/plugin/mapping/DisplayRuleElementTypeDelegatorFactory.cpp @@ -0,0 +1,19 @@ +#include "DisplayRuleElementTypeDelegatorFactory.h" + +namespace UKControllerPlugin::Mapping { + DisplayRuleElementTypeDelegatorFactory::DisplayRuleElementTypeDelegatorFactory( + std::map> factories) + : factories(std::move(factories)) + { + } + + auto DisplayRuleElementTypeDelegatorFactory::Make(const std::string& elementType, const nlohmann::json& data) + -> std::shared_ptr + { + if (!factories.contains(elementType)) { + throw std::invalid_argument("Invalid element type for display rule"); + } + + return factories.at(elementType)->Make(elementType, data); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRuleElementTypeDelegatorFactory.h b/src/plugin/mapping/DisplayRuleElementTypeDelegatorFactory.h new file mode 100644 index 000000000..faf00a4b8 --- /dev/null +++ b/src/plugin/mapping/DisplayRuleElementTypeDelegatorFactory.h @@ -0,0 +1,19 @@ +#pragma once +#include "DisplayRuleFactoryInterface.h" + +namespace UKControllerPlugin::Mapping { + + /** + * Delegates the building of display rule based on the type of element. + */ + class DisplayRuleElementTypeDelegatorFactory : public DisplayRuleFactoryInterface + { + public: + DisplayRuleElementTypeDelegatorFactory(std::map> factories); + auto Make(const std::string& elementType, const nlohmann::json& data) -> std::shared_ptr override; + + private: + // All the factories + const std::map> factories; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRuleFactoryFactory.cpp b/src/plugin/mapping/DisplayRuleFactoryFactory.cpp new file mode 100644 index 000000000..80281655a --- /dev/null +++ b/src/plugin/mapping/DisplayRuleFactoryFactory.cpp @@ -0,0 +1,27 @@ +#include "DisplayRuleElementTypeDelegatorFactory.h" +#include "DisplayRuleFactoryFactory.h" +#include "DisplayRuleTypeDelegatorFactory.h" +#include "VisualReferencePointRelatedAirfieldFactory.h" + +namespace UKControllerPlugin::Mapping { + + auto DisplayRuleFactoryFactory::Make(std::shared_ptr renderOptions) + -> std::shared_ptr + { + return std::make_shared(RuleTypeFactories(std::move(renderOptions))); + } + auto DisplayRuleFactoryFactory::RelatedAirfieldFactories(const std::shared_ptr& renderOptions) const + -> std::shared_ptr + { + const auto factories = std::map>{ + {"visual_reference_point", std::make_shared(renderOptions)}}; + + return std::make_shared(factories); + } + + auto DisplayRuleFactoryFactory::RuleTypeFactories(std::shared_ptr renderOptions) const + -> std::map> + { + return {{"related_airfield", RelatedAirfieldFactories(std::move(renderOptions))}}; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRuleFactoryFactory.h b/src/plugin/mapping/DisplayRuleFactoryFactory.h new file mode 100644 index 000000000..8be94c6a8 --- /dev/null +++ b/src/plugin/mapping/DisplayRuleFactoryFactory.h @@ -0,0 +1,22 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + class DisplayRuleFactoryInterface; + class MappingRenderOptions; + + /** + * Builds the display rule factory structure + */ + class DisplayRuleFactoryFactory + { + public: + [[nodiscard]] auto Make(std::shared_ptr renderOptions) + -> std::shared_ptr; + + private: + auto RuleTypeFactories(std::shared_ptr renderOptions) const + -> std::map>; + auto RelatedAirfieldFactories(const std::shared_ptr& renderOptions) const + -> std::shared_ptr; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRuleFactoryInterface.h b/src/plugin/mapping/DisplayRuleFactoryInterface.h new file mode 100644 index 000000000..f0f47ec71 --- /dev/null +++ b/src/plugin/mapping/DisplayRuleFactoryInterface.h @@ -0,0 +1,16 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + class DisplayRule; + + /** + * An interface for classes that want to build display rules. + */ + class DisplayRuleFactoryInterface + { + public: + virtual ~DisplayRuleFactoryInterface() = default; + [[nodiscard]] virtual auto Make(const std::string& elementType, const nlohmann::json& data) + -> std::shared_ptr = 0; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRuleTypeDelegatorFactory.cpp b/src/plugin/mapping/DisplayRuleTypeDelegatorFactory.cpp new file mode 100644 index 000000000..cee1d24ca --- /dev/null +++ b/src/plugin/mapping/DisplayRuleTypeDelegatorFactory.cpp @@ -0,0 +1,20 @@ +#include "DisplayRuleTypeDelegatorFactory.h" + +namespace UKControllerPlugin::Mapping { + DisplayRuleTypeDelegatorFactory::DisplayRuleTypeDelegatorFactory( + std::map> factories) + : factories(std::move(factories)) + { + } + + auto DisplayRuleTypeDelegatorFactory::Make(const std::string& elementType, const nlohmann::json& data) + -> std::shared_ptr + { + const auto ruleType = data.at("type").get(); + if (!factories.contains(ruleType)) { + throw std::invalid_argument("Invalid display rule type"); + } + + return factories.at(ruleType)->Make(elementType, data); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRuleTypeDelegatorFactory.h b/src/plugin/mapping/DisplayRuleTypeDelegatorFactory.h new file mode 100644 index 000000000..1b134dd27 --- /dev/null +++ b/src/plugin/mapping/DisplayRuleTypeDelegatorFactory.h @@ -0,0 +1,18 @@ +#pragma once +#include "DisplayRuleFactoryInterface.h" + +namespace UKControllerPlugin::Mapping { + /** + * Delegates the building of display rule based on the type of display rule. + */ + class DisplayRuleTypeDelegatorFactory : public DisplayRuleFactoryInterface + { + public: + DisplayRuleTypeDelegatorFactory(std::map> factories); + auto Make(const std::string& elementType, const nlohmann::json& data) -> std::shared_ptr override; + + private: + // All the factories + const std::map> factories; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetAggregatorFactory.cpp b/src/plugin/mapping/DisplayRulesetAggregatorFactory.cpp new file mode 100644 index 000000000..b9d8d0667 --- /dev/null +++ b/src/plugin/mapping/DisplayRulesetAggregatorFactory.cpp @@ -0,0 +1,23 @@ +#include "DisplayRulesetAggregatorFactory.h" + +namespace UKControllerPlugin::Mapping { + + DisplayRulesetAggregatorFactory::DisplayRulesetAggregatorFactory( + const DisplayRulesetFactoryInterface& dataDrivenFactories, + const DisplayRulesetFactoryInterface& defaultFactories) + : dataDrivenFactories(dataDrivenFactories), defaultFactories(defaultFactories) + { + } + + auto DisplayRulesetAggregatorFactory::Make(const std::string& elementType, const nlohmann::json& data) const + -> std::set> + { + auto dataDrivenRules = dataDrivenFactories.Make(elementType, data); + auto defaultRules = defaultFactories.Make(elementType, data); + std::set> rules; + rules.insert(dataDrivenRules.cbegin(), dataDrivenRules.cend()); + rules.insert(defaultRules.cbegin(), defaultRules.cend()); + + return rules; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetAggregatorFactory.h b/src/plugin/mapping/DisplayRulesetAggregatorFactory.h new file mode 100644 index 000000000..80c372326 --- /dev/null +++ b/src/plugin/mapping/DisplayRulesetAggregatorFactory.h @@ -0,0 +1,24 @@ +#pragma once +#include "DisplayRulesetFactoryInterface.h" + +namespace UKControllerPlugin::Mapping { + + /** + * Combines the data-driven and default display rulesets into one + */ + class DisplayRulesetAggregatorFactory : public DisplayRulesetFactoryInterface + { + public: + DisplayRulesetAggregatorFactory( + const DisplayRulesetFactoryInterface& dataDrivenFactories, + const DisplayRulesetFactoryInterface& defaultFactories); + auto Make(const std::string& elementType, const nlohmann::json& data) const + -> std::set> override; + + // Factories that are driven specifically by the data + const DisplayRulesetFactoryInterface& dataDrivenFactories; + + // Factories for default rules + const DisplayRulesetFactoryInterface& defaultFactories; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetFactory.cpp b/src/plugin/mapping/DisplayRulesetFactory.cpp new file mode 100644 index 000000000..b878dcd1a --- /dev/null +++ b/src/plugin/mapping/DisplayRulesetFactory.cpp @@ -0,0 +1,9 @@ +#include "DisplayRulesetFactory.h" + +namespace UKControllerPlugin::Mapping { + auto DisplayRulesetFactory::Make(const std::string& elementType, const nlohmann::json& data) const + -> std::set> + { + return nullptr; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetFactory.h b/src/plugin/mapping/DisplayRulesetFactory.h new file mode 100644 index 000000000..0ff491328 --- /dev/null +++ b/src/plugin/mapping/DisplayRulesetFactory.h @@ -0,0 +1,17 @@ +#pragma once +#include "DisplayRulesetFactoryInterface.h" + +namespace UKControllerPlugin::Mapping { + class DisplayRule; + + /** + * Creates a set of display rules + */ + class DisplayRulesetFactory : public DisplayRulesetFactoryInterface + { + public: + [[nodiscard]] auto Make(const std::string& elementType, const nlohmann::json& data) const + -> std::set> override; + }; + +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp b/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp new file mode 100644 index 000000000..be550ffe7 --- /dev/null +++ b/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp @@ -0,0 +1,7 @@ +#include "DisplayRulesetFactoryFactory.h" + +namespace UKControllerPlugin { + namespace Mapping { + + } // namespace Mapping +} // namespace UKControllerPlugin diff --git a/src/plugin/mapping/DisplayRulesetFactoryFactory.h b/src/plugin/mapping/DisplayRulesetFactoryFactory.h new file mode 100644 index 000000000..639ffea6f --- /dev/null +++ b/src/plugin/mapping/DisplayRulesetFactoryFactory.h @@ -0,0 +1,11 @@ +#pragma once + +namespace UKControllerPlugin { + namespace Mapping { + + class DisplayRulesetFactoryFactory + { + }; + + } // namespace Mapping +} // namespace UKControllerPlugin diff --git a/src/plugin/mapping/DisplayRulesetFactoryInterface.h b/src/plugin/mapping/DisplayRulesetFactoryInterface.h new file mode 100644 index 000000000..cfbb143fb --- /dev/null +++ b/src/plugin/mapping/DisplayRulesetFactoryInterface.h @@ -0,0 +1,15 @@ +#pragma once +namespace UKControllerPlugin::Mapping { + class DisplayRule; + + /** + * An interface for classes that make collections of display rules + */ + class DisplayRulesetFactoryInterface + { + public: + virtual ~DisplayRulesetFactoryInterface() = default; + [[nodiscard]] virtual auto Make(const std::string& elementType, const nlohmann::json& data) const + -> std::set> = 0; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/TypeSpecificDisplayRuleFactory.h b/src/plugin/mapping/TypeSpecificDisplayRuleFactory.h deleted file mode 100644 index b582ab0f9..000000000 --- a/src/plugin/mapping/TypeSpecificDisplayRuleFactory.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -namespace UKControllerPlugin::Mapping { - class DisplayRule; - - /** - * Builds display rules associated with mapping elements - */ - class TypeSpecificDisplayRuleFactory - { - public: - virtual ~TypeSpecificDisplayRuleFactory() = default; - [[nodiscard]] virtual auto Make(const nlohmann::json& data) -> std::set> = 0; - }; -} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp b/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp new file mode 100644 index 000000000..3bf30eebf --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp @@ -0,0 +1,10 @@ +#include "VisualReferencePointDefaultDisplayRulesetFactory.h" + +namespace UKControllerPlugin::Mapping { + + auto VisualReferencePointDefaultDisplayRulesetFactory::Make( + const std::string& elementType, const nlohmann::json& data) const -> std::set> + { + return nullptr; + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.h b/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.h new file mode 100644 index 000000000..097ac9865 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.h @@ -0,0 +1,14 @@ +#pragma once +#include "DisplayRulesetFactoryInterface.h" + +namespace UKControllerPlugin::Mapping { + /** + * Builds the default rulset for VRPS + */ + class VisualReferencePointDefaultDisplayRulesetFactory : public DisplayRulesetFactoryInterface + { + public: + [[nodiscard]] auto Make(const std::string& elementType, const nlohmann::json& data) const + -> std::set> override; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointRelatedAirfieldFactory.cpp b/src/plugin/mapping/VisualReferencePointRelatedAirfieldFactory.cpp new file mode 100644 index 000000000..7eaeec556 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointRelatedAirfieldFactory.cpp @@ -0,0 +1,30 @@ +#include "RelatedAirfield.h" +#include "VisualReferencePointRelatedAirfieldFactory.h" +#include "VisualReferencePointRelatedAirfieldProvider.h" + +namespace UKControllerPlugin::Mapping { + + VisualReferencePointRelatedAirfieldFactory::VisualReferencePointRelatedAirfieldFactory( + std::shared_ptr renderOptions) + : renderOptions(renderOptions) + { + } + + auto VisualReferencePointRelatedAirfieldFactory::Make(const std::string& elementType, const nlohmann::json& data) + -> std::shared_ptr + { + if (HasInvalidAirfields(data)) { + throw std::invalid_argument("Invalid airfields in VRP related airfield factory"); + } + return std::make_shared( + std::make_shared(renderOptions), + data.at("airfields").get>()); + } + + auto VisualReferencePointRelatedAirfieldFactory::HasInvalidAirfields(const nlohmann::json& data) const -> bool + { + return data.is_array() && std::find_if_not(data.begin(), data.end(), [](const nlohmann::json& airfield) { + return airfield.is_number_integer(); + }) == data.cend(); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointRelatedAirfieldFactory.h b/src/plugin/mapping/VisualReferencePointRelatedAirfieldFactory.h new file mode 100644 index 000000000..52c7d65d0 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointRelatedAirfieldFactory.h @@ -0,0 +1,21 @@ +#pragma once +#include "DisplayRuleFactoryInterface.h" + +namespace UKControllerPlugin::Mapping { + + class MappingRenderOptions; + + class VisualReferencePointRelatedAirfieldFactory : public DisplayRuleFactoryInterface + { + public: + VisualReferencePointRelatedAirfieldFactory(std::shared_ptr renderOptions); + [[nodiscard]] auto Make(const std::string& elementType, const nlohmann::json& data) + -> std::shared_ptr override; + + private: + [[nodiscard]] auto HasInvalidAirfields(const nlohmann::json& data) const -> bool; + + std::shared_ptr renderOptions; + }; + +} // namespace UKControllerPlugin::Mapping From c009fd0c66b52e0ce0d3c2d224b97b6b4134f077 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Sun, 15 May 2022 14:52:26 +0100 Subject: [PATCH 11/18] Start things --- .../DisplayRulesetAggregatorFactory.cpp | 10 ++++++---- .../mapping/DisplayRulesetAggregatorFactory.h | 10 +++++----- .../mapping/DisplayRulesetFactoryFactory.cpp | 12 +++++++++--- .../mapping/DisplayRulesetFactoryFactory.h | 18 ++++++++++-------- ...erencePointDefaultDisplayRulesetFactory.cpp | 9 ++++++++- ...eferencePointDefaultDisplayRulesetFactory.h | 7 +++++++ 6 files changed, 45 insertions(+), 21 deletions(-) diff --git a/src/plugin/mapping/DisplayRulesetAggregatorFactory.cpp b/src/plugin/mapping/DisplayRulesetAggregatorFactory.cpp index b9d8d0667..c9d7c75fc 100644 --- a/src/plugin/mapping/DisplayRulesetAggregatorFactory.cpp +++ b/src/plugin/mapping/DisplayRulesetAggregatorFactory.cpp @@ -3,17 +3,19 @@ namespace UKControllerPlugin::Mapping { DisplayRulesetAggregatorFactory::DisplayRulesetAggregatorFactory( - const DisplayRulesetFactoryInterface& dataDrivenFactories, - const DisplayRulesetFactoryInterface& defaultFactories) + std::shared_ptr dataDrivenFactories, + std::shared_ptr defaultFactories) : dataDrivenFactories(dataDrivenFactories), defaultFactories(defaultFactories) { + assert(dataDrivenFactories && "dataDrivenFactories not set in DisplayRulesetAggregatorFactory"); + assert(defaultFactories && "defaultFactories not set in DisplayRulesetAggregatorFactory"); } auto DisplayRulesetAggregatorFactory::Make(const std::string& elementType, const nlohmann::json& data) const -> std::set> { - auto dataDrivenRules = dataDrivenFactories.Make(elementType, data); - auto defaultRules = defaultFactories.Make(elementType, data); + auto dataDrivenRules = dataDrivenFactories->Make(elementType, data); + auto defaultRules = defaultFactories->Make(elementType, data); std::set> rules; rules.insert(dataDrivenRules.cbegin(), dataDrivenRules.cend()); rules.insert(defaultRules.cbegin(), defaultRules.cend()); diff --git a/src/plugin/mapping/DisplayRulesetAggregatorFactory.h b/src/plugin/mapping/DisplayRulesetAggregatorFactory.h index 80c372326..41d6a66c0 100644 --- a/src/plugin/mapping/DisplayRulesetAggregatorFactory.h +++ b/src/plugin/mapping/DisplayRulesetAggregatorFactory.h @@ -10,15 +10,15 @@ namespace UKControllerPlugin::Mapping { { public: DisplayRulesetAggregatorFactory( - const DisplayRulesetFactoryInterface& dataDrivenFactories, - const DisplayRulesetFactoryInterface& defaultFactories); - auto Make(const std::string& elementType, const nlohmann::json& data) const + std::shared_ptr dataDrivenFactories, + std::shared_ptr defaultFactories); + [[nodiscard]] auto Make(const std::string& elementType, const nlohmann::json& data) const -> std::set> override; // Factories that are driven specifically by the data - const DisplayRulesetFactoryInterface& dataDrivenFactories; + std::shared_ptr dataDrivenFactories; // Factories for default rules - const DisplayRulesetFactoryInterface& defaultFactories; + std::shared_ptr defaultFactories; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp b/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp index be550ffe7..0e2737d33 100644 --- a/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp +++ b/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp @@ -1,7 +1,13 @@ +#include "DisplayRulesetAggregatorFactory.h" #include "DisplayRulesetFactoryFactory.h" -namespace UKControllerPlugin { - namespace Mapping { +namespace UKControllerPlugin::Mapping { - } // namespace Mapping + auto DisplayRulesetFactoryFactory::Make(std::shared_ptr renderOptions) const + -> std::shared_ptr + { + assert(renderOptions && "Render options not set in DisplayRulesetFactoryFactory"); + + return std::make_shared() + } } // namespace UKControllerPlugin diff --git a/src/plugin/mapping/DisplayRulesetFactoryFactory.h b/src/plugin/mapping/DisplayRulesetFactoryFactory.h index 639ffea6f..d70cec8ab 100644 --- a/src/plugin/mapping/DisplayRulesetFactoryFactory.h +++ b/src/plugin/mapping/DisplayRulesetFactoryFactory.h @@ -1,11 +1,13 @@ #pragma once -namespace UKControllerPlugin { - namespace Mapping { +namespace UKControllerPlugin::Mapping { + class DisplayRulesetFactoryInterface; + class MappingRenderOptions; - class DisplayRulesetFactoryFactory - { - }; - - } // namespace Mapping -} // namespace UKControllerPlugin + class DisplayRulesetFactoryFactory + { + public: + [[nodiscard]] auto Make(std::shared_ptr renderOptions) const + -> std::shared_ptr; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp b/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp index 3bf30eebf..7dcbb9bb8 100644 --- a/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp +++ b/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp @@ -1,10 +1,17 @@ #include "VisualReferencePointDefaultDisplayRulesetFactory.h" +#include "VisualReferencePointShouldRender.h" namespace UKControllerPlugin::Mapping { + VisualReferencePointDefaultDisplayRulesetFactory::VisualReferencePointDefaultDisplayRulesetFactory( + std::shared_ptr renderOptions) + : renderOptions(renderOptions) + { + assert(renderOptions && "Render options not set in VisualReferencePointDefaultDisplayRulesetFactory"); + } auto VisualReferencePointDefaultDisplayRulesetFactory::Make( const std::string& elementType, const nlohmann::json& data) const -> std::set> { - return nullptr; + return {std::make_shared(renderOptions)}; } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.h b/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.h index 097ac9865..2290cfeb7 100644 --- a/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.h +++ b/src/plugin/mapping/VisualReferencePointDefaultDisplayRulesetFactory.h @@ -2,13 +2,20 @@ #include "DisplayRulesetFactoryInterface.h" namespace UKControllerPlugin::Mapping { + class MappingRenderOptions; + /** * Builds the default rulset for VRPS */ class VisualReferencePointDefaultDisplayRulesetFactory : public DisplayRulesetFactoryInterface { public: + VisualReferencePointDefaultDisplayRulesetFactory(std::shared_ptr renderOptions); [[nodiscard]] auto Make(const std::string& elementType, const nlohmann::json& data) const -> std::set> override; + + private: + // The render options + const std::shared_ptr renderOptions; }; } // namespace UKControllerPlugin::Mapping From 000fd381f288587abaa132d58c2fb682d888c1a4 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Fri, 3 Jun 2022 07:28:45 +0100 Subject: [PATCH 12/18] Commit where we are --- src/plugin/CMakeLists.txt | 2 +- .../mapping/DisplayRuleFactoryFactory.cpp | 8 +-- src/plugin/mapping/DisplayRulesetFactory.cpp | 21 +++++++- src/plugin/mapping/DisplayRulesetFactory.h | 6 +++ .../mapping/DisplayRulesetFactoryFactory.cpp | 29 +++++++++-- .../mapping/DisplayRulesetFactoryFactory.h | 9 ++++ .../mapping/MappingBootstrapProvider.cpp | 25 ++++++++-- .../MappingElementDrawerFactoryFactory.cpp | 13 +++++ .../MappingElementDrawerFactoryFactory.h | 7 +++ src/plugin/mapping/MappingElementFactory.cpp | 26 +++++----- src/plugin/mapping/MappingElementFactory.h | 12 +++-- src/plugin/mapping/MappingElementManager.cpp | 13 ++++- src/plugin/mapping/MappingElementManager.h | 1 + .../mapping/MappingElementManagerFactory.cpp | 34 ++++--------- .../mapping/MappingElementManagerFactory.h | 9 ++-- src/plugin/mapping/MappingElementTypes.cpp | 14 ++++++ src/plugin/mapping/MappingElementTypes.h | 14 ++++++ src/plugin/mapping/MappingModuleFactory.cpp | 19 ------- src/plugin/mapping/MappingModuleFactory.h | 8 --- .../mapping/MappingRenderOptionsAsrLoader.cpp | 50 +++++++++++++++++++ .../mapping/MappingRenderOptionsAsrLoader.h | 40 +++++++++++++++ src/plugin/mapping/MappingRenderer.cpp | 5 +- src/plugin/mapping/MappingRenderer.h | 4 +- 23 files changed, 279 insertions(+), 90 deletions(-) create mode 100644 src/plugin/mapping/MappingElementDrawerFactoryFactory.cpp create mode 100644 src/plugin/mapping/MappingElementDrawerFactoryFactory.h create mode 100644 src/plugin/mapping/MappingElementTypes.cpp create mode 100644 src/plugin/mapping/MappingElementTypes.h create mode 100644 src/plugin/mapping/MappingRenderOptionsAsrLoader.cpp create mode 100644 src/plugin/mapping/MappingRenderOptionsAsrLoader.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 4a9d58de9..494373db5 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -520,7 +520,7 @@ set(src__mapping mapping/DisplayRulesetFactory.cpp mapping/DisplayRulesetFactory.h mapping/DisplayRulesetFactoryInterface.h mapping/DisplayRulesetAggregatorFactory.cpp mapping/DisplayRulesetAggregatorFactory.h - mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp mapping/VisualReferencePointDefaultDisplayRulesetFactory.h mapping/DefaultDisplayRulesetDelegatorFactory.cpp mapping/DefaultDisplayRulesetDelegatorFactory.h mapping/DisplayRulesetFactoryFactory.cpp mapping/DisplayRulesetFactoryFactory.h) + mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp mapping/VisualReferencePointDefaultDisplayRulesetFactory.h mapping/DefaultDisplayRulesetDelegatorFactory.cpp mapping/DefaultDisplayRulesetDelegatorFactory.h mapping/DisplayRulesetFactoryFactory.cpp mapping/DisplayRulesetFactoryFactory.h mapping/MappingElementDrawerFactoryFactory.cpp mapping/MappingElementDrawerFactoryFactory.h mapping/MappingElementTypes.cpp mapping/MappingElementTypes.h mapping/MappingRenderOptionsAsrLoader.cpp mapping/MappingRenderOptionsAsrLoader.h) source_group("src\\mapping" FILES ${src__mapping}) set(src__message diff --git a/src/plugin/mapping/DisplayRuleFactoryFactory.cpp b/src/plugin/mapping/DisplayRuleFactoryFactory.cpp index 80281655a..fe13b25e1 100644 --- a/src/plugin/mapping/DisplayRuleFactoryFactory.cpp +++ b/src/plugin/mapping/DisplayRuleFactoryFactory.cpp @@ -1,6 +1,7 @@ #include "DisplayRuleElementTypeDelegatorFactory.h" #include "DisplayRuleFactoryFactory.h" #include "DisplayRuleTypeDelegatorFactory.h" +#include "MappingElementTypes.h" #include "VisualReferencePointRelatedAirfieldFactory.h" namespace UKControllerPlugin::Mapping { @@ -10,11 +11,12 @@ namespace UKControllerPlugin::Mapping { { return std::make_shared(RuleTypeFactories(std::move(renderOptions))); } - auto DisplayRuleFactoryFactory::RelatedAirfieldFactories(const std::shared_ptr& renderOptions) const - -> std::shared_ptr + auto DisplayRuleFactoryFactory::RelatedAirfieldFactories(const std::shared_ptr& renderOptions) + const -> std::shared_ptr { const auto factories = std::map>{ - {"visual_reference_point", std::make_shared(renderOptions)}}; + {MappingElementTypes::VisualReferencePoint(), + std::make_shared(renderOptions)}}; return std::make_shared(factories); } diff --git a/src/plugin/mapping/DisplayRulesetFactory.cpp b/src/plugin/mapping/DisplayRulesetFactory.cpp index b878dcd1a..97c8a5a04 100644 --- a/src/plugin/mapping/DisplayRulesetFactory.cpp +++ b/src/plugin/mapping/DisplayRulesetFactory.cpp @@ -1,9 +1,28 @@ +#include "DisplayRuleFactoryInterface.h" #include "DisplayRulesetFactory.h" namespace UKControllerPlugin::Mapping { + DisplayRulesetFactory::DisplayRulesetFactory(std::shared_ptr ruleFactory) + : ruleFactory(ruleFactory) + { + assert(ruleFactory && "ruleFactory not set in DisplayRulesetFactory"); + } + auto DisplayRulesetFactory::Make(const std::string& elementType, const nlohmann::json& data) const -> std::set> { - return nullptr; + std::set> rules; + + for (const auto& ruleData : data) { + const auto rule = ruleFactory->Make(elementType, ruleData); + if (!rule) { + LogWarning("Invalid mapping element display rule"); + continue; + } + + rules.insert(rule); + } + + return rules; } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetFactory.h b/src/plugin/mapping/DisplayRulesetFactory.h index 0ff491328..89d8cb8bd 100644 --- a/src/plugin/mapping/DisplayRulesetFactory.h +++ b/src/plugin/mapping/DisplayRulesetFactory.h @@ -3,6 +3,7 @@ namespace UKControllerPlugin::Mapping { class DisplayRule; + class DisplayRuleFactoryInterface; /** * Creates a set of display rules @@ -10,8 +11,13 @@ namespace UKControllerPlugin::Mapping { class DisplayRulesetFactory : public DisplayRulesetFactoryInterface { public: + DisplayRulesetFactory(std::shared_ptr ruleFactory); [[nodiscard]] auto Make(const std::string& elementType, const nlohmann::json& data) const -> std::set> override; + + private: + // Builds individual rules + std::shared_ptr ruleFactory; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp b/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp index 0e2737d33..b8ff20f4a 100644 --- a/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp +++ b/src/plugin/mapping/DisplayRulesetFactoryFactory.cpp @@ -1,5 +1,10 @@ +#include "DefaultDisplayRulesetDelegatorFactory.h" +#include "DisplayRuleFactoryFactory.h" #include "DisplayRulesetAggregatorFactory.h" +#include "DisplayRulesetFactory.h" #include "DisplayRulesetFactoryFactory.h" +#include "MappingElementTypes.h" +#include "VisualReferencePointDefaultDisplayRulesetFactory.h" namespace UKControllerPlugin::Mapping { @@ -7,7 +12,25 @@ namespace UKControllerPlugin::Mapping { -> std::shared_ptr { assert(renderOptions && "Render options not set in DisplayRulesetFactoryFactory"); - - return std::make_shared() + + return std::make_shared( + GetDataDrivenRulesetFactories(renderOptions), GetDefaultRulesetFactories(renderOptions)); + } + + auto DisplayRulesetFactoryFactory::GetDefaultRulesetFactories(std::shared_ptr renderOptions) + -> std::shared_ptr + { + const std::map> factories{ + {MappingElementTypes::VisualReferencePoint(), + std::make_shared(renderOptions)}}; + + return std::make_shared(factories); + } + + auto + DisplayRulesetFactoryFactory::GetDataDrivenRulesetFactories(std::shared_ptr renderOptions) + -> std::shared_ptr + { + return std::make_shared(DisplayRuleFactoryFactory().Make(renderOptions)); } -} // namespace UKControllerPlugin +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/DisplayRulesetFactoryFactory.h b/src/plugin/mapping/DisplayRulesetFactoryFactory.h index d70cec8ab..63d49f3e6 100644 --- a/src/plugin/mapping/DisplayRulesetFactoryFactory.h +++ b/src/plugin/mapping/DisplayRulesetFactoryFactory.h @@ -1,6 +1,8 @@ #pragma once namespace UKControllerPlugin::Mapping { + class DefaultDisplayRulesetDelegatorFactory; + class DisplayRulesetFactory; class DisplayRulesetFactoryInterface; class MappingRenderOptions; @@ -9,5 +11,12 @@ namespace UKControllerPlugin::Mapping { public: [[nodiscard]] auto Make(std::shared_ptr renderOptions) const -> std::shared_ptr; + + private: + [[nodiscard]] static auto GetDefaultRulesetFactories(std::shared_ptr renderOptions) + -> std::shared_ptr; + + [[nodiscard]] static auto GetDataDrivenRulesetFactories(std::shared_ptr renderOptions) + -> std::shared_ptr; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingBootstrapProvider.cpp b/src/plugin/mapping/MappingBootstrapProvider.cpp index ce4b57522..a19c59ec0 100644 --- a/src/plugin/mapping/MappingBootstrapProvider.cpp +++ b/src/plugin/mapping/MappingBootstrapProvider.cpp @@ -1,11 +1,18 @@ +#include "DisplayRulesetFactoryFactory.h" #include "MappingBootstrapProvider.h" +#include "MappingElementDrawerFactoryFactory.h" +#include "MappingElementFactory.h" +#include "MappingElementManager.h" +#include "MappingElementManagerFactory.h" #include "MappingModuleFactory.h" #include "MappingOptionsRenderer.h" #include "MappingRenderer.h" #include "MappingRenderOptions.h" +#include "MappingRenderOptionsAsrLoader.h" #include "ToggleMappingOptionsRender.h" #include "bootstrap/ModuleFactories.h" #include "bootstrap/PersistenceContainer.h" +#include "euroscope/AsrEventHandlerCollection.h" #include "radarscreen/RadarRenderableCollection.h" namespace UKControllerPlugin::Mapping { @@ -16,16 +23,24 @@ namespace UKControllerPlugin::Mapping { Euroscope::AsrEventHandlerCollection& asrHandlers, const RadarScreen::MenuToggleableDisplayFactory& toggleableDisplayFactory) { + // The rendering options + auto renderOptions = std::make_shared(); + + // Create the element manager for this radar screen + auto elementFactory = std::make_shared( + MakeDrawerFactory(), DisplayRulesetFactoryFactory().Make(renderOptions)); + auto elementManager = MakeMappingElementManager(*elementFactory, *container.dependencyLoader); + + // ASR loader + asrHandlers.RegisterHandler( + std::make_shared(*elementManager, renderOptions, *container.airfields)); + // Renders the mapping elements radarRenderables.RegisterRenderer( radarRenderables.ReserveRendererIdentifier(), - std::make_shared( - container.moduleFactories->Mapping().ElementManager(*container.dependencyLoader)), + std::make_shared(elementManager), RadarScreen::RadarRenderableCollection::beforeTags); - // The rendering options - auto renderOptions = std::make_shared(); - // Renders the options auto optionsRendererId = radarRenderables.ReserveRendererIdentifier(); radarRenderables.RegisterRenderer( diff --git a/src/plugin/mapping/MappingElementDrawerFactoryFactory.cpp b/src/plugin/mapping/MappingElementDrawerFactoryFactory.cpp new file mode 100644 index 000000000..65793db81 --- /dev/null +++ b/src/plugin/mapping/MappingElementDrawerFactoryFactory.cpp @@ -0,0 +1,13 @@ +#include "MappingElementDrawerFactoryDelegator.h" +#include "MappingElementDrawerFactoryFactory.h" +#include "MappingElementTypes.h" +#include "VisualReferencePointDrawerFactory.h" + +namespace UKControllerPlugin::Mapping { + auto MakeDrawerFactory() -> std::shared_ptr + { + return std::make_shared( + std::map>{ + {MappingElementTypes::VisualReferencePoint(), std::make_shared()}}); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementDrawerFactoryFactory.h b/src/plugin/mapping/MappingElementDrawerFactoryFactory.h new file mode 100644 index 000000000..6c5be2d7e --- /dev/null +++ b/src/plugin/mapping/MappingElementDrawerFactoryFactory.h @@ -0,0 +1,7 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + class MappingElementDrawerFactory; + + [[nodiscard]] auto MakeDrawerFactory() -> std::shared_ptr; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementFactory.cpp b/src/plugin/mapping/MappingElementFactory.cpp index 169adabcc..d384677cb 100644 --- a/src/plugin/mapping/MappingElementFactory.cpp +++ b/src/plugin/mapping/MappingElementFactory.cpp @@ -1,12 +1,18 @@ +#include "DisplayRulesetFactoryInterface.h" #include "MappingElement.h" #include "MappingElementDrawerFactory.h" #include "MappingElementFactory.h" +#include "MappingElementTypes.h" namespace UKControllerPlugin::Mapping { - MappingElementFactory::MappingElementFactory(const MappingElementDrawerFactory& drawerFactory) - : drawerFactory(drawerFactory) + MappingElementFactory::MappingElementFactory( + std::shared_ptr drawerFactory, + std::shared_ptr displayRuleFactory) + : drawerFactory(drawerFactory), displayRuleFactory(displayRuleFactory) { + assert(drawerFactory && "drawerFactory not set in MappingElementFactory"); + assert(displayRuleFactory && "displayRuleFactory not set in MappingElementFactory"); } auto MappingElementFactory::Make(const nlohmann::json& data) -> std::shared_ptr @@ -16,17 +22,17 @@ namespace UKControllerPlugin::Mapping { } const auto type = data.at("type").get(); - if (!IsKnownType(type)) { + if (!MappingElementTypes::TypeKnown(type)) { LogWarning("Detected mapping element of unknown type, ignoring"); return nullptr; } return std::make_shared( data.at("id").get(), - data.at("type").get(), + type, data.at("name").get(), - std::set>{}, - drawerFactory.Make(data)); + displayRuleFactory->Make(type, data.at("display_rules")), + drawerFactory->Make(data)); } /** @@ -35,11 +41,7 @@ namespace UKControllerPlugin::Mapping { auto MappingElementFactory::DataIsValid(const nlohmann::json& data) -> bool { return data.is_object() && data.contains("id") && data.at("id").is_number_integer() && data.contains("type") && - data.at("type").is_string() && data.contains("name") && data.at("name").is_string(); - } - - auto MappingElementFactory::IsKnownType(const std::string& type) -> bool - { - return type == "visual_reference_point"; + data.at("type").is_string() && data.contains("name") && data.at("name").is_string() && + data.contains("display_rules") && data.at("display_rules").is_array(); } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementFactory.h b/src/plugin/mapping/MappingElementFactory.h index 27df9dd8b..323503f83 100644 --- a/src/plugin/mapping/MappingElementFactory.h +++ b/src/plugin/mapping/MappingElementFactory.h @@ -1,20 +1,26 @@ #pragma once namespace UKControllerPlugin::Mapping { + class DisplayRulesetFactoryInterface; class MappingElementDrawerFactory; class MappingElement; class MappingElementFactory { public: - MappingElementFactory(const MappingElementDrawerFactory& drawerFactory); + MappingElementFactory( + std::shared_ptr drawerFactory, + std::shared_ptr displayRuleFactory + ); [[nodiscard]] auto Make(const nlohmann::json& data) -> std::shared_ptr; private: [[nodiscard]] static auto DataIsValid(const nlohmann::json& data) -> bool; - [[nodiscard]] static auto IsKnownType(const std::string& type) -> bool; // Builds drawers - const MappingElementDrawerFactory& drawerFactory; + std::shared_ptr drawerFactory; + + // Builds rulesets for display + std::shared_ptr displayRuleFactory; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManager.cpp b/src/plugin/mapping/MappingElementManager.cpp index 064628944..986f21004 100644 --- a/src/plugin/mapping/MappingElementManager.cpp +++ b/src/plugin/mapping/MappingElementManager.cpp @@ -24,10 +24,21 @@ namespace UKControllerPlugin::Mapping { return element == allElements.cend() ? nullptr : *element; } - void MappingElementManager::ForEachActiveElement(const std::function& function) const + void + MappingElementManager::ForEachActiveElement(const std::function& function) const { for (const auto& element : activeElements) { function(*element); } } + + void MappingElementManager::RefreshActiveElements() + { + activeElements.clear(); + for (const auto& element : allElements) { + if (element->ShouldDisplay()) { + activeElements.insert(element); + } + } + } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManager.h b/src/plugin/mapping/MappingElementManager.h index 187dd54e5..bc3cfb297 100644 --- a/src/plugin/mapping/MappingElementManager.h +++ b/src/plugin/mapping/MappingElementManager.h @@ -14,6 +14,7 @@ namespace UKControllerPlugin::Mapping { [[nodiscard]] auto Count() const -> size_t; [[nodiscard]] auto GetByTypeAndId(const std::string& type, int id) const -> std::shared_ptr; void ForEachActiveElement(const std::function& function) const; + void RefreshActiveElements(); private: // Active elements - those being drawn diff --git a/src/plugin/mapping/MappingElementManagerFactory.cpp b/src/plugin/mapping/MappingElementManagerFactory.cpp index f3f42e7f6..b074993df 100644 --- a/src/plugin/mapping/MappingElementManagerFactory.cpp +++ b/src/plugin/mapping/MappingElementManagerFactory.cpp @@ -1,15 +1,14 @@ #include "MappingElement.h" +#include "MappingElementFactory.h" #include "MappingElementManager.h" #include "MappingElementManagerFactory.h" -#include "MappingModuleFactory.h" -#include "VisualReferencePoint.h" #include "dependency/DependencyLoaderInterface.h" namespace UKControllerPlugin::Mapping { - auto - MakeMappingElementManager(MappingModuleFactory& module, Dependency::DependencyLoaderInterface& dependencyLoader) - -> std::unique_ptr + auto MakeMappingElementManager( + MappingElementFactory& elementFactory, Dependency::DependencyLoaderInterface& dependencyLoader) + -> std::shared_ptr { auto mapper = std::make_unique(); const auto& dependency = @@ -19,32 +18,17 @@ namespace UKControllerPlugin::Mapping { return mapper; } - for (const auto& element : dependency) { - if (!ElementValid(element)) { - LogError("Invalid mapping element " + element.dump()); + for (const auto& elementData : dependency) { + const auto element = elementFactory.Make(elementData); + if (!element) { + LogError("Invalid mapping element " + elementData.dump()); continue; } - EuroScopePlugIn::CPosition position; - position.m_Latitude = element.at("latitude").get(); - position.m_Longitude = element.at("longitude").get(); - mapper->Add(std::make_shared( - element.at("id").get(), - element.at("type").get(), - element.at("name").get(), - std::set>{}, - module.VrpDrawer(element.at("name").get(), position))); + mapper->Add(element); } LogInfo("Loaded " + std::to_string(mapper->Count()) + " mapping elements"); return mapper; } - - auto ElementValid(const nlohmann::json& data) -> bool - { - return data.is_object() && data.contains("id") && data.at("id").is_number_integer() && data.contains("type") && - data.at("type").is_string() && data.at("type").get() == "visual_reference_point" && - data.contains("latitude") && data.at("latitude").is_number() && data.contains("longitude") && - data.at("longitude").is_number() && data.contains("name") && data.at("name").is_string(); - } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementManagerFactory.h b/src/plugin/mapping/MappingElementManagerFactory.h index f4aedd290..181048324 100644 --- a/src/plugin/mapping/MappingElementManagerFactory.h +++ b/src/plugin/mapping/MappingElementManagerFactory.h @@ -6,10 +6,9 @@ namespace UKControllerPlugin::Dependency { namespace UKControllerPlugin::Mapping { class MappingElementManager; - class MappingModuleFactory; + class MappingElementFactory; - [[nodiscard]] auto MakeMappingElementManager(MappingModuleFactory& module, Dependency::DependencyLoaderInterface& - dependencyLoader) -> - std::unique_ptr; - [[nodiscard]] auto ElementValid(const nlohmann::json& data) -> bool; + [[nodiscard]] auto MakeMappingElementManager( + MappingElementFactory& elementFactory, Dependency::DependencyLoaderInterface& dependencyLoader) + -> std::shared_ptr; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementTypes.cpp b/src/plugin/mapping/MappingElementTypes.cpp new file mode 100644 index 000000000..d4231650c --- /dev/null +++ b/src/plugin/mapping/MappingElementTypes.cpp @@ -0,0 +1,14 @@ +#include "MappingElementTypes.h" + +namespace UKControllerPlugin::Mapping { + + auto MappingElementTypes::VisualReferencePoint() -> std::string + { + return "visual_reference_point"; + } + + auto MappingElementTypes::TypeKnown(const std::string& type) -> bool + { + return type == VisualReferencePoint(); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingElementTypes.h b/src/plugin/mapping/MappingElementTypes.h new file mode 100644 index 000000000..5e7c0189b --- /dev/null +++ b/src/plugin/mapping/MappingElementTypes.h @@ -0,0 +1,14 @@ +#pragma once + +namespace UKControllerPlugin::Mapping { + + class MappingElementTypes + { + public: + [[nodiscard]] static auto TypeKnown(const std::string& type) -> bool; + [[nodiscard]] static auto VisualReferencePoint() -> std::string; + + private: + MappingElementTypes() = default; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingModuleFactory.cpp b/src/plugin/mapping/MappingModuleFactory.cpp index 09cdea438..cad00f4bd 100644 --- a/src/plugin/mapping/MappingModuleFactory.cpp +++ b/src/plugin/mapping/MappingModuleFactory.cpp @@ -1,26 +1,7 @@ -#include "MappingElementManager.h" -#include "MappingElementManagerFactory.h" #include "MappingModuleFactory.h" -#include "VisualReferencePoint.h" namespace UKControllerPlugin::Mapping { MappingModuleFactory::MappingModuleFactory() = default; MappingModuleFactory::~MappingModuleFactory() = default; - - auto MappingModuleFactory::VrpDrawer(std::string label, EuroScopePlugIn::CPosition position) - -> std::shared_ptr - { - return std::make_shared(label, position); - } - - auto MappingModuleFactory::ElementManager(Dependency::DependencyLoaderInterface& dependencyLoader) - -> MappingElementManager& - { - if (!elementManager) { - elementManager = MakeMappingElementManager(*this, dependencyLoader); - } - - return *elementManager; - } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingModuleFactory.h b/src/plugin/mapping/MappingModuleFactory.h index 59d15908d..4d89bf4bb 100644 --- a/src/plugin/mapping/MappingModuleFactory.h +++ b/src/plugin/mapping/MappingModuleFactory.h @@ -16,13 +16,5 @@ namespace UKControllerPlugin::Mapping { public: MappingModuleFactory(); ~MappingModuleFactory(); - [[nodiscard]] auto VrpDrawer(std::string label, EuroScopePlugIn::CPosition position) -> - std::shared_ptr; - [[nodiscard]] auto ElementManager(Dependency::DependencyLoaderInterface& dependencyLoader) -> - MappingElementManager&; - - private: - // Manages mapping elements - std::unique_ptr elementManager; }; } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderOptionsAsrLoader.cpp b/src/plugin/mapping/MappingRenderOptionsAsrLoader.cpp new file mode 100644 index 000000000..2e0896e45 --- /dev/null +++ b/src/plugin/mapping/MappingRenderOptionsAsrLoader.cpp @@ -0,0 +1,50 @@ +#include "MappingElementManager.h" +#include "MappingRenderOptions.h" +#include "MappingRenderOptionsAsrLoader.h" +#include "airfield/AirfieldCollection.h" +#include "euroscope/UserSetting.h" +#include "helper/HelperFunctions.h" + +namespace UKControllerPlugin::Mapping { + + MappingRenderOptionsAsrLoader::MappingRenderOptionsAsrLoader( + MappingElementManager& elementManager, + std::shared_ptr options, + const Airfield::AirfieldCollection& airfields) + : elementManager(elementManager), options(options), airfields(airfields) + { + assert(options && "render options not set in MappingRenderOptionsAsrLoader"); + } + + void MappingRenderOptionsAsrLoader::AsrLoadedEvent(Euroscope::UserSetting& userSetting) + { + // VRP display + options->ShowVisualReferencePoints(userSetting.GetBooleanEntry(DISPLAY_VRPS_KEY, false)); + + // VRP selected airfields + std::set vrpAirfields; + for (const auto& airfield : userSetting.GetStringListEntry(AIRFIELDS_VRPS_KEY, {})) { + if (!HelperFunctions::IsAnInteger(airfield) || airfields.FetchById(std::stoi(airfield)) == nullptr) { + LogWarning("Invalid VRP airfield in ASR: " + airfield); + continue; + } + + vrpAirfields.insert(std::stoi(airfield)); + } + options->VisualReferencePointAirfields(vrpAirfields); + + // Trigger active element refresh + elementManager.RefreshActiveElements(); + } + + void MappingRenderOptionsAsrLoader::AsrClosingEvent(Euroscope::UserSetting& userSetting) + { + userSetting.Save(DISPLAY_VRPS_KEY, DISPLAY_VRPS_DESCRIPTION, options->ShowVisualReferencePoints()); + + std::vector airfieldList; + for (const auto& airfield : options->VisualReferencePointAirfields()) { + airfieldList.push_back(std::to_string(airfield)); + } + userSetting.Save(AIRFIELDS_VRPS_KEY, AIRFIELDS_VRPS_DESCRIPTION, airfieldList); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderOptionsAsrLoader.h b/src/plugin/mapping/MappingRenderOptionsAsrLoader.h new file mode 100644 index 000000000..7a614d42b --- /dev/null +++ b/src/plugin/mapping/MappingRenderOptionsAsrLoader.h @@ -0,0 +1,40 @@ +#pragma once +#include "euroscope/AsrEventHandlerInterface.h" + +namespace UKControllerPlugin::Airfield { + class AirfieldCollection; +} // namespace UKControllerPlugin::Airfield + +namespace UKControllerPlugin::Mapping { + class MappingElementManager; + class MappingRenderOptions; + + /** + * Loads the mapping rendering options from the ASR + */ + class MappingRenderOptionsAsrLoader : public Euroscope::AsrEventHandlerInterface + { + public: + MappingRenderOptionsAsrLoader( + MappingElementManager& elementManager, + std::shared_ptr options, + const Airfield::AirfieldCollection& airfields); + void AsrLoadedEvent(Euroscope::UserSetting& userSetting) override; + void AsrClosingEvent(Euroscope::UserSetting& userSetting) override; + + private: + // Manages mapping elements + MappingElementManager& elementManager; + + // Render options for mapping elements + std::shared_ptr options; + + // Airfields for checking if display is valid + const Airfield::AirfieldCollection& airfields; + + const std::string DISPLAY_VRPS_KEY = "displayVisualReferencePoints"; + const std::string DISPLAY_VRPS_DESCRIPTION = "Display Visual Reference Point"; + const std::string AIRFIELDS_VRPS_KEY = "visualReferencePointAirfields"; + const std::string AIRFIELDS_VRPS_DESCRIPTION = "Visual Reference Point Display Airfields"; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderer.cpp b/src/plugin/mapping/MappingRenderer.cpp index 8461f68db..2a9295803 100644 --- a/src/plugin/mapping/MappingRenderer.cpp +++ b/src/plugin/mapping/MappingRenderer.cpp @@ -5,7 +5,8 @@ #include "graphics/GdiGraphicsInterface.h" namespace UKControllerPlugin::Mapping { - MappingRenderer::MappingRenderer(const MappingElementManager& elementManager) : elementManager(elementManager) + MappingRenderer::MappingRenderer(std::shared_ptr elementManager) + : elementManager(elementManager) { } @@ -17,7 +18,7 @@ namespace UKControllerPlugin::Mapping { void MappingRenderer::Render( Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { - elementManager.ForEachActiveElement( + elementManager->ForEachActiveElement( [&graphics, &radarScreen](MappingElementInterface& element) { element.Draw(graphics, radarScreen); }); } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingRenderer.h b/src/plugin/mapping/MappingRenderer.h index 328d9aad8..a01c21f27 100644 --- a/src/plugin/mapping/MappingRenderer.h +++ b/src/plugin/mapping/MappingRenderer.h @@ -10,13 +10,13 @@ namespace UKControllerPlugin::Mapping { class MappingRenderer : public RadarScreen::RadarRenderableInterface { public: - MappingRenderer(const MappingElementManager& elementManager); + MappingRenderer(std::shared_ptr elementManager); auto IsVisible() const -> bool override; void Render( Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) override; private: // All the mapping elements - const MappingElementManager& elementManager; + std::shared_ptr elementManager; }; } // namespace UKControllerPlugin::Mapping From fc65dec5645da7f89f2b7944b7620e74dc6385d2 Mon Sep 17 00:00:00 2001 From: Andy Ford Date: Fri, 3 Jun 2022 11:38:03 +0100 Subject: [PATCH 13/18] VRPs Enabled Checkbox --- src/plugin/CMakeLists.txt | 2 +- src/plugin/components/Checkbox.cpp | 56 ++++++++++++++++++ src/plugin/components/Checkbox.h | 58 +++++++++++++++++++ src/plugin/components/Title.cpp | 24 ++++++++ src/plugin/components/Title.h | 40 +++++++++++++ src/plugin/mapping/MappingElementManager.cpp | 1 - src/plugin/mapping/MappingOptionsRenderer.cpp | 13 ++++- src/plugin/mapping/MappingOptionsRenderer.h | 3 + 8 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 src/plugin/components/Checkbox.cpp create mode 100644 src/plugin/components/Checkbox.h create mode 100644 src/plugin/components/Title.cpp create mode 100644 src/plugin/components/Title.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 494373db5..4f36aca9d 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -94,7 +94,7 @@ set(src__components "components/StandardButtons.h" "components/TitleBar.cpp" "components/TitleBar.h" - components/CollapsibleWindowTitleBar.cpp components/CollapsibleWindowTitleBar.h) + components/CollapsibleWindowTitleBar.cpp components/CollapsibleWindowTitleBar.h components/Title.cpp components/Title.h components/Checkbox.cpp components/Checkbox.h) source_group("src\\components" FILES ${src__components}) set(src__controller diff --git a/src/plugin/components/Checkbox.cpp b/src/plugin/components/Checkbox.cpp new file mode 100644 index 000000000..812b1d005 --- /dev/null +++ b/src/plugin/components/Checkbox.cpp @@ -0,0 +1,56 @@ +#include "Checkbox.h" +#include "ClickableArea.h" +#include "graphics/FontManager.h" +#include "graphics/GdiGraphicsInterface.h" +#include "graphics/StringFormatManager.h" + +namespace UKControllerPlugin::Components { + + Checkbox::Checkbox(std::wstring label, POINT position, int screenObjectId, std::string name) + : label(std::move(label)), area(position.x, position.y, DIMENSIONS, DIMENSIONS), + labelArea(area.GetRight() + 10, position.y, 250, DIMENSIONS), + pen(std::make_shared(Gdiplus::Color(255, 255, 255))), + brush(std::make_shared(Gdiplus::Color(255, 255, 255))), + clickableArea(ClickableArea::Create( + Gdiplus::Rect(area.GetLeft(), area.GetTop(), labelArea.GetRight() - area.GetLeft(), labelArea.Height), + screenObjectId, + name, + false)), + font(Graphics::FontManager::Instance().GetDefault()), + stringFormat(Graphics::StringFormatManager::Instance().GetLeftAlign()) + { + } + + auto Checkbox::Create(std::wstring label, POINT position, int screenObjectId, std::string name) + -> std::shared_ptr + { + return std::shared_ptr(new Checkbox(label, position, screenObjectId, name)); + } + + auto Checkbox::Checked(bool checked) -> std::shared_ptr + { + this->checked = checked; + return shared_from_this(); + } + + void Checkbox::Draw( + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const + { + // Draw the border + graphics.DrawRect(area, *pen); + + // Draw the checkmark if checked + if (checked) { + graphics.DrawLine( + *pen, Gdiplus::Point{area.GetLeft(), area.GetTop()}, Gdiplus::Point{area.GetRight(), area.GetBottom()}); + graphics.DrawLine( + *pen, Gdiplus::Point{area.GetLeft(), area.GetBottom()}, Gdiplus::Point{area.GetRight(), area.GetTop()}); + } + + // Clickspot + clickableArea->Apply(graphics, radarScreen); + + // Label + graphics.DrawString(label, labelArea, *brush, stringFormat, font); + } +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/Checkbox.h b/src/plugin/components/Checkbox.h new file mode 100644 index 000000000..155bc02d2 --- /dev/null +++ b/src/plugin/components/Checkbox.h @@ -0,0 +1,58 @@ +#pragma once + +namespace UKControllerPlugin { + namespace Euroscope { + class EuroscopeRadarLoopbackInterface; + } // namespace Euroscope + namespace Windows { + class GdiGraphicsInterface; + } // namespace Windows +} // namespace UKControllerPlugin + +namespace UKControllerPlugin::Components { + class ClickableArea; + + /** + * A checkbox + */ + class Checkbox : public std::enable_shared_from_this + { + public: + static auto Create(std::wstring label, POINT position, int screenObjectId, std::string name) + -> std::shared_ptr; + auto Checked(bool checked) -> std::shared_ptr; + void + Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const; + + protected: + Checkbox(std::wstring label, POINT position, int screenObjectId, std::string name); + + private: + // The label for the checkbox + std::wstring label; + + // Clickspot area + Gdiplus::Rect area; + Gdiplus::Rect labelArea; + + // Pen + std::shared_ptr pen; + std::shared_ptr brush; + + // Clickspot + std::shared_ptr clickableArea; + + // Font + const Gdiplus::Font& font; + + // String format + const Gdiplus::StringFormat& stringFormat; + + // Checked + bool checked = false; + + // How big is it + inline static const int DIMENSIONS = 15; + }; + +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/Title.cpp b/src/plugin/components/Title.cpp new file mode 100644 index 000000000..9fa20b37f --- /dev/null +++ b/src/plugin/components/Title.cpp @@ -0,0 +1,24 @@ +#include "Title.h" +#include "graphics/FontManager.h" +#include "graphics/StringFormatManager.h" +#include "graphics/GdiGraphicsInterface.h" + +namespace UKControllerPlugin::Components { + + Title::Title(std::wstring text, Gdiplus::Rect position) + : text(text), position(position), font(Graphics::FontManager::Instance().Get(14)), + format(Graphics::StringFormatManager::Instance().GetCentreAlign()), + textBrush(std::make_shared(Gdiplus::Color(255, 255, 255))) + { + } + + auto Title::Create(std::wstring text, Gdiplus::Rect position) -> std::shared_ptr + { + return std::shared_ptr<Title>(new Title(text, position)); + } + + void Title::Draw(Windows::GdiGraphicsInterface& graphics) const + { + graphics.DrawString(text, position, *textBrush, format, font); + } +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/Title.h b/src/plugin/components/Title.h new file mode 100644 index 000000000..6899114c4 --- /dev/null +++ b/src/plugin/components/Title.h @@ -0,0 +1,40 @@ +#pragma once + +namespace UKControllerPlugin { + namespace Windows { + class GdiGraphicsInterface; + } // namespace Windows +} // namespace UKControllerPlugin + +namespace UKControllerPlugin::Components { + + /** + * Prints a title to the screen + */ + class Title : public std::enable_shared_from_this<Title> + { + public: + static auto Create(std::wstring text, Gdiplus::Rect position) -> std::shared_ptr<Title>; + void Draw(Windows::GdiGraphicsInterface& graphics) const; + + protected: + Title(std::wstring text, Gdiplus::Rect position); + + private: + // The text to display + std::wstring text; + + // Where to show the text + Gdiplus::Rect position; + + // The font + const Gdiplus::Font& font; + + // Format + const Gdiplus::StringFormat& format; + + // The brush + std::shared_ptr<Gdiplus::Brush> textBrush; + }; + +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/mapping/MappingElementManager.cpp b/src/plugin/mapping/MappingElementManager.cpp index 986f21004..c04106928 100644 --- a/src/plugin/mapping/MappingElementManager.cpp +++ b/src/plugin/mapping/MappingElementManager.cpp @@ -6,7 +6,6 @@ namespace UKControllerPlugin::Mapping { void MappingElementManager::Add(std::shared_ptr<MappingElement> element) { allElements.insert(element); - activeElements.insert(element); } auto MappingElementManager::Count() const -> size_t diff --git a/src/plugin/mapping/MappingOptionsRenderer.cpp b/src/plugin/mapping/MappingOptionsRenderer.cpp index df0ceea4a..d29573a20 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.cpp +++ b/src/plugin/mapping/MappingOptionsRenderer.cpp @@ -1,5 +1,7 @@ #include "MappingOptionsRenderer.h" #include "MappingRenderOptions.h" +#include "components/Checkbox.h" +#include "components/Title.h" #include "components/TitleBar.h" #include "euroscope/EuroscopeRadarLoopbackInterface.h" #include "graphics/GdiGraphicsInterface.h" @@ -28,7 +30,10 @@ namespace UKControllerPlugin::Mapping { POINT mousePos, RECT itemArea) { - RadarRenderableInterface::LeftClick(radarScreen, objectId, objectDescription, mousePos, itemArea); + if (objectDescription == DISPLAY_VRP_CHECKBOX) { + mappingOptions->ShowVisualReferencePoints(!mappingOptions->ShowVisualReferencePoints()); + return; + } } void MappingOptionsRenderer::Render( @@ -45,6 +50,12 @@ namespace UKControllerPlugin::Mapping { ->WithDefaultBackgroundBrush() ->WithDefaultTextBrush() ->Draw(graphics, radarScreen); + + // VRPs + Components::Title::Create(L"Visual Reference Points", Gdiplus::Rect{10, 35, 300, 25})->Draw(graphics); + Components::Checkbox::Create(L"Display VRPs", {10, 70}, screenObjectId, DISPLAY_VRP_CHECKBOX) + ->Checked(mappingOptions->ShowVisualReferencePoints()) + ->Draw(graphics, radarScreen); }); } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingOptionsRenderer.h b/src/plugin/mapping/MappingOptionsRenderer.h index 386edc818..53d7ac592 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.h +++ b/src/plugin/mapping/MappingOptionsRenderer.h @@ -30,5 +30,8 @@ namespace UKControllerPlugin::Mapping { // Brushes std::shared_ptr<Gdiplus::Brush> backgroundBrush; + + // Screen objects + const std::string DISPLAY_VRP_CHECKBOX = "displayVrps"; }; } // namespace UKControllerPlugin::Mapping From d120ac35781ecfdcc4d0924debd2e38616b6e022 Mon Sep 17 00:00:00 2001 From: Andy Ford <andyford993@gmail.com> Date: Sat, 4 Jun 2022 16:43:05 +0100 Subject: [PATCH 14/18] Scrollbar stuff --- src/plugin/CMakeLists.txt | 4 +- src/plugin/components/ClickableArea.cpp | 33 +++----- src/plugin/components/Scrollbar.cpp | 76 +++++++++++++++++++ src/plugin/components/Scrollbar.h | 54 +++++++++++++ src/plugin/components/ScrollbarClickspot.cpp | 31 ++++++++ src/plugin/components/ScrollbarClickspot.h | 44 +++++++++++ src/plugin/components/ScrollbarFactory.cpp | 46 +++++++++++ src/plugin/components/ScrollbarFactory.h | 26 +++++++ src/plugin/components/ScrollbarOptions.cpp | 39 ++++++++++ src/plugin/components/ScrollbarOptions.h | 25 ++++++ .../mapping/MappingBootstrapProvider.cpp | 5 +- src/plugin/mapping/MappingOptionsRenderer.cpp | 14 +++- src/plugin/mapping/MappingOptionsRenderer.h | 13 +++- .../radarscreen/RadarRenderableCollection.cpp | 76 +++++++++++-------- .../radarscreen/RadarRenderableCollection.h | 3 + .../radarscreen/ScreenObjectInterface.cpp | 20 +++++ .../radarscreen/ScreenObjectInterface.h | 36 +++++++++ 17 files changed, 482 insertions(+), 63 deletions(-) create mode 100644 src/plugin/components/Scrollbar.cpp create mode 100644 src/plugin/components/Scrollbar.h create mode 100644 src/plugin/components/ScrollbarClickspot.cpp create mode 100644 src/plugin/components/ScrollbarClickspot.h create mode 100644 src/plugin/components/ScrollbarFactory.cpp create mode 100644 src/plugin/components/ScrollbarFactory.h create mode 100644 src/plugin/components/ScrollbarOptions.cpp create mode 100644 src/plugin/components/ScrollbarOptions.h create mode 100644 src/plugin/radarscreen/ScreenObjectInterface.cpp create mode 100644 src/plugin/radarscreen/ScreenObjectInterface.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 4f36aca9d..c9927bdc2 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -94,7 +94,7 @@ set(src__components "components/StandardButtons.h" "components/TitleBar.cpp" "components/TitleBar.h" - components/CollapsibleWindowTitleBar.cpp components/CollapsibleWindowTitleBar.h components/Title.cpp components/Title.h components/Checkbox.cpp components/Checkbox.h) + components/CollapsibleWindowTitleBar.cpp components/CollapsibleWindowTitleBar.h components/Title.cpp components/Title.h components/Checkbox.cpp components/Checkbox.h components/Scrollbar.cpp components/Scrollbar.h components/ScrollbarFactory.cpp components/ScrollbarFactory.h components/ScrollbarClickspot.cpp components/ScrollbarClickspot.h components/ScrollbarOptions.cpp components/ScrollbarOptions.h) source_group("src\\components" FILES ${src__components}) set(src__controller @@ -776,7 +776,7 @@ set(src__radarscreen "radarscreen/ScreenControlsBootstrap.h" "radarscreen/UKRadarScreen.cpp" "radarscreen/UKRadarScreen.h" - radarscreen/RadarRenderableInterface.cpp radarscreen/ConfigurableDisplayInterface.cpp radarscreen/MenuToggleableDisplayInterface.h radarscreen/ToggleDisplayFromMenu.cpp radarscreen/ToggleDisplayFromMenu.h radarscreen/MenuToggleableDisplayFactory.cpp radarscreen/MenuToggleableDisplayFactory.h) + radarscreen/RadarRenderableInterface.cpp radarscreen/ConfigurableDisplayInterface.cpp radarscreen/MenuToggleableDisplayInterface.h radarscreen/ToggleDisplayFromMenu.cpp radarscreen/ToggleDisplayFromMenu.h radarscreen/MenuToggleableDisplayFactory.cpp radarscreen/MenuToggleableDisplayFactory.h radarscreen/ScreenObjectInterface.cpp radarscreen/ScreenObjectInterface.h) source_group("src\\radarscreen" FILES ${src__radarscreen}) set(src__regional diff --git a/src/plugin/components/ClickableArea.cpp b/src/plugin/components/ClickableArea.cpp index 96ff70f67..38eb3c42d 100644 --- a/src/plugin/components/ClickableArea.cpp +++ b/src/plugin/components/ClickableArea.cpp @@ -1,22 +1,14 @@ -#include <utility> - -#include "pch/pch.h" #include "components/ClickableArea.h" #include "euroscope/EuroscopeRadarLoopbackInterface.h" #include "graphics/GdiGraphicsInterface.h" namespace UKControllerPlugin::Components { - std::shared_ptr<ClickableArea> ClickableArea::Create( - Gdiplus::Rect area, - int screenObjectId, - std::string screenObjectDescription, - bool draggable - ) + std::shared_ptr<ClickableArea> + ClickableArea::Create(Gdiplus::Rect area, int screenObjectId, std::string screenObjectDescription, bool draggable) { return std::shared_ptr<ClickableArea>( - new ClickableArea(area, screenObjectId, std::move(screenObjectDescription), draggable) - ); + new ClickableArea(area, screenObjectId, std::move(screenObjectDescription), draggable)); } void ClickableArea::WithPosition(Gdiplus::Rect area) @@ -29,9 +21,7 @@ namespace UKControllerPlugin::Components { * we can render the clickspot correctly on screen. */ void ClickableArea::Apply( - Windows::GdiGraphicsInterface& graphics, - Euroscope::EuroscopeRadarLoopbackInterface& radarScreen - ) const + Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const { std::shared_ptr<Gdiplus::Matrix> transform = graphics.GetTransform(); radarScreen.RegisterScreenObject( @@ -43,16 +33,13 @@ namespace UKControllerPlugin::Components { static_cast<LONG>(this->area.GetRight() + transform->OffsetX()), static_cast<LONG>(this->area.GetBottom() + transform->OffsetY()), }, - this->draggable - ); + this->draggable); } ClickableArea::ClickableArea( - Gdiplus::Rect area, - int screenObjectId, - std::string screenObjectDescription, - bool draggable - ): - screenObjectDescription(std::move(screenObjectDescription)), area(area), screenObjectId(screenObjectId), - draggable(draggable) {} + Gdiplus::Rect area, int screenObjectId, std::string screenObjectDescription, bool draggable) + : screenObjectDescription(std::move(screenObjectDescription)), area(area), screenObjectId(screenObjectId), + draggable(draggable) + { + } } // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/Scrollbar.cpp b/src/plugin/components/Scrollbar.cpp new file mode 100644 index 000000000..499db68a3 --- /dev/null +++ b/src/plugin/components/Scrollbar.cpp @@ -0,0 +1,76 @@ +#include "Scrollbar.h" +#include "ScrollbarClickspot.h" +#include "ScrollbarOptions.h" +#include "graphics/GdiGraphicsInterface.h" + +namespace UKControllerPlugin::Components { + + Scrollbar::Scrollbar( + Gdiplus::Rect area, + std::shared_ptr<ScrollbarOptions> options, + bool isHorizontal, + std::shared_ptr<ScrollbarClickspot> decrementClickspot, + std::shared_ptr<ScrollbarClickspot> incrementClickspot) + : area(area), options(options), isHorizontal(isHorizontal), decrementClickspot(decrementClickspot), + incrementClickspot(incrementClickspot), backgroundBrush(std::make_shared<Gdiplus::HatchBrush>( + Gdiplus::HatchStyle::HatchStyle25Percent, + Gdiplus::Color(255, 255, 255), + Gdiplus::Color(200, 64, 64, 64))), + progressBarBrush(std::make_shared<Gdiplus::SolidBrush>(Gdiplus::Color(64, 64, 64))) + { + assert(options && "scrollbar options not set in scrollbar"); + assert(decrementClickspot && "decrement clickspot not set in scrollbar"); + assert(incrementClickspot && "increment clickspot not set in scrollbar"); + } + + void + Scrollbar::Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) + { + if (isHorizontal || !isHorizontal) { + graphics.FillRect(area, *backgroundBrush); + } + + // Translated clickspots + decrementClickspot->Draw( + { + area.GetLeft(), + area.GetTop(), + area.Width, + area.Width, + }, + graphics, + radarScreen); + + incrementClickspot->Draw( + { + area.GetLeft(), + area.GetBottom() - area.Width, + area.Width, + area.Width, + }, + graphics, + radarScreen); + + // Progress bar + graphics.Translated(area.GetLeft(), area.GetTop() + (area.Width * options->Notch()), [&graphics, this]() { + graphics.FillRect( + Gdiplus::Rect{ + 0, + 0, + area.Width, + area.Width, + }, + *progressBarBrush); + }); + } + + auto Scrollbar::IncrementClickspot() const -> std::shared_ptr<ScrollbarClickspot> + { + return incrementClickspot; + } + + auto Scrollbar::DecrementClickspot() const -> std::shared_ptr<ScrollbarClickspot> + { + return decrementClickspot; + } +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/Scrollbar.h b/src/plugin/components/Scrollbar.h new file mode 100644 index 000000000..b7c6d703f --- /dev/null +++ b/src/plugin/components/Scrollbar.h @@ -0,0 +1,54 @@ +#pragma once + +namespace UKControllerPlugin { + namespace Euroscope { + class EuroscopeRadarLoopbackInterface; + } // namespace Euroscope + namespace Windows { + class GdiGraphicsInterface; + } // namespace Windows +} // namespace UKControllerPlugin + +namespace UKControllerPlugin::Components { + + class ScrollbarClickspot; + class ScrollbarOptions; + + /** + * A scrollbar + */ + class Scrollbar : public std::enable_shared_from_this<Scrollbar> + { + public: + Scrollbar( + Gdiplus::Rect area, + std::shared_ptr<ScrollbarOptions> options, + bool isHorizontal, + std::shared_ptr<ScrollbarClickspot> decrementClickspot, + std::shared_ptr<ScrollbarClickspot> incrementClickspot); + void Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen); + [[nodiscard]] auto IncrementClickspot() const -> std::shared_ptr<ScrollbarClickspot>; + [[nodiscard]] auto DecrementClickspot() const -> std::shared_ptr<ScrollbarClickspot>; + + private: + // Area to use + Gdiplus::Rect area; + + // Number of notches + std::shared_ptr<ScrollbarOptions> options; + + // Are we a horizonal scrollbar + const bool isHorizontal; + + // The clickspot for decrementing + std::shared_ptr<ScrollbarClickspot> decrementClickspot; + + // The clickspot for incrementing + std::shared_ptr<ScrollbarClickspot> incrementClickspot; + + // Brush + std::shared_ptr<Gdiplus::Brush> backgroundBrush; + std::shared_ptr<Gdiplus::Brush> progressBarBrush; + }; + +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarClickspot.cpp b/src/plugin/components/ScrollbarClickspot.cpp new file mode 100644 index 000000000..4a3626bbb --- /dev/null +++ b/src/plugin/components/ScrollbarClickspot.cpp @@ -0,0 +1,31 @@ +#include "ClickableArea.h" +#include "ScrollbarClickspot.h" +#include "StandardButtons.h" +#include "graphics/GdiGraphicsInterface.h" + +namespace UKControllerPlugin::Components { + + ScrollbarClickspot::ScrollbarClickspot(int screenObjectId, std::function<void()> clicked, bool increments) + : clicked(std::move(std::move(clicked))), increments(increments), + clickableArea(ClickableArea::Create({}, screenObjectId, "scrollbarClickspot", false)) + { + } + + void ScrollbarClickspot::Draw( + const Gdiplus::Rect& area, + Windows::GdiGraphicsInterface& graphics, + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) + { + graphics.Translated(area.GetLeft(), area.GetTop(), [this, &graphics, &area] { + CollapseButton([this]() { return increments; })(graphics, {0, 0, area.Width, area.Height}); + }); + clickableArea->WithPosition(area); + clickableArea->Apply(graphics, radarScreen); + } + + void ScrollbarClickspot::LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, const std::string& description, POINT mousePosition) + { + clicked(); + } +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarClickspot.h b/src/plugin/components/ScrollbarClickspot.h new file mode 100644 index 000000000..30e3c5f96 --- /dev/null +++ b/src/plugin/components/ScrollbarClickspot.h @@ -0,0 +1,44 @@ +#pragma once +#include <string> +#include <windef.h> +#include "radarscreen/ScreenObjectInterface.h" + +namespace UKControllerPlugin { + namespace Euroscope { + class EuroscopeRadarLoopbackInterface; + } // namespace Euroscope + namespace Windows { + class GdiGraphicsInterface; + } // namespace Windows +} // namespace UKControllerPlugin + +namespace UKControllerPlugin::Components { + class ClickableArea; + + /** + * Clickspot for scrollbars. + */ + class ScrollbarClickspot : public RadarScreen::ScreenObjectInterface + { + public: + ScrollbarClickspot(int screenObjectId, std::function<void()> clicked, bool increments); + void Draw( + const Gdiplus::Rect& area, + Windows::GdiGraphicsInterface& graphics, + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen); + void LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, + const std::string& description, + POINT mousePosition) override; + + private: + // What to do when its clicked + const std::function<void()> clicked; + + // Are we incrementing or decrementing (direction of arrow) + const bool increments; + + // The actual clickspot + std::shared_ptr<ClickableArea> clickableArea; + }; +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarFactory.cpp b/src/plugin/components/ScrollbarFactory.cpp new file mode 100644 index 000000000..4351417d6 --- /dev/null +++ b/src/plugin/components/ScrollbarFactory.cpp @@ -0,0 +1,46 @@ +#include "Scrollbar.h" +#include "ScrollbarClickspot.h" +#include "ScrollbarFactory.h" +#include "ScrollbarOptions.h" +#include "radarscreen/RadarRenderableCollection.h" + +namespace UKControllerPlugin::Components { + + ScrollbarFactory::ScrollbarFactory(RadarScreen::RadarRenderableCollection& radarRenderables) + : radarRenderables(radarRenderables) + { + } + auto ScrollbarFactory::MakeHorizontal(Gdiplus::Rect area, unsigned short notches) const + -> std::shared_ptr<Scrollbar> + { + return Make(std::move(area), notches, true); + } + + auto ScrollbarFactory::MakeVertical(Gdiplus::Rect area, unsigned short notches) const -> std::shared_ptr<Scrollbar> + { + return Make(std::move(area), notches, false); + } + + auto ScrollbarFactory::Make(Gdiplus::Rect area, unsigned short notches, bool horizontal) const + -> std::shared_ptr<Scrollbar> + { + auto options = std::make_shared<ScrollbarOptions>(notches); + std::shared_ptr<ScrollbarClickspot> incrementClickspot; + radarRenderables.RegisterScreenObject([&incrementClickspot, options](int screenObjectId) { + incrementClickspot = std::make_shared<ScrollbarClickspot>( + screenObjectId, [options]() { options->Increment(); }, true); + + return incrementClickspot; + }); + + std::shared_ptr<ScrollbarClickspot> decrementClickspot; + radarRenderables.RegisterScreenObject([&decrementClickspot, options](int screenObjectId) { + decrementClickspot = std::make_shared<ScrollbarClickspot>( + screenObjectId, [options]() { options->Decrement(); }, false); + + return decrementClickspot; + }); + + return std::make_shared<Scrollbar>(area, options, horizontal, decrementClickspot, incrementClickspot); + } +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarFactory.h b/src/plugin/components/ScrollbarFactory.h new file mode 100644 index 000000000..c942745fa --- /dev/null +++ b/src/plugin/components/ScrollbarFactory.h @@ -0,0 +1,26 @@ +#pragma once +#include "radarscreen/RadarRenderableCollection.h" + +namespace UKControllerPlugin::Components { + class Scrollbar; + + /** + * Creates scrollbars + */ + class ScrollbarFactory + { + public: + ScrollbarFactory(RadarScreen::RadarRenderableCollection& radarRenderables); + [[nodiscard]] auto MakeVertical(Gdiplus::Rect area, unsigned short notches) const -> std::shared_ptr<Scrollbar>; + [[nodiscard]] auto MakeHorizontal(Gdiplus::Rect area, unsigned short notches) const + -> std::shared_ptr<Scrollbar>; + + private: + [[nodiscard]] auto Make(Gdiplus::Rect area, unsigned short notches, bool horizontal) const + -> std::shared_ptr<Scrollbar>; + + // Radar renderables + RadarScreen::RadarRenderableCollection& radarRenderables; + }; + +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarOptions.cpp b/src/plugin/components/ScrollbarOptions.cpp new file mode 100644 index 000000000..78f29c97e --- /dev/null +++ b/src/plugin/components/ScrollbarOptions.cpp @@ -0,0 +1,39 @@ +#include "ScrollbarOptions.h" + +namespace UKControllerPlugin::Components { + + ScrollbarOptions::ScrollbarOptions(unsigned short notches) : notches(notches), notch(1) + { + if (notches == 0) { + throw std::invalid_argument("A scrollbar must have at least one notch"); + } + } + + auto ScrollbarOptions::Notches() const -> unsigned short + { + return notches; + } + + auto ScrollbarOptions::Notch() const -> unsigned short + { + return notch; + } + + void ScrollbarOptions::Increment() + { + if (notch == notches) { + return; + } + + notch++; + } + + void ScrollbarOptions::Decrement() + { + if (notch == 1) { + return; + } + + notch--; + } +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarOptions.h b/src/plugin/components/ScrollbarOptions.h new file mode 100644 index 000000000..4413f8559 --- /dev/null +++ b/src/plugin/components/ScrollbarOptions.h @@ -0,0 +1,25 @@ +#pragma once + +namespace UKControllerPlugin::Components { + + /** + * Contains options about scrollbars + */ + class ScrollbarOptions + { + public: + ScrollbarOptions(unsigned short notches); + [[nodiscard]] auto Notches() const -> unsigned short; + [[nodiscard]] auto Notch() const -> unsigned short; + void Increment(); + void Decrement(); + + private: + // The total number of notches + const unsigned short notches; + + // The current notch + unsigned short notch; + }; + +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/mapping/MappingBootstrapProvider.cpp b/src/plugin/mapping/MappingBootstrapProvider.cpp index a19c59ec0..5365bc380 100644 --- a/src/plugin/mapping/MappingBootstrapProvider.cpp +++ b/src/plugin/mapping/MappingBootstrapProvider.cpp @@ -12,6 +12,7 @@ #include "ToggleMappingOptionsRender.h" #include "bootstrap/ModuleFactories.h" #include "bootstrap/PersistenceContainer.h" +#include "components/ScrollbarFactory.h" #include "euroscope/AsrEventHandlerCollection.h" #include "radarscreen/RadarRenderableCollection.h" @@ -46,7 +47,9 @@ namespace UKControllerPlugin::Mapping { radarRenderables.RegisterRenderer( optionsRendererId, std::make_shared<MappingOptionsRenderer>( - renderOptions, radarRenderables.ReserveScreenObjectIdentifier(optionsRendererId)), + renderOptions, + Components::ScrollbarFactory(radarRenderables), + radarRenderables.ReserveScreenObjectIdentifier(optionsRendererId)), RadarScreen::RadarRenderableCollection::afterLists); // Toggles the options diff --git a/src/plugin/mapping/MappingOptionsRenderer.cpp b/src/plugin/mapping/MappingOptionsRenderer.cpp index d29573a20..67e2b8c1e 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.cpp +++ b/src/plugin/mapping/MappingOptionsRenderer.cpp @@ -1,6 +1,8 @@ #include "MappingOptionsRenderer.h" #include "MappingRenderOptions.h" #include "components/Checkbox.h" +#include "components/Scrollbar.h" +#include "components/ScrollbarFactory.h" #include "components/Title.h" #include "components/TitleBar.h" #include "euroscope/EuroscopeRadarLoopbackInterface.h" @@ -9,13 +11,15 @@ namespace UKControllerPlugin::Mapping { MappingOptionsRenderer::MappingOptionsRenderer( - std::shared_ptr<MappingRenderOptions> mappingOptions, int screenObjectId) - : mappingOptions(mappingOptions), screenObjectId(screenObjectId), + std::shared_ptr<MappingRenderOptions> mappingOptions, + const Components::ScrollbarFactory& scrollbarFactory, + int screenObjectId) + : mappingOptions(mappingOptions), vrpScrollbar(scrollbarFactory.MakeHorizontal({10, 110, 25, 300}, 10)), + screenObjectId(screenObjectId), backgroundBrush(std::make_shared<Gdiplus::SolidBrush>(Gdiplus::Color(170, 64, 64, 64))) { - int i = this->screenObjectId == 1 ? 1 : 2; - i++; assert(mappingOptions && "Mapping render options not set"); + assert(vrpScrollbar && "VRP Scrollbar Not Set"); } auto MappingOptionsRenderer::IsVisible() const -> bool @@ -56,6 +60,8 @@ namespace UKControllerPlugin::Mapping { Components::Checkbox::Create(L"Display VRPs", {10, 70}, screenObjectId, DISPLAY_VRP_CHECKBOX) ->Checked(mappingOptions->ShowVisualReferencePoints()) ->Draw(graphics, radarScreen); + + vrpScrollbar->Draw(graphics, radarScreen); }); } } // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/MappingOptionsRenderer.h b/src/plugin/mapping/MappingOptionsRenderer.h index 53d7ac592..fd5b8b1e2 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.h +++ b/src/plugin/mapping/MappingOptionsRenderer.h @@ -1,6 +1,11 @@ #pragma once #include "radarscreen/RadarRenderableInterface.h" +namespace UKControllerPlugin::Components { + class Scrollbar; + class ScrollbarFactory; +} // namespace UKControllerPlugin::Components + namespace UKControllerPlugin::Mapping { class MappingRenderOptions; @@ -10,7 +15,10 @@ namespace UKControllerPlugin::Mapping { class MappingOptionsRenderer : public RadarScreen::RadarRenderableInterface { public: - MappingOptionsRenderer(std::shared_ptr<MappingRenderOptions> mappingOptions, int screenObjectId); + MappingOptionsRenderer( + std::shared_ptr<MappingRenderOptions> mappingOptions, + const Components::ScrollbarFactory& scrollbarFactory, + int screenObjectId); [[nodiscard]] auto IsVisible() const -> bool override; void LeftClick( Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, @@ -25,6 +33,9 @@ namespace UKControllerPlugin::Mapping { // The options std::shared_ptr<MappingRenderOptions> mappingOptions; + // Scrollbar for VRPs + std::shared_ptr<Components::Scrollbar> vrpScrollbar; + // For clickspots const int screenObjectId; diff --git a/src/plugin/radarscreen/RadarRenderableCollection.cpp b/src/plugin/radarscreen/RadarRenderableCollection.cpp index dee634a47..8e2723135 100644 --- a/src/plugin/radarscreen/RadarRenderableCollection.cpp +++ b/src/plugin/radarscreen/RadarRenderableCollection.cpp @@ -1,10 +1,11 @@ #include "pch/pch.h" #include "radarscreen/RadarRenderableCollection.h" #include "radarscreen/RadarRenderableInterface.h" +#include "radarscreen/ScreenObjectInterface.h" #include "euroscope/EuroscopeRadarLoopbackInterface.h" -using UKControllerPlugin::RadarScreen::RadarRenderableInterface; using UKControllerPlugin::Euroscope::EuroscopeRadarLoopbackInterface; +using UKControllerPlugin::RadarScreen::RadarRenderableInterface; namespace UKControllerPlugin { namespace RadarScreen { @@ -48,7 +49,7 @@ namespace UKControllerPlugin { */ size_t RadarRenderableCollection::CountScreenObjects(void) const { - return this->screenObjectMap.size(); + return this->screenObjectMap.size() + this->screenObjects.size(); } /* @@ -63,7 +64,6 @@ namespace UKControllerPlugin { return this->screenObjectMap.at(objectId); } - /* Tell the renderer that a screen object has been left clicked. */ @@ -72,10 +72,14 @@ namespace UKControllerPlugin { int objectId, std::string objectDescription, POINT mousePos, - RECT itemArea - ) const { - this->allRenderers.at(this->screenObjectMap.at(objectId)) - ->LeftClick(radarScreen, objectId, objectDescription, mousePos, itemArea); + RECT itemArea) const + { + if (this->screenObjectMap.contains(objectId)) { + this->allRenderers.at(this->screenObjectMap.at(objectId)) + ->LeftClick(radarScreen, objectId, objectDescription, mousePos, itemArea); + } else { + this->screenObjects.at(objectId)->LeftClick(radarScreen, objectDescription, mousePos); + } } /* @@ -83,17 +87,19 @@ namespace UKControllerPlugin { */ void RadarRenderableCollection::MoveScreenObject(int objectId, std::string objectDes, RECT position) const { - this->allRenderers.at(this->screenObjectMap.at(objectId))->Move(position, objectDes); + if (this->screenObjectMap.contains(objectId)) { + this->allRenderers.at(this->screenObjectMap.at(objectId))->Move(position, objectDes); + } else { + this->screenObjects.at(objectId)->Drag(objectDes, position); + } } /* Registers a renderer for a specific phase. Returns the renderer ID. */ void RadarRenderableCollection::RegisterRenderer( - int rendererId, - std::shared_ptr<RadarRenderableInterface> renderer, - int renderPhase - ) { + int rendererId, std::shared_ptr<RadarRenderableInterface> renderer, int renderPhase) + { // Don't allow duplicate renderers if (this->allRenderers.count(rendererId) != 0) { throw std::invalid_argument("Renderer already exists!"); @@ -102,7 +108,7 @@ namespace UKControllerPlugin { // Only accept renderers in a given phase. if (renderPhase == this->initialPhase) { this->initialPhaseRenders.push_back(rendererId); - } else if(renderPhase == this->beforeTags) { + } else if (renderPhase == this->beforeTags) { this->beforeTagRenders.push_back(rendererId); } else if (renderPhase == this->afterTags) { this->afterTagRenders.push_back(rendererId); @@ -148,9 +154,8 @@ namespace UKControllerPlugin { */ void RadarRenderableCollection::Render( int phase, - UKControllerPlugin::Windows::GdiGraphicsInterface & graphics, - UKControllerPlugin::Euroscope::EuroscopeRadarLoopbackInterface & radarScreen - ) const + UKControllerPlugin::Windows::GdiGraphicsInterface& graphics, + UKControllerPlugin::Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const { if (phase == this->initialPhase) { this->RenderGroup(this->initialPhaseRenders, graphics, radarScreen); @@ -171,20 +176,23 @@ namespace UKControllerPlugin { void RadarRenderableCollection::RightClickScreenObject( int objectId, std::string objectDescription, - UKControllerPlugin::Euroscope::EuroscopeRadarLoopbackInterface & radarScreen - ) const { - this->allRenderers.at(this->screenObjectMap.at(objectId)) - ->RightClick(objectId, objectDescription, radarScreen); + UKControllerPlugin::Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const + { + if (this->screenObjectMap.contains(objectId)) { + this->allRenderers.at(this->screenObjectMap.at(objectId)) + ->RightClick(objectId, objectDescription, radarScreen); + } else { + this->screenObjects.at(objectId)->RightClick(radarScreen, objectDescription); + } } /* Renders a given group of renderers. */ void RadarRenderableCollection::RenderGroup( - const std::vector<int> & group, - UKControllerPlugin::Windows::GdiGraphicsInterface & graphics, - UKControllerPlugin::Euroscope::EuroscopeRadarLoopbackInterface & radarScreen - ) const + const std::vector<int>& group, + UKControllerPlugin::Windows::GdiGraphicsInterface& graphics, + UKControllerPlugin::Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const { for (std::vector<int>::const_iterator it = group.cbegin(); it != group.cend(); ++it) { if (this->allRenderers.at(*it)->IsVisible()) { @@ -198,14 +206,18 @@ namespace UKControllerPlugin { */ void RadarRenderableCollection::ResetPosition(void) const { - for ( - std::map<int, std::shared_ptr<RadarRenderableInterface>>::const_iterator it - = this->allRenderers.cbegin(); - it != this->allRenderers.cend(); - ++it - ) { + for (std::map<int, std::shared_ptr<RadarRenderableInterface>>::const_iterator it = + this->allRenderers.cbegin(); + it != this->allRenderers.cend(); + ++it) { it->second->ResetPosition(); } } - } // namespace RadarScreen -} // namespace UKControllerPlugin + void RadarRenderableCollection::RegisterScreenObject( + const std::function<std::shared_ptr<ScreenObjectInterface>(int)>& objectGenerator) + { + int screenObjectId = nextScreenObjectId++; + screenObjects[screenObjectId] = objectGenerator(screenObjectId); + } + } // namespace RadarScreen +} // namespace UKControllerPlugin diff --git a/src/plugin/radarscreen/RadarRenderableCollection.h b/src/plugin/radarscreen/RadarRenderableCollection.h index c1b2c0427..9f4bd5279 100644 --- a/src/plugin/radarscreen/RadarRenderableCollection.h +++ b/src/plugin/radarscreen/RadarRenderableCollection.h @@ -9,6 +9,7 @@ namespace UKControllerPlugin { } // namespace Euroscope namespace RadarScreen { class RadarRenderableInterface; + class ScreenObjectInterface; } // namespace RadarScreen } // namespace UKControllerPlugin @@ -38,6 +39,7 @@ namespace UKControllerPlugin::RadarScreen { int renderPhase); auto ReserveRendererIdentifier() -> int; auto ReserveScreenObjectIdentifier(int rendererId) -> int; + void RegisterScreenObject(const std::function<std::shared_ptr<ScreenObjectInterface>(int)>& objectGenerator); void Render( int phase, UKControllerPlugin::Windows::GdiGraphicsInterface& graphics, @@ -83,6 +85,7 @@ namespace UKControllerPlugin::RadarScreen { // Maps a given screen object ID to a given renderer. std::map<int, int> screenObjectMap; + std::map<int, std::shared_ptr<ScreenObjectInterface>> screenObjects; // The next renderer ID available for use - used to link screen objects to classes int nextRendererId; diff --git a/src/plugin/radarscreen/ScreenObjectInterface.cpp b/src/plugin/radarscreen/ScreenObjectInterface.cpp new file mode 100644 index 000000000..139fc7019 --- /dev/null +++ b/src/plugin/radarscreen/ScreenObjectInterface.cpp @@ -0,0 +1,20 @@ +#include "ScreenObjectInterface.h" + +namespace UKControllerPlugin::RadarScreen { + + ScreenObjectInterface::~ScreenObjectInterface() = default; + + void ScreenObjectInterface::LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, const std::string& description, POINT mousePosition) + { + } + + void ScreenObjectInterface::RightClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, const std::string& objectDescription) + { + } + + void ScreenObjectInterface::Drag(const std::string& objectDescription, RECT position) + { + } +} // namespace UKControllerPlugin::RadarScreen diff --git a/src/plugin/radarscreen/ScreenObjectInterface.h b/src/plugin/radarscreen/ScreenObjectInterface.h new file mode 100644 index 000000000..1f93734c3 --- /dev/null +++ b/src/plugin/radarscreen/ScreenObjectInterface.h @@ -0,0 +1,36 @@ +#pragma once + +namespace UKControllerPlugin::Euroscope { + class EuroscopeRadarLoopbackInterface; +} // namespace UKControllerPlugin::Euroscope + +namespace UKControllerPlugin::RadarScreen { + + /** + * A screen object that can be clicked or dragged + */ + class ScreenObjectInterface + { + public: + virtual ~ScreenObjectInterface(); + /* + Called when a screen object is left clicked on. + */ + virtual void LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, + const std::string& description, + POINT mousePosition); + + /* + Called when a screen object is right clicked on. + */ + virtual void + RightClick(Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, const std::string& objectDescription); + + /* + Called when an object is moved. + */ + virtual void Drag(const std::string& objectDescription, RECT position); + }; + +} // namespace UKControllerPlugin::RadarScreen From 2250342cf88c9cc71110460fb3c6fff9629c0592 Mon Sep 17 00:00:00 2001 From: Andy Ford <andyford993@gmail.com> Date: Sun, 5 Jun 2022 10:53:08 +0100 Subject: [PATCH 15/18] Make it horizontal --- src/plugin/CMakeLists.txt | 2 +- src/plugin/components/ClickableArea.cpp | 6 ++ src/plugin/components/Scrollbar.cpp | 69 ++++++++++--------- src/plugin/components/ScrollbarClickspot.cpp | 16 +++-- src/plugin/components/ScrollbarClickspot.h | 3 + src/plugin/components/ScrollbarFactory.cpp | 4 +- src/plugin/components/StandardButtons.cpp | 21 ++---- src/plugin/graphics/DrawTriangle.cpp | 24 +++++++ src/plugin/graphics/DrawTriangle.h | 10 +++ src/plugin/mapping/MappingOptionsRenderer.cpp | 8 ++- .../radarscreen/RadarRenderableCollection.cpp | 6 +- 11 files changed, 109 insertions(+), 60 deletions(-) create mode 100644 src/plugin/graphics/DrawTriangle.cpp create mode 100644 src/plugin/graphics/DrawTriangle.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index c9927bdc2..0dcab1370 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -264,7 +264,7 @@ set(src__graphics "graphics/GdiGraphicsWrapper.cpp" "graphics/GdiGraphicsWrapper.h" "graphics/GdiplusBrushes.h" - graphics/FontManager.cpp graphics/FontManager.h graphics/StringFormatManager.cpp graphics/StringFormatManager.h) + graphics/FontManager.cpp graphics/FontManager.h graphics/StringFormatManager.cpp graphics/StringFormatManager.h graphics/DrawTriangle.cpp graphics/DrawTriangle.h) source_group("src\\graphics" FILES ${src__graphics}) set(src__handoff diff --git a/src/plugin/components/ClickableArea.cpp b/src/plugin/components/ClickableArea.cpp index 38eb3c42d..cd3c31fe9 100644 --- a/src/plugin/components/ClickableArea.cpp +++ b/src/plugin/components/ClickableArea.cpp @@ -24,6 +24,12 @@ namespace UKControllerPlugin::Components { Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const { std::shared_ptr<Gdiplus::Matrix> transform = graphics.GetTransform(); + auto xTransform = transform->OffsetX(); + auto yTransform = transform->OffsetY(); + xTransform = yTransform; + yTransform = xTransform; + auto pen = std::make_shared<Gdiplus::Pen>(Gdiplus::Color(255, 0, 0)); + graphics.DrawRect(area, *pen); radarScreen.RegisterScreenObject( this->screenObjectId, this->screenObjectDescription, diff --git a/src/plugin/components/Scrollbar.cpp b/src/plugin/components/Scrollbar.cpp index 499db68a3..f32c3ea47 100644 --- a/src/plugin/components/Scrollbar.cpp +++ b/src/plugin/components/Scrollbar.cpp @@ -26,41 +26,44 @@ namespace UKControllerPlugin::Components { void Scrollbar::Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { - if (isHorizontal || !isHorizontal) { - graphics.FillRect(area, *backgroundBrush); - } + auto yTranslate = isHorizontal ? area.GetTop() + area.Width : area.GetTop(); + graphics.Translated(area.GetLeft(), yTranslate, [&graphics, this, &radarScreen] { + graphics.Rotated(Gdiplus::REAL(isHorizontal ? -90 : 0), [&graphics, this, &radarScreen] { + graphics.FillRect(Gdiplus::Rect{0, 0, area.Width, area.Height}, *backgroundBrush); + graphics.Translated(0, area.Width * options->Notch(), [&graphics, this]() { + graphics.FillRect( + Gdiplus::Rect{ + 0, + 0, + area.Width, + area.Width, + }, + *progressBarBrush); + }); - // Translated clickspots - decrementClickspot->Draw( - { - area.GetLeft(), - area.GetTop(), - area.Width, - area.Width, - }, - graphics, - radarScreen); + // Translated clickspots + decrementClickspot->Draw( + { + 0, + 0, + area.Width, + area.Width, + }, + graphics, + radarScreen); - incrementClickspot->Draw( - { - area.GetLeft(), - area.GetBottom() - area.Width, - area.Width, - area.Width, - }, - graphics, - radarScreen); - - // Progress bar - graphics.Translated(area.GetLeft(), area.GetTop() + (area.Width * options->Notch()), [&graphics, this]() { - graphics.FillRect( - Gdiplus::Rect{ - 0, - 0, - area.Width, - area.Width, - }, - *progressBarBrush); + graphics.Translated(0, area.Height - area.Width, [this, &graphics, &radarScreen] { + incrementClickspot->Draw( + { + 0, + 0, + area.Width, + area.Width, + }, + graphics, + radarScreen); + }); + }); }); } diff --git a/src/plugin/components/ScrollbarClickspot.cpp b/src/plugin/components/ScrollbarClickspot.cpp index 4a3626bbb..5fed7f7ec 100644 --- a/src/plugin/components/ScrollbarClickspot.cpp +++ b/src/plugin/components/ScrollbarClickspot.cpp @@ -1,13 +1,14 @@ #include "ClickableArea.h" #include "ScrollbarClickspot.h" -#include "StandardButtons.h" +#include "graphics/DrawTriangle.h" #include "graphics/GdiGraphicsInterface.h" namespace UKControllerPlugin::Components { ScrollbarClickspot::ScrollbarClickspot(int screenObjectId, std::function<void()> clicked, bool increments) : clicked(std::move(std::move(clicked))), increments(increments), - clickableArea(ClickableArea::Create({}, screenObjectId, "scrollbarClickspot", false)) + clickableArea(ClickableArea::Create({}, screenObjectId, "scrollbarClickspot", false)), + brush(std::make_shared<Gdiplus::SolidBrush>(Gdiplus::Color(255, 255, 255))) { } @@ -16,9 +17,14 @@ namespace UKControllerPlugin::Components { Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { - graphics.Translated(area.GetLeft(), area.GetTop(), [this, &graphics, &area] { - CollapseButton([this]() { return increments; })(graphics, {0, 0, area.Width, area.Height}); - }); + if (horizontal) { + } + graphics.Translated( + Graphics::TriangleDrawDimensions(), Graphics::TriangleDrawDimensions(), [this, &graphics, &area] { + graphics.Rotated(Gdiplus::REAL((increments ? 180 : 0)), [this, &graphics, &area] { + Graphics::FillTriangle(graphics, *brush, area); + }); + }); clickableArea->WithPosition(area); clickableArea->Apply(graphics, radarScreen); } diff --git a/src/plugin/components/ScrollbarClickspot.h b/src/plugin/components/ScrollbarClickspot.h index 30e3c5f96..04b8eefd9 100644 --- a/src/plugin/components/ScrollbarClickspot.h +++ b/src/plugin/components/ScrollbarClickspot.h @@ -40,5 +40,8 @@ namespace UKControllerPlugin::Components { // The actual clickspot std::shared_ptr<ClickableArea> clickableArea; + + // Brush + std::shared_ptr<Gdiplus::Brush> brush; }; } // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarFactory.cpp b/src/plugin/components/ScrollbarFactory.cpp index 4351417d6..050731a65 100644 --- a/src/plugin/components/ScrollbarFactory.cpp +++ b/src/plugin/components/ScrollbarFactory.cpp @@ -26,7 +26,7 @@ namespace UKControllerPlugin::Components { { auto options = std::make_shared<ScrollbarOptions>(notches); std::shared_ptr<ScrollbarClickspot> incrementClickspot; - radarRenderables.RegisterScreenObject([&incrementClickspot, options](int screenObjectId) { + radarRenderables.RegisterScreenObject([&incrementClickspot, options, horizontal](int screenObjectId) { incrementClickspot = std::make_shared<ScrollbarClickspot>( screenObjectId, [options]() { options->Increment(); }, true); @@ -34,7 +34,7 @@ namespace UKControllerPlugin::Components { }); std::shared_ptr<ScrollbarClickspot> decrementClickspot; - radarRenderables.RegisterScreenObject([&decrementClickspot, options](int screenObjectId) { + radarRenderables.RegisterScreenObject([&decrementClickspot, options, horizontal](int screenObjectId) { decrementClickspot = std::make_shared<ScrollbarClickspot>( screenObjectId, [options]() { options->Decrement(); }, false); diff --git a/src/plugin/components/StandardButtons.cpp b/src/plugin/components/StandardButtons.cpp index 333c03409..92d97d001 100644 --- a/src/plugin/components/StandardButtons.cpp +++ b/src/plugin/components/StandardButtons.cpp @@ -1,4 +1,5 @@ #include "StandardButtons.h" +#include "graphics/DrawTriangle.h" #include "graphics/GdiGraphicsInterface.h" namespace UKControllerPlugin::Components { @@ -9,9 +10,6 @@ namespace UKControllerPlugin::Components { Gdiplus::Point closeBottomLeft = {-5, 5}; Gdiplus::Point closeTopRight = {5, -5}; - // Coordinates of the collapse triangle - Gdiplus::Point collapsePoints[3] = {Gdiplus::Point(0, -5), Gdiplus::Point(5, 5), Gdiplus::Point(-5, 5)}; - // The standard button sizing Gdiplus::REAL buttonSize(10); @@ -53,20 +51,15 @@ namespace UKControllerPlugin::Components { { auto brush = std::make_shared<Gdiplus::SolidBrush>(colour); return [brush, stateFunction](Windows::GdiGraphicsInterface& graphics, const Gdiplus::Rect& drawArea) { - Gdiplus::REAL scaleX = drawArea.Width / buttonSize; - Gdiplus::REAL scaleY = drawArea.Height / buttonSize; - graphics.Translated( - static_cast<Gdiplus::REAL>(5) * scaleX, - static_cast<Gdiplus::REAL>(5) * scaleY, - [&graphics, &stateFunction, &brush, &scaleX, &scaleY] { + static_cast<Gdiplus::REAL>(Graphics::TriangleDrawDimensions() / 2) * drawArea.Width / + Graphics::TriangleDrawDimensions(), + static_cast<Gdiplus::REAL>(Graphics::TriangleDrawDimensions() / 2) * drawArea.Height / + Graphics::TriangleDrawDimensions(), + [&graphics, &stateFunction, &brush, drawArea] { graphics.Rotated( stateFunction() ? static_cast<Gdiplus::REAL>(180) : static_cast<Gdiplus::REAL>(0), - [&graphics, &brush, &scaleX, &scaleY]() { - graphics.Scaled(scaleX, scaleY, [&graphics, &brush]() { - graphics.FillPolygon(collapsePoints, *brush, 3); - }); - }); + [&graphics, &brush, drawArea]() { Graphics::FillTriangle(graphics, *brush, drawArea); }); }); }; } diff --git a/src/plugin/graphics/DrawTriangle.cpp b/src/plugin/graphics/DrawTriangle.cpp new file mode 100644 index 000000000..f595779a5 --- /dev/null +++ b/src/plugin/graphics/DrawTriangle.cpp @@ -0,0 +1,24 @@ +#include "DrawTriangle.h" +#include "graphics/GdiGraphicsInterface.h" + +namespace UKControllerPlugin::Graphics { + + // Coordinates of the triangle + Gdiplus::Point trianglePoints[3] = {Gdiplus::Point(0, -5), Gdiplus::Point(5, 5), Gdiplus::Point(-5, 5)}; + + // The default draw size of a triangle + Gdiplus::REAL triangleSize(10); + + void FillTriangle(Windows::GdiGraphicsInterface& graphics, Gdiplus::Brush& brush, const Gdiplus::Rect& drawArea) + { + Gdiplus::REAL scaleX = drawArea.Width / triangleSize; + Gdiplus::REAL scaleY = drawArea.Height / triangleSize; + + graphics.Scaled(scaleX, scaleY, [&graphics, &brush]() { graphics.FillPolygon(trianglePoints, brush, 3); }); + } + + auto TriangleDrawDimensions() -> Gdiplus::REAL + { + return triangleSize; + } +} // namespace UKControllerPlugin::Graphics diff --git a/src/plugin/graphics/DrawTriangle.h b/src/plugin/graphics/DrawTriangle.h new file mode 100644 index 000000000..42d650606 --- /dev/null +++ b/src/plugin/graphics/DrawTriangle.h @@ -0,0 +1,10 @@ +#pragma once + +namespace UKControllerPlugin::Windows { + class GdiGraphicsInterface; +} // namespace UKControllerPlugin::Windows + +namespace UKControllerPlugin::Graphics { + void FillTriangle(Windows::GdiGraphicsInterface& graphics, Gdiplus::Brush& brush, const Gdiplus::Rect& drawArea); + [[nodiscard]] auto TriangleDrawDimensions() -> Gdiplus::REAL; +} // namespace UKControllerPlugin::Graphics diff --git a/src/plugin/mapping/MappingOptionsRenderer.cpp b/src/plugin/mapping/MappingOptionsRenderer.cpp index 67e2b8c1e..b612b369b 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.cpp +++ b/src/plugin/mapping/MappingOptionsRenderer.cpp @@ -1,6 +1,7 @@ #include "MappingOptionsRenderer.h" #include "MappingRenderOptions.h" #include "components/Checkbox.h" +#include "components/ClickableArea.h" #include "components/Scrollbar.h" #include "components/ScrollbarFactory.h" #include "components/Title.h" @@ -14,7 +15,7 @@ namespace UKControllerPlugin::Mapping { std::shared_ptr<MappingRenderOptions> mappingOptions, const Components::ScrollbarFactory& scrollbarFactory, int screenObjectId) - : mappingOptions(mappingOptions), vrpScrollbar(scrollbarFactory.MakeHorizontal({10, 110, 25, 300}, 10)), + : mappingOptions(mappingOptions), vrpScrollbar(scrollbarFactory.MakeVertical({10, 110, 25, 300}, 10)), screenObjectId(screenObjectId), backgroundBrush(std::make_shared<Gdiplus::SolidBrush>(Gdiplus::Color(170, 64, 64, 64))) { @@ -45,9 +46,12 @@ namespace UKControllerPlugin::Mapping { { graphics.Translated(50, 50, [&graphics, &radarScreen, this]() { const auto viewport = radarScreen.GetRadarViewport(); + // Background const auto width = viewport.right - viewport.left - 100; - graphics.FillRect(Gdiplus::Rect{0, 0, width, viewport.bottom - viewport.top - 100}, *backgroundBrush); + Gdiplus::Rect backgroundRect{0, 0, width, viewport.bottom - viewport.top - 100}; + graphics.FillRect(backgroundRect, *backgroundBrush); + Components::ClickableArea::Create(backgroundRect, -9999, "", false)->Apply(graphics, radarScreen); // Titlebar Components::TitleBar::Create(L"Mapping Options", Gdiplus::Rect{0, 0, width, 25}) diff --git a/src/plugin/radarscreen/RadarRenderableCollection.cpp b/src/plugin/radarscreen/RadarRenderableCollection.cpp index 8e2723135..38419d47a 100644 --- a/src/plugin/radarscreen/RadarRenderableCollection.cpp +++ b/src/plugin/radarscreen/RadarRenderableCollection.cpp @@ -77,7 +77,7 @@ namespace UKControllerPlugin { if (this->screenObjectMap.contains(objectId)) { this->allRenderers.at(this->screenObjectMap.at(objectId)) ->LeftClick(radarScreen, objectId, objectDescription, mousePos, itemArea); - } else { + } else if (this->screenObjects.contains(objectId)) { this->screenObjects.at(objectId)->LeftClick(radarScreen, objectDescription, mousePos); } } @@ -89,7 +89,7 @@ namespace UKControllerPlugin { { if (this->screenObjectMap.contains(objectId)) { this->allRenderers.at(this->screenObjectMap.at(objectId))->Move(position, objectDes); - } else { + } else if (this->screenObjects.contains(objectId)) { this->screenObjects.at(objectId)->Drag(objectDes, position); } } @@ -181,7 +181,7 @@ namespace UKControllerPlugin { if (this->screenObjectMap.contains(objectId)) { this->allRenderers.at(this->screenObjectMap.at(objectId)) ->RightClick(objectId, objectDescription, radarScreen); - } else { + } else if (this->screenObjects.contains(objectId)) { this->screenObjects.at(objectId)->RightClick(radarScreen, objectDescription); } } From 681e48361c8ae94078ac70655692264fc6cfac84 Mon Sep 17 00:00:00 2001 From: Andy Ford <andyford993@gmail.com> Date: Sun, 5 Jun 2022 11:05:19 +0100 Subject: [PATCH 16/18] Alignment --- src/plugin/components/ScrollbarClickspot.cpp | 8 ++++---- src/plugin/components/ScrollbarFactory.cpp | 4 ++-- src/plugin/graphics/DrawTriangle.cpp | 17 +++++++++++++---- src/plugin/graphics/DrawTriangle.h | 2 ++ 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/plugin/components/ScrollbarClickspot.cpp b/src/plugin/components/ScrollbarClickspot.cpp index 5fed7f7ec..8e9ad315d 100644 --- a/src/plugin/components/ScrollbarClickspot.cpp +++ b/src/plugin/components/ScrollbarClickspot.cpp @@ -17,11 +17,11 @@ namespace UKControllerPlugin::Components { Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) { - if (horizontal) { - } graphics.Translated( - Graphics::TriangleDrawDimensions(), Graphics::TriangleDrawDimensions(), [this, &graphics, &area] { - graphics.Rotated(Gdiplus::REAL((increments ? 180 : 0)), [this, &graphics, &area] { + Graphics::TriangleDrawDimensions() * (Graphics::TriangleXScale(area) / 2), + Graphics::TriangleDrawDimensions() * (Graphics::TriangleYScale(area) / 2), + [this, &graphics, &area] { + graphics.Rotated(Gdiplus::REAL(increments ? 180 : 0), [this, &graphics, &area] { Graphics::FillTriangle(graphics, *brush, area); }); }); diff --git a/src/plugin/components/ScrollbarFactory.cpp b/src/plugin/components/ScrollbarFactory.cpp index 050731a65..4351417d6 100644 --- a/src/plugin/components/ScrollbarFactory.cpp +++ b/src/plugin/components/ScrollbarFactory.cpp @@ -26,7 +26,7 @@ namespace UKControllerPlugin::Components { { auto options = std::make_shared<ScrollbarOptions>(notches); std::shared_ptr<ScrollbarClickspot> incrementClickspot; - radarRenderables.RegisterScreenObject([&incrementClickspot, options, horizontal](int screenObjectId) { + radarRenderables.RegisterScreenObject([&incrementClickspot, options](int screenObjectId) { incrementClickspot = std::make_shared<ScrollbarClickspot>( screenObjectId, [options]() { options->Increment(); }, true); @@ -34,7 +34,7 @@ namespace UKControllerPlugin::Components { }); std::shared_ptr<ScrollbarClickspot> decrementClickspot; - radarRenderables.RegisterScreenObject([&decrementClickspot, options, horizontal](int screenObjectId) { + radarRenderables.RegisterScreenObject([&decrementClickspot, options](int screenObjectId) { decrementClickspot = std::make_shared<ScrollbarClickspot>( screenObjectId, [options]() { options->Decrement(); }, false); diff --git a/src/plugin/graphics/DrawTriangle.cpp b/src/plugin/graphics/DrawTriangle.cpp index f595779a5..6f22e4104 100644 --- a/src/plugin/graphics/DrawTriangle.cpp +++ b/src/plugin/graphics/DrawTriangle.cpp @@ -11,14 +11,23 @@ namespace UKControllerPlugin::Graphics { void FillTriangle(Windows::GdiGraphicsInterface& graphics, Gdiplus::Brush& brush, const Gdiplus::Rect& drawArea) { - Gdiplus::REAL scaleX = drawArea.Width / triangleSize; - Gdiplus::REAL scaleY = drawArea.Height / triangleSize; - - graphics.Scaled(scaleX, scaleY, [&graphics, &brush]() { graphics.FillPolygon(trianglePoints, brush, 3); }); + graphics.Scaled(TriangleXScale(drawArea), TriangleYScale(drawArea), [&graphics, &brush]() { + graphics.FillPolygon(trianglePoints, brush, 3); + }); } auto TriangleDrawDimensions() -> Gdiplus::REAL { return triangleSize; } + + auto TriangleXScale(const Gdiplus::Rect& drawArea) -> Gdiplus::REAL + { + return drawArea.Width / TriangleDrawDimensions(); + } + + auto TriangleYScale(const Gdiplus::Rect& drawArea) -> Gdiplus::REAL + { + return drawArea.Height / TriangleDrawDimensions(); + } } // namespace UKControllerPlugin::Graphics diff --git a/src/plugin/graphics/DrawTriangle.h b/src/plugin/graphics/DrawTriangle.h index 42d650606..8001e9a0d 100644 --- a/src/plugin/graphics/DrawTriangle.h +++ b/src/plugin/graphics/DrawTriangle.h @@ -7,4 +7,6 @@ namespace UKControllerPlugin::Windows { namespace UKControllerPlugin::Graphics { void FillTriangle(Windows::GdiGraphicsInterface& graphics, Gdiplus::Brush& brush, const Gdiplus::Rect& drawArea); [[nodiscard]] auto TriangleDrawDimensions() -> Gdiplus::REAL; + [[nodiscard]] auto TriangleXScale(const Gdiplus::Rect& drawArea) -> Gdiplus::REAL; + [[nodiscard]] auto TriangleYScale(const Gdiplus::Rect& drawArea) -> Gdiplus::REAL; } // namespace UKControllerPlugin::Graphics From 3536a69c8e0505d3333eb844079860c80fdff8fb Mon Sep 17 00:00:00 2001 From: Andy Ford <andyford993@gmail.com> Date: Sun, 5 Jun 2022 11:35:05 +0100 Subject: [PATCH 17/18] Clicks --- src/plugin/components/ClickableArea.cpp | 17 ++++++++--------- src/plugin/graphics/GdiGraphicsInterface.h | 1 + src/plugin/graphics/GdiGraphicsWrapper.cpp | 11 +++++++++++ src/plugin/graphics/GdiGraphicsWrapper.h | 4 ++++ src/plugin/mapping/MappingOptionsRenderer.cpp | 2 +- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/plugin/components/ClickableArea.cpp b/src/plugin/components/ClickableArea.cpp index cd3c31fe9..8f4eececd 100644 --- a/src/plugin/components/ClickableArea.cpp +++ b/src/plugin/components/ClickableArea.cpp @@ -23,21 +23,20 @@ namespace UKControllerPlugin::Components { void ClickableArea::Apply( Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const { - std::shared_ptr<Gdiplus::Matrix> transform = graphics.GetTransform(); - auto xTransform = transform->OffsetX(); - auto yTransform = transform->OffsetY(); - xTransform = yTransform; - yTransform = xTransform; + std::shared_ptr<Gdiplus::Matrix> transform = graphics.GetTotalTransform(); + Gdiplus::Point points[2]{{area.GetLeft(), area.GetTop()}, {area.GetRight(), area.GetBottom()}}; + transform->TransformPoints(points, 2); + auto pen = std::make_shared<Gdiplus::Pen>(Gdiplus::Color(255, 0, 0)); graphics.DrawRect(area, *pen); radarScreen.RegisterScreenObject( this->screenObjectId, this->screenObjectDescription, RECT{ - static_cast<LONG>(this->area.GetLeft() + transform->OffsetX()), - static_cast<LONG>(this->area.GetTop() + transform->OffsetY()), - static_cast<LONG>(this->area.GetRight() + transform->OffsetX()), - static_cast<LONG>(this->area.GetBottom() + transform->OffsetY()), + static_cast<LONG>(points[0].X < points[1].X ? points[0].X : points[1].X), + static_cast<LONG>(points[0].Y < points[1].Y ? points[0].Y : points[1].Y), + static_cast<LONG>(points[0].X < points[1].X ? points[1].X : points[0].X), + static_cast<LONG>(points[0].Y < points[1].Y ? points[1].Y : points[0].Y), }, this->draggable); } diff --git a/src/plugin/graphics/GdiGraphicsInterface.h b/src/plugin/graphics/GdiGraphicsInterface.h index 6f79491d2..f59588120 100644 --- a/src/plugin/graphics/GdiGraphicsInterface.h +++ b/src/plugin/graphics/GdiGraphicsInterface.h @@ -45,6 +45,7 @@ namespace UKControllerPlugin { virtual void Clipped(Gdiplus::Region& clipRegion, std::function<void()> drawFunction) = 0; virtual void Translated(Gdiplus::REAL x, Gdiplus::REAL y, std::function<void()> drawFunction) = 0; virtual std::shared_ptr<Gdiplus::Matrix> GetTransform() = 0; + virtual std::shared_ptr<Gdiplus::Matrix> GetTotalTransform() = 0; virtual Gdiplus::RectF GetClipBounds() = 0; virtual void Scaled(Gdiplus::REAL x, Gdiplus::REAL y, std::function<void()> drawFunction) = 0; virtual void Rotated(Gdiplus::REAL angle, std::function<void()> drawFunction) = 0; diff --git a/src/plugin/graphics/GdiGraphicsWrapper.cpp b/src/plugin/graphics/GdiGraphicsWrapper.cpp index ee0f7559c..814aa20a6 100644 --- a/src/plugin/graphics/GdiGraphicsWrapper.cpp +++ b/src/plugin/graphics/GdiGraphicsWrapper.cpp @@ -186,7 +186,9 @@ namespace UKControllerPlugin { { const auto container = this->api->BeginContainer(); this->api->TranslateTransform(x, y); + this->fullTransform.Translate(x, y); drawFunction(); + this->fullTransform.Translate(-x, -y); this->api->EndContainer(container); } @@ -194,7 +196,9 @@ namespace UKControllerPlugin { { const auto container = this->api->BeginContainer(); this->api->ScaleTransform(x, y); + this->fullTransform.Scale(x, y); drawFunction(); + this->fullTransform.Scale(1 / x, 1 / y); this->api->EndContainer(container); } @@ -205,6 +209,11 @@ namespace UKControllerPlugin { return std::shared_ptr<Gdiplus::Matrix>(transform.Clone()); } + std::shared_ptr<Gdiplus::Matrix> GdiGraphicsWrapper::GetTotalTransform() + { + return std::shared_ptr<Gdiplus::Matrix>(fullTransform.Clone()); + } + Gdiplus::RectF GdiGraphicsWrapper::GetClipBounds() { Gdiplus::RectF bounds; @@ -216,7 +225,9 @@ namespace UKControllerPlugin { { const auto container = this->api->BeginContainer(); this->api->RotateTransform(angle); + this->fullTransform.Rotate(angle); drawFunction(); + this->fullTransform.Rotate(-angle); this->api->EndContainer(container); } diff --git a/src/plugin/graphics/GdiGraphicsWrapper.h b/src/plugin/graphics/GdiGraphicsWrapper.h index 77c64e9ab..6b024aa3d 100644 --- a/src/plugin/graphics/GdiGraphicsWrapper.h +++ b/src/plugin/graphics/GdiGraphicsWrapper.h @@ -44,6 +44,7 @@ namespace UKControllerPlugin { void Translated(Gdiplus::REAL x, Gdiplus::REAL y, std::function<void()> drawFunction) override; void Scaled(Gdiplus::REAL x, Gdiplus::REAL y, std::function<void()> drawFunction) override; std::shared_ptr<Gdiplus::Matrix> GetTransform() override; + std::shared_ptr<Gdiplus::Matrix> GetTotalTransform() override; Gdiplus::RectF GetClipBounds() override; void Rotated(Gdiplus::REAL angle, std::function<void()> drawFunction) override; void FillPolygon(Gdiplus::Point* points, const Gdiplus::Brush& brush, int numPoints) override; @@ -53,6 +54,9 @@ namespace UKControllerPlugin { private: std::unique_ptr<Gdiplus::Graphics> api; + + // The full transform as it currently is + Gdiplus::Matrix fullTransform; }; } // namespace Windows } // namespace UKControllerPlugin diff --git a/src/plugin/mapping/MappingOptionsRenderer.cpp b/src/plugin/mapping/MappingOptionsRenderer.cpp index b612b369b..9c2e4e504 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.cpp +++ b/src/plugin/mapping/MappingOptionsRenderer.cpp @@ -15,7 +15,7 @@ namespace UKControllerPlugin::Mapping { std::shared_ptr<MappingRenderOptions> mappingOptions, const Components::ScrollbarFactory& scrollbarFactory, int screenObjectId) - : mappingOptions(mappingOptions), vrpScrollbar(scrollbarFactory.MakeVertical({10, 110, 25, 300}, 10)), + : mappingOptions(mappingOptions), vrpScrollbar(scrollbarFactory.MakeHorizontal({10, 110, 25, 300}, 10)), screenObjectId(screenObjectId), backgroundBrush(std::make_shared<Gdiplus::SolidBrush>(Gdiplus::Color(170, 64, 64, 64))) { From deeaea13c9d6d8d1d82363321f801a5554228f64 Mon Sep 17 00:00:00 2001 From: Andy Ford <andyford993@gmail.com> Date: Sun, 5 Jun 2022 14:08:27 +0100 Subject: [PATCH 18/18] Checkbox things --- src/plugin/CMakeLists.txt | 4 +- src/plugin/components/Checkbox.cpp | 37 +++++++++++++++---- src/plugin/components/Checkbox.h | 23 +++++++++--- .../components/CheckboxProviderInterface.cpp | 6 +++ .../components/CheckboxProviderInterface.h | 15 ++++++++ .../components/ScrollableCheckboxes.cpp | 5 +++ src/plugin/components/ScrollableCheckboxes.h | 34 +++++++++++++++++ src/plugin/components/ScrollbarClickspot.cpp | 7 +++- src/plugin/components/ScrollbarClickspot.h | 4 ++ src/plugin/components/ScrollbarFactory.cpp | 20 +++------- .../mapping/MappingBootstrapProvider.cpp | 11 ++++-- src/plugin/mapping/MappingOptionsRenderer.cpp | 12 +++--- src/plugin/mapping/MappingOptionsRenderer.h | 11 +++--- .../VisualReferencePointCheckboxProvider.cpp | 22 +++++++++++ .../VisualReferencePointCheckboxProvider.h | 21 +++++++++++ .../radarscreen/RadarRenderableCollection.cpp | 11 ++++-- .../radarscreen/RadarRenderableCollection.h | 3 +- .../radarscreen/ScreenObjectInterface.h | 3 ++ test/plugin/CMakeLists.txt | 2 +- 19 files changed, 201 insertions(+), 50 deletions(-) create mode 100644 src/plugin/components/CheckboxProviderInterface.cpp create mode 100644 src/plugin/components/CheckboxProviderInterface.h create mode 100644 src/plugin/components/ScrollableCheckboxes.cpp create mode 100644 src/plugin/components/ScrollableCheckboxes.h create mode 100644 src/plugin/mapping/VisualReferencePointCheckboxProvider.cpp create mode 100644 src/plugin/mapping/VisualReferencePointCheckboxProvider.h diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index 0dcab1370..0bc47a549 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -94,7 +94,7 @@ set(src__components "components/StandardButtons.h" "components/TitleBar.cpp" "components/TitleBar.h" - components/CollapsibleWindowTitleBar.cpp components/CollapsibleWindowTitleBar.h components/Title.cpp components/Title.h components/Checkbox.cpp components/Checkbox.h components/Scrollbar.cpp components/Scrollbar.h components/ScrollbarFactory.cpp components/ScrollbarFactory.h components/ScrollbarClickspot.cpp components/ScrollbarClickspot.h components/ScrollbarOptions.cpp components/ScrollbarOptions.h) + components/CollapsibleWindowTitleBar.cpp components/CollapsibleWindowTitleBar.h components/Title.cpp components/Title.h components/Checkbox.cpp components/Checkbox.h components/Scrollbar.cpp components/Scrollbar.h components/ScrollbarFactory.cpp components/ScrollbarFactory.h components/ScrollbarClickspot.cpp components/ScrollbarClickspot.h components/ScrollbarOptions.cpp components/ScrollbarOptions.h components/ScrollableCheckboxes.cpp components/ScrollableCheckboxes.h components/CheckboxProviderInterface.cpp components/CheckboxProviderInterface.h) source_group("src\\components" FILES ${src__components}) set(src__controller @@ -520,7 +520,7 @@ set(src__mapping mapping/DisplayRulesetFactory.cpp mapping/DisplayRulesetFactory.h mapping/DisplayRulesetFactoryInterface.h mapping/DisplayRulesetAggregatorFactory.cpp mapping/DisplayRulesetAggregatorFactory.h - mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp mapping/VisualReferencePointDefaultDisplayRulesetFactory.h mapping/DefaultDisplayRulesetDelegatorFactory.cpp mapping/DefaultDisplayRulesetDelegatorFactory.h mapping/DisplayRulesetFactoryFactory.cpp mapping/DisplayRulesetFactoryFactory.h mapping/MappingElementDrawerFactoryFactory.cpp mapping/MappingElementDrawerFactoryFactory.h mapping/MappingElementTypes.cpp mapping/MappingElementTypes.h mapping/MappingRenderOptionsAsrLoader.cpp mapping/MappingRenderOptionsAsrLoader.h) + mapping/VisualReferencePointDefaultDisplayRulesetFactory.cpp mapping/VisualReferencePointDefaultDisplayRulesetFactory.h mapping/DefaultDisplayRulesetDelegatorFactory.cpp mapping/DefaultDisplayRulesetDelegatorFactory.h mapping/DisplayRulesetFactoryFactory.cpp mapping/DisplayRulesetFactoryFactory.h mapping/MappingElementDrawerFactoryFactory.cpp mapping/MappingElementDrawerFactoryFactory.h mapping/MappingElementTypes.cpp mapping/MappingElementTypes.h mapping/MappingRenderOptionsAsrLoader.cpp mapping/MappingRenderOptionsAsrLoader.h mapping/VisualReferencePointCheckboxProvider.cpp mapping/VisualReferencePointCheckboxProvider.h) source_group("src\\mapping" FILES ${src__mapping}) set(src__message diff --git a/src/plugin/components/Checkbox.cpp b/src/plugin/components/Checkbox.cpp index 812b1d005..eac6fd7e9 100644 --- a/src/plugin/components/Checkbox.cpp +++ b/src/plugin/components/Checkbox.cpp @@ -1,30 +1,31 @@ #include "Checkbox.h" +#include "CheckboxProviderInterface.h" #include "ClickableArea.h" #include "graphics/FontManager.h" #include "graphics/GdiGraphicsInterface.h" #include "graphics/StringFormatManager.h" +#include "helper/HelperFunctions.h" namespace UKControllerPlugin::Components { - Checkbox::Checkbox(std::wstring label, POINT position, int screenObjectId, std::string name) - : label(std::move(label)), area(position.x, position.y, DIMENSIONS, DIMENSIONS), - labelArea(area.GetRight() + 10, position.y, 250, DIMENSIONS), + Checkbox::Checkbox(std::shared_ptr<CheckboxProviderInterface> provider, int screenObjectId) + : provider(provider), screenObjectId(screenObjectId), pen(std::make_shared<Gdiplus::Pen>(Gdiplus::Color(255, 255, 255))), brush(std::make_shared<Gdiplus::SolidBrush>(Gdiplus::Color(255, 255, 255))), clickableArea(ClickableArea::Create( Gdiplus::Rect(area.GetLeft(), area.GetTop(), labelArea.GetRight() - area.GetLeft(), labelArea.Height), screenObjectId, - name, + "checkbox" + provider->Label(), false)), font(Graphics::FontManager::Instance().GetDefault()), stringFormat(Graphics::StringFormatManager::Instance().GetLeftAlign()) { } - auto Checkbox::Create(std::wstring label, POINT position, int screenObjectId, std::string name) + auto Checkbox::Create(std::shared_ptr<CheckboxProviderInterface> provider, int screenObjectId) -> std::shared_ptr<Checkbox> { - return std::shared_ptr<Checkbox>(new Checkbox(label, position, screenObjectId, name)); + return std::shared_ptr<Checkbox>(new Checkbox(provider, screenObjectId)); } auto Checkbox::Checked(bool checked) -> std::shared_ptr<Checkbox> @@ -51,6 +52,28 @@ namespace UKControllerPlugin::Components { clickableArea->Apply(graphics, radarScreen); // Label - graphics.DrawString(label, labelArea, *brush, stringFormat, font); + graphics.DrawString( + HelperFunctions::ConvertToWideString(provider->Label()), labelArea, *brush, stringFormat, font); + } + + void Checkbox::LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, const std::string& description, POINT mousePosition) + { + checked = !checked; + provider->StateChanged(checked); + } + + auto Checkbox::WithPosition(POINT position) -> std::shared_ptr<Checkbox> + { + area = {position.x, position.y, DIMENSIONS, DIMENSIONS}; + labelArea = {area.GetRight() + 10, position.y, 250, DIMENSIONS}; + this->clickableArea->WithPosition( + {area.GetLeft(), area.GetTop(), labelArea.GetRight() - area.GetLeft(), labelArea.Height}); + return shared_from_this(); + } + + auto Checkbox::ScreenObjectId() const -> int + { + return screenObjectId; } } // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/Checkbox.h b/src/plugin/components/Checkbox.h index 155bc02d2..b68f3bb69 100644 --- a/src/plugin/components/Checkbox.h +++ b/src/plugin/components/Checkbox.h @@ -1,4 +1,7 @@ #pragma once +#include <string> +#include <windef.h> +#include "radarscreen/ScreenObjectInterface.h" namespace UKControllerPlugin { namespace Euroscope { @@ -10,26 +13,36 @@ namespace UKControllerPlugin { } // namespace UKControllerPlugin namespace UKControllerPlugin::Components { + class CheckboxProviderInterface; class ClickableArea; /** * A checkbox */ - class Checkbox : public std::enable_shared_from_this<Checkbox> + class Checkbox : public std::enable_shared_from_this<Checkbox>, public RadarScreen::ScreenObjectInterface { public: - static auto Create(std::wstring label, POINT position, int screenObjectId, std::string name) + static auto Create(std::shared_ptr<CheckboxProviderInterface> provider, int screenObjectId) -> std::shared_ptr<Checkbox>; auto Checked(bool checked) -> std::shared_ptr<Checkbox>; void Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const; + void LeftClick( + Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, + const std::string& description, + POINT mousePosition) override; + auto ScreenObjectId() const -> int override; + auto WithPosition(POINT position) -> std::shared_ptr<Checkbox>; protected: - Checkbox(std::wstring label, POINT position, int screenObjectId, std::string name); + Checkbox(std::shared_ptr<CheckboxProviderInterface> provider, int screenObjectId); private: - // The label for the checkbox - std::wstring label; + // The provider + std::shared_ptr<CheckboxProviderInterface> provider; + + // The id of the screen object + int screenObjectId; // Clickspot area Gdiplus::Rect area; diff --git a/src/plugin/components/CheckboxProviderInterface.cpp b/src/plugin/components/CheckboxProviderInterface.cpp new file mode 100644 index 000000000..a648ade87 --- /dev/null +++ b/src/plugin/components/CheckboxProviderInterface.cpp @@ -0,0 +1,6 @@ +#include "CheckboxProviderInterface.h" + +namespace UKControllerPlugin::Components { + + CheckboxProviderInterface::~CheckboxProviderInterface() = default; +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/CheckboxProviderInterface.h b/src/plugin/components/CheckboxProviderInterface.h new file mode 100644 index 000000000..8c6f6fb86 --- /dev/null +++ b/src/plugin/components/CheckboxProviderInterface.h @@ -0,0 +1,15 @@ +#pragma once + +namespace UKControllerPlugin::Components { + + /** + * Provides the information required to have a checkbox. + */ + class CheckboxProviderInterface + { + public: + virtual ~CheckboxProviderInterface(); + [[nodiscard]] virtual auto Label() -> std::string = 0; + virtual void StateChanged(bool checked) = 0; + }; +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollableCheckboxes.cpp b/src/plugin/components/ScrollableCheckboxes.cpp new file mode 100644 index 000000000..7bceae9ec --- /dev/null +++ b/src/plugin/components/ScrollableCheckboxes.cpp @@ -0,0 +1,5 @@ +#include "ScrollableCheckboxes.h" + +namespace UKControllerPlugin::Components { + +} // namespace UKControllerPlugin diff --git a/src/plugin/components/ScrollableCheckboxes.h b/src/plugin/components/ScrollableCheckboxes.h new file mode 100644 index 000000000..07c1647fe --- /dev/null +++ b/src/plugin/components/ScrollableCheckboxes.h @@ -0,0 +1,34 @@ +#pragma once + +namespace UKControllerPlugin { + namespace Euroscope { + class EuroscopeRadarLoopbackInterface; + } // namespace Euroscope + namespace Windows { + class GdiGraphicsInterface; + } // namespace Windows +} // namespace UKControllerPlugin + +namespace UKControllerPlugin::Components { + class Checkbox; + class Scrollbar; + + /** + * Multiple checkboxes that have a scrollbar + */ + class ScrollableCheckboxes + { + public: + ScrollableCheckboxes(std::list<std::shared_ptr<Checkbox>> checkboxes, std::shared_ptr<Scrollbar> scrollbar); + void + Draw(Windows::GdiGraphicsInterface& graphics, Euroscope::EuroscopeRadarLoopbackInterface& radarScreen) const; + + private: + // All the checkboxes to display + std::list<std::shared_ptr<Checkbox>> checkboxes; + + // The scrollbar + std::shared_ptr<Scrollbar> scrollbar; + }; + +} // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarClickspot.cpp b/src/plugin/components/ScrollbarClickspot.cpp index 8e9ad315d..0db33d224 100644 --- a/src/plugin/components/ScrollbarClickspot.cpp +++ b/src/plugin/components/ScrollbarClickspot.cpp @@ -6,7 +6,7 @@ namespace UKControllerPlugin::Components { ScrollbarClickspot::ScrollbarClickspot(int screenObjectId, std::function<void()> clicked, bool increments) - : clicked(std::move(std::move(clicked))), increments(increments), + : screenObjectId(screenObjectId), clicked(std::move(std::move(clicked))), increments(increments), clickableArea(ClickableArea::Create({}, screenObjectId, "scrollbarClickspot", false)), brush(std::make_shared<Gdiplus::SolidBrush>(Gdiplus::Color(255, 255, 255))) { @@ -34,4 +34,9 @@ namespace UKControllerPlugin::Components { { clicked(); } + + auto ScrollbarClickspot::ScreenObjectId() const -> int + { + return screenObjectId; + } } // namespace UKControllerPlugin::Components diff --git a/src/plugin/components/ScrollbarClickspot.h b/src/plugin/components/ScrollbarClickspot.h index 04b8eefd9..086afa620 100644 --- a/src/plugin/components/ScrollbarClickspot.h +++ b/src/plugin/components/ScrollbarClickspot.h @@ -30,8 +30,12 @@ namespace UKControllerPlugin::Components { Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, const std::string& description, POINT mousePosition) override; + auto ScreenObjectId() const -> int override; private: + // The id of the screen object + const int screenObjectId; + // What to do when its clicked const std::function<void()> clicked; diff --git a/src/plugin/components/ScrollbarFactory.cpp b/src/plugin/components/ScrollbarFactory.cpp index 4351417d6..1ee8bc4f7 100644 --- a/src/plugin/components/ScrollbarFactory.cpp +++ b/src/plugin/components/ScrollbarFactory.cpp @@ -25,21 +25,13 @@ namespace UKControllerPlugin::Components { -> std::shared_ptr<Scrollbar> { auto options = std::make_shared<ScrollbarOptions>(notches); - std::shared_ptr<ScrollbarClickspot> incrementClickspot; - radarRenderables.RegisterScreenObject([&incrementClickspot, options](int screenObjectId) { - incrementClickspot = std::make_shared<ScrollbarClickspot>( - screenObjectId, [options]() { options->Increment(); }, true); + std::shared_ptr<ScrollbarClickspot> incrementClickspot = std::make_shared<ScrollbarClickspot>( + radarRenderables.ReserveScreenObjectIdentifier(), [options]() { options->Increment(); }, true); + radarRenderables.RegisterScreenObject(incrementClickspot); - return incrementClickspot; - }); - - std::shared_ptr<ScrollbarClickspot> decrementClickspot; - radarRenderables.RegisterScreenObject([&decrementClickspot, options](int screenObjectId) { - decrementClickspot = std::make_shared<ScrollbarClickspot>( - screenObjectId, [options]() { options->Decrement(); }, false); - - return decrementClickspot; - }); + std::shared_ptr<ScrollbarClickspot> decrementClickspot = std::make_shared<ScrollbarClickspot>( + radarRenderables.ReserveScreenObjectIdentifier(), [options]() { options->Decrement(); }, false); + radarRenderables.RegisterScreenObject(decrementClickspot); return std::make_shared<Scrollbar>(area, options, horizontal, decrementClickspot, incrementClickspot); } diff --git a/src/plugin/mapping/MappingBootstrapProvider.cpp b/src/plugin/mapping/MappingBootstrapProvider.cpp index 5365bc380..08ed8bca9 100644 --- a/src/plugin/mapping/MappingBootstrapProvider.cpp +++ b/src/plugin/mapping/MappingBootstrapProvider.cpp @@ -10,8 +10,10 @@ #include "MappingRenderOptions.h" #include "MappingRenderOptionsAsrLoader.h" #include "ToggleMappingOptionsRender.h" +#include "VisualReferencePointCheckboxProvider.h" #include "bootstrap/ModuleFactories.h" #include "bootstrap/PersistenceContainer.h" +#include "components/Checkbox.h" #include "components/ScrollbarFactory.h" #include "euroscope/AsrEventHandlerCollection.h" #include "radarscreen/RadarRenderableCollection.h" @@ -43,13 +45,16 @@ namespace UKControllerPlugin::Mapping { RadarScreen::RadarRenderableCollection::beforeTags); // Renders the options + std::shared_ptr<Components::Checkbox> vrpCheckbox = Components::Checkbox::Create( + std::make_shared<VisualReferencePointCheckboxProvider>(renderOptions), + radarRenderables.ReserveScreenObjectIdentifier()); + radarRenderables.RegisterScreenObject(vrpCheckbox); + auto optionsRendererId = radarRenderables.ReserveRendererIdentifier(); radarRenderables.RegisterRenderer( optionsRendererId, std::make_shared<MappingOptionsRenderer>( - renderOptions, - Components::ScrollbarFactory(radarRenderables), - radarRenderables.ReserveScreenObjectIdentifier(optionsRendererId)), + renderOptions, vrpCheckbox, Components::ScrollbarFactory(radarRenderables)), RadarScreen::RadarRenderableCollection::afterLists); // Toggles the options diff --git a/src/plugin/mapping/MappingOptionsRenderer.cpp b/src/plugin/mapping/MappingOptionsRenderer.cpp index 9c2e4e504..a8d5d766c 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.cpp +++ b/src/plugin/mapping/MappingOptionsRenderer.cpp @@ -13,10 +13,10 @@ namespace UKControllerPlugin::Mapping { MappingOptionsRenderer::MappingOptionsRenderer( std::shared_ptr<MappingRenderOptions> mappingOptions, - const Components::ScrollbarFactory& scrollbarFactory, - int screenObjectId) - : mappingOptions(mappingOptions), vrpScrollbar(scrollbarFactory.MakeHorizontal({10, 110, 25, 300}, 10)), - screenObjectId(screenObjectId), + std::shared_ptr<Components::Checkbox> vrpCheckbox, + const Components::ScrollbarFactory& scrollbarFactory) + : mappingOptions(mappingOptions), vrpCheckbox(vrpCheckbox), + vrpScrollbar(scrollbarFactory.MakeHorizontal({10, 400, 25, 300}, 10)), backgroundBrush(std::make_shared<Gdiplus::SolidBrush>(Gdiplus::Color(170, 64, 64, 64))) { assert(mappingOptions && "Mapping render options not set"); @@ -61,9 +61,7 @@ namespace UKControllerPlugin::Mapping { // VRPs Components::Title::Create(L"Visual Reference Points", Gdiplus::Rect{10, 35, 300, 25})->Draw(graphics); - Components::Checkbox::Create(L"Display VRPs", {10, 70}, screenObjectId, DISPLAY_VRP_CHECKBOX) - ->Checked(mappingOptions->ShowVisualReferencePoints()) - ->Draw(graphics, radarScreen); + vrpCheckbox->WithPosition({10, 85})->Draw(graphics, radarScreen); vrpScrollbar->Draw(graphics, radarScreen); }); diff --git a/src/plugin/mapping/MappingOptionsRenderer.h b/src/plugin/mapping/MappingOptionsRenderer.h index fd5b8b1e2..18c497c0b 100644 --- a/src/plugin/mapping/MappingOptionsRenderer.h +++ b/src/plugin/mapping/MappingOptionsRenderer.h @@ -2,6 +2,7 @@ #include "radarscreen/RadarRenderableInterface.h" namespace UKControllerPlugin::Components { + class Checkbox; class Scrollbar; class ScrollbarFactory; } // namespace UKControllerPlugin::Components @@ -17,8 +18,8 @@ namespace UKControllerPlugin::Mapping { public: MappingOptionsRenderer( std::shared_ptr<MappingRenderOptions> mappingOptions, - const Components::ScrollbarFactory& scrollbarFactory, - int screenObjectId); + std::shared_ptr<Components::Checkbox> vrpCheckbox, + const Components::ScrollbarFactory& scrollbarFactory); [[nodiscard]] auto IsVisible() const -> bool override; void LeftClick( Euroscope::EuroscopeRadarLoopbackInterface& radarScreen, @@ -33,12 +34,12 @@ namespace UKControllerPlugin::Mapping { // The options std::shared_ptr<MappingRenderOptions> mappingOptions; + // Checkbox for whether to display VRPs + std::shared_ptr<Components::Checkbox> vrpCheckbox; + // Scrollbar for VRPs std::shared_ptr<Components::Scrollbar> vrpScrollbar; - // For clickspots - const int screenObjectId; - // Brushes std::shared_ptr<Gdiplus::Brush> backgroundBrush; diff --git a/src/plugin/mapping/VisualReferencePointCheckboxProvider.cpp b/src/plugin/mapping/VisualReferencePointCheckboxProvider.cpp new file mode 100644 index 000000000..09aa5a35a --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointCheckboxProvider.cpp @@ -0,0 +1,22 @@ +#include "MappingRenderOptions.h" +#include "VisualReferencePointCheckboxProvider.h" + +namespace UKControllerPlugin::Mapping { + + VisualReferencePointCheckboxProvider::VisualReferencePointCheckboxProvider( + std::shared_ptr<MappingRenderOptions> renderOptions) + : renderOptions(renderOptions) + { + assert(renderOptions && "Render options not set in VisualReferencePointCheckboxProvider"); + } + + auto VisualReferencePointCheckboxProvider::Label() -> std::string + { + return "Display VRPs"; + } + + void VisualReferencePointCheckboxProvider::StateChanged(bool checked) + { + renderOptions->ShowVisualReferencePoints(checked); + } +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/mapping/VisualReferencePointCheckboxProvider.h b/src/plugin/mapping/VisualReferencePointCheckboxProvider.h new file mode 100644 index 000000000..84c141e15 --- /dev/null +++ b/src/plugin/mapping/VisualReferencePointCheckboxProvider.h @@ -0,0 +1,21 @@ +#pragma once +#include "components/CheckboxProviderInterface.h" + +namespace UKControllerPlugin::Mapping { + class MappingRenderOptions; + + /** + * Provides the visual reference point checkbox + */ + class VisualReferencePointCheckboxProvider : public Components::CheckboxProviderInterface + { + public: + VisualReferencePointCheckboxProvider(std::shared_ptr<MappingRenderOptions> renderOptions); + auto Label() -> std::string override; + void StateChanged(bool checked) override; + + private: + // The render options + std::shared_ptr<MappingRenderOptions> renderOptions; + }; +} // namespace UKControllerPlugin::Mapping diff --git a/src/plugin/radarscreen/RadarRenderableCollection.cpp b/src/plugin/radarscreen/RadarRenderableCollection.cpp index 38419d47a..32817273c 100644 --- a/src/plugin/radarscreen/RadarRenderableCollection.cpp +++ b/src/plugin/radarscreen/RadarRenderableCollection.cpp @@ -213,11 +213,14 @@ namespace UKControllerPlugin { it->second->ResetPosition(); } } - void RadarRenderableCollection::RegisterScreenObject( - const std::function<std::shared_ptr<ScreenObjectInterface>(int)>& objectGenerator) + void RadarRenderableCollection::RegisterScreenObject(std::shared_ptr<ScreenObjectInterface> screenObject) { - int screenObjectId = nextScreenObjectId++; - screenObjects[screenObjectId] = objectGenerator(screenObjectId); + screenObjects[screenObject->ScreenObjectId()] = screenObject; + } + + auto RadarRenderableCollection::ReserveScreenObjectIdentifier() -> int + { + return nextScreenObjectId++; } } // namespace RadarScreen } // namespace UKControllerPlugin diff --git a/src/plugin/radarscreen/RadarRenderableCollection.h b/src/plugin/radarscreen/RadarRenderableCollection.h index 9f4bd5279..196cdc54f 100644 --- a/src/plugin/radarscreen/RadarRenderableCollection.h +++ b/src/plugin/radarscreen/RadarRenderableCollection.h @@ -39,7 +39,8 @@ namespace UKControllerPlugin::RadarScreen { int renderPhase); auto ReserveRendererIdentifier() -> int; auto ReserveScreenObjectIdentifier(int rendererId) -> int; - void RegisterScreenObject(const std::function<std::shared_ptr<ScreenObjectInterface>(int)>& objectGenerator); + auto ReserveScreenObjectIdentifier() -> int; + void RegisterScreenObject(std::shared_ptr<ScreenObjectInterface> screenObject); void Render( int phase, UKControllerPlugin::Windows::GdiGraphicsInterface& graphics, diff --git a/src/plugin/radarscreen/ScreenObjectInterface.h b/src/plugin/radarscreen/ScreenObjectInterface.h index 1f93734c3..9b099f6a1 100644 --- a/src/plugin/radarscreen/ScreenObjectInterface.h +++ b/src/plugin/radarscreen/ScreenObjectInterface.h @@ -13,6 +13,9 @@ namespace UKControllerPlugin::RadarScreen { { public: virtual ~ScreenObjectInterface(); + + [[nodiscard]] virtual auto ScreenObjectId() const -> int = 0; + /* Called when a screen object is left clicked on. */ diff --git a/test/plugin/CMakeLists.txt b/test/plugin/CMakeLists.txt index a79cb40a3..6431ae87e 100644 --- a/test/plugin/CMakeLists.txt +++ b/test/plugin/CMakeLists.txt @@ -61,7 +61,7 @@ set(test__components "components/ButtonTest.cpp" "components/ClickableAreaTest.cpp" "components/TitleBarTest.cpp" -) + ../../src/plugin/mapping/VisualReferencePointCheckboxProvider.cpp ../../src/plugin/mapping/VisualReferencePointCheckboxProvider.h) source_group("test\\components" FILES ${test__components}) set(test__controller