double click support

This commit is contained in:
MihailRis 2024-05-16 06:43:53 +03:00
parent b6f2456a82
commit a678eddb77
7 changed files with 102 additions and 10 deletions

View File

@ -45,8 +45,11 @@ void GUI::onAssetsLoad(Assets* assets) {
), "core:root");
}
// @brief Mouse related input and logic handling
void GUI::actMouse() {
/// @brief Mouse related input and logic handling
void GUI::actMouse(float delta) {
doubleClicked = false;
doubleClickTimer += delta + glm::length(Events::delta) * 0.1f;
auto hover = container->getAt(Events::cursor, nullptr);
if (this->hover && this->hover != hover) {
this->hover->setHover(false);
@ -62,7 +65,13 @@ void GUI::actMouse() {
if (Events::jclicked(mousecode::BUTTON_1)) {
if (pressed == nullptr && this->hover) {
pressed = hover;
pressed->click(this, Events::cursor.x, Events::cursor.y);
if (doubleClickTimer < doubleClickDelay) {
pressed->doubleClick(this, Events::cursor.x, Events::cursor.y);
doubleClicked = true;
} else {
pressed->click(this, Events::cursor.x, Events::cursor.y);
}
doubleClickTimer = 0.0f;
if (focus && focus != pressed) {
focus->defocus();
}
@ -107,7 +116,9 @@ void GUI::actFocused() {
if (Events::clicked(mousecode::BUTTON_1) &&
(Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y))
{
focus->mouseMove(this, Events::cursor.x, Events::cursor.y);
if (!doubleClicked) {
focus->mouseMove(this, Events::cursor.x, Events::cursor.y);
}
}
}
}
@ -124,7 +135,7 @@ void GUI::act(float delta, const Viewport& vp) {
auto prevfocus = focus;
if (!Events::_cursor_locked) {
actMouse();
actMouse(delta);
}
if (focus) {
@ -144,7 +155,7 @@ void GUI::draw(const DrawContext* pctx, Assets* assets) {
Shader* uishader = assets->getShader("ui");
uishader->use();
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
uishader->uniformMatrix("u_projview", uicamera->getProjView());
pctx->getBatch2D()->begin();
container->draw(pctx, assets);
@ -199,3 +210,11 @@ std::shared_ptr<Container> GUI::getContainer() const {
void GUI::postRunnable(runnable callback) {
postRunnables.push(callback);
}
void GUI::setDoubleClickDelay(float delay) {
doubleClickDelay = delay;
}
float GUI::getDoubleClickDelay() const {
return doubleClickDelay;
}

View File

@ -62,7 +62,12 @@ namespace gui {
std::unique_ptr<Camera> uicamera;
std::shared_ptr<Menu> menu;
std::queue<runnable> postRunnables;
void actMouse();
float doubleClickTimer = 0.0f;
float doubleClickDelay = 0.5f;
bool doubleClicked = false;
void actMouse(float delta);
void actFocused();
public:
GUI();
@ -121,6 +126,9 @@ namespace gui {
void onAssetsLoad(Assets* assets);
void postRunnable(runnable callback);
void setDoubleClickDelay(float delay);
float getDoubleClickDelay() const;
};
}

View File

@ -294,6 +294,41 @@ int TextBox::calcIndexAt(int x, int y) const {
return std::min(offset+label->getTextLineOffset(line), input.length());
}
inline std::wstring get_alphabet(wchar_t c) {
std::wstring alphabet {c};
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '_') {
return L"abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
} else if (c >= '0' && c <= '9') {
return L"0123456789";
}
return alphabet;
}
void TextBox::tokenSelectAt(int index) {
int left = index;
int right = index;
std::wstring alphabet = get_alphabet(input.at(index));
while (left >= 0) {
if (alphabet.find(input.at(left)) == std::wstring::npos) {
break;
}
left--;
}
while (static_cast<size_t>(right) < input.length()) {
if (alphabet.find(input.at(right)) == std::wstring::npos) {
break;
}
right++;
}
select(left+1, right);
}
void TextBox::doubleClick(GUI* gui, int x, int y) {
UINode::doubleClick(gui, x, y);
tokenSelectAt(normalizeIndex(calcIndexAt(x, y)-1));
}
void TextBox::click(GUI*, int x, int y) {
int index = normalizeIndex(calcIndexAt(x, y));
selectionStart = index;

View File

@ -47,6 +47,7 @@ namespace gui {
bool eraseSelected();
void resetSelection();
void extendSelection(int index);
void tokenSelectAt(int index);
size_t getLineLength(uint line) const;
/// @brief Get total length of the selection
@ -141,6 +142,7 @@ namespace gui {
virtual void onFocus(GUI*) override;
virtual void refresh() override;
virtual void doubleClick(GUI*, int x, int y) override;
virtual void click(GUI*, int, int) override;
virtual void mouseMove(GUI*, int x, int y) override;
virtual bool isFocuskeeper() const override {return true;}

View File

@ -64,10 +64,24 @@ UINode* UINode::listenAction(onaction action) {
return this;
}
UINode* UINode::listenDoubleClick(onaction action) {
doubleClickCallbacks.push_back(action);
return this;
}
void UINode::click(GUI*, int, int) {
pressed = true;
}
void UINode::doubleClick(GUI* gui, int x, int y) {
pressed = true;
if (isInside(glm::vec2(x, y))) {
for (auto callback : doubleClickCallbacks) {
callback(gui);
}
}
}
void UINode::mouseRelease(GUI* gui, int x, int y) {
pressed = false;
if (isInside(glm::vec2(x, y))) {

View File

@ -88,6 +88,8 @@ namespace gui {
vec2supplier sizefunc = nullptr;
/// @brief 'onclick' callbacks
std::vector<onaction> actions;
/// @brief 'ondoubleclick' callbacks
std::vector<onaction> doubleClickCallbacks;
UINode(glm::vec2 size);
public:
@ -138,8 +140,10 @@ namespace gui {
int getZIndex() const;
virtual UINode* listenAction(onaction action);
virtual UINode* listenDoubleClick(onaction action);
virtual void onFocus(GUI*) {focused = true;}
virtual void doubleClick(GUI*, int x, int y);
virtual void click(GUI*, int x, int y);
virtual void clicked(GUI*, mousecode button) {}
virtual void mouseMove(GUI*, int x, int y) {};

View File

@ -123,15 +123,25 @@ static void _readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& no
std::string text = element->attr("onclick").getText();
if (!text.empty()) {
auto callback = scripting::create_runnable(
reader.getEnvironment(),
text,
reader.getFilename()
reader.getEnvironment(), text, reader.getFilename()
);
node.listenAction([callback](GUI*) {
callback();
});
}
}
if (element->has("ondoubleclick")) {
std::string text = element->attr("ondoubleclick").getText();
if (!text.empty()) {
auto callback = scripting::create_runnable(
reader.getEnvironment(), text, reader.getFilename()
);
node.listenDoubleClick([callback](GUI*) {
callback();
});
}
}
}
static void _readContainer(UiXmlReader& reader, xml::xmlelement element, Container& container) {