From 03b39813121a3673327b82548948d39011825d28 Mon Sep 17 00:00:00 2001 From: Jan Date: Sat, 20 Nov 2021 22:01:01 +0100 Subject: [PATCH] Add menu key handlers --- .../Parsing/Menu/Domain/CommonItemDef.h | 1 + .../Parsing/Menu/Domain/CommonMenuDef.h | 2 +- .../Menu/Sequence/ItemScopeSequences.cpp | 82 ++++++++++++++++++- .../Menu/Sequence/MenuScopeSequences.cpp | 72 ++++++++++++++++ 4 files changed, 152 insertions(+), 5 deletions(-) diff --git a/src/ObjLoading/Parsing/Menu/Domain/CommonItemDef.h b/src/ObjLoading/Parsing/Menu/Domain/CommonItemDef.h index fcb53973..4ef06051 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/CommonItemDef.h +++ b/src/ObjLoading/Parsing/Menu/Domain/CommonItemDef.h @@ -152,6 +152,7 @@ namespace menu std::unique_ptr m_on_mouse_exit_text; std::unique_ptr m_on_action; std::unique_ptr m_on_accept; + std::map> m_key_handlers; std::unique_ptr m_list_box_features; std::unique_ptr m_edit_field_features; diff --git a/src/ObjLoading/Parsing/Menu/Domain/CommonMenuDef.h b/src/ObjLoading/Parsing/Menu/Domain/CommonMenuDef.h index df7a3a96..ad806273 100644 --- a/src/ObjLoading/Parsing/Menu/Domain/CommonMenuDef.h +++ b/src/ObjLoading/Parsing/Menu/Domain/CommonMenuDef.h @@ -45,7 +45,7 @@ namespace menu std::unique_ptr m_on_close; std::unique_ptr m_on_request_close; std::unique_ptr m_on_esc; - std::map> m_key_handler; + std::map> m_key_handlers; bool m_full_screen; bool m_screen_space; diff --git a/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp index 4040f5a6..cb8ba142 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/ItemScopeSequences.cpp @@ -382,10 +382,11 @@ namespace menu::item_scope_sequences class SequenceColumns final : public MenuFileParser::sequence_t { static constexpr auto CAPTURE_FIRST_TOKEN = 1; - static constexpr auto CAPTURE_POS = 2; - static constexpr auto CAPTURE_WIDTH = 3; - static constexpr auto CAPTURE_MAX_CHARS = 4; - static constexpr auto CAPTURE_ALIGNMENT = 5; + static constexpr auto CAPTURE_COLUMN_COUNT = 2; + static constexpr auto CAPTURE_POS = 3; + static constexpr auto CAPTURE_WIDTH = 4; + static constexpr auto CAPTURE_MAX_CHARS = 5; + static constexpr auto CAPTURE_ALIGNMENT = 6; public: SequenceColumns() @@ -394,6 +395,7 @@ namespace menu::item_scope_sequences AddMatchers({ create.KeywordIgnoreCase("columns").Capture(CAPTURE_FIRST_TOKEN), + create.Integer().Capture(CAPTURE_COLUMN_COUNT), create.Loop(create.And({ create.Integer().Capture(CAPTURE_POS), create.Integer().Capture(CAPTURE_WIDTH), @@ -426,6 +428,76 @@ namespace menu::item_scope_sequences } } }; + + class SequenceExecKey final : public MenuFileParser::sequence_t + { + static constexpr auto CAPTURE_KEY = 1; + + public: + SequenceExecKey() + { + const MenuMatcherFactory create(this); + + AddMatchers({ + create.KeywordIgnoreCase("execKey"), + create.String().Capture(CAPTURE_KEY), + create.Char('{') + }); + } + + protected: + void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override + { + assert(state->m_current_item); + + const auto& keyToken = result.NextCapture(CAPTURE_KEY); + const auto& keyValue = keyToken.StringValue(); + + if (keyValue.empty() || keyValue.size() > 1) + throw ParsingException(keyToken.GetPos(), "Key handler string must have exactly one character"); + + const auto key = static_cast(static_cast(keyValue[0])); + + auto newEventHandlerSet = std::make_unique(); + state->m_current_event_handler_set = newEventHandlerSet.get(); + state->m_current_nested_event_handler_set = newEventHandlerSet.get(); + state->m_current_item->m_key_handlers.emplace(std::make_pair(key, std::move(newEventHandlerSet))); + } + }; + + class SequenceExecKeyInt final : public MenuFileParser::sequence_t + { + static constexpr auto CAPTURE_KEY = 1; + + public: + SequenceExecKeyInt() + { + const MenuMatcherFactory create(this); + + AddMatchers({ + create.KeywordIgnoreCase("execKeyInt"), + create.Integer().Capture(CAPTURE_KEY), + create.Char('{') + }); + } + + protected: + void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override + { + assert(state->m_current_item); + + const auto& keyToken = result.NextCapture(CAPTURE_KEY); + const auto& keyValue = keyToken.IntegerValue(); + + if (keyValue < 0) + throw ParsingException(keyToken.GetPos(), "Key handler value must be positive"); + + auto newEventHandlerSet = std::make_unique(); + state->m_current_event_handler_set = newEventHandlerSet.get(); + state->m_current_nested_event_handler_set = newEventHandlerSet.get(); + state->m_current_item->m_key_handlers.emplace(std::make_pair(keyValue, std::move(newEventHandlerSet))); + } + }; } using namespace item_scope_sequences; @@ -724,6 +796,8 @@ void ItemScopeSequences::AddSequences(FeatureLevel featureLevel) { state->m_current_item->m_on_accept = std::move(value); })); + AddSequence(std::make_unique()); + AddSequence(std::make_unique()); // ============== ListBox ============== AddSequence(std::make_unique()); diff --git a/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp b/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp index 94ad3bd6..64840370 100644 --- a/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp +++ b/src/ObjLoading/Parsing/Menu/Sequence/MenuScopeSequences.cpp @@ -127,6 +127,76 @@ namespace menu::menu_scope_sequences state->m_current_menu->m_rect = rect; } }; + + class SequenceExecKey final : public MenuFileParser::sequence_t + { + static constexpr auto CAPTURE_KEY = 1; + + public: + SequenceExecKey() + { + const MenuMatcherFactory create(this); + + AddMatchers({ + create.KeywordIgnoreCase("execKey"), + create.String().Capture(CAPTURE_KEY), + create.Char('{') + }); + } + + protected: + void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override + { + assert(state->m_current_menu); + + const auto& keyToken = result.NextCapture(CAPTURE_KEY); + const auto& keyValue = keyToken.StringValue(); + + if (keyValue.empty() || keyValue.size() > 1) + throw ParsingException(keyToken.GetPos(), "Key handler string must have exactly one character"); + + const auto key = static_cast(static_cast(keyValue[0])); + + auto newEventHandlerSet = std::make_unique(); + state->m_current_event_handler_set = newEventHandlerSet.get(); + state->m_current_nested_event_handler_set = newEventHandlerSet.get(); + state->m_current_menu->m_key_handlers.emplace(std::make_pair(key, std::move(newEventHandlerSet))); + } + }; + + class SequenceExecKeyInt final : public MenuFileParser::sequence_t + { + static constexpr auto CAPTURE_KEY = 1; + + public: + SequenceExecKeyInt() + { + const MenuMatcherFactory create(this); + + AddMatchers({ + create.KeywordIgnoreCase("execKeyInt"), + create.Integer().Capture(CAPTURE_KEY), + create.Char('{') + }); + } + + protected: + void ProcessMatch(MenuFileParserState* state, SequenceResult& result) const override + { + assert(state->m_current_menu); + + const auto& keyToken = result.NextCapture(CAPTURE_KEY); + const auto& keyValue = keyToken.IntegerValue(); + + if (keyValue < 0) + throw ParsingException(keyToken.GetPos(), "Key handler value must be positive"); + + auto newEventHandlerSet = std::make_unique(); + state->m_current_event_handler_set = newEventHandlerSet.get(); + state->m_current_nested_event_handler_set = newEventHandlerSet.get(); + state->m_current_menu->m_key_handlers.emplace(std::make_pair(keyValue, std::move(newEventHandlerSet))); + } + }; } using namespace menu_scope_sequences; @@ -289,4 +359,6 @@ void MenuScopeSequences::AddSequences(FeatureLevel featureLevel) { state->m_current_menu->m_on_esc = std::move(value); })); + AddSequence(std::make_unique()); + AddSequence(std::make_unique()); }