#ifndef CONTAINER_HPP #define CONTAINER_HPP #include #include #include #include #include #include #include namespace sftk { class Container; typedef std::shared_ptr pContainer; bool operator==(pContainer &shp, Container *rawp); class Container { public: // Public base functions static pContainer create(pContainer parent = nullptr); static pContainer create(sf::Vector2f pos, sf::Vector2f size, pContainer parent = nullptr); void setParent(pContainer parent); void setPosition(sf::Vector2f pos = sf::Vector2f(0, 0)); void setSize(sf::Vector2f size); pContainer asContainer() const; pContainer getParent() const; const sf::Vector2f &getPosition() const; const sf::Vector2f &getSize() const; const sf::View &getView() const; sf::FloatRect getGlobalBouds() const; virtual bool isRoot() const; virtual bool hasInternalChange() const; void update(sf::RenderWindow &window, sf::View parentView) const; template void registerEvent(EventType type, std::function handler); public: // Static and operators static pContainer getRoot(pContainer p = nullptr); friend bool sftk::operator==(pContainer &shp, Container *rawp); protected: // Must be overrided by child classes Container(pContainer parent = nullptr); Container(sf::Vector2f pos, sf::Vector2f size, pContainer parent = nullptr); // Only call by sftk::Window::Window() Container(sf::Vector2f pos, sf::Vector2f size, bool root = false); virtual sf::RenderWindow &windowSFWindow(); virtual void draw(sf::RenderWindow &sfwindow) const; // The events bases on sfml's Event, // so the Window class must use this function to // pass event to the root container // (itself's parent class)'s dispatchEvent(Event&) // to process it as Event. void dispatchEvent(sf::Event &event); private: uint64_t id; sf::RenderWindow &getSfWindow(); // When this container did deal with the passed event // it returns true. On the oppsite case it returns false. bool dispatchEvent(Event &event); pContainer parent; std::vector children; sf::Vector2f basepos; sf::Vector2f pos, size; sf::View view; static const int64_t maxClickTime = 300; static thread_local uint64_t containerCounter; static thread_local std::map globalContainers; static thread_local pContainer root; private: // Called on construction static void rootTest(Container *self); inline static int64_t currentTime(); private: // Event handlers std::function closed; std::function resized; std::function mousePressed; std::function mouseReleased; std::function mouseClicked; std::function mouseEntered; std::function mouseLeft; std::function mouseMoved; std::function mouseDragged; std::function mouseScrolled; std::function textInputed; private: // Second events asistant vars // When the values is not -1, mouse had pressed. int64_t lastMousePressTime[sf::Mouse::Button::ButtonCount]; // When the values is not (-1, -1), mouse had pressed. sf::Vector2f lastMousePressPos[sf::Mouse::Button::ButtonCount]; bool focused; bool mouseLocated; public: // Exceptions class RootContainerNotPresent : public SFTKException { public: RootContainerNotPresent(Container *container); const char *what() const noexcept override; }; class NotAWindowObj : public SFTKException { public: NotAWindowObj(Container *container); const char *what() const noexcept override; }; class HandlerNotMatched : public SFTKException { public: HandlerNotMatched(Container *container); const char *what() const noexcept override; }; class ConstructorCalledIllegally : public SFTKException { public: ConstructorCalledIllegally(Container *container); const char *what() const noexcept override; }; }; }; #endif