#ifndef GRAPHICS_UI_ELEMENTS_UINODE_H_ #define GRAPHICS_UI_ELEMENTS_UINODE_H_ #include #include #include #include #include #include #include "../../../delegates.h" #include "../../../window/input.h" class DrawContext; class Assets; namespace gui { class UINode; class GUI; using onaction = std::function; using onnumberchange = std::function; enum class Align { left, center, right, top=left, bottom=right, }; enum class Gravity { none, top_left, top_center, top_right, center_left, center_center, center_right, bottom_left, bottom_center, bottom_right }; /// @brief Base abstract class for all UI elements class UINode { /// @brief element identifier used for direct access in UiDocument std::string id = ""; protected: /// @brief element position within the parent element glm::vec2 pos {0.0f}; /// @brief element size (width, height) glm::vec2 size; /// @brief minimal element size glm::vec2 minSize {1.0f}; /// @brief element primary color (background-color or text-color if label) glm::vec4 color {1.0f}; /// @brief element color when mouse is over it glm::vec4 hoverColor {1.0f}; /// @brief element color when clicked glm::vec4 pressedColor {1.0f}; /// @brief element margin (only supported for Panel sub-nodes) glm::vec4 margin {1.0f}; /// @brief is element visible bool visible = true; /// @brief is mouse over the element bool hover = false; /// @brief is mouse has been pressed over the element and not released yet bool pressed = false; /// @brief is element focused bool focused = false; /// @brief is element opaque for cursor interaction bool interactive = true; /// @brief does the element support resizing by parent elements bool resizing = true; /// @brief z-index property specifies the stack order of an element int zindex = 0; /// @brief element content alignment (supported by Label only) Align align = Align::left; /// @brief parent element UINode* parent = nullptr; /// @brief position supplier for the element (called on parent element size update) vec2supplier positionfunc = nullptr; /// @brief 'onclick' callbacks std::vector actions; UINode(glm::vec2 size); public: virtual ~UINode(); /// @brief Called every frame for all visible elements /// @param delta delta timУ virtual void act(float delta) {}; virtual void draw(const DrawContext* pctx, Assets* assets) = 0; virtual void setVisible(bool flag); bool isVisible() const; virtual void setAlign(Align align); Align getAlign() const; virtual void setHover(bool flag); bool isHover() const; virtual void setParent(UINode* node); UINode* getParent() const; /// @brief Set element color (doesn't affect inner elements). /// Also replaces hover color to avoid adding extra properties virtual void setColor(glm::vec4 newColor); /// @brief Get element color /// @return (float R,G,B,A in range [0.0, 1.0]) glm::vec4 getColor() const; virtual void setHoverColor(glm::vec4 newColor); glm::vec4 getHoverColor() const; virtual glm::vec4 getPressedColor() const; virtual void setPressedColor(glm::vec4 color); virtual void setMargin(glm::vec4 margin); glm::vec4 getMargin() const; /// @brief Specifies the stack order of an element /// @attention Is not supported by Panel virtual void setZIndex(int idx); /// @brief Get element z-index int getZIndex() const; virtual UINode* listenAction(onaction action); virtual void onFocus(GUI*) {focused = true;} virtual void click(GUI*, int x, int y); virtual void clicked(GUI*, mousecode button) {} virtual void mouseMove(GUI*, int x, int y) {}; virtual void mouseRelease(GUI*, int x, int y); virtual void scrolled(int value); bool isPressed() const; void defocus(); bool isFocused() const; /** Check if element catches all user input when focused */ virtual bool isFocuskeeper() const {return false;} virtual void typed(unsigned int codepoint) {}; virtual void keyPressed(keycode key) {}; /** Check if screen position is inside of the element * @param pos screen position */ virtual bool isInside(glm::vec2 pos); /** Get element under the cursor. * @param pos cursor screen position * @param self shared pointer to element * @return self, sub-element or nullptr if element is not interractive */ virtual std::shared_ptr getAt(glm::vec2 pos, std::shared_ptr self); /* Check if element is opaque for cursor */ virtual bool isInteractive() const; /* Make the element opaque (true) or transparent (false) for cursor */ virtual void setInteractive(bool flag); virtual void setResizing(bool flag); virtual bool isResizing() const; /* Get inner content offset. Used for scroll */ virtual glm::vec2 contentOffset() {return glm::vec2(0.0f);}; /* Calculate screen position of the element */ virtual glm::vec2 calcPos() const; virtual void setPos(glm::vec2 pos); virtual glm::vec2 getPos() const; virtual glm::vec2 getSize() const; virtual void setSize(glm::vec2 size); virtual glm::vec2 getMinSize() const; virtual void setMinSize(glm::vec2 size); /* Called in containers when new element added */ virtual void refresh() {}; virtual void fullRefresh() { if (parent) { parent->fullRefresh(); } }; virtual void lock(); virtual vec2supplier getPositionFunc() const; virtual void setPositionFunc(vec2supplier); void setId(const std::string& id); const std::string& getId() const; /* Fetch pos from positionfunc if assigned */ void reposition(); virtual void setGravity(Gravity gravity); // @brief collect all nodes having id static void getIndices( std::shared_ptr node, std::unordered_map>& map ); }; } #endif // GRAPHICS_UI_ELEMENTS_UINODE_H_