SFTK/include/containers/container.hpp

148 lines
4.7 KiB
C++

#ifndef CONTAINER_HPP
#define CONTAINER_HPP
#include <vector>
#include <map>
#include <memory>
#include <functional>
#include <exceptions.hpp>
#include <event.hpp>
#include <SFML/Graphics.hpp>
namespace sftk
{
class Container;
typedef std::shared_ptr<Container> 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 <class T>
void registerEvent(EventType type, std::function<T> 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<pContainer> 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<uint64_t, pContainer> 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<void()> closed;
std::function<void(sf::Vector2f)> resized;
std::function<void(sf::Vector2f, sf::Mouse::Button)> mousePressed;
std::function<void(sf::Vector2f, sf::Mouse::Button)> mouseReleased;
std::function<void(sf::Vector2f, sf::Mouse::Button)> mouseClicked;
std::function<void(sf::Vector2f)> mouseEntered;
std::function<void(sf::Vector2f)> mouseLeft;
std::function<void(sf::Vector2f)> mouseMoved;
std::function<void(sf::Vector2f, sf::Vector2f, sf::Mouse::Button)> mouseDragged;
std::function<void(float)> mouseScrolled;
std::function<void(wchar_t)> 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<Container>
{
public:
RootContainerNotPresent(Container *container);
const char *what() const noexcept override;
};
class NotAWindowObj : public SFTKException<Container>
{
public:
NotAWindowObj(Container *container);
const char *what() const noexcept override;
};
class HandlerNotMatched : public SFTKException<Container>
{
public:
HandlerNotMatched(Container *container);
const char *what() const noexcept override;
};
class ConstructorCalledIllegally : public SFTKException<Container>
{
public:
ConstructorCalledIllegally(Container *container);
const char *what() const noexcept override;
};
};
};
#endif