Fix second events' detection bugs.

This commit is contained in:
pointer-to-bios 2024-08-04 00:19:19 +08:00
parent 4b63b35d07
commit c7cd5bad91
3 changed files with 111 additions and 49 deletions

View File

@ -1,3 +1,5 @@
#include <iostream>
#include <sftk.hpp> #include <sftk.hpp>
int main() int main()
@ -5,5 +7,13 @@ int main()
auto &window = sftk::Window::create(800, 600, L"demo1"); 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()); auto container = sftk::Container::create(vec(100.f, 100.f), vec(400.f, 400.f), window.getRoot());
container->setBackgroudColor(sf::Color::White); 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(); window.exec();
} }

View File

@ -96,7 +96,9 @@ namespace sftk
std::function<void(wchar_t)> textInputed; std::function<void(wchar_t)> textInputed;
private: // Second events asistant vars private: // Second events asistant vars
// When the values is not -1, mouse had pressed.
int64_t lastMousePressTime[sf::Mouse::Button::ButtonCount]; int64_t lastMousePressTime[sf::Mouse::Button::ButtonCount];
// When the values is not (-1, -1), mouse had pressed.
sf::Vector2f lastMousePressPos[sf::Mouse::Button::ButtonCount]; sf::Vector2f lastMousePressPos[sf::Mouse::Button::ButtonCount];
bool focused; bool focused;
@ -116,6 +118,13 @@ namespace sftk
NotAWindowObj(Container *container); NotAWindowObj(Container *container);
const char *what() const noexcept override; const char *what() const noexcept override;
}; };
class HandlerNotMatched : public SFTKException<Container>
{
public:
HandlerNotMatched(Container *container);
const char *what() const noexcept override;
};
}; };
}; };

View File

@ -3,6 +3,7 @@
#include <gtypes.hpp> #include <gtypes.hpp>
#include <window.hpp> #include <window.hpp>
#include <iostream>
#include <chrono> #include <chrono>
using namespace sftk; using namespace sftk;
@ -33,6 +34,8 @@ Container::Container(pContainer parent) : parent(nullptr)
this->parent = parent; this->parent = parent;
} }
this->parent->childs.push_back(pContainer(this)); 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) 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( view.setViewport(vec(
(parent->basepos.x + pos.x) / rootsize.x, (parent->basepos.y + pos.y) / rootsize.y, (parent->basepos.x + pos.x) / rootsize.x, (parent->basepos.y + pos.y) / rootsize.y,
size.x / rootsize.x, size.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) 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) backgroudColor(sf::Color::Black)
{ {
view.setViewport(vec(0.f, 0.f, 1.f, 1.f)); 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) pContainer Container::create(pContainer parent)
@ -147,13 +154,15 @@ void Container::update() const
if (isRoot()) if (isRoot())
{ {
window.clear(backgroudColor); window.clear(backgroudColor);
return;
} }
window.setView(view); else
sf::RectangleShape bg(vec(size.x, size.y)); {
bg.setPosition(vec(0.f, 0.f)); window.setView(view);
bg.setFillColor(backgroudColor); sf::RectangleShape bg(vec(size.x, size.y));
window.draw(bg); bg.setPosition(vec(0.f, 0.f));
bg.setFillColor(backgroudColor);
window.draw(bg);
}
for (auto c : childs) for (auto c : childs)
{ {
c->update(); c->update();
@ -165,7 +174,7 @@ void Container::registerEvent(EventType type, std::function<void()> handler)
{ {
if (type != EventType::Closed) if (type != EventType::Closed)
return; return;
closed = handler; closed = std::move(handler);
} }
template <> template <>
@ -174,17 +183,19 @@ void Container::registerEvent(EventType type, std::function<void(sf::Vector2f)>
switch (type) switch (type)
{ {
case EventType::Resized: case EventType::Resized:
resized = handler; resized = std::move(handler);
break; break;
case EventType::MouseEntered: case EventType::MouseEntered:
mouseEntered = handler; mouseEntered = std::move(handler);
break; break;
case EventType::MouseLeft: case EventType::MouseLeft:
mouseLeft = handler; mouseLeft = std::move(handler);
break; break;
case EventType::MouseMoved: case EventType::MouseMoved:
mouseMoved = handler; mouseMoved = std::move(handler);
break; break;
default:
throw new HandlerNotMatched(this);
} }
} }
@ -194,14 +205,16 @@ void Container::registerEvent(EventType type, std::function<void(sf::Vector2f, s
switch (type) switch (type)
{ {
case EventType::MousePressed: case EventType::MousePressed:
mousePressed = handler; mousePressed = std::move(handler);
break; break;
case EventType::MouseReleased: case EventType::MouseReleased:
mouseReleased = handler; mouseReleased = std::move(handler);
break; break;
case EventType::MouseClicked: case EventType::MouseClicked:
mouseClicked = handler; mouseClicked = std::move(handler);
break; break;
default:
throw new HandlerNotMatched(this);
} }
} }
@ -210,7 +223,7 @@ void Container::registerEvent(EventType type, std::function<void(sf::Vector2f, s
{ {
if (type != EventType::MouseDragged) if (type != EventType::MouseDragged)
return; return;
mouseDragged = handler; mouseDragged = std::move(handler);
} }
template <> template <>
@ -218,7 +231,7 @@ void Container::registerEvent(EventType type, std::function<void(float)> handler
{ {
if (type != EventType::MouseScrolled) if (type != EventType::MouseScrolled)
return; return;
mouseScrolled = handler; mouseScrolled = std::move(handler);
} }
template <> template <>
@ -226,7 +239,7 @@ void Container::registerEvent(EventType type, std::function<void(wchar_t)> handl
{ {
if (type != EventType::TextInputed) if (type != EventType::TextInputed)
return; return;
textInputed = handler; textInputed = std::move(handler);
} }
void Container::dispatchEvent(sf::Event &event) void Container::dispatchEvent(sf::Event &event)
@ -317,6 +330,8 @@ bool Container::dispatchEvent(Event &event)
_MouseEnteredLeftMoved mmov; _MouseEnteredLeftMoved mmov;
_MouseDragged mdra; _MouseDragged mdra;
time_t now;
switch (event.type) switch (event.type)
{ {
case EventType::Closed: case EventType::Closed:
@ -346,31 +361,39 @@ bool Container::dispatchEvent(Event &event)
break; break;
case EventType::MousePressed: case EventType::MousePressed:
mpr = event.data.mousePressed; mpr = event.data.mousePressed;
if (mousePressed && getGlobalBouds().contains(mpr.pos)) if (mouseLocated)
{ {
handler_effective = true; if (mousePressed)
mousePressed(mpr.pos - basepos - pos, mpr.button); {
handler_effective = true;
mousePressed(mpr.pos - basepos - pos, mpr.button);
}
lastMousePressTime[mpr.button] = currentTime();
lastMousePressPos[mpr.button] = mpr.pos;
} }
lastMousePressTime[mpr.button] = currentTime();
break; break;
case EventType::MouseReleased: case EventType::MouseReleased:
mrel = event.data.mouseReleased; mrel = event.data.mouseReleased;
lastMousePressTime[mrel.button] = -1; if (mouseLocated)
lastMousePressPos[mrel.button] = vec(-1.f, -1.f);
if (mouseReleased && getGlobalBouds().contains(mrel.pos))
{ {
handler_effective = true; if (mouseReleased)
mouseReleased(mrel.pos - basepos - pos, mrel.button); {
} handler_effective = true;
if (isRoot() && mouseReleased(mrel.pos - basepos - pos, mrel.button);
lastMousePressTime[mrel.button] >= 0 && }
lastMousePressTime[mrel.button] < maxClickTime) now = currentTime();
{ if (isRoot() &&
auto tmp = Event{ now - lastMousePressTime[mrel.button] >= 0 &&
.type = EventType::MouseClicked, now - lastMousePressTime[mrel.button] < maxClickTime)
.data = EventData{ {
.mouseClicked = mrel}}; auto tmp = Event{
dispatchEvent(tmp); .type = EventType::MouseClicked,
.data = EventData{
.mouseClicked = mrel}};
dispatchEvent(tmp);
}
lastMousePressTime[mrel.button] = -1;
lastMousePressPos[mrel.button] = vec(-1.f, -1.f);
} }
break; break;
case EventType::MouseClicked: case EventType::MouseClicked:
@ -390,6 +413,7 @@ bool Container::dispatchEvent(Event &event)
} }
break; break;
case EventType::MouseEntered: case EventType::MouseEntered:
spread = false;
mouseLocated = true; mouseLocated = true;
if (mouseEntered) if (mouseEntered)
{ {
@ -398,6 +422,7 @@ bool Container::dispatchEvent(Event &event)
} }
break; break;
case EventType::MouseLeft: case EventType::MouseLeft:
spread = false;
mouseLocated = false; mouseLocated = false;
if (mouseLeft) if (mouseLeft)
{ {
@ -407,33 +432,38 @@ bool Container::dispatchEvent(Event &event)
break; break;
case EventType::MouseMoved: case EventType::MouseMoved:
mmov = event.data.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);
handler_effective = true; }
mouseMoved(mmov.pos - basepos - pos); // Enter and left
} if (!isRoot() && getGlobalBouds().contains(mmov.pos))
if (isRoot() && !mouseLocated) {
if (!mouseLocated)
{ {
auto tmp = Event{ auto tmp = Event{
.type = EventType::MouseEntered, .type = EventType::MouseEntered,
.data = event.data}; .data = {
.mouseEntered = _MouseEnteredLeftMoved{
.pos = mmov.pos}}};
dispatchEvent(tmp); dispatchEvent(tmp);
} }
} }
else if (isRoot() && mouseLocated) else if (!isRoot() && mouseLocated)
{ {
auto tmp = Event{ auto tmp = Event{
.type = EventType::MouseLeft, .type = EventType::MouseLeft,
.data = event.data}; .data = {
.mouseEntered = _MouseEnteredLeftMoved{
.pos = mmov.pos}}};
dispatchEvent(tmp); dispatchEvent(tmp);
} }
if (!isRoot()) if (!isRoot())
break; break;
for (auto i = 0; i < sf::Mouse::Button::ButtonCount; i++) 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; continue;
auto tmp = Event{ auto tmp = Event{
.type = EventType::MouseDragged, .type = EventType::MouseDragged,
@ -447,10 +477,10 @@ bool Container::dispatchEvent(Event &event)
break; break;
case EventType::MouseDragged: case EventType::MouseDragged:
mdra = event.data.mouseDragged; mdra = event.data.mouseDragged;
if (mouseDragged) if (mouseDragged && getGlobalBouds().contains(mdra.start))
{ {
handler_effective = true; handler_effective = true;
mouseDragged(mdra.start, mdra.now, mdra.button); mouseDragged(mdra.start - basepos - pos, mdra.now - basepos - pos, mdra.button);
} }
break; break;
case EventType::MouseScrolled: case EventType::MouseScrolled:
@ -472,6 +502,9 @@ bool Container::dispatchEvent(Event &event)
if (!spread) if (!spread)
return handler_effective; return handler_effective;
if (!broadcast && handler_effective)
return true;
bool child_handled; bool child_handled;
bool handler_handled = false; bool handler_handled = false;
for (auto container : childs) for (auto container : childs)
@ -527,3 +560,13 @@ const char *Container::NotAWindowObj::what() const noexcept
SFTKException::formatAddress(msg, sizeof(msg)); SFTKException::formatAddress(msg, sizeof(msg));
return 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;
}