diff --git a/demo/demo1.cpp b/demo/demo1.cpp index e3822e9..e1b37b7 100644 --- a/demo/demo1.cpp +++ b/demo/demo1.cpp @@ -1,3 +1,5 @@ +#include + #include int main() @@ -5,5 +7,13 @@ int main() auto &window = sftk::Window::create(800, 600, L"demo1"); auto container = sftk::Container::create(vec(100.f, 100.f), vec(400.f, 400.f), window.getRoot()); container->setBackgroudColor(sf::Color::White); + container->registerEvent( + sftk::EventType::MouseDragged, + std::function( + [](sf::Vector2f start, sf::Vector2f now, sf::Mouse::Button button) + { std::cout << "(" << start.x << "," << start.y << ")" + << "->(" << now.x << "," << now.y << ")" + << "|" << button + << std::endl; })); window.exec(); } diff --git a/include/containers/container.hpp b/include/containers/container.hpp index b9bf23e..218dd26 100644 --- a/include/containers/container.hpp +++ b/include/containers/container.hpp @@ -96,7 +96,9 @@ namespace sftk 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; @@ -116,6 +118,13 @@ namespace sftk NotAWindowObj(Container *container); const char *what() const noexcept override; }; + + class HandlerNotMatched : public SFTKException + { + public: + HandlerNotMatched(Container *container); + const char *what() const noexcept override; + }; }; }; diff --git a/src/containers/container.cpp b/src/containers/container.cpp index 806da3b..db4149d 100644 --- a/src/containers/container.cpp +++ b/src/containers/container.cpp @@ -3,6 +3,7 @@ #include #include +#include #include using namespace sftk; @@ -33,6 +34,8 @@ Container::Container(pContainer parent) : parent(nullptr) this->parent = parent; } this->parent->childs.push_back(pContainer(this)); + for (auto &p : lastMousePressPos) + p = vec(-1.f, -1.f); } Container::Container(sf::Vector2f pos, sf::Vector2f size, pContainer parent) @@ -57,6 +60,8 @@ Container::Container(sf::Vector2f pos, sf::Vector2f size, pContainer parent) view.setViewport(vec( (parent->basepos.x + pos.x) / rootsize.x, (parent->basepos.y + pos.y) / rootsize.y, size.x / rootsize.x, size.y / rootsize.y)); + for (auto &p : lastMousePressPos) + p = vec(-1.f, -1.f); } Container::Container(sf::Vector2f pos, sf::Vector2f size, bool root) @@ -68,6 +73,8 @@ Container::Container(sf::Vector2f pos, sf::Vector2f size, bool root) backgroudColor(sf::Color::Black) { view.setViewport(vec(0.f, 0.f, 1.f, 1.f)); + for (auto &p : lastMousePressPos) + p = vec(-1.f, -1.f); } pContainer Container::create(pContainer parent) @@ -147,13 +154,15 @@ void Container::update() const if (isRoot()) { window.clear(backgroudColor); - return; } - window.setView(view); - sf::RectangleShape bg(vec(size.x, size.y)); - bg.setPosition(vec(0.f, 0.f)); - bg.setFillColor(backgroudColor); - window.draw(bg); + else + { + window.setView(view); + sf::RectangleShape bg(vec(size.x, size.y)); + bg.setPosition(vec(0.f, 0.f)); + bg.setFillColor(backgroudColor); + window.draw(bg); + } for (auto c : childs) { c->update(); @@ -165,7 +174,7 @@ void Container::registerEvent(EventType type, std::function handler) { if (type != EventType::Closed) return; - closed = handler; + closed = std::move(handler); } template <> @@ -174,17 +183,19 @@ void Container::registerEvent(EventType type, std::function switch (type) { case EventType::Resized: - resized = handler; + resized = std::move(handler); break; case EventType::MouseEntered: - mouseEntered = handler; + mouseEntered = std::move(handler); break; case EventType::MouseLeft: - mouseLeft = handler; + mouseLeft = std::move(handler); break; case EventType::MouseMoved: - mouseMoved = handler; + mouseMoved = std::move(handler); break; + default: + throw new HandlerNotMatched(this); } } @@ -194,14 +205,16 @@ void Container::registerEvent(EventType type, std::function @@ -218,7 +231,7 @@ void Container::registerEvent(EventType type, std::function handler { if (type != EventType::MouseScrolled) return; - mouseScrolled = handler; + mouseScrolled = std::move(handler); } template <> @@ -226,7 +239,7 @@ void Container::registerEvent(EventType type, std::function handl { if (type != EventType::TextInputed) return; - textInputed = handler; + textInputed = std::move(handler); } void Container::dispatchEvent(sf::Event &event) @@ -317,6 +330,8 @@ bool Container::dispatchEvent(Event &event) _MouseEnteredLeftMoved mmov; _MouseDragged mdra; + time_t now; + switch (event.type) { case EventType::Closed: @@ -346,31 +361,39 @@ bool Container::dispatchEvent(Event &event) break; case EventType::MousePressed: mpr = event.data.mousePressed; - if (mousePressed && getGlobalBouds().contains(mpr.pos)) + if (mouseLocated) { - handler_effective = true; - mousePressed(mpr.pos - basepos - pos, mpr.button); + if (mousePressed) + { + handler_effective = true; + mousePressed(mpr.pos - basepos - pos, mpr.button); + } + lastMousePressTime[mpr.button] = currentTime(); + lastMousePressPos[mpr.button] = mpr.pos; } - lastMousePressTime[mpr.button] = currentTime(); break; case EventType::MouseReleased: mrel = event.data.mouseReleased; - lastMousePressTime[mrel.button] = -1; - lastMousePressPos[mrel.button] = vec(-1.f, -1.f); - if (mouseReleased && getGlobalBouds().contains(mrel.pos)) + if (mouseLocated) { - handler_effective = true; - mouseReleased(mrel.pos - basepos - pos, mrel.button); - } - if (isRoot() && - lastMousePressTime[mrel.button] >= 0 && - lastMousePressTime[mrel.button] < maxClickTime) - { - auto tmp = Event{ - .type = EventType::MouseClicked, - .data = EventData{ - .mouseClicked = mrel}}; - dispatchEvent(tmp); + if (mouseReleased) + { + handler_effective = true; + mouseReleased(mrel.pos - basepos - pos, mrel.button); + } + now = currentTime(); + if (isRoot() && + now - lastMousePressTime[mrel.button] >= 0 && + now - lastMousePressTime[mrel.button] < maxClickTime) + { + auto tmp = Event{ + .type = EventType::MouseClicked, + .data = EventData{ + .mouseClicked = mrel}}; + dispatchEvent(tmp); + } + lastMousePressTime[mrel.button] = -1; + lastMousePressPos[mrel.button] = vec(-1.f, -1.f); } break; case EventType::MouseClicked: @@ -390,6 +413,7 @@ bool Container::dispatchEvent(Event &event) } break; case EventType::MouseEntered: + spread = false; mouseLocated = true; if (mouseEntered) { @@ -398,6 +422,7 @@ bool Container::dispatchEvent(Event &event) } break; case EventType::MouseLeft: + spread = false; mouseLocated = false; if (mouseLeft) { @@ -407,33 +432,38 @@ bool Container::dispatchEvent(Event &event) break; case EventType::MouseMoved: mmov = event.data.mouseMoved; - if (getGlobalBouds().contains(mmov.pos)) + if (getGlobalBouds().contains(mmov.pos) && mouseMoved) { - if (mouseMoved) - { - handler_effective = true; - mouseMoved(mmov.pos - basepos - pos); - } - if (isRoot() && !mouseLocated) + handler_effective = true; + mouseMoved(mmov.pos - basepos - pos); + } + // Enter and left + if (!isRoot() && getGlobalBouds().contains(mmov.pos)) + { + if (!mouseLocated) { auto tmp = Event{ .type = EventType::MouseEntered, - .data = event.data}; + .data = { + .mouseEntered = _MouseEnteredLeftMoved{ + .pos = mmov.pos}}}; dispatchEvent(tmp); } } - else if (isRoot() && mouseLocated) + else if (!isRoot() && mouseLocated) { auto tmp = Event{ .type = EventType::MouseLeft, - .data = event.data}; + .data = { + .mouseEntered = _MouseEnteredLeftMoved{ + .pos = mmov.pos}}}; dispatchEvent(tmp); } if (!isRoot()) break; for (auto i = 0; i < sf::Mouse::Button::ButtonCount; i++) { - if (lastMousePressPos[i] == vec(-1.f, -1.f)) + if (lastMousePressPos[i] == vec(-1.f, -1.f) || lastMousePressTime[i] == -1) continue; auto tmp = Event{ .type = EventType::MouseDragged, @@ -447,10 +477,10 @@ bool Container::dispatchEvent(Event &event) break; case EventType::MouseDragged: mdra = event.data.mouseDragged; - if (mouseDragged) + if (mouseDragged && getGlobalBouds().contains(mdra.start)) { handler_effective = true; - mouseDragged(mdra.start, mdra.now, mdra.button); + mouseDragged(mdra.start - basepos - pos, mdra.now - basepos - pos, mdra.button); } break; case EventType::MouseScrolled: @@ -472,6 +502,9 @@ bool Container::dispatchEvent(Event &event) if (!spread) return handler_effective; + if (!broadcast && handler_effective) + return true; + bool child_handled; bool handler_handled = false; for (auto container : childs) @@ -527,3 +560,13 @@ const char *Container::NotAWindowObj::what() const noexcept SFTKException::formatAddress(msg, sizeof(msg)); return msg; } + +Container::HandlerNotMatched::HandlerNotMatched(Container *container) + : SFTKException(container) {} + +const char *Container::HandlerNotMatched::what() const noexcept +{ + static char msg[] = "sftk::Container 0x********_********: When calling Container::registerEvent(), passed a closure with wrong arguments."; + SFTKException::formatAddress(msg, sizeof(msg)); + return msg; +}