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>
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();
}

View File

@ -96,7 +96,9 @@ namespace sftk
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;
@ -116,6 +118,13 @@ namespace sftk
NotAWindowObj(Container *container);
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 <window.hpp>
#include <iostream>
#include <chrono>
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;
}
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<void()> handler)
{
if (type != EventType::Closed)
return;
closed = handler;
closed = std::move(handler);
}
template <>
@ -174,17 +183,19 @@ void Container::registerEvent(EventType type, std::function<void(sf::Vector2f)>
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<void(sf::Vector2f, s
switch (type)
{
case EventType::MousePressed:
mousePressed = handler;
mousePressed = std::move(handler);
break;
case EventType::MouseReleased:
mouseReleased = handler;
mouseReleased = std::move(handler);
break;
case EventType::MouseClicked:
mouseClicked = handler;
mouseClicked = std::move(handler);
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)
return;
mouseDragged = handler;
mouseDragged = std::move(handler);
}
template <>
@ -218,7 +231,7 @@ void Container::registerEvent(EventType type, std::function<void(float)> handler
{
if (type != EventType::MouseScrolled)
return;
mouseScrolled = handler;
mouseScrolled = std::move(handler);
}
template <>
@ -226,7 +239,7 @@ void Container::registerEvent(EventType type, std::function<void(wchar_t)> 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,25 +361,30 @@ bool Container::dispatchEvent(Event &event)
break;
case EventType::MousePressed:
mpr = event.data.mousePressed;
if (mousePressed && getGlobalBouds().contains(mpr.pos))
if (mouseLocated)
{
if (mousePressed)
{
handler_effective = true;
mousePressed(mpr.pos - basepos - pos, mpr.button);
}
lastMousePressTime[mpr.button] = currentTime();
lastMousePressPos[mpr.button] = mpr.pos;
}
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)
{
if (mouseReleased)
{
handler_effective = true;
mouseReleased(mrel.pos - basepos - pos, mrel.button);
}
now = currentTime();
if (isRoot() &&
lastMousePressTime[mrel.button] >= 0 &&
lastMousePressTime[mrel.button] < maxClickTime)
now - lastMousePressTime[mrel.button] >= 0 &&
now - lastMousePressTime[mrel.button] < maxClickTime)
{
auto tmp = Event{
.type = EventType::MouseClicked,
@ -372,6 +392,9 @@ bool Container::dispatchEvent(Event &event)
.mouseClicked = mrel}};
dispatchEvent(tmp);
}
lastMousePressTime[mrel.button] = -1;
lastMousePressPos[mrel.button] = vec(-1.f, -1.f);
}
break;
case EventType::MouseClicked:
mcli = event.data.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 (mouseMoved)
if (getGlobalBouds().contains(mmov.pos) && mouseMoved)
{
handler_effective = true;
mouseMoved(mmov.pos - basepos - pos);
}
if (isRoot() && !mouseLocated)
// 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;
}