From b08b55316e9684b6dfd5de7f5b40194e5d5fd22e Mon Sep 17 00:00:00 2001 From: Adrian Del Grosso <10929341+ad3154@users.noreply.github.com> Date: Fri, 10 Nov 2023 10:34:27 -0700 Subject: [PATCH] [VT]: Add Virtual Terminal Object Classes Added classes to represent most VT objects. This is intended to be used with a VT server (coming soon) or with an object pool editor program. --- CMakeLists.txt | 1 + isobus/CMakeLists.txt | 2 + .../include/isobus/isobus/can_constants.hpp | 2 + .../isobus_virtual_terminal_objects.hpp | 3601 ++++++++++- .../src/isobus_virtual_terminal_objects.cpp | 5491 +++++++++++++++++ test/vt_object_tests.cpp | 2028 ++++++ 6 files changed, 11123 insertions(+), 2 deletions(-) create mode 100644 isobus/src/isobus_virtual_terminal_objects.cpp create mode 100644 test/vt_object_tests.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index f7b5a894..98436d05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,7 @@ if(BUILD_TESTING) test/guidance_tests.cpp test/speed_distance_message_tests.cpp test/maintain_power_tests.cpp + test/vt_object_tests.cpp test/nmea2000_message_tests.cpp) add_executable(unit_tests ${TEST_SRC}) diff --git a/isobus/CMakeLists.txt b/isobus/CMakeLists.txt index 992dcd93..80ab13a1 100644 --- a/isobus/CMakeLists.txt +++ b/isobus/CMakeLists.txt @@ -38,6 +38,7 @@ set(ISOBUS_SRC "isobus_guidance_interface.cpp" "isobus_speed_distance_messages.cpp" "isobus_maintain_power_interface.cpp" + "isobus_virtual_terminal_objects.cpp" "nmea2000_message_definitions.cpp" "nmea2000_message_interface.cpp") @@ -79,6 +80,7 @@ set(ISOBUS_INCLUDE "isobus_functionalities.hpp" "isobus_speed_distance_messages.hpp" "isobus_maintain_power_interface.hpp" + "isobus_virtual_terminal_objects.hpp" "nmea2000_message_definitions.hpp" "nmea2000_message_interface.hpp") # Prepend the include directory path to all the include files diff --git a/isobus/include/isobus/isobus/can_constants.hpp b/isobus/include/isobus/isobus/can_constants.hpp index 561a54e0..119957c8 100644 --- a/isobus/include/isobus/isobus/can_constants.hpp +++ b/isobus/include/isobus/isobus/can_constants.hpp @@ -9,6 +9,8 @@ #ifndef CAN_CONSTANTS_HPP #define CAN_CONSTANTS_HPP +#include + namespace isobus { constexpr std::uint64_t DEFAULT_NAME = 0xFFFFFFFFFFFFFFFF; ///< An invalid NAME used as a default diff --git a/isobus/include/isobus/isobus/isobus_virtual_terminal_objects.hpp b/isobus/include/isobus/isobus/isobus_virtual_terminal_objects.hpp index 9f2a1dd4..8e6d3260 100644 --- a/isobus/include/isobus/isobus/isobus_virtual_terminal_objects.hpp +++ b/isobus/include/isobus/isobus/isobus_virtual_terminal_objects.hpp @@ -1,7 +1,7 @@ //================================================================================================ /// @file isobus_virtual_terminal_objects.hpp /// -/// @brief Enumerates the different VT object types that can comprise a VT object pool +/// @brief Defines the different VT object types that can comprise a VT object pool. /// @author Adrian Del Grosso /// /// @copyright 2023 Adrian Del Grosso @@ -9,12 +9,20 @@ #ifndef ISOBUS_VIRTUAL_TERMINAL_OBJECTS_HPP #define ISOBUS_VIRTUAL_TERMINAL_OBJECTS_HPP +#include "isobus/isobus/can_constants.hpp" + +#include +#include +#include +#include +#include + namespace isobus { /// @brief The types of objects in an object pool by object type byte value enum class VirtualTerminalObjectType { - WorkingSet = 0, ///< Top level object that describes an implement’s ECU or group of ECUs + WorkingSet = 0, ///< Top level object that describes an implement’s ECU or group of ECUs DataMask = 1, ///< Top level object that contains other objects. A Data Mask is activated by a Working Set to become the active set of objects on the VT display. AlarmMask = 2, ///< Top level object that contains other objects. Describes an alarm display. Container = 3, ///< Used to group objects. @@ -40,6 +48,8 @@ namespace isobus GraphicsContext = 36, ///< Used to output a graphics context. Animation = 44, ///< The Animation object is used to display simple animations PictureGraphic = 20, ///< Used to output a picture graphic (bitmap). + GraphicData = 46, ///< Used to define the data for a graphic image + ScaledGraphic = 48, ///< Used to display a scaled representation of a graphic object NumberVariable = 21, ///< Used to store a 32-bit unsigned integer value. StringVariable = 22, ///< Used to store a fixed length string value. FontAttributes = 23, ///< Used to group font based attributes. Can only be referenced by other objects. @@ -76,6 +86,3593 @@ namespace isobus ManufacturerDefined15 = 254, ///< Manufacturer defined objects should not be sent to any other Vendors VT Reserved = 255 ///< Reserved for future use. (See Clause D.14 Get Supported Objects message) }; + + /// @brief VT 3 component colour vector + class VTColourVector + { + public: + float r; ///< Red value for a pixel, range 0.0f to 1.0f + float g; ///< Green value for a pixel, range 0.0f to 1.0f + float b; ///< Blue value for a pixel, range 0.0f to 1.0f + + /// @brief Default constructor for a VT Colour, which produces the colour black + constexpr VTColourVector() : + r(0.0f), g(0.0f), b(0.0f) {} + + /// @brief Constructor for a VT Colour which initializes to an arbitrary colour + /// @param[in] red The red value for a pixel, range 0.0f to 1.0f + /// @param[in] green The green value for a pixel, range 0.0f to 1.0f + /// @param[in] blue The blue value for a pixel, range 0.0f to 1.0f + constexpr VTColourVector(float red, float green, float blue) : + r(red), g(green), b(blue) {} + }; + + /// @brief An object that represents the VT's active colour table + class VTColourTable + { + public: + /// @brief Constructor for a VT colour table + VTColourTable(); + + /// @brief Returns the colour vector associated to the specified VT colour index, which + /// is what gets provided normally in most VT CAN messages, so this essentially maps the index + /// to an actually usable colour definition. + /// @param[in] colourIndex The VT colour index to retrieve + /// @returns An RGB colour vector associated to the specified VT colour index + VTColourVector get_colour(std::uint8_t colourIndex) const; + + /// @brief Sets the specified VT colour index to a new RGB colour value + /// @param[in] colourIndex The VT colour index to modify + /// @param[in] newColour The RGB colour to set the specified index to + void set_colour(std::uint8_t colourIndex, VTColourVector newColour); + + private: + static constexpr std::size_t VT_COLOUR_TABLE_SIZE = 256; ///< The size of the VT colour table as specified in ISO11783-6 + + std::array colourTable; ///< Colour table data. Associates VT colour index with RGB value. + }; + + static constexpr std::uint16_t NULL_OBJECT_ID = 0xFFFF; ///< The NULL Object ID, usually drawn as blank space + + /// @brief Generic VT object base class + class VTObject + { + public: + /// @brief Enumerates the bit indices of the error fields that can be set when changing an attribute + enum class AttributeError : std::uint8_t + { + InvalidObjectID = 0, + InvalidAttributeID = 1, + InvalidValue = 2, + AnyOtherError = 4 + }; + + /// @brief Constructor for a generic VT object. Sets up default values and the pointer to the member object pool + /// @param[in] memberObjectPool a reference to the object tree that this object will be a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + VTObject(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + virtual VirtualTerminalObjectType get_object_type() const = 0; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + virtual std::uint32_t get_minumum_object_length() const = 0; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + virtual bool get_is_valid() const = 0; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + virtual bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) = 0; + + /// @brief Returns the object ID of this VT object + /// @returns The object ID of this VT object + std::uint16_t get_id() const; + + /// @brief Sets the object ID of this VT object + /// @param[in] value The new object ID for this object. Must be unique in this pool. + void set_id(std::uint16_t value); + + /// @brief Returns the width of this object in px + /// @returns The width of this object in px + std::uint16_t get_width() const; + + /// @brief Sets the width of this object in px + /// @param[in] value The new width of this object in px + void set_width(std::uint16_t value); + + /// @brief Returns the height of this object in px + /// @returns The height of this object in px + std::uint16_t get_height() const; + + /// @brief Sets the height of this object in px + /// @param[in] value The new height of this object in px + void set_height(std::uint16_t value); + + /// @brief Returns the background color attribute of this object + /// @returns The background color attribute of this object (index to the actual color in the color table) + std::uint8_t get_background_color() const; + + /// @brief Sets the background color attribute of this object + /// @param[in] value The new background color attribute for this object (index to the actual color in the color table) + void set_background_color(std::uint8_t value); + + /// @brief Returns a VT object from its member pool by ID, or the null id if it does not exist + /// @returns The object with the corresponding ID + std::shared_ptr get_object_by_id(std::uint16_t objectID) const; + + /// @brief Returns the number of child objects within this object + std::uint16_t get_number_children() const; + + /// @brief Adds an object as a child to another object, which essentially creates a tree of object association + /// @param[in] objectID The object ID of the child to add + /// @param[in] relativeXLocation The X offset of this object to its parent + /// @param[in] relativeYLocation The Y offset of this object to its parent + void add_child(std::uint16_t objectID, std::int16_t relativeXLocation, std::int16_t relativeYLocation); + + /// @brief Returns the ID of the child by index, if one was added previously + /// @note NULL_OBJECT_ID is a valid child, so you should always check the number of children to know if the return value of this is "valid" + /// @returns The ID of the child at the specified index, or NULL_OBJECT_ID if the index is out of range + std::uint16_t get_child_id(std::uint16_t index) const; + + /// @brief Returns the X offset of the child object associated with the specified index into the parent object + /// @returns The relative X position of the child, and always 0 if the index is out of range + std::int16_t get_child_x(std::uint16_t index) const; + + /// @brief Returns the Y offset of the child object associated with the specified index into the parent object + /// @returns The relative Y position of the child, and always 0 if the index is out of range + std::int16_t get_child_y(std::uint16_t index) const; + + /// @brief Sets the X offset of the child object associated with the specified index into the parent object + /// @param[in] index The child index to affect + /// @param[in] xOffset The relative X position of the child, and always 0 if the index is out of range + void set_child_x(std::uint16_t index, std::int16_t xOffset); + + /// @brief Sets the Y offset of the child object associated with the specified index into the parent object + /// @param[in] index The child index to affect + /// @param[in] yOffset The relative Y position of the child, and always 0 if the index is out of range + void set_child_y(std::uint16_t index, std::int16_t yOffset); + + /// @brief Offsets all child objects with the specified ID by the amount specified relative to its parent + /// @param[in] childObjectID The object ID of the children to offset + /// @param[in] xOffset The relative amount to offset the object(s) by in the X axis + /// @param[in] yOffset The relative amount to offset the object(s) by in the Y axis + /// @returns true if any child matched the specified object ID, otherwise false if no children were found with the specified ID. + bool offset_all_children_with_id(std::uint16_t childObjectID, std::int8_t xOffset, std::int8_t yOffset); + + /// @brief Removes an object reference from another object. All fields must exactly match for the object to be removed. + /// This is because objects can have multiple of the same child at different places, so we can't infer which one to + /// remove without the exact position. + /// @param[in] objectIDToRemove The object ID of the child to remove + /// @param[in] relativeXLocation The X offset of this object to its parent + /// @param[in] relativeYLocation The Y offset of this object to its parent + void remove_child(std::uint16_t objectIDToRemove, std::int16_t relativeXLocation, std::int16_t relativeYLocation); + + /// @brief Removes the last added child object. + /// This is meant to be a faster way to deal with objects that only have a max of 1 child. + void pop_child(); + + protected: + /// @brief Storage for child object data + class ChildObjectData + { + public: + /// @brief Default constructor for child object data with default values + ChildObjectData() = default; + + /// @brief Constructor that initializes all members with parameters + /// @param[in] objectId The object ID of this child object + /// @param[in] x The x location of this child relative to the parent object + /// @param[in] y The y location of this child relative to the parent object + ChildObjectData(std::uint16_t objectId, + std::int16_t x, + std::int16_t y); + std::uint16_t id = NULL_OBJECT_ID; ///< Object identifier. Shall be unique within the object pool. + std::int16_t xLocation = 0; ///< Relative X location of the top left corner of the object + std::int16_t yLocation = 0; ///< Relative Y location of the top left corner of the object + }; + + /// @brief A helper function to swap a child object of specified type with a new object. + /// This is meant to be used to replace attributes of which there can be only 1, such as a string variable in an output string. + /// @param[in] newID The new child object's ID + /// @param[in] typeToRemove The object type of both the current child, and the new child (they must match) + /// @returns True if the replacement succeeded, otherwise false + bool replace_only_child_of_type(std::uint16_t newID, VirtualTerminalObjectType typeToRemove); + + VTColourTable &colourTable; ///< A reference to the current object pool's colour table. Useful for rendering most objects. + std::map> &thisObjectPool; ///< A pointer to the rest of the object pool. Convenient for lookups by object ID. + std::vector children; ///< List of child objects + std::uint16_t objectID = NULL_OBJECT_ID; ///< Object identifier. Shall be unique within the object pool. + std::uint16_t width = 0; ///< The width of the object. Not always applicable, but often used. + std::uint16_t height = 0; ///< The height of the object. Not always applicable, but often used. + std::uint8_t backgroundColor = 0; ///< The background color (from the VT colour table) + }; + + /// @brief This object shall include one or more objects that fit inside a Soft Key designator for use as an + /// identification of the Working Set. + class WorkingSet : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + BackgroundColour = 1, + Selectable = 2, + ActiveMask = 3, + + NumberOfAttributes = 4 + }; + + /// @brief Constructor for a working set object + /// @param[in] memberObjectPool a reference to the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + WorkingSet(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns if the working set is currently selectable + /// @returns `true` if the working set is currently selectable, otherwise false + bool get_selectable() const; + + /// @brief Sets if the working set is selectable + /// @param[in] value `true` to make the working set selectable, otherwise false + void set_selectable(bool value); + + /// @brief Returns tha currently active mask for this working set + /// @returns The object ID of the active mask for this working set + std::uint16_t get_active_mask() const; + + /// @brief Sets the object id of the active mask for this working set + /// @param[in] value The object ID of the active mask for this working set + void set_active_mask(std::uint16_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 18; ///< The fewest bytes of IOP data that can represent this object + + std::vector languageCodes; ///< A list of 2 character language codes, like "en" + std::uint16_t activeMask = NULL_OBJECT_ID; ///< The currently active mask for this working set + bool selectable = false; ///< If this working set is selectable right now + }; + + /// @brief The Data Mask describes the objects that will appear in the Data Mask area of the physical display. + class DataMask : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + BackgroundColour = 1, + SoftKeyMask = 2, + + NumberOfAttributes = 3 + }; + + /// @brief Constructor for a data mask object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + DataMask(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Changes the soft key mask associated to this data mask to a new object ID + /// @param[in] newMaskID The object ID of the new soft key mask to associate with this data mask + /// @returns True if the mask was changed, false if the new ID was not valid and the mask was not changed + bool change_soft_key_mask(std::uint16_t newMaskID); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 12; ///< The fewest bytes of IOP data that can represent this object + }; + + /// @brief Similar to a data mask, but takes priority and will be shown over data masks. + class AlarmMask : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + BackgroundColour = 1, + SoftKeyMask = 2, + Priority = 3, + AcousticSignal = 4, + + NumberOfAttributes = 5 + }; + + /// @brief Enumerates the different mask priorities. Higher priority masks will be shown over lower priority ones across all working sets. + enum class Priority : std::uint8_t + { + High = 0, ///< High, operator is in danger or urgent machine malfunction + Medium = 1, ///< Medium, normal alarm, machine is malfunctioning + Low = 2 ///< Low, information only + }; + + /// @brief Enumerates the acoustic signal values for the alarm mask. Works only if your VT has a way to make sounds. + /// @details The result of this setting is somewhat proprietary depending on your VT + enum AcousticSignal : std::uint8_t + { + Highest = 0, ///< Most aggressive beeping + Medium = 1, ///< Medium beeping + Lowest = 3, ///< Low beeping + None = 4 ///< No beeping + }; + + /// @brief Constructor for a alarm mask object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + AlarmMask(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the priority of the alarm mask + /// @details Higher priority masks will be shown over lower priority ones. + /// @returns The priority of the alarm mask + Priority get_mask_priority() const; + + /// @brief Sets the priority of the alarm mask. + /// @details Higher priority masks will be shown over lower priority ones. + /// @param[in] value The priority to set + void set_mask_priority(Priority value); + + /// @brief Returns the acoustic signal priority for the alarm mask. + /// @details Controls how aggressive the beep is on VTs with a speaker or whistle chip. + /// @returns The acoustic signal priority of the alarm mask + AcousticSignal get_signal_priority() const; + + /// @brief Sets the acoustic signal priority for the alarm mask + /// @details Controls how aggressive the beep is on VTs with a speaker or whistle chip. + /// @param value The acoustic signal priority to set + void set_signal_priority(AcousticSignal value); + + /// @brief Changes the soft key mask associated to this alarm mask to a new object ID + /// @param[in] newMaskID The object ID of the new soft key mask to associate with this alarm mask + /// @returns True if the mask was changed, false if the new ID was not valid and the mask was not changed + bool change_soft_key_mask(std::uint16_t newMaskID); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 10; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t softKeyMask = NULL_OBJECT_ID; ///< Object ID of a soft key mask for this alarm mask, or the null ID + Priority maskPriority = Priority::High; ///< The priority of this mask + AcousticSignal signalPriority = AcousticSignal::Highest; ///< The acoustic signal priority for this mask + }; + + /// @brief The Container object is used to group objects for the purpose of moving, hiding or sharing the group. + /// @details A container is not a visible object, only a logical grouping of other objects. Unlike masks, containers can be + /// hidden and shown at run-time + class Container : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + Hidden = 3, + + NumberOfAttributes = 4 + }; + + /// @brief Constructor for a container object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + Container(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the "hidden" attribute for this container + /// @returns true if the hidden attribute is set, otherwise `false` + bool get_hidden() const; + + /// @brief Sets the "hidden" attribute for this container + /// @param[in] value The new attribute state + void set_hidden(bool value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 9; ///< The fewest bytes of IOP data that can represent this object + + bool hidden = false; ///< The hidden attribute state for this container object. True means it will be hidden when rendered. + }; + + /// @brief The Soft Key Mask is a Container object that contains Key objects, Object Pointer objects, or External Object + /// Pointer objects. + /// @details Keys are assigned to physical Soft Keys in the order listed. It is allowable for a Soft Key Mask to + /// contain no Keys in order that all Soft Keys are effectively disabled when this mask is activated + class SoftKeyMask : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + BackgroundColour = 1, + + NumberOfAttributes = 2 + }; + + /// @brief Constructor for a soft key mask object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + SoftKeyMask(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 6; ///< The fewest bytes of IOP data that can represent this object + }; + + /// @brief The Key object defines the designator and key code for a Soft Key. Any object located outside of a Soft Key + /// designator is clipped. + class Key : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + BackgroundColour = 1, + KeyCode = 2, + + NumberOfAttributes = 3 + }; + + /// @brief Constructor for a key object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + Key(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the key code associated to this key object + /// @returns The key code associated to this key object + std::uint8_t get_key_code() const; + + /// @brief Sets the key code associated to this key object + /// @param[in] value The key code to set + void set_key_code(std::uint8_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 7; ///< The fewest bytes of IOP data that can represent this object + + std::uint8_t keyCode = 0; ///< They key code associated with events from this key object + }; + + /// @brief The Key objects contained in this object shall be a grouping of Key objects, or Object Pointers to Key objects + class KeyGroup : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Options = 1, + Name = 2, + + NumberOfAttributes = 3 + }; + + /// @brief Enumerates the options bits in the options bitfield of a KeyGroup + enum class Options : std::uint8_t + { + Available = 0, ///< If 0 (FALSE) this object is not available for use at the present time, even though defined + Transparent = 1 ///< If this bit is 1, the VT shall ignore the background colour attribute in all child Key objects + }; + + /// @brief Constructor for a key group object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + KeyGroup(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the key group icon that represents this key group + /// @returns Object ID of the key group icon that represents this key group + std::uint16_t get_key_group_icon() const; + + /// @brief Sets the object ID of the icon to use when representing this key group + /// @param[in] value Object ID of a picture graphic to use as the key group icon + void set_key_group_icon(std::uint16_t value); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + /// @brief Sets the Object ID of an Output String object or an Object Pointer object + /// that points to an Output String object that contains a name for this object + /// @returns Object ID of an Output String object or an Object Pointer object that will represent the name of this key group + std::uint16_t get_name_object_id() const; + + /// @brief Sets the Object ID of an Output String object or an Object Pointer object + /// that points to an Output String object that contains a name for this object + /// @param[in] value The object ID of the object that will represent the name of this key group, CANNOT BE the null object ID + void set_name_object_id(std::uint16_t value); + + static constexpr std::uint8_t MAX_CHILD_KEYS = 4; ///< There shall be a max of 4 keys per group according to the standard + + private: + bool validate_name(std::uint16_t nameIDToValidate) const; ///< Validates that the specified name ID is valid for this object + + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 10; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t keyGroupIcon = NULL_OBJECT_ID; ///< The VT may use this in the proprietary mapping screen to represent the key group + std::uint16_t nameID = NULL_OBJECT_ID; ///< Object ID of a string variable that contains the name of the key group + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + }; + + /// @brief The Button object defines a button control. + /// @details This object is intended mainly for VTs with touch screens or a + /// pointing method but shall be supported by all VTs. + class Button : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + BackgroundColour = 3, + BorderColour = 4, + KeyCode = 5, + Options = 6, // Version 4 and later + + NumberOfAttributes = 7 + }; + + /// @brief Enumerates the options encoded into the options bitfield for a button + enum class Options : std::uint8_t + { + Latchable = 0, ///< If TRUE, the Button is latchable and remains pressed until the next activation. If FALSE, the Button is momentary. + CurrentButtonStateIfLatchable = 1, ///< For latchable Buttons. 0=released, 1=latched + SuppressBorder = 2, ///< If FALSE, VT draws the proprietary border. If TRUE, no border is ever drawn + TransparentBackground = 3, ///< If FALSE, the Button's interior background is filled using the background colour attribute. If TRUE, the Button's background is always transparent + Disabled = 4, ///< If FALSE, the Button is enabled and can be selected and activated by the operator. If TRUE, the Button is drawn disabled (method proprietary) + NoBorder = 5, ///< If FALSE, the Button Border area is used by the VT as described in Bit 2. If TRUE, Bit 2 is ignored therefore no border is ever drawn and the Button Face extends to the full Button Area + Reserved1 = 6, ///< Set to 0 + Reserved2 = 7 ///< Set to 0 + }; + + /// @brief Constructor for a button object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + Button(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the key code associated with this button's events + /// @returns The key code associated with this button's events + std::uint8_t get_key_code() const; + + /// @brief Sets the key code associated with this button's events + /// @param[in] value The key code to set + void set_key_code(std::uint8_t value); + + /// @brief Returns the colour of the button's border as an index into the VT colour table + /// @returns The colour of the button's border as an index into the VT colour table + std::uint8_t get_border_colour() const; + + /// @brief Sets the border colour + /// @param[in] value The border colour to set as an index into the VT colour table + void set_border_colour(std::uint8_t value); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 13; ///< The fewest bytes of IOP data that can represent this object + + std::uint8_t borderColour = 0; ///< Border colour. + std::uint8_t keyCode = 0; ///< Key code assigned by ECU. VT reports this code in the Button Activation message. + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + }; + + /// @brief The Input Boolean object is used to input a TRUE/FALSE type indication from the operator + class InputBoolean : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + BackgroundColour = 1, + Width = 2, + ForegroundColour = 3, + VariableReference = 4, + Value = 5, + Enabled = 6, // Version 4 and later + + NumberOfAttributes = 7 + }; + + /// @brief Constructor for an input boolean object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + InputBoolean(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the value of the boolean (only matters if a reference object is not present) + /// @note The reference object will be a child number variable object if it is present + /// @returns The value of the boolean object + std::uint8_t get_value() const; + + /// @brief Sets the value of the boolean object (only matters if a reference object is not present) + /// @note The reference object will be a child number variable object if it is present + /// @param[in] inputValue The value to set for the boolean's state + void set_value(std::uint8_t inputValue); + + /// @brief Returns if this object is enabled based on the enabled attribute + /// @returns `true` If the enabled attribute on this object is `true`, otherwise `false` + bool get_enabled() const; + + /// @brief Sets the enabled attribute on this object to a new value + /// @param[in] isEnabled The new state for the enabled attribute for this object + void set_enabled(bool isEnabled); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 13; ///< The fewest bytes of IOP data that can represent this object + + std::uint8_t value = 0; ///< Used only if it has no number variable child object + bool enabled = false; ///< If the bool is interactable + }; + + /// @brief This object is used to input a character string from the operator + class InputString : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + BackgroundColour = 3, + FontAttributes = 4, + InputAttributes = 5, + Options = 6, + VariableReference = 7, + Justification = 8, + Enabled = 9, // Version 4 and later + + NumberOfAttributes = 10 + }; + + /// @brief Options that can be applied to the input string + enum class Options : std::uint8_t + { + Transparent = 0, ///< If TRUE, the input field is displayed with background showing through instead of using the background colour + AutoWrap = 1, ///< Auto-Wrapping rules apply + WrapOnHyphen = 2 ///< If TRUE, Auto-Wrapping can occur between a hyphen and the following character. + }; + + /// @brief The allowable horizontal justification options + enum class HorizontalJustification : std::uint8_t + { + PositionLeft = 0, ///< The input string is horizontally justified to the left side of its bounding box + PositionMiddle = 1, ///< The input string is horizontally justified to the center of its bounding box + PositionRight = 2, ///< The input string is horizontally justified to the right side of its bounding box + Reserved = 3 ///< Reserved + }; + + /// @brief The allowable vertical justification options + enum class VerticalJustification : std::uint8_t + { + PositionTop = 0, ///< The input string is vertically justified to the top of its bounding box + PositionMiddle = 1, ///< The input string is vertically justified to the center of its bounding box + PositionBottom = 2, ///< The input string is vertically justified to the bottom of its bounding box + Reserved = 3 ///< Reserved + }; + + /// @brief Constructor for a input string object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + InputString(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns if the input string is enabled for text entry + /// @returns `true` if the input string is enabled for entry + bool get_enabled() const; + + /// @brief Sets the enable/disable state of the input string + /// @param[in] value The new enable/disable state for the input string + void set_enabled(bool value); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + /// @brief Returns the horizontal justification setting of the string + /// @returns The horizontal justification setting of the string + HorizontalJustification get_horizontal_justification() const; + + /// @brief Returns the vertical justification setting of the string + /// @returns The vertical justification setting of the string + VerticalJustification get_vertical_justification() const; + + /// @brief Sets the justification bitfield of the string + /// @param[in] value The justification bitfield to set + void set_justification_bitfield(std::uint8_t value); + + /// @brief Returns a copy of the stored string value. Used only when no string + /// variable objects are children of this object. + /// @returns The value of the string stored in this object + std::string get_value() const; + + /// @brief Changes the stored string value. Use only when no + /// string variable objects are children of this object. + /// @param[in] value The new string value + void set_value(const std::string &value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 19; ///< The fewest bytes of IOP data that can represent this object + + std::string stringValue; ///< The actual string. Used only if variable reference attribute is NULL. Pad with spaces as necessary to satisfy length attribute. + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + std::uint8_t justificationBitfield = 0; ///< Bitfield of justification options + std::uint8_t length = 0; ///< Maximum fixed length of the Input String object value in bytes. This may be set to 0 if a variable reference is used + bool enabled = false; ///< If the string is interactable + }; + + /// @brief This object is used to format, display and change a numeric value based on a supplied integer value. + /// @details Displayed value = (value attribute + Offset) * Scaling Factor + class InputNumber : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + BackgroundColour = 3, + FontAttributes = 4, + Options = 5, + VariableReference = 6, + MinValue = 7, + MaxValue = 8, + Offset = 9, + Scale = 10, + NumberOfDecimals = 11, + Format = 12, + Justification = 13, + Value = 14, + Options2 = 15, // Version 4 and after + + NumberOfAttributes = 16 + }; + + /// @brief Options that can be applied to the input number + enum class Options : std::uint8_t + { + Transparent = 0, ///< If TRUE, the input field is displayed with background showing through instead of using the background colour + DisplayLeadingZeros = 1, ///< If TRUE, fill left to width of field with zeros; justification is applied after filling + DisplayZeroAsBlank = 2, ///< When this option bit is set, a blank field is displayed if and only if the displayed value of the object is exactly zero + Truncate = 3 ///< If TRUE the value shall be truncated to the specified number of decimals. Otherwise it shall be rounded off to the specified number of decimals. + }; + + /// @brief More options, for some reason they are different bytes + enum class Options2 : std::uint8_t + { + Enabled = 0, ///< If TRUE the object shall be enabled + RealTimeEditing = 1 ///< If TRUE the value shall be transmitted to the ECU as it is being changed + }; + + /// @brief The allowable horizontal justification options + enum class HorizontalJustification : std::uint8_t + { + PositionLeft = 0, ///< The input number is horizontally justified to the left side of its bounding box + PositionMiddle = 1, ///< The input number is horizontally justified to the center of its bounding box + PositionRight = 2, ///< The input number is horizontally justified to the right side of its bounding box + Reserved = 3 ///< Reserved + }; + + /// @brief The allowable vertical justification options + enum class VerticalJustification : std::uint8_t + { + PositionTop = 0, ///< The input number is vertically justified to the top of its bounding box + PositionMiddle = 1, ///< The input number is vertically justified to the center of its bounding box + PositionBottom = 2, ///< The input number is vertically justified to the bottom of its bounding box + Reserved = 3 ///< Reserved + }; + + /// @brief Constructor for an input number object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + InputNumber(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the horizontal justification setting of the input number + /// @returns The horizontal justification setting of the input number + HorizontalJustification get_horizontal_justification() const; + + /// @brief Returns the vertical justification setting of the input number + /// @returns The vertical justification setting of the input number + VerticalJustification get_vertical_justification() const; + + /// @brief Sets the justification bitfield of the input number + /// @param[in] value The justification bitfield to set + void set_justification_bitfield(std::uint8_t newJustification); + + /// @brief Returns the scale factor that is applied to the value of the input number + /// @returns The scale factor that is applied to the value of the input number + float get_scale() const; + + /// @brief Sets the scale factor that is applied to the value of the input number + /// @param[in] value The scale factor to set + void set_scale(float newScale); + + /// @brief Returns the maximum value for the input number + /// @details The VT shall not accept values higher than this for this input number's value + /// @returns The maximum value for the input number + std::uint32_t get_maximum_value() const; + + /// @brief Sets the maximum value for the input number + /// @details The VT shall not accept values higher than this for this input number's value + /// @param[in] value The maximum value for the input number + void set_maximum_value(std::uint32_t newMax); + + /// @brief Returns the minimum value for this input number + /// @details The VT shall not accept values smaller than this value for this input number + /// @returns The minimum value for this input number + std::uint32_t get_minimum_value() const; + + /// @brief Sets the minimum value for the input number + /// @details The VT shall not accept values smaller than this value for this input number + /// @param[in] value The minimum value to set for the input number + void set_minimum_value(std::uint32_t newMin); + + /// @brief Returns the offset that will be applied to the number's value when it is displayed + /// @returns The offset that will be applied to the number's value when it is displayed + std::int32_t get_offset() const; + + /// @brief Sets the offset that will be applied to the number's value when it is displayed + /// @param[in] value The new offset that will be applied to the number's value when it is displayed + void set_offset(std::int32_t newOffset); + + /// @brief Returns the number of decimals to display when rendering this input number + /// @returns The number of decimals to display when rendering the input number + std::uint8_t get_number_of_decimals() const; + + /// @brief Sets the number of decimals to display when rendering this number + /// @param[in] value The number of decimals to display + void set_number_of_decimals(std::uint8_t newDecimals); + + /// @brief Returns if the format option is set for this input number + /// @details The format option determines if the value is shown in fixed decimal or exponential form. + /// A value of `true` means fixed decimal (####.nn), and `false` means exponential ([−]###.nnE[+/−]##) + /// @returns `true` if the format option is set for this input number, otherwise `false` + bool get_format() const; + + /// @brief Sets the format option + /// @details The format option determines if the value is shown in fixed decimal or exponential form. + /// A value of `true` means fixed decimal (####.nn), and `false` means exponential ([−]###.nnE[+/−]##) + /// @param[in] value The format value to set. `true` for fixed decimal, false for exponential. + void set_format(bool newFormat); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t newOptions); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool newOption); + + /// @brief Returns the state of a single option in the object's second option bitfield + /// @param[in] option The option to check the value of in the object's second option bitfield + /// @returns The state of the associated option bit + bool get_option2(Options2 newOption) const; + + /// @brief Sets the second options bitfield for this object to a new value + /// @param[in] value The new value for the second options bitfield + void set_options2(std::uint8_t newOptions); + + /// @brief Sets a single option in the second options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option2(Options2 option, bool newOption); + + /// @brief Returns the value of the input number (only matters if there's no child number variable object). + /// @returns The value of the input number + std::uint32_t get_value() const; + + /// @brief Sets the value of the input number (only matters if there's no child number variable object). + /// @param[in] inputValue The value to set for the input number + void set_value(std::uint32_t inputValue); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 38; ///< The fewest bytes of IOP data that can represent this object + + float scale = 0.0f; ///< Scale to be applied to the input value and min/max values. + std::uint32_t maximumValue = 0; ///< Raw maximum value for the input + std::uint32_t minimumValue = 0; ///< Raw minimum value for the input before scaling + std::uint32_t value = 0; ///< The raw value of the object, used if no number variable child has been set + std::int32_t offset = 0; ///< Offset to be applied to the input value and min/max values + std::uint8_t numberOfDecimals = 0; ///< Specifies number of decimals to display after the decimal point + std::uint8_t options = 0; ///< Options byte 1 + std::uint8_t options2 = 0; ///< Options byte 2 + std::uint8_t justificationBitfield = 0; ///< Indicates how the number is positioned in the field defined by height and width + bool format = false; ///< 0 = use fixed format decimal display (####.nn), 1 = use exponential format ([-]###.nnE[+/-]##) where n is set by the number of decimals + }; + + /// @brief The Input List object is used to show one object out of a set of objects, + /// and to allow operator selection of one object from the set. + class InputList : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + VariableReference = 3, + Value = 4, + Options = 5, // Version 4 and after + + NumberOfAttributes = 6 + }; + + /// @brief Enumerates the bits in the options bitfield for an InputList + enum class Options + { + Enabled = 0, ///< If true the object shall be enabled + RealTimeEditing = 1 ///< If true the value shall be transmitted to the ECU as it is being changed + }; + + /// @brief Constructor for an input list object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + InputList(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t options); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + /// @brief Returns the value of the selected list index (only matters if there is no child number variable) + /// @returns The value of the selected list index + std::uint8_t get_value() const; + + /// @brief Sets the selected list index (only matters when the object has no child number variable) + /// @param[in] inputValue The new value for the selected list index + void set_value(std::uint8_t inputValue); + + /// @brief A dedicated way to set the stored variable reference so we don't have + /// to worry about the child object list getting messed up from changing the attribute + /// or a list item. + /// @param[in] referencedObjectID The object ID of a number variable to set as the value reference + void set_variable_reference(std::uint16_t referencedObjectID); + + /// @brief Returns the variable reference, which is an object ID of a number variable or NULL_OBJECT_ID (0xFFFF) + std::uint16_t get_variable_reference() const; + + /// @brief Changes a list item to a new ID by index + /// @param[in] index The index to change (starting from 0) + /// @param[in] newListItem The object ID to use as the new list item at the specified index + /// @returns True if the operation was successful, otherwise false (perhaps the index is out of bounds?) + bool change_list_item(std::uint8_t index, std::uint16_t newListItem); + + /// @brief Returns the number of items in the list + /// @note This is not the number of children, it's the number of allocated + /// list items. The number of children can be less than this number. + /// @returns The number of items in the list + std::uint8_t get_number_of_list_items() const; + + /// @brief Sets the number of items in the list + /// @note This is not the number of children, it's the number of allocated + /// list items. The number of children can be less than this number. + /// @param[in] value The number of items in the list + void set_number_of_list_items(std::uint8_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 13; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t variableReference = NULL_OBJECT_ID; ///< Stores the object ID of a number variable that will be used as the value, or the NULL_OBJECT_ID if not used. + std::uint8_t numberOfListItems = 0; ///< Number of object references to follow. The size of the list can never exceed this number and this attribute cannot be changed. + std::uint8_t optionsBitfield = 0; ///< Options byte + std::uint8_t value = 0; ///< Selected list index of this object. Used only if variable reference attribute is NULL + }; + + /// @brief This object is used to output a string of text + class OutputString : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + BackgroundColour = 3, + FontAttributes = 4, + Options = 5, + VariableReference = 6, + Justification = 7, + + NumberOfAttributes = 8 + }; + + /// @brief Enumerates the option bits in the options bitfield for an output string + enum class Options + { + Transparent = 0, ///< If TRUE, the output field is displayed with background showing through instead of using the background colour + AutoWrap = 1, ///< Auto-Wrapping rules apply + WrapOnHyphen = 2 ///< If TRUE, Auto-Wrapping can occur between a hyphen and the next character + }; + + /// @brief The allowable horizontal justification options + enum class HorizontalJustification : std::uint8_t + { + PositionLeft = 0, ///< Output string is horizontally aligned to the left of its bounding box + PositionMiddle = 1, ///< Output string is horizontally aligned to the center of its bounding box + PositionRight = 2, ///< Output string is horizontally aligned to the right of its bounding box + Reserved = 3 ///< Reserved + }; + + /// @brief The allowable vertical justification options + enum class VerticalJustification : std::uint8_t + { + PositionTop = 0, ///< Output string is vertically aligned to the top of its bounding box + PositionMiddle = 1, ///< Output string is vertically aligned to the center of its bounding box + PositionBottom = 2, ///< Output string is vertically aligned to the bottom of its bounding box + Reserved = 3 ///< Reserved + }; + + /// @brief Constructor for an output string object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputString(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + /// @brief Returns the horizontal justification of the output string within its bounding box + /// @returns The horizontal justification of the output string within its bounding box + HorizontalJustification get_horizontal_justification() const; + + /// @brief Returns the vertical justification of the output string within its bounding box + /// @returns The vertical justification of the output string within its bounding box + VerticalJustification get_vertical_justification() const; + + /// @brief Sets the justification bitfield for the object to a new value + /// @param[in] value The new value for the justification bitfield + void set_justification_bitfield(std::uint8_t value); + + /// @brief Returns the value of the string, used only if the variable reference (a child var string) is NULL_OBJECT_ID + /// @returns The value of the string + std::string get_value() const; + + /// @brief Sets the value of the string (only matters if it has no child string variable) + /// @param[in] value The new value for the string + void set_value(const std::string &value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 16; ///< The fewest bytes of IOP data that can represent this object + + std::string stringValue; ///< The actual string. Used only if variable reference attribute is NULL. Pad with spaces as necessary to satisfy length attribute. + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + std::uint8_t justificationBitfield = 0; ///< Bitfield of justification options + std::uint8_t length = 0; ///< Maximum fixed length of the Input String object value in bytes. This may be set to 0 if a variable reference is used + }; + + /// @brief This object is used to format and output a numeric value based on a supplied integer value. + class OutputNumber : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + BackgroundColour = 3, + FontAttributes = 4, + Options = 5, + VariableReference = 6, + Offset = 7, + Scale = 8, + NumberOfDecimals = 9, + Format = 10, + Justification = 11, + + NumberOfAttributes = 12 + }; + + /// @brief Options that can be applied to the input number + enum class Options : std::uint8_t + { + Transparent = 0, ///< If true, the input field is displayed with background showing through instead of using the background colour + DisplayLeadingZeros = 1, ///< If true, fill left to width of field with zeros; justification is applied after filling + DisplayZeroAsBlank = 2, ///< When this option bit is set, a blank field is displayed if and only if the displayed value of the object is exactly zero + Truncate = 3 ///< If true the value shall be truncated to the specified number of decimals. Otherwise it shall be rounded off to the specified number of decimals. + }; + + /// @brief The allowable horizontal justification options + enum class HorizontalJustification : std::uint8_t + { + PositionLeft = 0, ///< The output number is horizontally justified to the left side of its bounding box + PositionMiddle = 1, ///< The output number is horizontally justified to the center of its bounding box + PositionRight = 2, ///< The output number is horizontally justified to the right side of its bounding box + Reserved = 3 ///< Reserved + }; + + /// @brief The allowable vertical justification options + enum class VerticalJustification : std::uint8_t + { + PositionTop = 0, ///< The output number is vertically justified to the top of its bounding box + PositionMiddle = 1, ///< The output number is vertically justified to the center of its bounding box + PositionBottom = 2, ///< The output number is vertically justified to the bottom of its bounding box + Reserved = 3 ///< Reserved + }; + + /// @brief Constructor for an output number object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputNumber(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + /// @brief Returns the horizontal justification of the output number within its bounding box + /// @return The horizontal justification of the output number within its bounding box + HorizontalJustification get_horizontal_justification() const; + + /// @brief Returns the vertical justification of the output number within its bounding box + /// @return The vertical justification of the output number within its bounding box + VerticalJustification get_vertical_justification() const; + + /// @brief Sets the justification bitfield to a new value + /// @param[in] value The new value for the justification bitfield + void set_justification_bitfield(std::uint8_t value); + + /// @brief Returns the scale factor of the output number + /// @returns The scale factor of the output number + float get_scale() const; + + /// @brief Sets the scale factor for the output number + /// @param[in] value The new value for the scale factor + void set_scale(float value); + + /// @brief Returns the offset that is applied to the output number + /// @returns The offset of the output number + std::int32_t get_offset() const; + + /// @brief Sets the offset of the output number + /// @param[in] value The offset to set for the output number + void set_offset(std::int32_t value); + + /// @brief Returns the number of decimals to render in the output number + /// @returns The number of decimals to render in the output number + std::uint8_t get_number_of_decimals() const; + + /// @brief Sets the number of decimals to render in the output number + /// @param[in] value The number of decimals to render in the output number + void set_number_of_decimals(std::uint8_t value); + + /// @brief Returns if the "format" option is set for this object + /// @details The format option determines if fixed decimal or exponential notation is used. + /// A value of `false` is fixed decimal notation, and `true` is exponential notation + /// @returns `true` if the format option is set + bool get_format() const; + + /// @brief Sets the format option for this object. + /// @details The format option determines if fixed decimal or exponential notation is used. + /// A value of `false` is fixed decimal notation, and `true` is exponential notation + /// @param[in] value `true` to use fixed decimal notation (####.nn), `false` to use exponential ([−]###.nnE[+/−]##) + void set_format(bool value); + + /// @brief Returns the value of the output number (only matters if there's no child number variable object). + /// @returns The value of the output number. + std::uint32_t get_value() const; + + /// @brief Sets the value of the output number (only matters if there's no child number variable object). + /// @param[in] inputValue The value to set for the output number + void set_value(std::uint32_t inputValue); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 29; ///< The fewest bytes of IOP data that can represent this object + + float scale = 1.0f; ///< Scale to be applied to the input value and min/max values. + std::int32_t offset = 0; ///< Offset to be applied to the input value and min/max values + std::uint32_t value = 0; ///< Raw unsigned value of the output field before scaling (unsigned 32-bit integer). Used only if variable reference attribute is NULL + std::uint8_t numberOfDecimals = 0; ///< Specifies number of decimals to display after the decimal point + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + std::uint8_t justificationBitfield = 0; ///< Bitfield of justification options + bool format = false; ///< 0 = use fixed format decimal display (####.nn), 1 = use exponential format ([-]###.nnE[+/-]##) where n is set by the number of decimals + }; + + /// @brief Used to show one object out of a set of objects + class OutputList : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + VariableReference = 3, + Value = 4, + + NumberOfAttributes = 5 + }; + + /// @brief Constructor for an output list object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputList(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the number of items in the list + /// @note This is not the number of children, it's the number of allocated + /// list items. The number of children can be less than this number. + /// @returns The number of items in the list + std::uint8_t get_number_of_list_items() const; + + /// @brief Sets the number of items in the list + /// @note This is not the number of children, it's the number of allocated + /// list items. The number of children can be less than this number. + /// @param[in] value The number of items in the list + void set_number_of_list_items(std::uint8_t value); + + /// @brief Returns the value of the selected list index (only matters if no child number variable object is present) + /// @returns The value of the selected list index + std::uint8_t get_value() const; + + /// @brief Sets the value of the selected list index (only matters if no child number variable object is present) + /// @param[in] value The value to set for the list's selected index + void set_value(std::uint8_t value); + + /// @brief A dedicated way to set the stored variable reference so we don't have + /// to worry about the child object list getting messed up from changing the attribute + /// or a list item. + /// @param[in] referencedObjectID The object ID of a number variable to set as the value reference + void set_variable_reference(std::uint16_t referencedObjectID); + + /// @brief Returns the variable reference, which is an object ID of a number variable or NULL_OBJECT_ID (0xFFFF) + std::uint16_t get_variable_reference() const; + + /// @brief Changes a list item to a new ID by index + /// @param[in] index The index to change (starting from 0) + /// @param[in] newListItem The object ID to use as the new list item at the specified index + /// @returns True if the operation was successful, otherwise false (perhaps the index is out of bounds?) + bool change_list_item(std::uint8_t index, std::uint16_t newListItem); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 12; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t variableReference = NULL_OBJECT_ID; ///< The object ID of a number variable to use for the value/selected index, or NULL_OBJECT_ID + std::uint8_t numberOfListItems = 0; ///< Number of object references to follow. The size of the list can never exceed this number and this attribute cannot be changed. + std::uint8_t value = 0; ///< Selected list index of this object. Used only if variable reference attribute is NULL + }; + + /// @brief This object outputs a line shape. The starting point for the line is found in the parent object + class OutputLine : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + LineAttributes = 1, + Width = 2, + Height = 3, + LineDirection = 4, + + NumberOfAttributes = 5 + }; + + /// @brief Enumerates the different directions a line can be drawn + enum class LineDirection : std::uint8_t + { + TopLeftToBottomRight = 0, + BottomLeftToTopRight = 1 + }; + + /// @brief Constructor for an output line object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputLine(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the line's direction. + /// @details When the line direction is zero, the ine is drawn from top left to bottom right of + /// enclosing virtual rectangle. When the line direction is 1, the line is drawn from bottom left to top right of + /// enclosing virtual rectangle. + /// @returns The line's direction (see details). + LineDirection get_line_direction() const; + + /// @brief Sets the line's direction. + /// @details When the line direction is zero, the ine is drawn from top left to bottom right of + /// enclosing virtual rectangle. When the line direction is 1, the line is drawn from bottom left to top right of + /// enclosing virtual rectangle. + /// @param[in] value The line direction to set (see details). + void set_line_direction(LineDirection value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 11; ///< The fewest bytes of IOP data that can represent this object + + std::uint8_t lineDirection = 0; ///< 0 = Line is drawn from top left to bottom right of enclosing virtual rectangle, 1 = Line is drawn from bottom left to top right + }; + + /// @brief This object outputs a rectangle shape + class OutputRectangle : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + LineAttributes = 1, + Width = 2, + Height = 3, + LineSuppression = 4, + FillAttributes = 5, + + NumberOfAttributes = 6 + }; + /// @brief The different line suppression options + enum class LineSuppressionOption + { + SuppressTopLine = 0, ///< Suppress the top line of the rectangle + SuppressRightSideLine = 1, ///< Suppress the right side of the rectangle + SuppressBottomLine = 2, ///< Suppress the bottom line of the rectangle + SuppressLeftSideLine = 3 ///< Suppress the left line of the rectangle + }; + + /// @brief Constructor for an output rectangle object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputRectangle(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the line suppression bitfield. + /// @note See LineSuppressionOption for the bit definitions. + /// @returns The line suppression bitfield (see LineSuppressionOption). + std::uint8_t get_line_suppression_bitfield() const; + + /// @brief Sets the line suppression bitfield value. + /// @note See LineSuppressionOption for the bit definitions. + /// @param[in] value The line suppression bitfield to set. + void set_line_suppression_bitfield(std::uint8_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 13; ///< The fewest bytes of IOP data that can represent this object + + std::uint8_t lineSuppressionBitfield = 0; ///< Bitfield of line suppression options + }; + + /// @brief This object outputs an ellipse or circle shape + class OutputEllipse : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + LineAttributes = 1, + Width = 2, + Height = 3, + EllipseType = 4, + StartAngle = 5, + EndAngle = 6, + FillAttributes = 7, + + NumberOfAttributes = 8 + }; + + /// @brief Types of ellipse + enum class EllipseType + { + Closed = 0, ///< Closed ellipse + OpenDefinedByStartEndAngles = 1, ///< The ellipse is defined by start and end angles + ClosedEllipseSegment = 2, + ClosedEllipseSection = 3 + }; + + /// @brief Constructor for an output ellipse object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputEllipse(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the type of the ellipse + /// @returns The type of the ellipse + EllipseType get_ellipse_type() const; + + /// @brief Sets the ellipse type + /// @param[in] value The ellipse type to set + void set_ellipse_type(EllipseType value); + + /// @brief Returns the Start angle/2 (in degrees) from positive X axis + /// counter clockwise(90° is straight up) for the ellipse. + /// @details The range for this is 0 to 180. + /// @note If type > 0 and start and end angles are the same, the ellipse is drawn closed. + /// @returns Start angle/2 (in degrees) from positive X axis counter clockwise (90° is straight up) + std::uint8_t get_start_angle() const; + + /// @brief Sets the start angle for the ellipse + /// @note If type > 0 and start and end angles are the same, the ellipse is drawn closed. + /// @param[in] value Start angle/2 (in degrees) from positive X axis counter clockwise(90° is straight up) + void set_start_angle(std::uint8_t value); + + /// @brief Returns the end angle/2 (in degrees) from positive X axis counter clockwise(90° is straight up). + /// @details The range for this is 0 to 180. + /// @note If type > 0 and start and end angles are the same, the ellipse is drawn closed. + /// @returns End angle/2 (in degrees) from positive X axis counter clockwise (90° is straight up) + std::uint8_t get_end_angle() const; + + /// @brief Sets the end angle for the ellipse. + /// @note If type > 0 and start and end angles are the same, the ellipse is drawn closed. + /// @param[in] value The end angle/2 (in degrees) from positive X axis counter clockwise(90° is straight up). + void set_end_angle(std::uint8_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 15; ///< The fewest bytes of IOP data that can represent this object + + std::uint8_t ellipseType = 0; ///< The type of ellipse + std::uint8_t startAngle = 0; ///< Start angle/2 (in degrees) from positive X axis counter clockwise (90° is straight up). + std::uint8_t endAngle = 0; ///< End angle/2 (in degrees) from positive X axis counter clockwise (90° is straight up) + }; + + /// @brief This object outputs a polygon + class OutputPolygon : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + LineAttributes = 3, + FillAttributes = 4, + PolygonType = 5, + + NumberOfAttributes = 6 + }; + + /// @brief Polygon type. The first three types are useful only if the polygon is to be filled. + enum class PolygonType + { + Convex = 0, ///< On any given horizontal line, only two points on the polygon are encountered + NonConvex = 1, ///< On any given horizontal line, more than two points on the polygon edges can be encountered but the polygon edges do not cross + Complex = 2, ///< Similar to Non-convex but edges cross. Uses Complex Fill Algorithm + Open = 3 ///< This type cannot be filled + }; + + /// @brief Stores a cartesian polygon point + struct PolygonPoint + { + std::uint16_t xValue; ///< X value of a point relative to the top left corner of the polygon + std::uint16_t yValue; ///< Y value of a point relative to the top left corner of the polygon + }; + + /// @brief Constructor for an output polygon object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputPolygon(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Adds a point to the polygon, defined by x and y coordinates + /// @param[in] x The X value of a point relative to the top left corner of the polygon + /// @param[in] y The Y value of a point relative to the top left corner of the polygon + void add_point(std::uint16_t x, std::uint16_t y); + + /// @brief Returns the number of polygon points + /// @returns The number of polygon points + std::uint8_t get_number_of_points() const; + + /// @brief Returns a point from the polygon by index + /// @param[in] index The index of the point to retrieve + /// @returns A point in the polygon by index, or zeros if the index is out of range. + PolygonPoint get_point(std::uint8_t index); + + /// @brief Returns the polygon type of this object + /// @returns The polygon type of this object + PolygonType get_type() const; + + /// @brief Sets the polygon type for this object + /// @param[in] value The new polygon type for this object + void set_type(PolygonType value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 14; ///< The fewest bytes of IOP data that can represent this object + + std::vector pointList; ///< List of points that make up the polygon. Must be at least 3 points! + std::uint8_t polygonType = 0; ///< The polygon type. Affects how the object gets drawn. + }; + + /// @brief This object is a meter. Meter is drawn about a circle enclosed within a defined square. + class OutputMeter : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + NeedleColour = 2, + BorderColour = 3, + ArcAndTickColour = 4, + Options = 5, + NumberOfTicks = 6, + StartAngle = 7, + EndAngle = 8, + MinValue = 9, + MaxValue = 10, + VariableReference = 11, + Value = 12, + + NumberOfAttributes = 13 + }; + + /// @brief Options that can be applied to the input number + enum class Options : std::uint8_t + { + DrawArc = 0, ///< Draw Arc + DrawBorder = 1, ///< Draw Border + DrawTicks = 2, ///< Draw Ticks + DeflectionDirection = 3 ///< 0 = From min to max, counterclockwisee. 1 = from min to max, clockwise + }; + + /// @brief Constructor for an output meter object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputMeter(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the minimum value of the output meter + /// @returns The minimum value of the output meter + std::uint16_t get_min_value() const; + + /// @brief Sets the minimum value of the output meter + /// @param[in] value The minimum value to set for the output meter + void set_min_value(std::uint16_t value); + + /// @brief Returns the max value for the output meter + /// @returns The max value for the output meter + std::uint16_t get_max_value() const; + + /// @brief Sets the max value for the output meter + /// @param[in] value The max value to set for the output meter + void set_max_value(std::uint16_t value); + + /// @brief Returns the value for the output meter (only matters if there's no child number variable object). + /// @returns The value of the output meter + std::uint16_t get_value() const; + + /// @brief Sets the value of the output meter (only matters if there's no child number variable object). + /// @param[in] value The value to set for the output meter + void set_value(std::uint16_t value); + + /// @brief Returns the value of the needle colour + /// @returns The value of the needle colour as an index into the VT colour table + std::uint8_t get_needle_colour() const; + + /// @brief Sets the value of the needle colour + /// @param[in] value The colour to set for the needle as an index into the VT colour table + void set_needle_colour(std::uint8_t value); + + /// @brief Returns the border colour of the meter + /// @returns The border colour of the meter as an index into the VT colour table + std::uint8_t get_border_colour() const; + + /// @brief Sets the border colour of the meter + /// @param[in] value The border colour to set for the meter as an index into the VT colour table + void set_border_colour(std::uint8_t value); + + /// @brief Returns the arc and tick colour for the meter + /// @returns The arc and tick colour for the meter as an index into the VT colour table + std::uint8_t get_arc_and_tick_colour() const; + + /// @brief Sets the arc and tick colour for the meter + /// @param[in] value The arc and tick colour to set for the meter as an index into the VT colour table + void set_arc_and_tick_colour(std::uint8_t value); + + /// @brief Returns the number of ticks to render across the meter + /// @returns The number of ticks to render across the meter + std::uint8_t get_number_of_ticks() const; + + /// @brief Sets the number of ticks to render when drawing the meter + /// @param[in] value The number of ticks to render + void set_number_of_ticks(std::uint8_t value); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + /// @brief Returns the start angle for the meter + /// @note If the start and end angles are the same the meter’s arc is closed. + /// @returns Start angle/2 (in degrees) from positive X axis anticlockwise(90° is straight up). + std::uint8_t get_start_angle() const; + + /// @brief Sets the start angle for the meter + /// @note If the start and end angles are the same the meter’s arc is closed. + /// @param[in] value Start angle/2 (in degrees) from positive X axis anticlockwise(90° is straight up). + void set_start_angle(std::uint8_t value); + + /// @brief Returns the end angle of the meter. + /// @note If the start and end angles are the same the meter’s arc is closed. + /// @returns The end angle/2 (in degrees) from positive X axis anticlockwise(90° is straight up). + std::uint8_t get_end_angle() const; + + /// @brief Sets the end angle for this meter in degrees from the +x axis counter clockwise + /// @note If the start and end angles are the same the meter’s arc is closed. + /// @param[in] value End angle/2 (in degrees) from positive X axis anticlockwise(90° is straight up). + void set_end_angle(std::uint8_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 21; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t minValue = 0; ///< Minimum value. Represents value when needle is at the start of arc + std::uint16_t maxValue = 0; ///< Maximum value. Represents when the needle is at the end of the arc. + std::uint16_t value = 0; ///< Current value. Needle position set to this value, used if variable ref is NULL. + std::uint8_t needleColour = 0; ///< Needle (indicator) colour + std::uint8_t borderColour = 0; ///< Border colour (if drawn) + std::uint8_t arcAndTickColour = 0; ///< Meter arc and tick colour (if drawn) + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + std::uint8_t numberOfTicks = 0; ///< Number of ticks to draw about meter arc + std::uint8_t startAngle = 0; ///< Start angle / 2 in degrees from positive X axis counterclockwise + std::uint8_t endAngle = 0; ///< End angle / 2 in degrees from positve X axis counterclockwise + }; + + /// @brief This is a linear bar graph or thermometer, defined by an enclosing rectangle. + class OutputLinearBarGraph : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + Colour = 3, + TargetLineColour = 4, + Options = 5, + NumberOfTicks = 6, + MinValue = 7, + MaxValue = 8, + VariableReference = 9, + TargetValueVariableReference = 10, + TargetValue = 11, + Value = 12, + + NumberOfAttributes = 13 + }; + + /// @brief Options that can be applied to the input number + enum class Options : std::uint8_t + { + DrawBorder = 0, ///< Draw Border + DrawTargetLine = 1, ///< Draw Target Line + DrawTicks = 2, ///< Draw Ticks + BarGraphType = 3, ///< 0 = Filled, 1 = not filled with value line + AxisOrientation = 4, ///< 0 = vertical, 1 = horizontal + Direction = 5 ///< 0 = Grows negative, 1 = Grows positive + }; + + /// @brief Constructor for an output linear bar graph object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputLinearBarGraph(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the minimum value on the graph. Used to scale the graph's range. + /// @returns The minimum value that will be shown on the graph. + std::uint16_t get_min_value() const; + + /// @brief Sets the minimum value on the graph. + /// @details Used to scale the graph's range. Values below this will be clamped to the min. + /// @param[in] value The minimum value to set + void set_min_value(std::uint16_t value); + + /// @brief Returns the max value for the graph + /// @returns The max value for the graph + std::uint16_t get_max_value() const; + + /// @brief Sets the max value for the graph + /// @param[in] value The max value to set for the graph + void set_max_value(std::uint16_t value); + + /// @brief Returns the value of the graph (only matters if there's no child number variable object). + /// @returns The value of the graph + std::uint16_t get_value() const; + + /// @brief Sets the value of the graph (only matters if there's no child number variable object). + /// @param[in] value The value to set for the graph + void set_value(std::uint16_t value); + + /// @brief Returns the graph's target value (only matters if there's no target value reference). + /// @returns The graph's target value + std::uint16_t get_target_value() const; + + /// @brief Sets the target value for the graph (only matters if there's no target value reference). + /// @param[in] value The target value to set + void set_target_value(std::uint16_t value); + + /// @brief Returns the target value reference object ID + /// @details This object will be used (if it's not NULL_OBJECT_ID) + /// to determine the target value of the graph instead of the target value itself. + /// @returns The object ID of a number variable to use for the target value + std::uint16_t get_target_value_reference() const; + + /// @brief Sets the target value reference object ID + /// @details This object will be used (if it's not NULL_OBJECT_ID) + /// to determine the target value of the graph instead of the target value itself. + /// @param[in] value The object ID of a number variable to use for the target value + void set_target_value_reference(std::uint16_t value); + + /// @brief Returns the number of ticks to render across the graph + /// @returns The number of ticks to render across the graph + std::uint8_t get_number_of_ticks() const; + + /// @brief Sets the number of ticks to render when drawing the graph + /// @param[in] value The number of ticks to graph + void set_number_of_ticks(std::uint8_t value); + + /// @brief Returns the colour of the graph + /// @returns The colour of the graph as an index into the VT colour table + std::uint8_t get_colour() const; + + /// @brief Sets the colour of the graph + /// @param[in] value The colour of the graph to set as an index into the VT colour table + void set_colour(std::uint8_t value); + + /// @brief Returns the target line colour as an index into the VT colour table + /// @returns The target line colour as an index into the VT colour table + std::uint8_t get_target_line_colour() const; + + /// @brief Sets the target line colour + /// @param[in] value The colour to set for the target line as an index into the VT colour table + void set_target_line_colour(std::uint8_t value); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 24; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t minValue = 0; ///< Minimum value + std::uint16_t maxValue = 0; ///< Maximum value + std::uint16_t targetValue = 0; ///< Current target value. Used only if Target value variable Reference attribute is NULL. + std::uint16_t targetValueReference = NULL_OBJECT_ID; ///< Object ID of a Number Variable object in which to retrieve the bar graph’s target value. + std::uint16_t value = 0; ///< Current value. Needle position set to this value, used if variable ref is NULL. + std::uint8_t numberOfTicks = 0; ///< Number of ticks to draw along the bar graph + std::uint8_t colour = 0; ///< Bar graph fill and border colour. + std::uint8_t targetLineColour = 0; ///< Target line colour (if drawn). + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + }; + + /// @brief TThis object is similar in concept to a linear bar graph but appears arched. Arched bar graphs are drawn about + /// an Output Ellipse object enclosed within a defined rectangle + class OutputArchedBarGraph : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Height = 2, + Colour = 3, + TargetLineColour = 4, + Options = 5, + StartAngle = 6, + EndAngle = 7, + BarGraphWidth = 8, + MinValue = 9, + MaxValue = 10, + VariableReference = 11, + TargetValueVariableReference = 12, + TargetValue = 13, + + NumberOfAttributes = 14 + }; + + /// @brief Options that can be applied to the input number + enum class Options : std::uint8_t + { + DrawBorder = 0, ///< Draw border + DrawTargetLine = 1, ///< Draw a target line + Undefined = 2, ///< Undefined, set to 0 recommended + BarGraphType = 3, ///< bar graph type. If this bit is FALSE (0), bar graph is filled + Deflection = 4 ///< 0 = anticlockwise and 1 = clockwise + }; + + /// @brief Constructor for an output arched bar graph object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + OutputArchedBarGraph(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the width (px) of the bar graph + /// @returns The width (px) of the bar graph + std::uint16_t get_bar_graph_width() const; + + /// @brief Sets the width (px) of the bar graph + /// @param[in] value The width (px) to set for the bar graph + void set_bar_graph_width(std::uint16_t value); + + /// @brief Returns the minimum value of the bar graph. + /// @note Values below this will be clamped to the min when rendered. + /// @returns The minimum value of the bar graph + std::uint16_t get_min_value() const; + + /// @brief Sets the minimum value for the bar graph + /// @note Values below this will be clamped to the min when rendered. + /// @param[in] value The minimum value to set + void set_min_value(std::uint16_t value); + + /// @brief Returns the maximum value of the bar graph + /// @note Values above this will be clamped to the max when rendered. + /// @returns The maximum value of the bar graph + std::uint16_t get_max_value() const; + + /// @brief Sets the max value of the bar graph + /// @note Values above this will be clamped to the max when rendered. + /// @param[in] value The maximum value of the bar graph to set + void set_max_value(std::uint16_t value); + + /// @brief Returns the value of the bar graph (only matters when no child number variable is used) + /// @returns The value of the bar graph + std::uint16_t get_value() const; + + /// @brief Sets the value of the bar graph (only matters when no child number variable is used) + /// @param[in] value The value to set for the bar graph + void set_value(std::uint16_t value); + + /// @brief Returns the colour of the target line + /// @returns The colour of the target line as an index into the VT colour table + std::uint8_t get_target_line_colour() const; + + /// @brief Sets the colour of the target line + /// @param[in] value The colour to set as an index into the VT colour table + void set_target_line_colour(std::uint8_t value); + + /// @brief Returns the colour of the bar graph + /// @returns The colour of the bar graph as an index into the VT colour table + std::uint8_t get_colour() const; + + /// @brief Sets the colour of the bar graph + /// @param[in] value The colour to set for the bar graph as an index into the VT colour table + void set_colour(std::uint8_t value); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + /// @brief Returns the start angle of the graph + /// @returns Start angle/2 (in degrees) from positive X axis anticlockwise (90° is straight up) for the graph + std::uint8_t get_start_angle() const; + + /// @brief Sets the start angle for the graph + /// @param[in] value Start angle/2 (in degrees) from positive X axis anticlockwise (90° is straight up) for the graph + void set_start_angle(std::uint8_t value); + + /// @brief Returns the end angle of the graph + /// @returns End angle/2 (in degrees) from positive X axis anticlockwise (90° is straight up) for the graph + std::uint8_t get_end_angle() const; + + /// @brief Sets the end angle for the graph + /// @param[in] value End angle/2 (in degrees) from positive X axis anticlockwise (90° is straight up) for the graph + void set_end_angle(std::uint8_t value); + + /// @brief Returns the target value of the graph (only matters when no target value reference is used) + /// @returns The target value of the graph + std::uint16_t get_target_value() const; + + /// @brief Sets the target value of the graph (only matters when no target value reference is used) + /// @param[in] value The target value of the graph + void set_target_value(std::uint16_t value); + + /// @brief Returns the target value reference object ID + /// @details This object will be used (if it's not NULL_OBJECT_ID) + /// to determine the target value of the graph instead of the target value itself. + /// @returns The object ID of a number variable to use for the target value + std::uint16_t get_target_value_reference() const; + + /// @brief Sets the target value reference object ID + /// @details This object will be used (if it's not NULL_OBJECT_ID) + /// to determine the target value of the graph instead of the target value itself. + /// @param[in] value The object ID of a number variable to use for the target value + void set_target_value_reference(std::uint16_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 27; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t barGraphWidth = 0; ///< Bar graph width in pixels. Bar graph width should be less than half the total width, or less than half the total height, whichever is least. + std::uint16_t minValue = 0; ///< Minimum value. Represents value when needle is at the start of arc + std::uint16_t maxValue = 0; ///< Maximum value. Represents when the needle is at the end of the arc. + std::uint16_t value = 0; ///< Current value. Needle position set to this value, used if variable ref is NULL. + std::uint16_t targetValue = 0; ///< Current target value. Used only if Target value variable Reference attribute is NULL. + std::uint16_t targetValueReference = NULL_OBJECT_ID; ///< Object ID of a Number Variable object in which to retrieve the bar graph’s target value. + std::uint8_t targetLineColour = 0; ///< Target line colour (if drawn) + std::uint8_t colour = 0; ///< Bar graph fill and border colour + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + std::uint8_t startAngle = 0; ///< Start angle / 2 in degrees from positive X axis counterclockwise + std::uint8_t endAngle = 0; ///< End angle / 2 in degrees from positve X axis counterclockwise + }; + + /// @brief This object displays a picture graphic (bitmap) + class PictureGraphic : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Width = 1, + Options = 2, + TransparencyColour = 3, + ActualWidth = 4, + ActualHeight = 5, + Format = 6, + + NumberOfAttributes = 7 + }; + + /// @brief Enumerates the different colour formats a picture graphic can have (mutually exclusive) + enum class Format + { + Monochrome = 0, ///< Monochrome; 8 pixels per byte. Each bit represents a colour palette index of 0 or 1. + FourBitColour = 1, ///< 2 colour pixels per byte. Each nibble(4 bits) represents a colour palette index of 0 through 15. + EightBitColour = 2 ///< colour pixel per byte. Each byte represents a colour palette index of 0 through 255 + }; + + /// @brief Enumerates the different options bits in the options bitfield + enum class Options + { + Transparent = 0, ///< 0 = Opaque, 1 = Transparent + Flashing = 1, ///< 0 = Normal, 1 = Flashing + RunLengthEncoded = 2 ///< Data is RLE See Clause B.12.2 Picture Graphic object raw data format and compression + }; + + /// @brief Constructor for a picture graphic (bitmap) object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + PictureGraphic(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns a reference to the underlying bitmap data + /// @returns A reference to the underlying bitmap data + std::vector &get_raw_data(); + + /// @brief Sets a large chunk of data to the underlying bitmap + /// @param[in] data Pointer to a buffer of data + /// @param[in] size The length of the data buffer to add to the underlying bitmap + void set_raw_data(std::uint8_t *data, std::uint32_t size); + + /// @brief Sets one byte of raw data to the underlying bitmap + /// @param[in] dataByte One byte of bitmap data + void add_raw_data(std::uint8_t dataByte); + + /// @brief Returns the number of bytes in the raw data that comprises the underlying bitmap + /// @returns The number of bytes in the raw data that comprises the underlying bitmap + std::uint32_t get_number_of_bytes_in_raw_data() const; + + /// @brief Sets the number of bytes in the raw data that comprises the underlying bitmap + /// @param[in] value The number of bytes in the raw data that comprises the underlying bitmap + void set_number_of_bytes_in_raw_data(std::uint32_t value); + + /// @brief Returns the actual width of the underlying bitmap + /// @returns The actual width of the underlying bitmap (px) + std::uint16_t get_actual_width() const; + + /// @brief Sets the actual width of the underlying bitmap + /// @param[in] value Actual width to set for the underlying bitmap (px) + void set_actual_width(std::uint16_t value); + + /// @brief Returns the actual height of the underlying bitmap + /// @returns The actual height of the underlying bitmap (px) + std::uint16_t get_actual_height() const; + + /// @brief Sets the actual height of the underlying bitmap + /// @param[in] value Actual height to set for the underlying bitmap (px) + void set_actual_height(std::uint16_t value); + + /// @brief Returns the picture's colour format + /// @returns The picture colour format + Format get_format() const; + + /// @brief Sets the picture's colour format + /// @param[in] value The colour format to use for this picture graphic + void set_format(Format value); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + /// @brief Returns the transparency colour to use when rendering the object as an index into the VT colour table + /// @returns Transparency colour to use when rendering the object as an index into the VT colour table + std::uint8_t get_transparency_colour() const; + + /// @brief Sets the transparency colour to use when rendering the object as an index into the VT colour table + /// @param[in] value The colour to use when rendering the object as an index into the VT colour table + void set_transparency_colour(std::uint8_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 17; ///< The fewest bytes of IOP data that can represent this object + + std::vector rawData; ///< The raw picture data. Not a standard bitmap, but rather indicies into the VT colour table. + std::uint32_t numberOfBytesInRawData = 0; ///< Number of bytes of raw data + std::uint16_t actualWidth = 0; ///< The actual width of the bitmap + std::uint16_t actualHeight = 0; ///< The actual height of the bitmap + std::uint8_t formatByte = 0; ///< The format option byte + std::uint8_t optionsBitfield = 0; ///< Options bitfield, see the `options` enum + std::uint8_t transparencyColour = 0; ///< The colour to render as transparent if so set in the options + }; + + /// @brief A number variable holds a 32-bit unsigned integer value + class NumberVariable : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Value = 1, + + NumberOfAttributes = 2 + }; + + /// @brief Constructor for a number variable object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + NumberVariable(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the number variable's value + /// @returns The number variable's value + std::uint32_t get_value() const; + + /// @brief Sets the number variable's value + /// @param[in] value The value to set for the number variable + void set_value(std::uint32_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 7; ///< The fewest bytes of IOP data that can represent this object + + std::uint32_t value = 0; ///< 32-bit unsigned integer value + }; + + /// @brief A String Variable holds a fixed length string. + class StringVariable : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + + NumberOfAttributes = 1 + }; + + /// @brief Constructor for a string variable object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + StringVariable(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the actual string value stored in this object + /// @returns The string value stored in this object + std::string get_value(); + + /// @brief Sets the actual string value stored in this object + /// @param[in] value The new string value for this object + void set_value(std::string value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 5; ///< The fewest bytes of IOP data that can represent this object + + std::string value; ///< The actual value of the string, for non utf-16 strings + }; + + /// @brief This object holds attributes related to fonts. + class FontAttributes : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + FontColour = 1, + FontSize = 2, + FontType = 3, + FontStyle = 4, + + NumberOfAttributes = 5 + }; + + /// @brief Enumerates the different font sizes + enum class FontSize : std::uint8_t + { + Size6x8 = 0, ///< 6x8 Font size + Size8x8 = 1, ///< 8x8 Font size + Size8x12 = 2, ///< 8x12 Font size + Size12x16 = 3, ///< 12x16 Font size + Size16x16 = 4, ///< 16x16 Font size + Size16x24 = 5, ///< 16x24 Font size + Size24x32 = 6, ///< 24x32 Font size + Size32x32 = 7, ///< 32x32 Font size + Size32x48 = 8, ///< 32x48 Font size + Size48x64 = 9, ///< 48x64 Font size + Size64x64 = 10, ///< 64x64 Font size + Size64x96 = 11, ///< 64x96 Font size + Size96x128 = 12, ///< 96x128 Font size + Size128x128 = 13, ///< 128x128 Font size + Size128x192 = 14 ///< 128x192 Font size + }; + + /// @brief Enumerates the font style options that can be encoded in a font style bitfield + enum class FontStyleBits : std::uint8_t + { + Bold = 0, ///< Bold font style + CrossedOut = 1, ///< Crossed-out font style (strikethrough) + Underlined = 2, ///< Underlined font style + Italic = 3, ///< Italic font style + Inverted = 4, ///< Inverted font style (upside down) + Flashing = 5, ///< Flashing font style + FlashingHidden = 6, ///< Flashing between hidden and shown font style + ProportionalFontRendering = 7 ///< Enables proportional font rendering if supported by the server + }; + + /// @brief Enumerates the different font types + enum class FontType : std::uint8_t + { + ISO8859_1 = 0, ///< ISO Latin 1 + ISO8859_15 = 1, ///< ISO Latin 9 + ISO8859_2 = 2, ///< ISO Latin 2 + Reserved_1 = 3, ///< Reserved + ISO8859_4 = 4, ///< ISO Latin 4 + ISO8859_5 = 5, ///< Cyrillic + Reserved_2 = 6, ///< Reserved + ISO8859_7 = 7, ///< Greek + ReservedEnd = 239, ///< Reserved from ISO8859_7 to this value + ProprietaryBegin = 240, ///< The beginning of the proprietary range + ProprietaryEnd = 255 ///< The end of the proprietary region + }; + + /// @brief Constructor for a font attributes object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + FontAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the font type associated to this font attributes object + /// @returns The font type associated to this font attributes object + FontType get_type() const; + + /// @brief Sets the font type + /// @param[in] value The font type to set + void set_type(FontType value); + + /// @brief Returns the font style bitfield + /// @returns The style bitfield, which is comprised of FontStyleBits + std::uint8_t get_style() const; + + /// @brief Returns a specific font style bit's state + /// @param[in] styleSetting The font style bit to check + /// @returns The state of the selected style bit + bool get_style(FontStyleBits styleSetting); + + /// @brief Sets a specific font style bit to a new value + /// @param[in] bit The style bit to change + /// @param[in] value The state to set for the selected style bit + void set_style(FontStyleBits bit, bool value); + + /// @brief Sets the font style bitfield to a new value + /// @param[in] value The value to set to the font style bitfield + void set_style(std::uint8_t value); + + /// @brief Returns the font size + /// @returns The font size + FontSize get_size() const; + + /// @brief Sets the font size to a new value + /// @param[in] value The new font size + void set_size(FontSize value); + + /// @brief Returns the font colour as an index into the VT colour table + /// @returns The font colour as an index into the VT colour table + std::uint8_t get_colour() const; + + /// @brief Sets the colour of the font to a new VT colour + /// @param[in] value An index into the VT colour table associated to the desired colour + void set_colour(std::uint8_t value); + + /// @brief Returns the width of the associated font size in pixels + /// @returns The width of the associated font size in pixels + std::uint8_t get_font_width_pixels() const; + + /// @brief Returns the height of the associated font size in pixels + /// @returns The height of the associated font size in pixels + std::uint8_t get_font_height_pixels() const; + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 8; ///< The fewest bytes of IOP data that can represent this object + + std::uint8_t colour = 0; ///< Text colour + std::uint8_t size = 0; ///< Font size + std::uint8_t type = 0; ///< Encoding type + std::uint8_t style = 0; ///< Font style + }; + + /// @brief Defines a line attributes object, which describes how lines should be displayed on the VT + class LineAttributes : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + LineColour = 1, + LineWidth = 2, + LineArt = 3, + + NumberOfAttributes = 4 + }; + + /// @brief Constructor for a line attributes object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + LineAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Sets the line art bit pattern. Each bit represents 1 pixel's on/off state. + /// @returns The line attribute's line art bit pattern + std::uint16_t get_line_art_bit_pattern() const; + + /// @brief Sets the line art bit patter for the line attribute + /// @param[in] value The line art bit pattern to set + void set_line_art_bit_pattern(std::uint16_t value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 8; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t lineArtBitpattern = 0; ///< Bit pattern art for line. Each bit represents a paintbrush spot + }; + + /// @brief This object holds attributes related to filling output shape objects + class FillAttributes : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + FillType = 1, + FillColour = 2, + FillPattern = 3, + + NumberOfAttributes = 4 + }; + + /// @brief Enumerates the different fill types for an object + enum class FillType : std::uint8_t + { + NoFill = 0, ///< No fill will be applied + FillWithLineColor = 1, ///< Fill with the color of the outline of the shape + FillWithSpecifiedColorInFillColorAttribute = 2, ///< Fill with the color specified by a fill attribute + FillWithPatternGivenByFillPatternAttribute = 3 ///< Fill with a patter provided by a fill pattern attribute + }; + + /// @brief Constructor for a fill attributes object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + FillAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the fill pattern associated with this fill attributes object + /// @returns The fill pattern for this attribute object + std::uint16_t get_fill_pattern() const; + + /// @brief Sets the fill pattern for this fill attributes object + /// @param[in] value The fill pattern to set for this object + void set_fill_pattern(std::uint16_t value); + + /// @brief Returns the fill type/mode associated with this object + /// @returns The fill type/mode associated with this object + FillType get_type() const; + + /// @brief Sets the fill type/mode associated with this object + /// @param[in] value The fill type/mode associated with this object + void set_type(FillType value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 8; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t fillPattern; ///< Object id of a Picture Graphic object to use as a Fill pattern + FillType type; ///< The fill type/mode associated with this object + }; + + /// @brief This object defines the valid or invalid characters for an Input String object + class InputAttributes : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + ValidationType = 1, + + NumberOfAttributes = 2 + }; + + /// @brief Enumerates the different validation types for this object, which + /// describe how to interpret the validation string + enum class ValidationType : std::uint8_t + { + ValidCharactersAreListed = 0, + InvalidCharactersAreListed = 1 + }; + + /// @brief Constructor for a input attributes object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + InputAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the validation string associated to this input attributes object + /// @returns The validation string associated to this input attributes object + std::string get_validation_string() const; + + /// @brief Sets the validation string for this object + /// @param[in] value The new validation string for this object + void set_validation_string(std::string value); + + /// @brief Returns the validation type setting for this object + /// @returns The validation type associated to this object + ValidationType get_validation_type() const; + + /// @brief Sets the validation type setting for this object + /// @param[in] newValidationType The validation type + void set_validation_type(ValidationType newValidationType); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 7; ///< The fewest bytes of IOP data that can represent this object + + std::string validationString; ///< String containing all valid or invalid character codes + ValidationType validationType = ValidationType::ValidCharactersAreListed; ///< Describes how to interpret the validation string + }; + + /// @brief The Extended Input Attributes object, available in VT version 4 and later, defines the valid or invalid + /// characters for an Input String object + class ExtendedInputAttributes : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + ValidationType = 1, + + NumberOfAttributes = 2 + }; + + /// @brief Enumerates the different validation types for this object, which + /// describe how to interpret the validation string + enum class ValidationType : std::uint8_t + { + ValidCharactersAreListed = 0, + InvalidCharactersAreListed = 1 + }; + + /// @brief Constructor for an extended input attributes object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + ExtendedInputAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the number of code planes in this extended input attributes + /// @returns The number of code planes in this extended input attributes + std::uint8_t get_number_of_code_planes() const; + + /// @brief Sets the number of code planes in this extended input attributes object + /// @param[in] value The new number of code planes + void set_number_of_code_planes(std::uint8_t value); + + /// @brief Returns the validation type setting for this object + /// @returns The validation type associated to this object + ValidationType get_validation_type() const; + + /// @brief Sets the validation type setting for this object + /// @param[in] value The validation type + void set_validation_type(ValidationType value); + + /// @todo Finish ExtendedInputAttributes implementation + + private: + /// @brief Stores data for a code plane (for utf-16 strings) + class CodePlane + { + public: + std::vector> characterRanges; ///< A list of character ranges for this code plane + std::uint8_t numberOfCharacterRanges; ///< The number of expected character ranges for this code plane + }; + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 5; ///< The fewest bytes of IOP data that can represent this object + + std::vector codePlanes; ///< Code planes to which the character ranges belong. + ValidationType validationType = ValidationType::ValidCharactersAreListed; ///< Describes how to interpret the validation string + }; + + /// @brief Points to another object + class ObjectPointer : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + Value = 1, + + NumberOfAttributes = 2 + }; + + /// @brief Constructor for a object pointer object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + ObjectPointer(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 5; ///< The fewest bytes of IOP data that can represent this object + }; + + /// @brief The External Object Pointer object, available in VT version 5 and later, allows a Working Set to display + /// objects that exist in another Working Set’s object pool + class ExternalObjectPointer : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + DefaultObjectID = 1, + ExternalReferenceNAMEID = 2, + ExternalObjectID = 3, + + NumberOfAttributes = 4 + }; + + /// @brief Constructor for a object pointer object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + ExternalObjectPointer(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns the default object id which is the + /// object ID of an object which shall be displayed if the External Object ID is not valid, + /// or the NULL Object ID. + /// @returns The default object ID or the null object ID + std::uint16_t get_default_object_id() const; + + /// @brief Sets the default object id which is the + /// object ID of an object which shall be displayed if the External Object ID is not valid, + /// or the NULL Object ID. + /// @param[in] id The default object ID or the null object ID + void set_default_object_id(std::uint16_t id); + + /// @brief Returns the external reference NAME ID + /// @returns External reference NAME ID + std::uint16_t get_external_reference_name_id() const; + + /// @brief Sets the external reference NAME ID + /// @param[in] id External reference NAME ID + void set_external_reference_name_id(std::uint16_t id); + + /// @brief Returns the external object ID. + /// The referenced object is found in + /// the object pool of the Working Set Master + /// identified by the External Reference NAME + /// ID attribute and listed in the corresponding + /// External Object Definition object. + /// @returns The external object ID. + std::uint16_t get_external_object_id() const; + + /// @brief Sets the external object ID. + /// The referenced object is found in + /// the object pool of the Working Set Master + /// identified by the External Reference NAME + /// ID attribute and listed in the corresponding + /// External Object Definition object. + /// @param[in] id The external object ID. + void set_external_object_id(std::uint16_t id); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 5; ///< The fewest bytes of IOP data that can represent this object + + std::uint16_t defaultObjectID = NULL_OBJECT_ID; ///< Object ID of an object which shall be displayed if the External Object ID is not valid, or the NULL Object ID + std::uint16_t externalReferenceNAMEID = NULL_OBJECT_ID; ///< Object id of an External Reference NAME object or the NULL Object ID + std::uint16_t externalObjectID = NULL_OBJECT_ID; ///< Object ID of a referenced object or the NULL Object ID + }; + + /// @brief Defines a macro object. Performs a list of commands based on a message or event. + class Macro : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + + NumberOfAttributes = 1 + }; + + /// @brief A subset of the VT command multiplexors that support use in macros + enum class Command + { + HideShowObject = 0xA0, + EnableDisableObject = 0xA1, + SelectInputObject = 0xA2, + ControlAudioSignal = 0xA3, + SetAudioVolume = 0xA4, + ChangeChildLocation = 0xA5, + ChangeSize = 0xA6, + ChangeBackgroundColour = 0xA7, + ChangeNumericValue = 0xA8, + ChangeEndPoint = 0xA9, + ChangeFontAttributes = 0xAA, + ChangeLineAttributes = 0xAB, + ChangeFillAttributes = 0xAC, + ChangeActiveMask = 0xAD, + ChangeSoftKeyMask = 0xAE, + ChangeAttribute = 0xAF, + ChangePriority = 0xB0, + ChangeListItem = 0xB1, + ChangeStringValue = 0xB3, + ChangeChildPosition = 0xB4, + ChangeObjectLabel = 0xB5, + ChangePolygonPoint = 0xB6, + LockUnlockMask = 0xBD, + ExecuteMacro = 0xBE, + ChangePolygonScale = 0xB7, + GraphicsContextCommand = 0xB8, + SelectColourMap = 0xBA, + ExecuteExtendedMacro = 0xBC + }; + + /// @brief Constructor for a macro object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + Macro(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Adds a macro command packet to this macro. Essentially these are CAN messages that represent normal + /// ECU to VT commands that will be executed in order by this macro. + /// @param[in] command The command packet (CAN message data) to add + /// @returns true if the command was added to the macro, otherwise false (maybe the max number of commands has been hit) + bool add_command_packet(std::array command); + + /// @brief Returns the number of stored command packets inside this macro (max 255) + /// @returns The number of stored command packets inside this macro + std::uint8_t get_number_of_commands() const; + + /// @brief Returns a command packet by index + /// @param[in] index The index of the packet to retreive + /// @param[out] command The returned command packet if the return value is true, otherwise the returned + /// command packet content is undefined. + /// @returns true if a valid command packet was returned, otherwise false (index out of range) + bool get_command_packet(std::uint8_t index, std::array &command); + + /// @brief Deletes a command packet from the macro by index + /// @returns true if the specified command packet was removed, otherwise false (index out of range) + bool remove_command_packet(std::uint8_t index); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 5; ///< The fewest bytes of IOP data that can represent this object + static const std::array ALLOWED_COMMANDS_LOOKUP_TABLE; ///< The list of all allowed commands in a table for easy lookup when validating macro content + std::vector> commandPackets; ///< Macro command list + }; + + /// @brief Defines a colour map object. The Colour Map object, optionally available in VT version 4 and 5, and mandatory in VT version 6 and + /// later, allows the Working Set designer to alter the transformation of the VT colour index values to the + /// defined RGB value. This provides a mechanism where the colours table can be changed at run-time. + class ColourMap : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + + NumberOfAttributes = 1 + }; + + /// @brief Constructor for a colour map object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + ColourMap(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief This is used to initialize the colour map data to either 2, 16, or 256 colour indexes. + /// Values will be initialized from the default color table to the colour map data whenever this is called. + /// @param[in] value The number of colour indexes to initialize the colour map to + /// @returns true if the number of colour indexes was set, otherwise false (invalid value or value is unchanged) + bool set_number_of_colour_indexes(std::uint16_t value); + + /// @brief Returns the number of colour indexes in this colour map + /// @returns The number of colour indexes in this colour map (2, 16, or 256) + std::uint16_t get_number_of_colour_indexes() const; + + /// @brief Sets the colour map index to the specified value/colour + /// @param[in] index The index to set + /// @param[in] value The colour to set the index to + /// @returns true if the colour map index was set, otherwise false (index out of range) + bool set_colour_map_index(std::uint8_t index, std::uint8_t value); + + /// @brief Returns the colour index into the VT colour table at the specified index in this colour map + /// @param[in] index The index in this map to get the VT colour index for + /// @returns The VT colour index at the specified index in this colour map + std::uint8_t get_colour_map_index(std::uint8_t index) const; + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 5; ///< The fewest bytes of IOP data that can represent this object + std::vector colourMapData; ///< The actual colour map data, which remaps each index from the default table based on the size of this vector. + }; + + /// @brief Defines a window mask object + class WindowMask : public VTObject + { + public: + /// @brief Enumerates this object's attributes which are assigned an attribute ID. + /// The Change Attribute command allows any writable attribute with an AID to be changed. + enum class AttributeName : std::uint8_t + { + Type = 0, + BackgroundColour = 1, + Options = 2, + Name = 3, + + NumberOfAttributes = 4 + }; + + /// @brief Enumerates the different kinds of window masks which imply how they are displayed and what they contain + enum class WindowType : std::uint8_t + { + Freeform = 0, ///< the Working Set supplies and positions all child objects contained inside the window. In this case the Working Set has complete control over the look and feel of the window. + NumericOutputValueWithUnits1x1 = 1, ///< This window displays a single numeric output with units of measure in a single window cell. + NumericOutputValueNoUnits1x1 = 2, ///< This window displays a single numeric output with no units of measure in a single window cell. + StringOutputValue1x1 = 3, ///< This window displays a single string output in a single window cell. + NumericInputValueWithUnits1x1 = 4, ///< This window displays a single numeric input with units of measure in a single window cell + NumericInputValueNoUnits1x1 = 5, ///< This window displays a single numeric input with no units of measure in a single window cell + StringInputValue1x1 = 6, ///< This window displays a single string input in a single window cell + HorizontalLinearBarGraphNoUnits1x1 = 7, ///< This window displays a single horizontal linear bar graph in a single window cell + SingleButton1x1 = 8, ///< This window displays a single Button object in a single window cell + DoubleButton1x1 = 9, ///< This window displays two Button objects in a single window cell + NumericOutputValueWithUnits2x1 = 10, ///< This window displays a single numeric output with units of measure in two horizontal window cells + NumericOutputValueNoUnits2x1 = 11, ///< This window displays a single numeric output with no units of measure in two horizontal window cells + StringOutputValue2x1 = 12, ///< This window displays a single string output in two horizontal window cells. + NumericInputValueWithUnits2x1 = 13, ///< This window displays a single numeric input with units of measure in two horizontal window cells + NumericInputValueNoUnits2x1 = 14, ///< This window displays a single numeric input with no units of measure in two horizontal window cells + StringInputValue2x1 = 15, ///< This window displays a single string input in two horizontal window cells. + HorizontalLinearBarGraphNoUnits2x1 = 16, ///< This window displays a single horizontal linear bar graph in two horizontal window cells + SingleButton2x1 = 17, ///< This window displays a single Button object in two horizontal window cells + DoubleButton2x1 = 18 ///< This window displays two Button objects in two horizontal window cells + }; + + /// @brief Enumerates the bit indexes of options encoded in the object's options bitfield + enum class Options + { + Available = 0, ///< If 0 (FALSE) this window is not available for use at the present time, even though defined. + Transparent = 1 ///< Transparent. If this bit is 1, the background colour attribute shall not be used and the Window shall be transparent. + }; + + /// @brief Constructor for a window mask object + /// @param[in] memberObjectPool a reference to the rest of the object pool this object is a member of + /// @param[in] currentColourTable a reference to the current colour table the working set is using + WindowMask(std::map> &memberObjectPool, VTColourTable ¤tColourTable); + + /// @brief Returns the VT object type of the underlying derived object + /// @returns The VT object type of the underlying derived object + VirtualTerminalObjectType get_object_type() const override; + + /// @brief Returns the minimum binary serialized length of the associated object + /// @returns The minimum binary serialized length of the associated object + std::uint32_t get_minumum_object_length() const override; + + /// @brief Performs basic error checking on the object and returns if the object is valid + /// @returns `true` if the object passed basic error checks + bool get_is_valid() const override; + + /// @brief Sets an attribute and optionally returns an error code in the last parameter + /// @param[in] attributeID The ID of the attribute to change + /// @param[in] rawAttributeData The raw data to change the attribute to, as decoded in little endian format with unused + /// bytes/bits set to zero. + /// @param[out] returnedError If this function returns false, this will be the error code. If the function + /// returns true, this value is undefined. + /// @returns True if the attribute was changed, otherwise false (check the returnedError in this case to know why). + bool set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) override; + + /// @brief Returns object ID of an Output String object or an Object Pointer object that points + /// to an Output String object that contains the string that gives a proper name to this object + /// @returns Object ID corresponding to this object's proper name + std::uint16_t get_name_object_id() const; + + /// @brief Sets the object ID of an Output String object or an Object Pointer object that points + /// to an Output String object that contains the string that gives a proper name to this object + /// @param[in] object The object ID that contains the string for this object's proper name + void set_name_object_id(std::uint16_t object); + + /// @brief Returns Object ID of an Output String object or an Object Pointer + /// object that points to an Output String object that + /// contains the string that supplies window title text + /// @returns Object ID corresponding to this object's window title text + std::uint16_t get_title_object_id() const; + + /// @brief Sets the Object ID of an Output String object or an Object Pointer + /// object that points to an Output String object that + /// contains the string that supplies window title text + /// @param[in] object The object ID that contains the string for this object's title text + void set_title_object_id(std::uint16_t object); + + /// @brief Returns the object ID of an output object that contains an icon for the window. + /// @returns The object ID of an output object that contains an icon for the window. + std::uint16_t get_icon_object_id() const; + + /// @brief Sets the object ID of an output object that contains an icon for the window. + /// @param[in] object The object ID of an output object that contains an icon for the window. + void set_icon_object_id(std::uint16_t object); + + /// @brief Returns the window type for this object + /// @returns The window type for this object + WindowType get_window_type() const; + + /// @brief Sets the window type for this object + /// @param[in] type The window type for this object + void set_window_type(WindowType type); + + /// @brief Returns the state of a single option in the object's option bitfield + /// @param[in] option The option to check the value of in the object's option bitfield + /// @returns The state of the associated option bit + bool get_option(Options option) const; + + /// @brief Sets the options bitfield for this object to a new value + /// @param[in] value The new value for the options bitfield + void set_options(std::uint8_t value); + + /// @brief Sets a single option in the options bitfield to the specified value + /// @param[in] option The option to set + /// @param[in] value The new value of the option bit + void set_option(Options option, bool value); + + private: + static constexpr std::uint32_t MIN_OBJECT_LENGTH = 17; ///< The fewest bytes of IOP data that can represent this object + std::uint16_t name = NULL_OBJECT_ID; ///< Object ID of an Output String object or an Object Pointer object that points to an Output String object that contains the string that gives a proper name to this object + std::uint16_t title = NULL_OBJECT_ID; ///< Object ID of an Output String object or an Object Pointer object that points to an Output String object that supplies window title text + std::uint16_t icon = NULL_OBJECT_ID; ///< Object ID of an Output object or an Object Pointer object that points to an Output object that contains an icon for the window + std::uint8_t optionsBitfield = 0; ///< Bitfield of options defined in `Options` enum + std::uint8_t windowType = 0; ///< The window type, which implies its size + }; + } // namespace isobus #endif // ISOBUS_VIRTUAL_TERMINAL_OBJECTS_HPP diff --git a/isobus/src/isobus_virtual_terminal_objects.cpp b/isobus/src/isobus_virtual_terminal_objects.cpp new file mode 100644 index 00000000..5dab822b --- /dev/null +++ b/isobus/src/isobus_virtual_terminal_objects.cpp @@ -0,0 +1,5491 @@ +//================================================================================================ +/// @file isobus_virtual_terminal_objects.cpp +/// +/// @brief Implements VT server object pool objects. +/// @author Adrian Del Grosso +/// +/// @copyright 2023 Adrian Del Grosso +//================================================================================================ +#include "isobus/isobus/isobus_virtual_terminal_objects.hpp" + +namespace isobus +{ + VTColourTable::VTColourTable() + { + // The table can be altered at runtime. Init here to VT standard + colourTable[0] = VTColourVector(0.0f, 0.0f, 0.0f); // Black + colourTable[1] = VTColourVector(1.0f, 1.0f, 1.0f); // White + colourTable[2] = VTColourVector(0.0f, (153.0f / 255.0f), 0.0f); // Green + colourTable[3] = VTColourVector(0.0f, (153.0f / 255.0f), (153.0f / 255.0f)); // Teal + colourTable[4] = VTColourVector((153.0f / 255.0f), 0.0f, 0.0f); // Maroon + colourTable[5] = VTColourVector((153.0f / 255.0f), 0.0f, (153.0f / 255.0f)); // Purple + colourTable[6] = VTColourVector((153.0f / 255.0f), (153.0f / 255.0f), 0.0f); // Olive + colourTable[7] = VTColourVector((204.0f / 255.0f), (204.0f / 255.0f), (204.0f / 255.0f)); // Silver + colourTable[8] = VTColourVector((153.0f / 255.0f), (153.0f / 255.0f), (153.0f / 255.0f)); // Grey + colourTable[9] = VTColourVector(0.0f, 0.0f, 1.0f); // Blue + colourTable[10] = VTColourVector(0.0f, 1.0f, 0.0f); // Lime + colourTable[11] = VTColourVector(0.0f, 1.0f, 1.0f); // Cyan + colourTable[12] = VTColourVector(1.0f, 0.0f, 0.0f); // Red + colourTable[13] = VTColourVector(1.0f, 0.0f, 1.0f); // Magenta + colourTable[14] = VTColourVector(1.0f, 1.0f, 0.0f); // Yellow + colourTable[15] = VTColourVector(0.0f, 0.0f, (153.0f / 255.0f)); // Navy + + // This section of the table increases with a pattern + for (std::uint8_t i = 16; i <= 231; i++) + { + std::uint8_t index = i - 16; + + std::uint32_t redCounter = (index / 36); + std::uint32_t greenCounter = ((index / 6) % 6); + std::uint32_t blueCounter = (index % 6); + + colourTable[i] = VTColourVector((51.0f * (redCounter) / 255.0f), ((51.0f * (greenCounter)) / 255.0f), ((51.0f * blueCounter) / 255.0f)); + } + + // The rest are proprietary. Init to white for now. + for (std::uint16_t i = 232; i < VT_COLOUR_TABLE_SIZE; i++) + { + colourTable[i] = VTColourVector(1.0f, 1.0f, 1.0f); + } + } + + VTColourVector VTColourTable::get_colour(std::uint8_t colourIndex) const + { + return colourTable.at(colourIndex); + } + + void VTColourTable::set_colour(std::uint8_t colourIndex, VTColourVector newColour) + { + colourTable.at(colourIndex) = newColour; + } + + VTObject::VTObject(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + colourTable(currentColourTable), + thisObjectPool(memberObjectPool) + { + } + + std::uint16_t VTObject::get_id() const + { + return objectID; + } + + void VTObject::set_id(std::uint16_t value) + { + objectID = value; + } + + std::uint16_t VTObject::get_width() const + { + return width; + } + + void VTObject::set_width(std::uint16_t value) + { + width = value; + } + + std::uint16_t VTObject::get_height() const + { + return height; + } + + void VTObject::set_height(std::uint16_t value) + { + height = value; + } + + std::uint8_t VTObject::get_background_color() const + { + return backgroundColor; + } + + void VTObject::set_background_color(std::uint8_t value) + { + backgroundColor = value; + } + + std::shared_ptr VTObject::get_object_by_id(std::uint16_t objectID) const + { + return thisObjectPool[objectID]; + } + + std::uint16_t VTObject::get_number_children() const + { + return static_cast(children.size()); + } + + void VTObject::add_child(std::uint16_t objectID, std::int16_t relativeXLocation, std::int16_t relativeYLocation) + { + children.push_back(ChildObjectData(objectID, relativeXLocation, relativeYLocation)); + } + + std::uint16_t VTObject::get_child_id(std::uint16_t index) const + { + std::uint16_t retVal = NULL_OBJECT_ID; + + if (index < children.size()) + { + retVal = children[index].id; + } + return retVal; + } + + std::int16_t VTObject::get_child_x(std::uint16_t index) const + { + std::int16_t retVal = 0; + + if (index < children.size()) + { + retVal = children[index].xLocation; + } + return retVal; + } + + std::int16_t VTObject::get_child_y(std::uint16_t index) const + { + std::int16_t retVal = 0; + + if (index < children.size()) + { + retVal = children[index].yLocation; + } + return retVal; + } + + void VTObject::set_child_x(std::uint16_t index, std::int16_t xOffset) + { + if (index < children.size()) + { + children.at(index).xLocation = xOffset; + } + } + + void VTObject::set_child_y(std::uint16_t index, std::int16_t yOffset) + { + if (index < children.size()) + { + children.at(index).yLocation = yOffset; + } + } + + bool VTObject::offset_all_children_with_id(std::uint16_t childObjectID, std::int8_t xOffset, std::int8_t yOffset) + { + bool retVal = false; + + for (auto &child : children) + { + if (child.id == childObjectID) + { + child.xLocation += xOffset; + child.yLocation += yOffset; + } + } + return retVal; + } + + void VTObject::remove_child(std::uint16_t objectIDToRemove, std::int16_t relativeXLocation, std::int16_t relativeYLocation) + { + for (auto child = children.begin(); child != children.end(); child++) + { + if ((child->id == objectIDToRemove) && (child->xLocation == relativeXLocation) && (child->yLocation == relativeYLocation)) + { + children.erase(child); + break; + } + } + } + + void VTObject::pop_child() + { + if (!children.empty()) + { + children.pop_back(); + } + } + + VTObject::ChildObjectData::ChildObjectData(std::uint16_t objectId, + std::int16_t x, + std::int16_t y) : + id(objectId), + xLocation(x), + yLocation(y) + { + } + + bool VTObject::replace_only_child_of_type(std::uint16_t newID, VirtualTerminalObjectType typeToRemove) + { + bool retVal = false; + + for (std::uint16_t i = 0; i < get_number_children(); i++) + { + std::uint16_t childID = get_child_id(i); + auto childObject = thisObjectPool[childID]; + + if ((NULL_OBJECT_ID != childID) && (nullptr != childObject) && (typeToRemove == childObject->get_object_type())) + { + remove_child(childID, get_child_x(i), get_child_y(i)); + break; + } + } + + if ((NULL_OBJECT_ID == newID) || (nullptr != thisObjectPool[newID])) + { + add_child(newID, 0, 0); + retVal = true; + } + return retVal; + } + + WorkingSet::WorkingSet(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType WorkingSet::get_object_type() const + { + return VirtualTerminalObjectType::WorkingSet; + } + + std::uint32_t WorkingSet::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool WorkingSet::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::OutputList: + case VirtualTerminalObjectType::Container: + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::OutputNumber: + case VirtualTerminalObjectType::OutputLine: + case VirtualTerminalObjectType::OutputRectangle: + case VirtualTerminalObjectType::OutputEllipse: + case VirtualTerminalObjectType::OutputPolygon: + case VirtualTerminalObjectType::OutputMeter: + case VirtualTerminalObjectType::OutputLinearBarGraph: + case VirtualTerminalObjectType::OutputArchedBarGraph: + case VirtualTerminalObjectType::GraphicsContext: + case VirtualTerminalObjectType::PictureGraphic: + case VirtualTerminalObjectType::ObjectPointer: + { + // Valid Objects + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool WorkingSet::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Selectable: + { + set_selectable(0 != rawAttributeData); + retVal = true; + } + break; + + case AttributeName::ActiveMask: + { + set_active_mask(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + bool WorkingSet::get_selectable() const + { + return selectable; + } + + void WorkingSet::set_selectable(bool value) + { + selectable = value; + } + + std::uint16_t WorkingSet::get_active_mask() const + { + return activeMask; + } + + void WorkingSet::set_active_mask(std::uint16_t value) + { + activeMask = value; + } + + DataMask::DataMask(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType DataMask::get_object_type() const + { + return VirtualTerminalObjectType::DataMask; + } + + std::uint32_t DataMask::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool DataMask::get_is_valid() const + { + bool anyWrongChildType = false; + std::uint8_t numberOfSoftKeyMasks = 0; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::WorkingSet: + case VirtualTerminalObjectType::Button: + case VirtualTerminalObjectType::InputBoolean: + case VirtualTerminalObjectType::InputString: + case VirtualTerminalObjectType::InputNumber: + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::InputList: + case VirtualTerminalObjectType::OutputNumber: + case VirtualTerminalObjectType::OutputList: + case VirtualTerminalObjectType::OutputLine: + case VirtualTerminalObjectType::OutputRectangle: + case VirtualTerminalObjectType::OutputEllipse: + case VirtualTerminalObjectType::OutputPolygon: + case VirtualTerminalObjectType::OutputMeter: + case VirtualTerminalObjectType::OutputLinearBarGraph: + case VirtualTerminalObjectType::OutputArchedBarGraph: + case VirtualTerminalObjectType::GraphicsContext: + case VirtualTerminalObjectType::Animation: + case VirtualTerminalObjectType::PictureGraphic: + case VirtualTerminalObjectType::ObjectPointer: + case VirtualTerminalObjectType::ExternalObjectPointer: + case VirtualTerminalObjectType::AuxiliaryFunctionType2: + case VirtualTerminalObjectType::AuxiliaryInputType2: + case VirtualTerminalObjectType::AuxiliaryControlDesignatorType2: + case VirtualTerminalObjectType::Macro: + { + // Valid Objects + } + break; + + case VirtualTerminalObjectType::SoftKeyMask: + { + // Valid Objects + numberOfSoftKeyMasks++; + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + + if (numberOfSoftKeyMasks > 1) + { + anyWrongChildType = true; + } + } + } + + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool DataMask::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(DataMask::AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case DataMask::AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case DataMask::AttributeName::SoftKeyMask: + { + returnedError = AttributeError::InvalidAttributeID; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::SoftKeyMask); + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + bool DataMask::change_soft_key_mask(std::uint16_t newMaskID) + { + return replace_only_child_of_type(newMaskID, VirtualTerminalObjectType::SoftKeyMask); + } + + AlarmMask::AlarmMask(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType AlarmMask::get_object_type() const + { + return VirtualTerminalObjectType::AlarmMask; + } + + std::uint32_t AlarmMask::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool AlarmMask::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::WorkingSet: + case VirtualTerminalObjectType::Button: + case VirtualTerminalObjectType::InputBoolean: + case VirtualTerminalObjectType::InputString: + case VirtualTerminalObjectType::InputNumber: + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::InputList: + case VirtualTerminalObjectType::OutputNumber: + case VirtualTerminalObjectType::OutputList: + case VirtualTerminalObjectType::OutputLine: + case VirtualTerminalObjectType::OutputRectangle: + case VirtualTerminalObjectType::OutputEllipse: + case VirtualTerminalObjectType::OutputPolygon: + case VirtualTerminalObjectType::OutputMeter: + case VirtualTerminalObjectType::OutputLinearBarGraph: + case VirtualTerminalObjectType::OutputArchedBarGraph: + case VirtualTerminalObjectType::GraphicsContext: + case VirtualTerminalObjectType::Animation: + case VirtualTerminalObjectType::PictureGraphic: + case VirtualTerminalObjectType::ObjectPointer: + case VirtualTerminalObjectType::ExternalObjectPointer: + case VirtualTerminalObjectType::AuxiliaryFunctionType2: + case VirtualTerminalObjectType::AuxiliaryInputType2: + case VirtualTerminalObjectType::AuxiliaryControlDesignatorType2: + case VirtualTerminalObjectType::Macro: + case VirtualTerminalObjectType::SoftKeyMask: + { + // Valid Objects + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool AlarmMask::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AlarmMask::AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AlarmMask::AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AlarmMask::AttributeName::SoftKeyMask: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::SoftKeyMask); + } + break; + + case AlarmMask::AttributeName::Priority: + { + if (rawAttributeData <= static_cast(AlarmMask::Priority::Low)) + { + set_mask_priority(static_cast(rawAttributeData)); + retVal = true; + } + else + { + returnedError = AttributeError::AnyOtherError; + } + } + break; + + case AlarmMask::AttributeName::AcousticSignal: + { + if (rawAttributeData <= static_cast(AlarmMask::AcousticSignal::None)) + { + set_signal_priority(static_cast(rawAttributeData)); + retVal = true; + } + else + { + returnedError = AttributeError::AnyOtherError; + } + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + AlarmMask::Priority AlarmMask::get_mask_priority() const + { + return maskPriority; + } + + void AlarmMask::set_mask_priority(Priority value) + { + maskPriority = value; + } + + AlarmMask::AcousticSignal AlarmMask::get_signal_priority() const + { + return signalPriority; + } + + void AlarmMask::set_signal_priority(AcousticSignal value) + { + signalPriority = value; + } + + bool AlarmMask::change_soft_key_mask(std::uint16_t newMaskID) + { + return replace_only_child_of_type(newMaskID, VirtualTerminalObjectType::SoftKeyMask); + } + + Container::Container(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType Container::get_object_type() const + { + return VirtualTerminalObjectType::Container; + } + + std::uint32_t Container::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool Container::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::WorkingSet: + case VirtualTerminalObjectType::Container: + case VirtualTerminalObjectType::Button: + case VirtualTerminalObjectType::InputBoolean: + case VirtualTerminalObjectType::InputString: + case VirtualTerminalObjectType::InputNumber: + case VirtualTerminalObjectType::InputList: + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::OutputNumber: + case VirtualTerminalObjectType::OutputList: + case VirtualTerminalObjectType::OutputLine: + case VirtualTerminalObjectType::OutputRectangle: + case VirtualTerminalObjectType::OutputEllipse: + case VirtualTerminalObjectType::OutputPolygon: + case VirtualTerminalObjectType::OutputMeter: + case VirtualTerminalObjectType::GraphicsContext: + case VirtualTerminalObjectType::OutputArchedBarGraph: + case VirtualTerminalObjectType::OutputLinearBarGraph: + case VirtualTerminalObjectType::Animation: + case VirtualTerminalObjectType::PictureGraphic: + case VirtualTerminalObjectType::ObjectPointer: + case VirtualTerminalObjectType::ExternalObjectPointer: + case VirtualTerminalObjectType::AuxiliaryFunctionType2: + case VirtualTerminalObjectType::AuxiliaryInputType2: + case VirtualTerminalObjectType::AuxiliaryControlDesignatorType2: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool Container::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + // All attributes are read only + returnedError = AttributeError::InvalidAttributeID; + return false; + } + + bool Container::get_hidden() const + { + return hidden; + } + + void Container::set_hidden(bool value) + { + hidden = value; + } + + SoftKeyMask::SoftKeyMask(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType SoftKeyMask::get_object_type() const + { + return VirtualTerminalObjectType::SoftKeyMask; + } + + std::uint32_t SoftKeyMask::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool SoftKeyMask::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::ObjectPointer: + case VirtualTerminalObjectType::ExternalObjectPointer: + case VirtualTerminalObjectType::Key: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool SoftKeyMask::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + Key::Key(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType Key::get_object_type() const + { + return VirtualTerminalObjectType::Key; + } + + std::uint32_t Key::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool Key::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::WorkingSet: + case VirtualTerminalObjectType::Container: + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::OutputNumber: + case VirtualTerminalObjectType::OutputList: + case VirtualTerminalObjectType::OutputLine: + case VirtualTerminalObjectType::OutputRectangle: + case VirtualTerminalObjectType::OutputEllipse: + case VirtualTerminalObjectType::OutputPolygon: + case VirtualTerminalObjectType::OutputMeter: + case VirtualTerminalObjectType::GraphicsContext: + case VirtualTerminalObjectType::OutputArchedBarGraph: + case VirtualTerminalObjectType::OutputLinearBarGraph: + case VirtualTerminalObjectType::Animation: + case VirtualTerminalObjectType::PictureGraphic: + case VirtualTerminalObjectType::ObjectPointer: + case VirtualTerminalObjectType::ExternalObjectPointer: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool Key::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::KeyCode: + { + set_key_code(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint8_t Key::get_key_code() const + { + return keyCode; + } + + void Key::set_key_code(std::uint8_t value) + { + keyCode = value; + } + + KeyGroup::KeyGroup(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType KeyGroup::get_object_type() const + { + return VirtualTerminalObjectType::KeyGroup; + } + + std::uint32_t KeyGroup::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool KeyGroup::get_is_valid() const + { + bool anyWrongChildType = false; + + if (NULL_OBJECT_ID != get_name_object_id()) + { + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::Key: + case VirtualTerminalObjectType::Macro: + { + // Key and macro are always valid + } + break; + + case VirtualTerminalObjectType::ObjectPointer: + { + auto objectPointer = std::static_pointer_cast(childObject); + + if (objectPointer->get_number_children() > 0) + { + auto objectPointerChildObject = thisObjectPool[objectPointer->get_child_id(0)]; + + if ((nullptr != objectPointerChildObject) && + (VirtualTerminalObjectType::Key == objectPointerChildObject->get_object_type())) + { + // Valid Child Object + } + else + { + anyWrongChildType = true; + } + } + else + { + // If there's no children, then it's valid + } + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + + if (!validate_name(nameID)) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool KeyGroup::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Name: + { + auto newName = static_cast(rawAttributeData); + auto newNameObject = thisObjectPool[newName]; + + if (validate_name(newName)) + { + nameID = newName; + retVal = true; + } + else + { + returnedError = AttributeError::InvalidValue; + } + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint16_t KeyGroup::get_key_group_icon() const + { + return keyGroupIcon; + } + + void KeyGroup::set_key_group_icon(std::uint16_t value) + { + keyGroupIcon = value; + } + + bool KeyGroup::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void KeyGroup::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void KeyGroup::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + std::uint16_t KeyGroup::get_name_object_id() const + { + return nameID; + } + + void KeyGroup::set_name_object_id(std::uint16_t value) + { + // This value cannot be NULL_OBJECT_ID after it has been set! + if (NULL_OBJECT_ID != value) + { + nameID = value; + } + } + + bool KeyGroup::validate_name(std::uint16_t nameIDToValidate) const + { + auto newNameObject = thisObjectPool[nameIDToValidate]; + bool retVal = false; + + if ((NULL_OBJECT_ID != nameIDToValidate) && + (nullptr != newNameObject) && + ((VirtualTerminalObjectType::OutputString == newNameObject->get_object_type()) || + (VirtualTerminalObjectType::ObjectPointer == newNameObject->get_object_type()))) + { + if (VirtualTerminalObjectType::ObjectPointer == newNameObject->get_object_type()) + { + if (newNameObject->get_number_children() > 0) + { + auto label = thisObjectPool[std::static_pointer_cast(newNameObject)->get_child_id(0)]; + + if ((nullptr != label) && + (VirtualTerminalObjectType::OutputString == label->get_object_type())) + { + retVal = true; + } + } + } + else + { + retVal = true; + } + } + return retVal; + } + + Button::Button(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType Button::get_object_type() const + { + return VirtualTerminalObjectType::Button; + } + + std::uint32_t Button::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool Button::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::WorkingSet: + case VirtualTerminalObjectType::OutputList: + case VirtualTerminalObjectType::Container: + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::OutputNumber: + case VirtualTerminalObjectType::OutputLine: + case VirtualTerminalObjectType::OutputRectangle: + case VirtualTerminalObjectType::OutputEllipse: + case VirtualTerminalObjectType::OutputPolygon: + case VirtualTerminalObjectType::OutputMeter: + case VirtualTerminalObjectType::OutputLinearBarGraph: + case VirtualTerminalObjectType::OutputArchedBarGraph: + case VirtualTerminalObjectType::GraphicsContext: + case VirtualTerminalObjectType::PictureGraphic: + case VirtualTerminalObjectType::ObjectPointer: + case VirtualTerminalObjectType::Animation: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool Button::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::BorderColour: + { + set_border_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::KeyCode: + { + set_key_code(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint8_t Button::get_key_code() const + { + return keyCode; + } + + void Button::set_key_code(std::uint8_t value) + { + keyCode = value; + } + + std::uint8_t Button::get_border_colour() const + { + return borderColour; + } + + void Button::set_border_colour(std::uint8_t value) + { + borderColour = value; + } + + bool Button::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void Button::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void Button::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + InputBoolean::InputBoolean(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType InputBoolean::get_object_type() const + { + return VirtualTerminalObjectType::InputBoolean; + } + + std::uint32_t InputBoolean::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool InputBoolean::get_is_valid() const + { + bool anyWrongChildType = false; + + for (const auto &child : children) + { + auto childObject = get_object_by_id(child.id); + + if (nullptr != childObject) + { + std::uint8_t numberOfFontAttributes = 0; + + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::NumberVariable: + case VirtualTerminalObjectType::Macro: + { + // Valid Object + } + break; + + case VirtualTerminalObjectType::FontAttributes: + { + numberOfFontAttributes++; + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + + if (numberOfFontAttributes > 1) + { + anyWrongChildType = true; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool InputBoolean::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::ForegroundColour: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::FontAttributes); + } + break; + + case AttributeName::VariableReference: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::Value: + { + set_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Enabled: + { + set_enabled(0 != rawAttributeData); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint8_t InputBoolean::get_value() const + { + return value; + } + + void InputBoolean::set_value(std::uint8_t inputValue) + { + value = inputValue; + } + + bool InputBoolean::get_enabled() const + { + return enabled; + } + + void InputBoolean::set_enabled(bool isEnabled) + { + enabled = isEnabled; + } + + InputString::InputString(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType InputString::get_object_type() const + { + return VirtualTerminalObjectType::InputString; + } + + std::uint32_t InputString::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool InputString::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::StringVariable: + case VirtualTerminalObjectType::FontAttributes: + case VirtualTerminalObjectType::InputAttributes: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool InputString::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FontAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::FontAttributes); + } + break; + + case AttributeName::InputAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::InputAttributes); + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::Justification: + { + set_justification_bitfield(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Enabled: + { + set_enabled(0 != rawAttributeData); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + bool InputString::get_enabled() const + { + return enabled; + } + + void InputString::set_enabled(bool value) + { + enabled = value; + } + + bool InputString::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void InputString::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void InputString::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + InputString::HorizontalJustification InputString::get_horizontal_justification() const + { + return static_cast(justificationBitfield & 0x0F); + } + + InputString::VerticalJustification InputString::get_vertical_justification() const + { + return static_cast((justificationBitfield >> 4) & 0x0F); + } + + void InputString::set_justification_bitfield(std::uint8_t value) + { + justificationBitfield = value; + } + + std::string InputString::get_value() const + { + return stringValue; + } + + void InputString::set_value(const std::string &value) + { + stringValue = value; + } + + InputNumber::InputNumber(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType InputNumber::get_object_type() const + { + return VirtualTerminalObjectType::InputNumber; + } + + std::uint32_t InputNumber::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool InputNumber::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::NumberVariable: + case VirtualTerminalObjectType::FontAttributes: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool InputNumber::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FontAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::FontAttributes); + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::MinValue: + { + set_minimum_value(rawAttributeData); + retVal = true; + } + break; + + case AttributeName::MaxValue: + { + set_maximum_value(rawAttributeData); + retVal = true; + } + break; + + case AttributeName::Offset: + { + auto temp = reinterpret_cast(&rawAttributeData); + set_offset(*temp); + retVal = true; + } + break; + + case AttributeName::Scale: + { + auto temp = reinterpret_cast(&rawAttributeData); + set_scale(*temp); + retVal = true; + } + break; + + case AttributeName::NumberOfDecimals: + { + set_number_of_decimals(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Format: + { + set_format(0 != rawAttributeData); + retVal = true; + } + break; + + case AttributeName::Justification: + { + set_justification_bitfield(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + InputNumber::HorizontalJustification InputNumber::get_horizontal_justification() const + { + return static_cast(justificationBitfield & 0x0F); + } + + InputNumber::VerticalJustification InputNumber::get_vertical_justification() const + { + return static_cast((justificationBitfield >> 4) & 0x0F); + } + + void InputNumber::set_justification_bitfield(std::uint8_t newJustification) + { + justificationBitfield = newJustification; + } + + float InputNumber::get_scale() const + { + return scale; + } + + void InputNumber::set_scale(float newScale) + { + scale = newScale; + } + + std::uint32_t InputNumber::get_maximum_value() const + { + return maximumValue; + } + + void InputNumber::set_maximum_value(std::uint32_t newMax) + { + maximumValue = newMax; + } + + std::uint32_t InputNumber::get_minimum_value() const + { + return minimumValue; + } + + void InputNumber::set_minimum_value(std::uint32_t newMin) + { + minimumValue = newMin; + } + + std::int32_t InputNumber::get_offset() const + { + return offset; + } + + void InputNumber::set_offset(std::int32_t newOffset) + { + offset = newOffset; + } + + std::uint8_t InputNumber::get_number_of_decimals() const + { + return numberOfDecimals; + } + + void InputNumber::set_number_of_decimals(std::uint8_t newDecimals) + { + numberOfDecimals = newDecimals; + } + + bool InputNumber::get_format() const + { + return format; + } + + void InputNumber::set_format(bool newFormat) + { + format = newFormat; + } + + bool InputNumber::get_option(Options newOption) const + { + return (0 != ((1 << static_cast(newOption)) & options)); + } + + void InputNumber::set_options(std::uint8_t newOptions) + { + options = newOptions; + } + + void InputNumber::set_option(Options option, bool newOption) + { + if (newOption) + { + options |= (1 << static_cast(option)); + } + else + { + options &= ~(1 << static_cast(option)); + } + } + + bool InputNumber::get_option2(Options2 newOption) const + { + return (0 != ((1 << static_cast(newOption)) & options2)); + } + + void InputNumber::set_options2(std::uint8_t newOptions) + { + options2 = newOptions; + } + + void InputNumber::set_option2(Options2 option, bool newOption) + { + if (newOption) + { + options2 |= (1 << static_cast(option)); + } + else + { + options2 &= ~(1 << static_cast(option)); + } + } + + std::uint32_t InputNumber::get_value() const + { + return value; + } + + void InputNumber::set_value(std::uint32_t inputValue) + { + value = inputValue; + } + + InputList::InputList(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType InputList::get_object_type() const + { + return VirtualTerminalObjectType::InputList; + } + + std::uint32_t InputList::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool InputList::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::NumberVariable: + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool InputList::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + set_variable_reference(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Value: + { + set_value(rawAttributeData); + retVal = true; + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + bool InputList::get_option(Options option) const + { + return (0 != (optionsBitfield & (1 << static_cast(option)))); + } + + void InputList::set_options(std::uint8_t options) + { + optionsBitfield = options; + } + + void InputList::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + std::uint8_t InputList::get_value() const + { + return value; + } + + void InputList::set_value(std::uint8_t inputValue) + { + value = inputValue; + } + + bool InputList::change_list_item(std::uint8_t index, std::uint16_t newListItem) + { + bool retVal = false; + + if ((index < children.size()) && + ((NULL_OBJECT_ID == newListItem) || + ((nullptr != thisObjectPool[newListItem]) && + (VirtualTerminalObjectType::NumberVariable == thisObjectPool[newListItem]->get_object_type())))) + { + children.at(index).id = newListItem; + retVal = true; + } + return retVal; + } + + void InputList::set_variable_reference(std::uint16_t referencedObjectID) + { + variableReference = referencedObjectID; + } + + std::uint16_t InputList::get_variable_reference() const + { + return variableReference; + } + + std::uint8_t InputList::get_number_of_list_items() const + { + return numberOfListItems; + } + + void InputList::set_number_of_list_items(std::uint8_t value) + { + numberOfListItems = value; + } + + OutputString::OutputString(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputString::get_object_type() const + { + return VirtualTerminalObjectType::OutputString; + } + + std::uint32_t OutputString::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputString::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::StringVariable: + case VirtualTerminalObjectType::FontAttributes: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputString::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FontAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::FontAttributes); + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::Justification: + { + set_justification_bitfield(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + bool OutputString::get_option(Options option) const + { + return (0 != (optionsBitfield & (1 << static_cast(option)))); + } + + void OutputString::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void OutputString::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + OutputString::HorizontalJustification OutputString::get_horizontal_justification() const + { + return static_cast(justificationBitfield & 0x0F); + } + + OutputString::VerticalJustification OutputString::get_vertical_justification() const + { + return static_cast((justificationBitfield >> 4) & 0x0F); + } + + void OutputString::set_justification_bitfield(std::uint8_t value) + { + justificationBitfield = value; + } + + std::string OutputString::get_value() const + { + return stringValue; + } + + void OutputString::set_value(const std::string &value) + { + stringValue = value; + } + + OutputNumber::OutputNumber(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputNumber::get_object_type() const + { + return VirtualTerminalObjectType::OutputNumber; + } + + std::uint32_t OutputNumber::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputNumber::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::NumberVariable: + case VirtualTerminalObjectType::FontAttributes: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputNumber::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FontAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::FontAttributes); + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::Offset: + { + auto temp = reinterpret_cast(&rawAttributeData); + set_offset(*temp); + retVal = true; + } + break; + + case AttributeName::Scale: + { + auto temp = reinterpret_cast(&rawAttributeData); + set_scale(*temp); + retVal = true; + } + break; + + case AttributeName::NumberOfDecimals: + { + set_number_of_decimals(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Format: + { + set_format(0 != rawAttributeData); + retVal = true; + } + break; + + case AttributeName::Justification: + { + set_justification_bitfield(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + bool OutputNumber::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void OutputNumber::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void OutputNumber::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + OutputNumber::HorizontalJustification OutputNumber::get_horizontal_justification() const + { + return static_cast(justificationBitfield & 0x0F); + } + + OutputNumber::VerticalJustification OutputNumber::get_vertical_justification() const + { + return static_cast((justificationBitfield >> 4) & 0x0F); + } + + void OutputNumber::set_justification_bitfield(std::uint8_t value) + { + justificationBitfield = value; + } + + float OutputNumber::get_scale() const + { + return scale; + } + + void OutputNumber::set_scale(float value) + { + scale = value; + } + + std::int32_t OutputNumber::get_offset() const + { + return offset; + } + + void OutputNumber::set_offset(std::int32_t value) + { + offset = value; + } + + std::uint8_t OutputNumber::get_number_of_decimals() const + { + return numberOfDecimals; + } + + void OutputNumber::set_number_of_decimals(std::uint8_t value) + { + numberOfDecimals = value; + } + + bool OutputNumber::get_format() const + { + return format; + } + + void OutputNumber::set_format(bool value) + { + format = value; + } + + std::uint32_t OutputNumber::get_value() const + { + return value; + } + + void OutputNumber::set_value(std::uint32_t inputValue) + { + value = inputValue; + } + + OutputList::OutputList(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputList::get_object_type() const + { + return VirtualTerminalObjectType::OutputList; + } + + std::uint32_t OutputList::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputList::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::NumberVariable: + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputList::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::Value: + { + set_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint8_t OutputList::get_number_of_list_items() const + { + return numberOfListItems; + } + + void OutputList::set_number_of_list_items(std::uint8_t value) + { + numberOfListItems = value; + } + + std::uint8_t OutputList::get_value() const + { + return value; + } + + void OutputList::set_value(std::uint8_t aValue) + { + value = aValue; + } + + bool OutputList::change_list_item(std::uint8_t index, std::uint16_t newListItem) + { + bool retVal = false; + + if ((index < children.size()) && + ((NULL_OBJECT_ID == newListItem) || + ((nullptr != thisObjectPool[newListItem]) && + (VirtualTerminalObjectType::NumberVariable == thisObjectPool[newListItem]->get_object_type())))) + { + children.at(index).id = newListItem; + retVal = true; + } + return retVal; + } + + void OutputList::set_variable_reference(std::uint16_t referencedObjectID) + { + variableReference = referencedObjectID; + } + + std::uint16_t OutputList::get_variable_reference() const + { + return variableReference; + } + + OutputLine::OutputLine(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputLine::get_object_type() const + { + return VirtualTerminalObjectType::OutputLine; + } + + bool OutputLine::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::LineAttributes: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputLine::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::LineAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::LineAttributes); + } + break; + + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::LineDirection: + { + if (rawAttributeData <= static_cast(LineDirection::BottomLeftToTopRight)) + { + set_line_direction(static_cast(rawAttributeData)); + retVal = true; + } + else + { + returnedError = AttributeError::AnyOtherError; + } + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint32_t OutputLine::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + OutputLine::LineDirection OutputLine::get_line_direction() const + { + return static_cast(lineDirection); + } + + void OutputLine::set_line_direction(LineDirection value) + { + lineDirection = static_cast(value); + } + + OutputRectangle::OutputRectangle(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputRectangle::get_object_type() const + { + return VirtualTerminalObjectType::OutputRectangle; + } + + std::uint32_t OutputRectangle::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputRectangle::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::LineAttributes: + case VirtualTerminalObjectType::FillAttributes: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputRectangle::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::LineAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::LineAttributes); + } + break; + + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::LineSuppression: + { + set_line_suppression_bitfield(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FillAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::FillAttributes); + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint8_t OutputRectangle::get_line_suppression_bitfield() const + { + return lineSuppressionBitfield; + } + + void OutputRectangle::set_line_suppression_bitfield(std::uint8_t value) + { + lineSuppressionBitfield = value; + } + + OutputEllipse::OutputEllipse(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputEllipse::get_object_type() const + { + return VirtualTerminalObjectType::OutputEllipse; + } + + std::uint32_t OutputEllipse::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputEllipse::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::LineAttributes: + case VirtualTerminalObjectType::FillAttributes: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputEllipse::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::LineAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::LineAttributes); + } + break; + + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::EllipseType: + { + if (rawAttributeData <= static_cast(EllipseType::ClosedEllipseSection)) + { + set_ellipse_type(static_cast(rawAttributeData)); + retVal = true; + } + else + { + returnedError = AttributeError::AnyOtherError; + } + } + break; + + case AttributeName::StartAngle: + { + set_start_angle(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::EndAngle: + { + set_end_angle(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FillAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::FillAttributes); + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + OutputEllipse::EllipseType OutputEllipse::get_ellipse_type() const + { + return static_cast(ellipseType); + } + + void OutputEllipse::set_ellipse_type(EllipseType value) + { + ellipseType = static_cast(value); + } + + std::uint8_t OutputEllipse::get_start_angle() const + { + return startAngle; + } + + void OutputEllipse::set_start_angle(std::uint8_t value) + { + startAngle = value; + } + + std::uint8_t OutputEllipse::get_end_angle() const + { + return endAngle; + } + + void OutputEllipse::set_end_angle(std::uint8_t value) + { + endAngle = value; + } + + OutputPolygon::OutputPolygon(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputPolygon::get_object_type() const + { + return VirtualTerminalObjectType::OutputPolygon; + } + + std::uint32_t OutputPolygon::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputPolygon::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::LineAttributes: + case VirtualTerminalObjectType::FillAttributes: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputPolygon::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::LineAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::LineAttributes); + } + break; + + case AttributeName::FillAttributes: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::FillAttributes); + } + break; + + case AttributeName::PolygonType: + { + if (rawAttributeData <= static_cast(PolygonType::Open)) + { + set_type(static_cast(rawAttributeData)); + retVal = true; + } + else + { + returnedError = AttributeError::AnyOtherError; + } + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + void OutputPolygon::add_point(std::uint16_t x, std::uint16_t y) + { + pointList.push_back({ x, y }); + } + + std::uint8_t OutputPolygon::get_number_of_points() const + { + return static_cast(pointList.size()); + } + + OutputPolygon::PolygonPoint OutputPolygon::get_point(std::uint8_t index) + { + PolygonPoint retVal = { 0, 0 }; + + if (index < pointList.size()) + { + retVal = pointList[index]; + } + return retVal; + } + + OutputPolygon::PolygonType OutputPolygon::get_type() const + { + return static_cast(polygonType); + } + + void OutputPolygon::set_type(PolygonType value) + { + polygonType = static_cast(value); + } + + OutputMeter::OutputMeter(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputMeter::get_object_type() const + { + return VirtualTerminalObjectType::OutputMeter; + } + + std::uint32_t OutputMeter::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputMeter::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::NumberVariable: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputMeter::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::NeedleColour: + { + set_needle_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::BorderColour: + { + set_border_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::ArcAndTickColour: + { + set_arc_and_tick_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::NumberOfTicks: + { + set_number_of_ticks(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::StartAngle: + { + set_start_angle(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::EndAngle: + { + set_end_angle(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::MinValue: + { + set_min_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::MaxValue: + { + set_max_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::Value: + { + set_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint16_t OutputMeter::get_min_value() const + { + return minValue; + } + + void OutputMeter::set_min_value(std::uint16_t value) + { + minValue = value; + } + + std::uint16_t OutputMeter::get_max_value() const + { + return maxValue; + } + + void OutputMeter::set_max_value(std::uint16_t value) + { + maxValue = value; + } + + std::uint16_t OutputMeter::get_value() const + { + return value; + } + + void OutputMeter::set_value(std::uint16_t aValue) + { + value = aValue; + } + + std::uint8_t OutputMeter::get_needle_colour() const + { + return needleColour; + } + + void OutputMeter::set_needle_colour(std::uint8_t value) + { + needleColour = value; + } + + std::uint8_t OutputMeter::get_border_colour() const + { + return borderColour; + } + + void OutputMeter::set_border_colour(std::uint8_t value) + { + borderColour = value; + } + + std::uint8_t OutputMeter::get_arc_and_tick_colour() const + { + return arcAndTickColour; + } + + void OutputMeter::set_arc_and_tick_colour(std::uint8_t value) + { + arcAndTickColour = value; + } + + std::uint8_t OutputMeter::get_number_of_ticks() const + { + return numberOfTicks; + } + + void OutputMeter::set_number_of_ticks(std::uint8_t value) + { + numberOfTicks = value; + } + + bool OutputMeter::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void OutputMeter::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void OutputMeter::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + std::uint8_t OutputMeter::get_start_angle() const + { + return startAngle; + } + + void OutputMeter::set_start_angle(std::uint8_t value) + { + startAngle = value; + } + + std::uint8_t OutputMeter::get_end_angle() const + { + return endAngle; + } + + void OutputMeter::set_end_angle(std::uint8_t value) + { + endAngle = value; + } + + OutputLinearBarGraph::OutputLinearBarGraph(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputLinearBarGraph::get_object_type() const + { + return VirtualTerminalObjectType::OutputLinearBarGraph; + } + + std::uint32_t OutputLinearBarGraph::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputLinearBarGraph::get_is_valid() const + { + bool anyWrongChildType = false; + + for (auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if (nullptr != childObject) + { + switch (childObject->get_object_type()) + { + case VirtualTerminalObjectType::NumberVariable: + case VirtualTerminalObjectType::Macro: + { + // Valid Child Object + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputLinearBarGraph::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Colour: + { + set_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::TargetLineColour: + { + set_target_line_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::NumberOfTicks: + { + set_number_of_ticks(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::MinValue: + { + set_min_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::MaxValue: + { + set_max_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + returnedError = AttributeError::AnyOtherError; + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::TargetValueVariableReference: + { + set_target_value_reference(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::TargetValue: + { + set_target_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Value: + { + set_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint16_t OutputLinearBarGraph::get_min_value() const + { + return minValue; + } + + void OutputLinearBarGraph::set_min_value(std::uint16_t value) + { + minValue = value; + } + + std::uint16_t OutputLinearBarGraph::get_max_value() const + { + return maxValue; + } + + void OutputLinearBarGraph::set_max_value(std::uint16_t value) + { + maxValue = value; + } + + std::uint16_t OutputLinearBarGraph::get_value() const + { + return value; + } + + void OutputLinearBarGraph::set_value(std::uint16_t aValue) + { + value = aValue; + } + + std::uint16_t OutputLinearBarGraph::get_target_value() const + { + return targetValue; + } + + void OutputLinearBarGraph::set_target_value(std::uint16_t value) + { + targetValue = value; + } + + std::uint16_t OutputLinearBarGraph::get_target_value_reference() const + { + return targetValueReference; + } + + void OutputLinearBarGraph::set_target_value_reference(std::uint16_t value) + { + targetValueReference = value; + } + + std::uint8_t OutputLinearBarGraph::get_number_of_ticks() const + { + return numberOfTicks; + } + + void OutputLinearBarGraph::set_number_of_ticks(std::uint8_t value) + { + numberOfTicks = value; + } + + std::uint8_t OutputLinearBarGraph::get_colour() const + { + return colour; + } + + void OutputLinearBarGraph::set_colour(std::uint8_t value) + { + colour = value; + } + + std::uint8_t OutputLinearBarGraph::get_target_line_colour() const + { + return targetLineColour; + } + + void OutputLinearBarGraph::set_target_line_colour(std::uint8_t value) + { + targetLineColour = value; + } + + bool OutputLinearBarGraph::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void OutputLinearBarGraph::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void OutputLinearBarGraph::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + OutputArchedBarGraph::OutputArchedBarGraph(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType OutputArchedBarGraph::get_object_type() const + { + return VirtualTerminalObjectType::OutputArchedBarGraph; + } + + std::uint32_t OutputArchedBarGraph::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool OutputArchedBarGraph::get_is_valid() const + { + bool anyWrongChildType = false; + + for (const auto &child : children) + { + auto childObject = get_object_by_id(child.id); + if ((nullptr != childObject) && + ((VirtualTerminalObjectType::NumberVariable != childObject->get_object_type()) && + (VirtualTerminalObjectType::Macro != childObject->get_object_type()))) + { + anyWrongChildType = true; + } + } + return ((!anyWrongChildType) && + (NULL_OBJECT_ID != objectID)); + } + + bool OutputArchedBarGraph::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Height: + { + set_height(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Colour: + { + set_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::TargetLineColour: + { + set_target_line_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::StartAngle: + { + set_start_angle(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::EndAngle: + { + set_end_angle(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::BarGraphWidth: + { + set_bar_graph_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::MinValue: + { + set_min_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::MaxValue: + { + set_max_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::VariableReference: + { + retVal = replace_only_child_of_type(static_cast(rawAttributeData), VirtualTerminalObjectType::NumberVariable); + } + break; + + case AttributeName::TargetValueVariableReference: + { + set_target_value_reference(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::TargetValue: + { + set_target_value(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint16_t OutputArchedBarGraph::get_bar_graph_width() const + { + return barGraphWidth; + } + + void OutputArchedBarGraph::set_bar_graph_width(std::uint16_t value) + { + barGraphWidth = value; + } + + std::uint16_t OutputArchedBarGraph::get_min_value() const + { + return minValue; + } + + void OutputArchedBarGraph::set_min_value(std::uint16_t value) + { + minValue = value; + } + + std::uint16_t OutputArchedBarGraph::get_max_value() const + { + return maxValue; + } + + void OutputArchedBarGraph::set_max_value(std::uint16_t value) + { + maxValue = value; + } + + std::uint16_t OutputArchedBarGraph::get_value() const + { + return value; + } + + void OutputArchedBarGraph::set_value(std::uint16_t aValue) + { + value = aValue; + } + + std::uint8_t OutputArchedBarGraph::get_target_line_colour() const + { + return targetLineColour; + } + + void OutputArchedBarGraph::set_target_line_colour(std::uint8_t value) + { + targetLineColour = value; + } + + std::uint8_t OutputArchedBarGraph::get_colour() const + { + return colour; + } + + void OutputArchedBarGraph::set_colour(std::uint8_t value) + { + colour = value; + } + + bool OutputArchedBarGraph::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void OutputArchedBarGraph::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void OutputArchedBarGraph::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + std::uint8_t OutputArchedBarGraph::get_start_angle() const + { + return startAngle; + } + + void OutputArchedBarGraph::set_start_angle(std::uint8_t value) + { + startAngle = value; + } + + std::uint8_t OutputArchedBarGraph::get_end_angle() const + { + return endAngle; + } + + void OutputArchedBarGraph::set_end_angle(std::uint8_t value) + { + endAngle = value; + } + + std::uint16_t OutputArchedBarGraph::get_target_value() const + { + return targetValue; + } + + void OutputArchedBarGraph::set_target_value(std::uint16_t value) + { + targetValue = value; + } + + std::uint16_t OutputArchedBarGraph::get_target_value_reference() const + { + return targetValueReference; + } + + void OutputArchedBarGraph::set_target_value_reference(std::uint16_t value) + { + targetValueReference = value; + } + + PictureGraphic::PictureGraphic(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType PictureGraphic::get_object_type() const + { + return VirtualTerminalObjectType::PictureGraphic; + } + + std::uint32_t PictureGraphic::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool PictureGraphic::get_is_valid() const + { + return true; + } + + bool PictureGraphic::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::Width: + { + set_width(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::TransparencyColour: + { + set_transparency_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::vector &PictureGraphic::get_raw_data() + { + return rawData; + } + + void PictureGraphic::set_raw_data(std::uint8_t *data, std::uint32_t size) + { + rawData.clear(); + rawData.resize(size); + + for (std::uint32_t i = 0; i < size; i++) + { + rawData[i] = data[i]; + } + } + + void PictureGraphic::add_raw_data(std::uint8_t dataByte) + { + rawData.push_back(dataByte); + } + + std::uint32_t PictureGraphic::get_number_of_bytes_in_raw_data() const + { + return numberOfBytesInRawData; + } + + void PictureGraphic::set_number_of_bytes_in_raw_data(std::uint32_t value) + { + numberOfBytesInRawData = value; + rawData.reserve(value); + } + + std::uint16_t PictureGraphic::get_actual_width() const + { + return actualWidth; + } + + void PictureGraphic::set_actual_width(std::uint16_t value) + { + actualWidth = value; + } + + std::uint16_t PictureGraphic::get_actual_height() const + { + return actualHeight; + } + + void PictureGraphic::set_actual_height(std::uint16_t value) + { + actualHeight = value; + } + + PictureGraphic::Format PictureGraphic::get_format() const + { + return static_cast(formatByte); + } + + void PictureGraphic::set_format(Format value) + { + formatByte = static_cast(value); + } + + bool PictureGraphic::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void PictureGraphic::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void PictureGraphic::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + + std::uint8_t PictureGraphic::get_transparency_colour() const + { + return transparencyColour; + } + + void PictureGraphic::set_transparency_colour(std::uint8_t value) + { + transparencyColour = value; + } + + NumberVariable::NumberVariable(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType NumberVariable::get_object_type() const + { + return VirtualTerminalObjectType::NumberVariable; + } + + std::uint32_t NumberVariable::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool NumberVariable::get_is_valid() const + { + return true; + } + + bool NumberVariable::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + returnedError = AttributeError::InvalidAttributeID; + return false; + } + + std::uint32_t NumberVariable::get_value() const + { + return value; + } + + void NumberVariable::set_value(std::uint32_t aValue) + { + value = aValue; + } + + StringVariable::StringVariable(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType StringVariable::get_object_type() const + { + return VirtualTerminalObjectType::StringVariable; + } + + std::uint32_t StringVariable::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool StringVariable::get_is_valid() const + { + return true; + } + + bool StringVariable::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + returnedError = AttributeError::InvalidAttributeID; + return false; + } + + std::string StringVariable::get_value() + { + return value; + } + + void StringVariable::set_value(std::string aValue) + { + value = aValue; + } + + FontAttributes::FontAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType FontAttributes::get_object_type() const + { + return VirtualTerminalObjectType::FontAttributes; + } + + std::uint32_t FontAttributes::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool FontAttributes::get_is_valid() const + { + return true; + } + + bool FontAttributes::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::FontColour: + { + set_colour(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FontSize: + { + if (rawAttributeData <= static_cast(FontAttributes::FontSize::Size128x192)) + { + set_size(static_cast(rawAttributeData)); + retVal = true; + } + else + { + returnedError = AttributeError::AnyOtherError; + } + } + break; + + case AttributeName::FontType: + { + set_type(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FontStyle: + { + set_style(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + FontAttributes::FontType FontAttributes::get_type() const + { + return static_cast(type); + } + + void FontAttributes::set_type(FontType value) + { + type = static_cast(value); + } + + std::uint8_t FontAttributes::get_style() const + { + return style; + } + + bool FontAttributes::get_style(FontStyleBits styleSetting) + { + return (style >> static_cast(styleSetting)) & 0x01; + } + + void FontAttributes::set_style(FontStyleBits bit, bool value) + { + style = (static_cast(value) << static_cast(bit)); + } + + void FontAttributes::set_style(std::uint8_t value) + { + style = value; + } + + FontAttributes::FontSize FontAttributes::get_size() const + { + return static_cast(size); + } + + void FontAttributes::set_size(FontSize value) + { + size = static_cast(value); + } + + std::uint8_t FontAttributes::get_colour() const + { + return colour; + } + + void FontAttributes::set_colour(std::uint8_t value) + { + colour = value; + } + + std::uint8_t FontAttributes::get_font_width_pixels() const + { + std::uint8_t retVal = 0; + + switch (static_cast(size)) + { + case FontSize::Size6x8: + { + retVal = 6; + } + break; + + case FontSize::Size8x8: + case FontSize::Size8x12: + { + retVal = 8; + } + break; + + case FontSize::Size12x16: + { + retVal = 12; + } + break; + + case FontSize::Size16x16: + case FontSize::Size16x24: + { + retVal = 16; + } + break; + + case FontSize::Size24x32: + { + retVal = 24; + } + break; + + case FontSize::Size32x32: + case FontSize::Size32x48: + { + retVal = 32; + } + break; + + case FontSize::Size48x64: + { + retVal = 48; + } + break; + + case FontSize::Size64x64: + case FontSize::Size64x96: + { + retVal = 64; + } + break; + + case FontSize::Size96x128: + { + retVal = 96; + } + break; + + case FontSize::Size128x128: + case FontSize::Size128x192: + { + retVal = 128; + } + break; + + default: + break; + } + return retVal; + } + + std::uint8_t FontAttributes::get_font_height_pixels() const + { + std::uint8_t retVal = 0; + + switch (static_cast(size)) + { + case FontSize::Size6x8: + case FontSize::Size8x8: + { + retVal = 8; + } + break; + + case FontSize::Size8x12: + { + retVal = 12; + } + break; + + case FontSize::Size12x16: + case FontSize::Size16x16: + { + retVal = 16; + } + break; + + case FontSize::Size16x24: + { + retVal = 24; + } + break; + + case FontSize::Size24x32: + case FontSize::Size32x32: + { + retVal = 32; + } + break; + + case FontSize::Size32x48: + { + retVal = 48; + } + break; + + case FontSize::Size48x64: + case FontSize::Size64x64: + { + retVal = 64; + } + break; + + case FontSize::Size64x96: + { + retVal = 96; + } + break; + + case FontSize::Size96x128: + case FontSize::Size128x128: + { + retVal = 128; + } + break; + + case FontSize::Size128x192: + { + retVal = 192; + } + break; + + default: + break; + } + return retVal; + } + + LineAttributes::LineAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType LineAttributes::get_object_type() const + { + return VirtualTerminalObjectType::LineAttributes; + } + + std::uint32_t LineAttributes::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool LineAttributes::get_is_valid() const + { + return true; + } + + bool LineAttributes::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::LineColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::LineWidth: + { + set_width(static_cast(rawAttributeData & 0xFF)); + retVal = true; + } + break; + + case AttributeName::LineArt: + { + set_line_art_bit_pattern(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint16_t LineAttributes::get_line_art_bit_pattern() const + { + return lineArtBitpattern; + } + + void LineAttributes::set_line_art_bit_pattern(std::uint16_t value) + { + lineArtBitpattern = value; + } + + FillAttributes::FillAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable), + fillPattern(NULL_OBJECT_ID), + type(FillType::NoFill) + { + } + + VirtualTerminalObjectType FillAttributes::get_object_type() const + { + return VirtualTerminalObjectType::FillAttributes; + } + + std::uint32_t FillAttributes::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool FillAttributes::get_is_valid() const + { + return true; + } + + bool FillAttributes::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::FillType: + { + if (rawAttributeData <= static_cast(FillType::FillWithPatternGivenByFillPatternAttribute)) + { + set_type(static_cast(rawAttributeData)); + retVal = true; + } + else + { + returnedError = AttributeError::AnyOtherError; + } + } + break; + + case AttributeName::FillColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::FillPattern: + { + set_fill_pattern(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint16_t FillAttributes::get_fill_pattern() const + { + return fillPattern; + } + + void FillAttributes::set_fill_pattern(std::uint16_t value) + { + fillPattern = value; + } + + FillAttributes::FillType FillAttributes::get_type() const + { + return type; + } + + void FillAttributes::set_type(FillType value) + { + type = value; + } + + InputAttributes::InputAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType InputAttributes::get_object_type() const + { + return VirtualTerminalObjectType::InputAttributes; + } + + std::uint32_t InputAttributes::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool InputAttributes::get_is_valid() const + { + return true; + } + + bool InputAttributes::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + returnedError = AttributeError::InvalidAttributeID; + return false; + } + + std::string InputAttributes::get_validation_string() const + { + return validationString; + } + + void InputAttributes::set_validation_string(std::string value) + { + validationString = value; + } + + InputAttributes::ValidationType InputAttributes::get_validation_type() const + { + return validationType; + } + + void InputAttributes::set_validation_type(ValidationType newValidationType) + { + validationType = newValidationType; + } + + ExtendedInputAttributes::ExtendedInputAttributes(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType ExtendedInputAttributes::get_object_type() const + { + return VirtualTerminalObjectType::ExtendedInputAttributes; + } + + std::uint32_t ExtendedInputAttributes::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool ExtendedInputAttributes::get_is_valid() const + { + return true; + } + + bool ExtendedInputAttributes::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + returnedError = AttributeError::InvalidAttributeID; + return false; + } + + std::uint8_t ExtendedInputAttributes::get_number_of_code_planes() const + { + return static_cast(codePlanes.size()); + } + + void ExtendedInputAttributes::set_number_of_code_planes(std::uint8_t value) + { + codePlanes.resize(value); + } + + ExtendedInputAttributes::ValidationType ExtendedInputAttributes::get_validation_type() const + { + return validationType; + } + + void ExtendedInputAttributes::set_validation_type(ValidationType value) + { + validationType = value; + } + + ObjectPointer::ObjectPointer(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType ObjectPointer::get_object_type() const + { + return VirtualTerminalObjectType::ObjectPointer; + } + + std::uint32_t ObjectPointer::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool ObjectPointer::get_is_valid() const + { + return true; + } + + bool ObjectPointer::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + returnedError = AttributeError::InvalidAttributeID; + return false; + } + + ExternalObjectPointer::ExternalObjectPointer(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType ExternalObjectPointer::get_object_type() const + { + return VirtualTerminalObjectType::ExternalObjectPointer; + } + + std::uint32_t ExternalObjectPointer::get_minumum_object_length() const + { + return 9; + } + + bool ExternalObjectPointer::get_is_valid() const + { + return true; + } + + bool ExternalObjectPointer::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::DefaultObjectID: + { + if ((NULL_OBJECT_ID == rawAttributeData) || + (nullptr != thisObjectPool[static_cast(rawAttributeData)])) + { + set_default_object_id(static_cast(rawAttributeData)); + retVal = true; + } + else + { + returnedError = AttributeError::AnyOtherError; + } + } + break; + + case AttributeName::ExternalReferenceNAMEID: + { + set_external_reference_name_id(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::ExternalObjectID: + { + set_external_object_id(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint16_t ExternalObjectPointer::get_default_object_id() const + { + return defaultObjectID; + } + + void ExternalObjectPointer::set_default_object_id(std::uint16_t id) + { + defaultObjectID = id; + } + + std::uint16_t ExternalObjectPointer::get_external_reference_name_id() const + { + return externalReferenceNAMEID; + } + + void ExternalObjectPointer::set_external_reference_name_id(std::uint16_t id) + { + externalReferenceNAMEID = id; + } + + std::uint16_t ExternalObjectPointer::get_external_object_id() const + { + return externalObjectID; + } + + void ExternalObjectPointer::set_external_object_id(std::uint16_t id) + { + externalObjectID = id; + } + + const std::array Macro::ALLOWED_COMMANDS_LOOKUP_TABLE = { + static_cast(Command::HideShowObject), + static_cast(Command::EnableDisableObject), + static_cast(Command::SelectInputObject), + static_cast(Command::ControlAudioSignal), + static_cast(Command::SetAudioVolume), + static_cast(Command::ChangeChildLocation), + static_cast(Command::ChangeSize), + static_cast(Command::ChangeBackgroundColour), + static_cast(Command::ChangeNumericValue), + static_cast(Command::ChangeEndPoint), + static_cast(Command::ChangeFontAttributes), + static_cast(Command::ChangeLineAttributes), + static_cast(Command::ChangeFillAttributes), + static_cast(Command::ChangeActiveMask), + static_cast(Command::ChangeSoftKeyMask), + static_cast(Command::ChangeAttribute), + static_cast(Command::ChangePriority), + static_cast(Command::ChangeListItem), + static_cast(Command::ChangeStringValue), + static_cast(Command::ChangeChildPosition), + static_cast(Command::ChangeObjectLabel), + static_cast(Command::ChangePolygonPoint), + static_cast(Command::LockUnlockMask), + static_cast(Command::ExecuteMacro), + static_cast(Command::ChangePolygonScale), + static_cast(Command::GraphicsContextCommand), + static_cast(Command::SelectColourMap), + static_cast(Command::ExecuteExtendedMacro) + }; + + Macro::Macro(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType Macro::get_object_type() const + { + return VirtualTerminalObjectType::Macro; + } + + std::uint32_t Macro::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool Macro::get_is_valid() const + { + bool retVal = true; + + if (commandPackets.empty()) + { + retVal = true; + } + else + { + for (const auto &command : commandPackets) + { + bool currentCommandAllowed = false; + + for (const auto &allowedCommand : ALLOWED_COMMANDS_LOOKUP_TABLE) + { + if (command.at(0) == allowedCommand) + { + currentCommandAllowed = true; + break; + } + } + + if (!currentCommandAllowed) + { + retVal = false; + break; + } + } + } + return retVal; + } + + bool Macro::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + returnedError = AttributeError::InvalidAttributeID; + return false; + } + + bool Macro::add_command_packet(std::array command) + { + bool retVal = false; + + if (commandPackets.size() < 255) + { + commandPackets.push_back(command); + retVal = true; + } + return retVal; + } + + std::uint8_t Macro::get_number_of_commands() const + { + return static_cast(commandPackets.size()); + } + + bool Macro::get_command_packet(std::uint8_t index, std::array &command) + { + bool retVal = false; + + if (index < commandPackets.size()) + { + std::copy(std::begin(commandPackets.at(index)), std::end(commandPackets.at(index)), std::begin(command)); + retVal = true; + } + return retVal; + } + + bool Macro::remove_command_packet(std::uint8_t index) + { + bool retVal = false; + + if (index < commandPackets.size()) + { + auto eraseLocation = commandPackets.begin() + index; + commandPackets.erase(eraseLocation); + retVal = true; + } + return retVal; + } + + ColourMap::ColourMap(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType ColourMap::get_object_type() const + { + return VirtualTerminalObjectType::ColourMap; + } + + std::uint32_t ColourMap::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool ColourMap::get_is_valid() const + { + return true; + } + + bool ColourMap::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + returnedError = AttributeError::InvalidAttributeID; + return false; + } + + bool ColourMap::set_number_of_colour_indexes(std::uint16_t value) + { + bool retVal = false; + + if ((value != colourMapData.size()) && + ((2 == value) || + (16 == value) || + (256 == value))) + { + colourMapData.clear(); + colourMapData.resize(value); + + for (std::size_t i = 0; i < colourMapData.size(); i++) + { + colourMapData[i] = static_cast(i); + } + retVal = true; + } + return retVal; + } + + std::uint16_t ColourMap::get_number_of_colour_indexes() const + { + return static_cast(colourMapData.size()); + } + + bool ColourMap::set_colour_map_index(std::uint8_t index, std::uint8_t value) + { + bool retVal = false; + + if (index < colourMapData.size()) + { + colourMapData[index] = value; + retVal = true; + } + return retVal; + } + + std::uint8_t ColourMap::get_colour_map_index(std::uint8_t index) const + { + std::uint8_t retVal = 0; + + if (index < get_number_of_colour_indexes()) + { + retVal = colourMapData[index]; + } + return retVal; + } + + WindowMask::WindowMask(std::map> &memberObjectPool, VTColourTable ¤tColourTable) : + VTObject(memberObjectPool, currentColourTable) + { + } + + VirtualTerminalObjectType WindowMask::get_object_type() const + { + return VirtualTerminalObjectType::WindowMask; + } + + std::uint32_t WindowMask::get_minumum_object_length() const + { + return MIN_OBJECT_LENGTH; + } + + bool WindowMask::get_is_valid() const + { + bool anyWrongChildType = false; + + if (WindowType::Freeform != get_window_type()) + { + if (NULL_OBJECT_ID != title) + { + auto titleObject = get_object_by_id(title); + + if (nullptr != titleObject) + { + if ((VirtualTerminalObjectType::ObjectPointer != titleObject->get_object_type()) && + (VirtualTerminalObjectType::OutputString != titleObject->get_object_type())) + { + anyWrongChildType = true; + } + else if (VirtualTerminalObjectType::ObjectPointer == titleObject->get_object_type()) + { + if (0 == titleObject->get_number_children()) + { + anyWrongChildType = true; + } + else + { + std::uint16_t titleObjectPointedTo = std::static_pointer_cast(titleObject)->get_child_id(0); + auto child = get_object_by_id(titleObjectPointedTo); + + if ((nullptr != child) && (VirtualTerminalObjectType::OutputString == child->get_object_type())) + { + // Valid + } + else + { + anyWrongChildType = true; + } + } + } + else + { + // Valid + } + } + else + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + + if (NULL_OBJECT_ID != name) + { + auto nameObject = get_object_by_id(name); + + if (nullptr != nameObject) + { + if ((VirtualTerminalObjectType::ObjectPointer != nameObject->get_object_type()) && + (VirtualTerminalObjectType::OutputString != nameObject->get_object_type())) + { + anyWrongChildType = true; + } + else if (VirtualTerminalObjectType::ObjectPointer == nameObject->get_object_type()) + { + if (0 == nameObject->get_number_children()) + { + anyWrongChildType = true; + } + else + { + std::uint16_t titleObjectPointedTo = std::static_pointer_cast(nameObject)->get_child_id(0); + auto child = get_object_by_id(titleObjectPointedTo); + + if ((nullptr != child) && (VirtualTerminalObjectType::OutputString == child->get_object_type())) + { + // Valid + } + else + { + anyWrongChildType = true; + } + } + } + else + { + // Valid + } + } + else + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + + if (NULL_OBJECT_ID != icon) + { + auto nameObject = get_object_by_id(icon); + + if (nullptr != nameObject) + { + switch (nameObject->get_object_type()) + { + case VirtualTerminalObjectType::OutputString: + case VirtualTerminalObjectType::Container: + case VirtualTerminalObjectType::OutputNumber: + case VirtualTerminalObjectType::OutputList: + case VirtualTerminalObjectType::OutputLine: + case VirtualTerminalObjectType::OutputRectangle: + case VirtualTerminalObjectType::OutputEllipse: + case VirtualTerminalObjectType::OutputPolygon: + case VirtualTerminalObjectType::OutputMeter: + case VirtualTerminalObjectType::OutputLinearBarGraph: + case VirtualTerminalObjectType::OutputArchedBarGraph: + case VirtualTerminalObjectType::GraphicsContext: + case VirtualTerminalObjectType::PictureGraphic: + case VirtualTerminalObjectType::ObjectPointer: + case VirtualTerminalObjectType::ScaledGraphic: + { + // Valid + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + } + else + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + else if (NULL_OBJECT_ID != title) + { + anyWrongChildType = true; + } + + // Validate the actual child object references for each window type + switch (static_cast(windowType)) + { + case WindowType::Freeform: + { + // Basically anything goes + } + break; + + case WindowType::NumericOutputValueWithUnits1x1: + case WindowType::NumericOutputValueWithUnits2x1: + { + if (2 == get_number_children()) + { + auto outputNum = get_object_by_id(get_child_id(0)); + auto outputString = get_object_by_id(get_child_id(0)); + + if ((nullptr == outputNum) || + (nullptr == outputString) || + (VirtualTerminalObjectType::OutputNumber != outputNum->get_object_type()) || + (VirtualTerminalObjectType::OutputString != outputString->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + case WindowType::NumericOutputValueNoUnits1x1: + case WindowType::NumericOutputValueNoUnits2x1: + { + if (1 == get_number_children()) + { + auto outputNum = get_object_by_id(get_child_id(0)); + + if ((nullptr == outputNum) || + (VirtualTerminalObjectType::OutputNumber != outputNum->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + case WindowType::StringOutputValue1x1: + case WindowType::StringOutputValue2x1: + { + if (1 == get_number_children()) + { + auto outputString = get_object_by_id(get_child_id(0)); + + if ((nullptr == outputString) || + (VirtualTerminalObjectType::OutputString != outputString->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + case WindowType::NumericInputValueWithUnits1x1: + case WindowType::NumericInputValueWithUnits2x1: + { + if (2 == get_number_children()) + { + auto inputNum = get_object_by_id(get_child_id(0)); + auto outputString = get_object_by_id(get_child_id(0)); + + if ((nullptr == inputNum) || + (nullptr == outputString) || + (VirtualTerminalObjectType::InputNumber != inputNum->get_object_type()) || + (VirtualTerminalObjectType::OutputString != outputString->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + case WindowType::NumericInputValueNoUnits1x1: + case WindowType::NumericInputValueNoUnits2x1: + { + if (1 == get_number_children()) + { + auto inputNum = get_object_by_id(get_child_id(0)); + + if ((nullptr == inputNum) || + (VirtualTerminalObjectType::InputNumber != inputNum->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + case WindowType::StringInputValue1x1: + case WindowType::StringInputValue2x1: + { + if (1 == get_number_children()) + { + auto inputStr = get_object_by_id(get_child_id(0)); + + if ((nullptr == inputStr) || + (VirtualTerminalObjectType::InputString != inputStr->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + case WindowType::HorizontalLinearBarGraphNoUnits1x1: + case WindowType::HorizontalLinearBarGraphNoUnits2x1: + { + if (1 == get_number_children()) + { + auto outputBargraph = get_object_by_id(get_child_id(0)); + + if ((nullptr == outputBargraph) || + (VirtualTerminalObjectType::OutputLinearBarGraph != outputBargraph->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + case WindowType::SingleButton1x1: + case WindowType::SingleButton2x1: + { + if (1 == get_number_children()) + { + auto button = get_object_by_id(get_child_id(0)); + + if ((nullptr == button) || + (VirtualTerminalObjectType::Button != button->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + case WindowType::DoubleButton1x1: + case WindowType::DoubleButton2x1: + { + if (2 == get_number_children()) + { + auto button1 = get_object_by_id(get_child_id(0)); + auto button2 = get_object_by_id(get_child_id(0)); + + if ((nullptr == button1) || + (nullptr == button2) || + (VirtualTerminalObjectType::Button != button1->get_object_type()) || + (VirtualTerminalObjectType::Button != button2->get_object_type())) + { + anyWrongChildType = true; + } + } + else + { + anyWrongChildType = true; + } + } + break; + + default: + { + anyWrongChildType = true; + } + break; + } + return !anyWrongChildType; + } + + bool WindowMask::set_attribute(std::uint8_t attributeID, std::uint32_t rawAttributeData, AttributeError &returnedError) + { + bool retVal = false; + + if (attributeID < static_cast(AttributeName::NumberOfAttributes)) + { + switch (static_cast(attributeID)) + { + case AttributeName::BackgroundColour: + { + set_background_color(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Options: + { + set_options(static_cast(rawAttributeData)); + retVal = true; + } + break; + + case AttributeName::Name: + { + set_name_object_id(static_cast(rawAttributeData)); + retVal = true; + } + break; + + default: + { + returnedError = AttributeError::InvalidAttributeID; + } + break; + } + } + else + { + returnedError = AttributeError::InvalidAttributeID; + } + return retVal; + } + + std::uint16_t WindowMask::get_name_object_id() const + { + return name; + } + + void WindowMask::set_name_object_id(std::uint16_t object) + { + name = object; + } + + std::uint16_t WindowMask::get_title_object_id() const + { + return title; + } + + void WindowMask::set_title_object_id(std::uint16_t object) + { + title = object; + } + + std::uint16_t WindowMask::get_icon_object_id() const + { + return icon; + } + + void WindowMask::set_icon_object_id(std::uint16_t object) + { + icon = object; + } + + WindowMask::WindowType WindowMask::get_window_type() const + { + return static_cast(windowType); + } + + void WindowMask::set_window_type(WindowType type) + { + if (static_cast(type) <= static_cast(WindowType::DoubleButton2x1)) + { + windowType = static_cast(type); + } + } + + bool WindowMask::get_option(Options option) const + { + return (0 != ((1 << static_cast(option)) & optionsBitfield)); + } + + void WindowMask::set_options(std::uint8_t value) + { + optionsBitfield = value; + } + + void WindowMask::set_option(Options option, bool value) + { + if (value) + { + optionsBitfield |= (1 << static_cast(option)); + } + else + { + optionsBitfield &= ~(1 << static_cast(option)); + } + } + +} // namespace isobus diff --git a/test/vt_object_tests.cpp b/test/vt_object_tests.cpp new file mode 100644 index 00000000..00a83c09 --- /dev/null +++ b/test/vt_object_tests.cpp @@ -0,0 +1,2028 @@ +//================================================================================================ +/// @file vt_object_tests.cpp +/// +/// @brief Unit tests for the various VT objects +/// @author Adrian Del Grosso +/// +/// @copyright 2023 Adrian Del Grosso +//================================================================================================ +#include + +#include "isobus/isobus/isobus_virtual_terminal_objects.hpp" + +using namespace isobus; + +static void run_baseline_tests(VTObject *objectUnderTest) +{ + ASSERT_NE(nullptr, objectUnderTest); + EXPECT_EQ(objectUnderTest->get_background_color(), 0); + EXPECT_EQ(objectUnderTest->get_number_children(), 0); + EXPECT_EQ(objectUnderTest->get_id(), NULL_OBJECT_ID); + EXPECT_EQ(objectUnderTest->get_height(), 0); + EXPECT_EQ(objectUnderTest->get_width(), 0); + EXPECT_NE(objectUnderTest->get_minumum_object_length(), 0); + + objectUnderTest->set_background_color(9); + EXPECT_EQ(objectUnderTest->get_background_color(), 9); + objectUnderTest->set_height(100); + EXPECT_EQ(objectUnderTest->get_height(), 100); + objectUnderTest->set_width(200); + EXPECT_EQ(objectUnderTest->get_width(), 200); + objectUnderTest->add_child(300, 0, 0); + EXPECT_EQ(objectUnderTest->get_number_children(), 1); + ASSERT_NO_THROW(objectUnderTest->get_child_id(0)); + EXPECT_EQ(objectUnderTest->get_child_id(0), 300); + objectUnderTest->remove_child(300, 0, 0); + EXPECT_EQ(objectUnderTest->get_number_children(), 0); +} + +TEST(VIRTUAL_TERMINAL_OBJECT_TESTS, WorkingSetTests) +{ + std::map> objects; + VTColourTable colourTable; + auto ws = std::make_shared(objects, colourTable); + + run_baseline_tests(ws.get()); + EXPECT_EQ(ws->get_active_mask(), 0xFFFF); + EXPECT_EQ(ws->get_active_mask(), 0xFFFF); + EXPECT_FALSE(ws->get_selectable()); + EXPECT_EQ(ws->get_object_type(), VirtualTerminalObjectType::WorkingSet); + + ws->set_active_mask(1234); + EXPECT_EQ(ws->get_active_mask(), 1234); + ws->set_selectable(true); + EXPECT_TRUE(ws->get_selectable()); + + VTObject::AttributeError error = VTObject::AttributeError::AnyOtherError; + EXPECT_TRUE(ws->set_attribute(static_cast(WorkingSet::AttributeName::ActiveMask), 4321, error)); + EXPECT_EQ(ws->get_active_mask(), 4321); + + EXPECT_TRUE(ws->set_attribute(static_cast(WorkingSet::AttributeName::Selectable), 1, error)); + EXPECT_EQ(ws->get_selectable(), true); + EXPECT_TRUE(ws->set_attribute(static_cast(WorkingSet::AttributeName::Selectable), 0, error)); + EXPECT_EQ(ws->get_selectable(), false); + + EXPECT_TRUE(ws->set_attribute(static_cast(WorkingSet::AttributeName::BackgroundColour), 41, error)); + EXPECT_EQ(ws->get_background_color(), 41); + EXPECT_TRUE(ws->set_attribute(static_cast(WorkingSet::AttributeName::BackgroundColour), 0, error)); + EXPECT_EQ(ws->get_background_color(), 0); + + // Setting the type attribute should always fail + EXPECT_FALSE(ws->set_attribute(static_cast(WorkingSet::AttributeName::Type), 4, error)); + EXPECT_NE(0, static_cast(error)); + + // Setting the number of attributes should always fail + EXPECT_FALSE(ws->set_attribute(static_cast(WorkingSet::AttributeName::NumberOfAttributes), 4, error)); + EXPECT_NE(0, static_cast(error)); + + // Test the validity checker + EXPECT_FALSE(ws->get_is_valid()); + ws->set_id(10); + objects[ws->get_id()] = ws; + EXPECT_TRUE(ws->get_is_valid()); + + // Add a valid object, a container + auto container = std::make_shared(objects, colourTable); + container->set_id(20); + objects[container->get_id()] = container; + ws->add_child(container->get_id(), 0, 0); + EXPECT_TRUE(ws->get_is_valid()); + + // Add an invalid object, a Key + auto key = std::make_shared(objects, colourTable); + key->set_id(30); + objects[key->get_id()] = key; + ws->add_child(key->get_id(), 0, 0); + EXPECT_FALSE(ws->get_is_valid()); + + // Test some basic colour table stuff + auto white = colourTable.get_colour(1); + EXPECT_NEAR(white.r, 1.0f, 0.0001f); + EXPECT_NEAR(white.g, 1.0f, 0.0001f); + EXPECT_NEAR(white.b, 1.0f, 0.0001f); + + // Change white to be some other random colour + colourTable.set_colour(1, { 0.5f, 0.5f, 0.5f }); + white = colourTable.get_colour(1); + EXPECT_NEAR(white.r, 0.5f, 0.0001f); + EXPECT_NEAR(white.g, 0.5f, 0.0001f); + EXPECT_NEAR(white.b, 0.5f, 0.0001f); +} + +TEST(VIRTUAL_TERMINAL_OBJECT_TESTS, DataMaskTests) +{ + std::map> objects; + VTColourTable colourTable; + DataMask mask(objects, colourTable); + + run_baseline_tests(&mask); + EXPECT_EQ(mask.get_object_type(), VirtualTerminalObjectType::DataMask); + + // Test data mask background colour + VTObject::AttributeError error = VTObject::AttributeError::AnyOtherError; + mask.set_background_color(10); + EXPECT_EQ(mask.get_background_color(), 10); + EXPECT_TRUE(mask.set_attribute(static_cast(DataMask::AttributeName::BackgroundColour), 20, error)); + EXPECT_EQ(mask.get_background_color(), 20); + + // Setting the type attribute should always fail + EXPECT_FALSE(mask.set_attribute(static_cast(DataMask::AttributeName::Type), 4, error)); + + // We expect there to normally be some kind of object that goes around + // and adds things to the object map. We'll simulate that here. + // + // Test adding a soft key mask and changing it + // We'll make a new shared pointer to an data mask + auto dataMask2 = std::make_shared(objects, colourTable); + dataMask2->set_id(1); // Arbitrary ID + objects[dataMask2->get_id()] = dataMask2; + + // Let's add a soft key mask to the alarm mask + auto softKeyMask = std::make_shared(objects, colourTable); + softKeyMask->set_id(100); + dataMask2->add_child(softKeyMask->get_id(), 0, 0); + objects[softKeyMask->get_id()] = softKeyMask; + + // now let's make a different soft key mask that we'll use to replace the old one + auto softKeyMask2 = std::make_shared(objects, colourTable); + softKeyMask2->set_id(200); + objects[softKeyMask2->get_id()] = softKeyMask2; + + EXPECT_TRUE(dataMask2->get_is_valid()); + + // Add an invalid object, another data mask + auto dataMask3 = std::make_shared(objects, colourTable); + dataMask3->set_id(2); // Arbitrary ID + objects[dataMask3->get_id()] = dataMask3; + dataMask2->add_child(dataMask3->get_id(), 0, 0); + EXPECT_FALSE(dataMask2->get_is_valid()); + + // Take this opportunity to check that getting an object by ID works in the base class + auto testObject = softKeyMask2->get_object_by_id(200); + ASSERT_NE(nullptr, testObject); + EXPECT_EQ(200, testObject->get_id()); + + EXPECT_TRUE(dataMask2->set_attribute(static_cast(DataMask::AttributeName::SoftKeyMask), 200, error)); + EXPECT_EQ(dataMask2->get_child_id(1), 200); + EXPECT_NE(0, static_cast(error)); + + // Try changing the soft key mask to the other one, which is ID 100 + EXPECT_TRUE(dataMask2->change_soft_key_mask(100)); + + // Setting the number of attributes should always fail + EXPECT_FALSE(dataMask2->set_attribute(static_cast(DataMask::AttributeName::NumberOfAttributes), 4, error)); + EXPECT_NE(0, static_cast(error)); +} + +TEST(VIRTUAL_TERMINAL_OBJECT_TESTS, ContainerTests) +{ + std::map> objects; + VTColourTable colourTable; + Container container(objects, colourTable); + + run_baseline_tests(&container); + EXPECT_EQ(container.get_object_type(), VirtualTerminalObjectType::Container); + + EXPECT_EQ(container.get_hidden(), false); + container.set_hidden(true); + EXPECT_EQ(container.get_hidden(), true); + + // Check read only attributes + VTObject::AttributeError error = VTObject::AttributeError::AnyOtherError; + container.set_attribute(static_cast(Container::AttributeName::Hidden), 0, error); + EXPECT_NE(0, static_cast(error)); + container.set_attribute(static_cast(Container::AttributeName::Height), 50, error); + EXPECT_NE(0, static_cast(error)); + container.set_attribute(static_cast(Container::AttributeName::Width), 50, error); + EXPECT_NE(0, static_cast(error)); + EXPECT_TRUE(container.get_hidden()); + EXPECT_NE(50, container.get_width()); + EXPECT_NE(50, container.get_height()); + + // Setting the type attribute should always fail + EXPECT_FALSE(container.set_attribute(static_cast(Container::AttributeName::Type), 4, error)); + EXPECT_NE(0, static_cast(error)); + + // Setting the number of attributes should always fail + EXPECT_FALSE(container.set_attribute(static_cast(Container::AttributeName::NumberOfAttributes), 4, error)); + EXPECT_NE(0, static_cast(error)); + + // Take this opportunity to test child object offsets and pop_child + container.add_child(100, 10, 20); + container.set_child_x(0, 50); + container.set_child_y(0, 60); + EXPECT_EQ(container.get_child_x(0), 50); + EXPECT_EQ(container.get_child_y(0), 60); + container.pop_child(); + EXPECT_EQ(container.get_number_children(), 0); + + container.set_id(100); + + // Add a valid child object, a Button + auto button = std::make_shared