diff --git a/include/AlarmMaskComponent.hpp b/include/AlarmMaskComponent.hpp index 2b0200b..af7978e 100644 --- a/include/AlarmMaskComponent.hpp +++ b/include/AlarmMaskComponent.hpp @@ -18,7 +18,7 @@ class AlarmMaskComponent : public isobus::AlarmMask , public Component { public: - AlarmMaskComponent(std::shared_ptr workingSet, isobus::AlarmMask sourceObject); + AlarmMaskComponent(std::shared_ptr workingSet, isobus::AlarmMask sourceObject, int dataMaskSize); void on_content_changed(bool initial = false); diff --git a/include/DataMaskComponent.hpp b/include/DataMaskComponent.hpp index 9c17d28..e2f4251 100644 --- a/include/DataMaskComponent.hpp +++ b/include/DataMaskComponent.hpp @@ -18,7 +18,7 @@ class DataMaskComponent : public isobus::DataMask , public Component { public: - DataMaskComponent(std::shared_ptr workingSet, isobus::DataMask sourceObject); + DataMaskComponent(std::shared_ptr workingSet, isobus::DataMask sourceObject, int dataMaskSize); void on_content_changed(bool initial = false); diff --git a/include/JuceManagedWorkingSetCache.hpp b/include/JuceManagedWorkingSetCache.hpp index fbe1063..a5a4c11 100644 --- a/include/JuceManagedWorkingSetCache.hpp +++ b/include/JuceManagedWorkingSetCache.hpp @@ -17,6 +17,12 @@ class JuceManagedWorkingSetCache public: static std::shared_ptr create_component(std::shared_ptr workingSet, std::shared_ptr sourceObject); + static void set_data_alarm_mask_size(int size); + + static void set_soft_key_width(int size); + + static void set_soft_key_height(int size); + private: class ComponentCacheClass { @@ -28,6 +34,9 @@ class JuceManagedWorkingSetCache //std::map> componentLookup; }; static std::vector workingSetComponentCache; + static int dataAndAlarmMaskSize; + static int keyWidth; + static int keyHeight; }; #endif // JUCE_MANAGED_WORKING_SET_HPP diff --git a/include/KeyComponent.hpp b/include/KeyComponent.hpp index e4c8e76..5453899 100644 --- a/include/KeyComponent.hpp +++ b/include/KeyComponent.hpp @@ -18,7 +18,7 @@ class KeyComponent : public isobus::Key , public Component { public: - KeyComponent(std::shared_ptr workingSet, isobus::Key sourceObject); + KeyComponent(std::shared_ptr workingSet, isobus::Key sourceObject, int keyWidth, int keyHeight); void paint(Graphics &g) override; diff --git a/include/ServerMainComponent.hpp b/include/ServerMainComponent.hpp index 75db7d2..e1cf907 100644 --- a/include/ServerMainComponent.hpp +++ b/include/ServerMainComponent.hpp @@ -96,7 +96,8 @@ class ServerMainComponent : public juce::Component NoCommand = 0, /// 0 Is an invalid command ID About, ConfigureLanguageCommand, - ConfigureReportedVersion + ConfigureReportedVersion, + ConfigureReportedHardware }; class LanguageCommandConfigClosed @@ -132,6 +133,10 @@ class ServerMainComponent : public juce::Component AudioDeviceManager mAudioDeviceManager; std::unique_ptr popupMenu; std::uint8_t numberOfPoolsToRender = 0; + std::uint8_t numberPhysicalSoftKeys = 6; + std::uint8_t numberVirtualSoftKeys = 64; + std::uint8_t softKeyDesignatorWidth = 60; + std::uint8_t softKeyDesignatorHeight = 60; VTVersion versionToReport = VTVersion::Version5; bool needToRepaint = false; diff --git a/src/AlarmMaskComponent.cpp b/src/AlarmMaskComponent.cpp index 09755d0..9c391cd 100644 --- a/src/AlarmMaskComponent.cpp +++ b/src/AlarmMaskComponent.cpp @@ -6,12 +6,12 @@ #include "AlarmMaskComponent.hpp" #include "JuceManagedWorkingSetCache.hpp" -AlarmMaskComponent::AlarmMaskComponent(std::shared_ptr workingSet, isobus::AlarmMask sourceObject) : +AlarmMaskComponent::AlarmMaskComponent(std::shared_ptr workingSet, isobus::AlarmMask sourceObject, int dataMaskSize) : isobus::AlarmMask(sourceObject), parentWorkingSet(workingSet) { setOpaque(true); - setBounds(0, 0, 480, 480); + setBounds(0, 0, dataMaskSize, dataMaskSize); on_content_changed(true); } diff --git a/src/DataMaskComponent.cpp b/src/DataMaskComponent.cpp index bc30d2a..38d029f 100644 --- a/src/DataMaskComponent.cpp +++ b/src/DataMaskComponent.cpp @@ -6,12 +6,12 @@ #include "DataMaskComponent.hpp" #include "JuceManagedWorkingSetCache.hpp" -DataMaskComponent::DataMaskComponent(std::shared_ptr workingSet, isobus::DataMask sourceObject) : +DataMaskComponent::DataMaskComponent(std::shared_ptr workingSet, isobus::DataMask sourceObject, int dataMaskSize) : isobus::DataMask(sourceObject), parentWorkingSet(workingSet) { setOpaque(true); - setBounds(0, 0, 480, 480); + setBounds(0, 0, dataMaskSize, dataMaskSize); on_content_changed(true); } diff --git a/src/DataMaskRenderAreaComponent.cpp b/src/DataMaskRenderAreaComponent.cpp index 109a7f5..24c4133 100644 --- a/src/DataMaskRenderAreaComponent.cpp +++ b/src/DataMaskRenderAreaComponent.cpp @@ -46,7 +46,7 @@ void DataMaskRenderAreaComponent::paint(Graphics &g) if (nullptr != parentWorkingSet) { - g.drawRect(0, 0, 480, 480, 1); + g.drawRect(0, 0, getWidth(), getHeight(), 1); } else { diff --git a/src/JuceManagedWorkingSetCache.cpp b/src/JuceManagedWorkingSetCache.cpp index 7b50dec..e5eb5d1 100644 --- a/src/JuceManagedWorkingSetCache.cpp +++ b/src/JuceManagedWorkingSetCache.cpp @@ -38,6 +38,9 @@ #include "WorkingSetComponent.hpp" std::vector JuceManagedWorkingSetCache::workingSetComponentCache; +int JuceManagedWorkingSetCache::dataAndAlarmMaskSize = 480; +int JuceManagedWorkingSetCache::keyWidth = 60; +int JuceManagedWorkingSetCache::keyHeight = 60; std::shared_ptr JuceManagedWorkingSetCache::create_component(std::shared_ptr workingSet, std::shared_ptr sourceObject) { @@ -64,13 +67,13 @@ std::shared_ptr JuceManagedWorkingSetCache::create_component(std::sha { case isobus::VirtualTerminalObjectType::AlarmMask: { - retVal = std::make_shared(workingSet, *std::static_pointer_cast(sourceObject)); + retVal = std::make_shared(workingSet, *std::static_pointer_cast(sourceObject), dataAndAlarmMaskSize); } break; case isobus::VirtualTerminalObjectType::DataMask: { - retVal = std::make_shared(workingSet, *std::static_pointer_cast(sourceObject)); + retVal = std::make_shared(workingSet, *std::static_pointer_cast(sourceObject), dataAndAlarmMaskSize); } break; @@ -93,7 +96,7 @@ std::shared_ptr JuceManagedWorkingSetCache::create_component(std::sha case isobus::VirtualTerminalObjectType::Key: { - retVal = std::make_shared(workingSet, *std::static_pointer_cast(sourceObject)); + retVal = std::make_shared(workingSet, *std::static_pointer_cast(sourceObject), keyWidth, keyHeight); } break; @@ -218,3 +221,18 @@ std::shared_ptr JuceManagedWorkingSetCache::create_component(std::sha } return retVal; } + +void JuceManagedWorkingSetCache::set_data_alarm_mask_size(int size) +{ + dataAndAlarmMaskSize = size; +} + +void JuceManagedWorkingSetCache::set_soft_key_width(int size) +{ + keyWidth = size; +} + +void JuceManagedWorkingSetCache::set_soft_key_height(int size) +{ + keyHeight = size; +} diff --git a/src/KeyComponent.cpp b/src/KeyComponent.cpp index 42c9e22..803b47f 100644 --- a/src/KeyComponent.cpp +++ b/src/KeyComponent.cpp @@ -7,11 +7,11 @@ #include "JuceManagedWorkingSetCache.hpp" -KeyComponent::KeyComponent(std::shared_ptr workingSet, isobus::Key sourceObject) : +KeyComponent::KeyComponent(std::shared_ptr workingSet, isobus::Key sourceObject, int keyWidth, int keyHeight) : isobus::Key(sourceObject), parentWorkingSet(workingSet) { - setSize(60, 60); + setSize(keyWidth, keyHeight); setOpaque(true); for (std::uint16_t i = 0; i < this->get_number_children(); i++) diff --git a/src/ServerMainComponent.cpp b/src/ServerMainComponent.cpp index 5c625a2..531201d 100644 --- a/src/ServerMainComponent.cpp +++ b/src/ServerMainComponent.cpp @@ -81,30 +81,77 @@ std::uint8_t ServerMainComponent::get_number_of_navigation_soft_keys() const std::uint8_t ServerMainComponent::get_soft_key_descriptor_x_pixel_width() const { - return 60; + std::uint8_t retVal = 32; + + if (versionToReport == VTVersion::Version6) + { + retVal = 60; // 60x60 is the minimum size for VT Version 6+ + } + if (softKeyDesignatorWidth > retVal) + { + retVal = softKeyDesignatorWidth; + } + return retVal; } std::uint8_t ServerMainComponent::get_soft_key_descriptor_y_pixel_width() const { - return 60; + // Min: 60 pixels wide + std::uint8_t retVal = 60; + + if (softKeyDesignatorHeight > retVal) + { + retVal = softKeyDesignatorHeight; + } + return retVal; } std::uint8_t ServerMainComponent::get_number_of_possible_virtual_soft_keys_in_soft_key_mask() const { - return 64; + constexpr std::uint8_t MAX_VIRTUAL_SOFT_KEYS = 64; + std::uint8_t retVal = numberVirtualSoftKeys; + + // VT Version 3 and prior shall support a maximum of 64 virtual Soft Keys per Soft Key Mask and shall + // support as a minimum the number of reported physical Soft Keys + if (versionToReport < VTVersion::Version3) + { + if (retVal > MAX_VIRTUAL_SOFT_KEYS) + { + retVal = MAX_VIRTUAL_SOFT_KEYS; + } + else if (retVal < get_number_of_physical_soft_keys()) + { + retVal = get_number_of_physical_soft_keys(); + } + } + else + { + retVal = MAX_VIRTUAL_SOFT_KEYS; // VT Version 4 and later shall support exactly 64 virtual Soft Keys per Soft Key Mask + } + return retVal; } std::uint8_t ServerMainComponent::get_number_of_physical_soft_keys() const { - return 0; + constexpr std::uint8_t MIN_PHYSICAL_SOFT_KEYS = 6; + + if (versionToReport >= isobus::VirtualTerminalBase::VTVersion::Version4) + { + // VT Version 4 and later VTs shall provide at least 6 physical Soft Keys. + return numberPhysicalSoftKeys < MIN_PHYSICAL_SOFT_KEYS ? MIN_PHYSICAL_SOFT_KEYS : numberPhysicalSoftKeys; + } + else + { + return numberPhysicalSoftKeys; + } } std::uint16_t ServerMainComponent::get_data_mask_area_size_x_pixels() const { - return 480; + return dataMaskRenderer.getWidth() != 0 ? dataMaskRenderer.getWidth() : 480; } std::uint16_t ServerMainComponent::get_data_mask_area_size_y_pixels() const { - return 480; + return dataMaskRenderer.getHeight() != 0 ? dataMaskRenderer.getHeight() : 480; } void ServerMainComponent::suspend_working_set(std::shared_ptr /*workingSetWithError*/) @@ -450,10 +497,10 @@ void ServerMainComponent::resized() auto lBounds = getLocalBounds(); workingSetSelector.setBounds(0, lMenuBarHeight + 4, 100, 600); - dataMaskRenderer.setBounds(100, lMenuBarHeight + 4, 500, 500); - softKeyMaskRenderer.setBounds(580, lMenuBarHeight + 4, 100, 480); - loggerViewport.setSize(getWidth(), getHeight() - 600); - loggerViewport.setTopLeftPosition(0, 600); + dataMaskRenderer.setBounds(100, lMenuBarHeight + 4, get_data_mask_area_size_x_pixels(), get_data_mask_area_size_y_pixels()); + softKeyMaskRenderer.setBounds(100 + get_data_mask_area_size_x_pixels(), lMenuBarHeight + 4, 100, get_data_mask_area_size_y_pixels()); + loggerViewport.setSize(getWidth(), getHeight() * .2f); + loggerViewport.setTopLeftPosition(0, getHeight() * .8f); menuBar.setBounds(lBounds.removeFromTop(lMenuBarHeight)); logger.setSize(loggerViewport.getWidth(), logger.getHeight()); @@ -473,6 +520,7 @@ void ServerMainComponent::getAllCommands(juce::Array &allComman allCommands.add(static_cast(CommandIDs::About)); allCommands.add(static_cast(CommandIDs::ConfigureLanguageCommand)); allCommands.add(static_cast(CommandIDs::ConfigureReportedVersion)); + allCommands.add(static_cast(CommandIDs::ConfigureReportedHardware)); } void ServerMainComponent::getCommandInfo(juce::CommandID commandID, ApplicationCommandInfo &result) @@ -497,6 +545,12 @@ void ServerMainComponent::getCommandInfo(juce::CommandID commandID, ApplicationC } break; + case CommandIDs::ConfigureReportedHardware: + { + result.setInfo("Reported Hardware Capabilities", "Change info reported to clients in the get hardware message", "Configure", 0); + } + break; + case CommandIDs::NoCommand: default: break; @@ -568,6 +622,26 @@ bool ServerMainComponent::perform(const InvocationInfo &info) } break; + case static_cast(CommandIDs::ConfigureReportedHardware): + { + popupMenu = std::make_unique("Configure Reported VT Capabilities", "You can use this menu to configure what the server will report to clients in the \"get hardware\" message response, as well as what will be displayed in the data/soft key mask render components of this application. Some of these settings may require you to close and reopen the application to avoid weird discrepancies with connected clients.", MessageBoxIconType::NoIcon); + popupMenu->addTextEditor("Data Mask Size (height and width)", String(dataMaskRenderer.getWidth()), "Data Mask Size (height and width)"); + popupMenu->addTextEditor("Soft Key Designator Height", String(get_soft_key_descriptor_y_pixel_width()), "Soft Key Designator Height (min 60)"); + popupMenu->addTextEditor("Soft Key Designator Width", String(get_soft_key_descriptor_x_pixel_width()), "Soft Key Designator Width (min 60)"); + popupMenu->addTextEditor("Number of Physical Soft Keys", String(get_number_of_physical_soft_keys()), "Number of Physical Soft Keys (min 6)"); + + popupMenu->getTextEditor("Data Mask Size (height and width)")->setInputRestrictions(4, "1234567890"); + popupMenu->getTextEditor("Soft Key Designator Height")->setInputRestrictions(4, "1234567890"); + popupMenu->getTextEditor("Soft Key Designator Width")->setInputRestrictions(4, "1234567890"); + popupMenu->getTextEditor("Number of Physical Soft Keys")->setInputRestrictions(2, "1234567890"); + + popupMenu->addButton("OK", 3, KeyPress(KeyPress::returnKey, 0, 0)); + popupMenu->addButton("Cancel", 0, KeyPress(KeyPress::escapeKey, 0, 0)); + popupMenu->enterModalState(true, ModalCallbackFunction::create(LanguageCommandConfigClosed{ *this })); + retVal = true; + } + break; + default: break; } @@ -589,6 +663,7 @@ PopupMenu ServerMainComponent::getMenuForIndex(int index, const juce::String &) { retVal.addCommandItem(&mCommandManager, static_cast(CommandIDs::ConfigureLanguageCommand)); retVal.addCommandItem(&mCommandManager, static_cast(CommandIDs::ConfigureReportedVersion)); + retVal.addCommandItem(&mCommandManager, static_cast(CommandIDs::ConfigureReportedHardware)); } break; @@ -708,6 +783,28 @@ void ServerMainComponent::LanguageCommandConfigClosed::operator()(int result) co } break; + case 3: // Save Reported Hardware + { + auto dataMaskSize = mParent.popupMenu->getTextEditorContents("Data Mask Size (height and width)"); + auto softKeyDesignatorHeight = mParent.popupMenu->getTextEditorContents("Soft Key Designator Height"); + auto softKeyDesignatorWidth = mParent.popupMenu->getTextEditorContents("Soft Key Designator Width"); + auto numberOfPhysicalSoftKeys = mParent.popupMenu->getTextEditorContents("Number of Physical Soft Keys"); + + mParent.dataMaskRenderer.setSize(dataMaskSize.getIntValue(), dataMaskSize.getIntValue()); + mParent.softKeyMaskRenderer.setSize(100, dataMaskSize.getIntValue()); + mParent.softKeyMaskRenderer.setTopLeftPosition(100 + dataMaskSize.getIntValue(), 4 + juce::LookAndFeel::getDefaultLookAndFeel().getDefaultMenuBarHeight()); + JuceManagedWorkingSetCache::set_data_alarm_mask_size(dataMaskSize.getIntValue()); + JuceManagedWorkingSetCache::set_soft_key_height(softKeyDesignatorHeight.getIntValue()); + JuceManagedWorkingSetCache::set_soft_key_width(softKeyDesignatorWidth.getIntValue()); + mParent.softKeyDesignatorWidth = softKeyDesignatorWidth.getIntValue(); + mParent.softKeyDesignatorHeight = softKeyDesignatorHeight.getIntValue(); + mParent.numberPhysicalSoftKeys = numberOfPhysicalSoftKeys.getIntValue(); + + mParent.save_settings(); + mParent.repaint_data_and_soft_key_mask(); + } + break; + default: { // Cancel. Do nothing @@ -878,6 +975,7 @@ void ServerMainComponent::check_load_settings() auto firstChild = settings.getChild(0); auto secondChild = settings.getChild(1); + auto thirdChild = settings.getChild(2); languageCommandInterface.set_commanded_area_units(static_cast(int(firstChild.getProperty("AreaUnits")))); languageCommandInterface.set_commanded_date_format(static_cast(int(firstChild.getProperty("DateFormat")))); languageCommandInterface.set_commanded_decimal_symbol(static_cast(int(firstChild.getProperty("DecimalSymbol")))); @@ -892,6 +990,11 @@ void ServerMainComponent::check_load_settings() languageCommandInterface.set_country_code(String(firstChild.getProperty("CountryCode").toString()).toStdString()); languageCommandInterface.set_language_code(String(firstChild.getProperty("LanguageCode").toString()).toStdString()); versionToReport = get_version_from_setting(static_cast(static_cast(secondChild.getProperty("Version")))); + + if (thirdChild.isValid()) + { + + } } } } @@ -921,6 +1024,7 @@ void ServerMainComponent::save_settings() ValueTree settings("Settings"); ValueTree languageCommandSettings("LanguageCommand"); ValueTree compatibilitySettings("Compatibility"); + ValueTree hardwareSettings("Hardware"); languageCommandSettings.setProperty("AreaUnits", static_cast(languageCommandInterface.get_commanded_area_units()), nullptr); languageCommandSettings.setProperty("DateFormat", static_cast(languageCommandInterface.get_commanded_date_format()), nullptr); @@ -936,8 +1040,13 @@ void ServerMainComponent::save_settings() languageCommandSettings.setProperty("CountryCode", String(languageCommandInterface.get_country_code()), nullptr); languageCommandSettings.setProperty("LanguageCode", String(languageCommandInterface.get_language_code()), nullptr); compatibilitySettings.setProperty("Version", get_vt_version_byte(versionToReport), nullptr); + hardwareSettings.setProperty("DataMaskRenderAreaSize", dataMaskRenderer.getWidth(), nullptr); + hardwareSettings.setProperty("SoftKeyDesignatorWidth", get_soft_key_descriptor_x_pixel_width(), nullptr); + hardwareSettings.setProperty("SoftKeyDesignatorHeight", get_soft_key_descriptor_y_pixel_width(), nullptr); + hardwareSettings.setProperty("PhysicalSoftkeys", get_number_of_physical_soft_keys(), nullptr); settings.appendChild(languageCommandSettings, nullptr); settings.appendChild(compatibilitySettings, nullptr); + settings.appendChild(hardwareSettings, nullptr); std::unique_ptr xml(settings.createXml()); if (nullptr != xml) diff --git a/src/SoftkeyMaskRenderArea.cpp b/src/SoftkeyMaskRenderArea.cpp index 428f864..803d656 100644 --- a/src/SoftkeyMaskRenderArea.cpp +++ b/src/SoftkeyMaskRenderArea.cpp @@ -67,7 +67,7 @@ void SoftKeyMaskRenderAreaComponent::paint(Graphics &g) if (nullptr != parentWorkingSet) { - g.drawRect(0, 0, 100, 480, 1); + g.drawRect(0, 0, getWidth(), getHeight(), 1); } }