double click support
This commit is contained in:
parent
b6f2456a82
commit
a678eddb77
@ -45,8 +45,11 @@ void GUI::onAssetsLoad(Assets* assets) {
|
|||||||
), "core:root");
|
), "core:root");
|
||||||
}
|
}
|
||||||
|
|
||||||
// @brief Mouse related input and logic handling
|
/// @brief Mouse related input and logic handling
|
||||||
void GUI::actMouse() {
|
void GUI::actMouse(float delta) {
|
||||||
|
doubleClicked = false;
|
||||||
|
doubleClickTimer += delta + glm::length(Events::delta) * 0.1f;
|
||||||
|
|
||||||
auto hover = container->getAt(Events::cursor, nullptr);
|
auto hover = container->getAt(Events::cursor, nullptr);
|
||||||
if (this->hover && this->hover != hover) {
|
if (this->hover && this->hover != hover) {
|
||||||
this->hover->setHover(false);
|
this->hover->setHover(false);
|
||||||
@ -62,7 +65,13 @@ void GUI::actMouse() {
|
|||||||
if (Events::jclicked(mousecode::BUTTON_1)) {
|
if (Events::jclicked(mousecode::BUTTON_1)) {
|
||||||
if (pressed == nullptr && this->hover) {
|
if (pressed == nullptr && this->hover) {
|
||||||
pressed = hover;
|
pressed = hover;
|
||||||
|
if (doubleClickTimer < doubleClickDelay) {
|
||||||
|
pressed->doubleClick(this, Events::cursor.x, Events::cursor.y);
|
||||||
|
doubleClicked = true;
|
||||||
|
} else {
|
||||||
pressed->click(this, Events::cursor.x, Events::cursor.y);
|
pressed->click(this, Events::cursor.x, Events::cursor.y);
|
||||||
|
}
|
||||||
|
doubleClickTimer = 0.0f;
|
||||||
if (focus && focus != pressed) {
|
if (focus && focus != pressed) {
|
||||||
focus->defocus();
|
focus->defocus();
|
||||||
}
|
}
|
||||||
@ -107,9 +116,11 @@ void GUI::actFocused() {
|
|||||||
if (Events::clicked(mousecode::BUTTON_1) &&
|
if (Events::clicked(mousecode::BUTTON_1) &&
|
||||||
(Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y))
|
(Events::jclicked(mousecode::BUTTON_1) || Events::delta.x || Events::delta.y))
|
||||||
{
|
{
|
||||||
|
if (!doubleClicked) {
|
||||||
focus->mouseMove(this, Events::cursor.x, Events::cursor.y);
|
focus->mouseMove(this, Events::cursor.x, Events::cursor.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GUI::act(float delta, const Viewport& vp) {
|
void GUI::act(float delta, const Viewport& vp) {
|
||||||
@ -124,7 +135,7 @@ void GUI::act(float delta, const Viewport& vp) {
|
|||||||
auto prevfocus = focus;
|
auto prevfocus = focus;
|
||||||
|
|
||||||
if (!Events::_cursor_locked) {
|
if (!Events::_cursor_locked) {
|
||||||
actMouse();
|
actMouse(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (focus) {
|
if (focus) {
|
||||||
@ -144,7 +155,7 @@ void GUI::draw(const DrawContext* pctx, Assets* assets) {
|
|||||||
|
|
||||||
Shader* uishader = assets->getShader("ui");
|
Shader* uishader = assets->getShader("ui");
|
||||||
uishader->use();
|
uishader->use();
|
||||||
uishader->uniformMatrix("u_projview", uicamera->getProjection()*uicamera->getView());
|
uishader->uniformMatrix("u_projview", uicamera->getProjView());
|
||||||
|
|
||||||
pctx->getBatch2D()->begin();
|
pctx->getBatch2D()->begin();
|
||||||
container->draw(pctx, assets);
|
container->draw(pctx, assets);
|
||||||
@ -199,3 +210,11 @@ std::shared_ptr<Container> GUI::getContainer() const {
|
|||||||
void GUI::postRunnable(runnable callback) {
|
void GUI::postRunnable(runnable callback) {
|
||||||
postRunnables.push(callback);
|
postRunnables.push(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GUI::setDoubleClickDelay(float delay) {
|
||||||
|
doubleClickDelay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GUI::getDoubleClickDelay() const {
|
||||||
|
return doubleClickDelay;
|
||||||
|
}
|
||||||
|
|||||||
@ -62,7 +62,12 @@ namespace gui {
|
|||||||
std::unique_ptr<Camera> uicamera;
|
std::unique_ptr<Camera> uicamera;
|
||||||
std::shared_ptr<Menu> menu;
|
std::shared_ptr<Menu> menu;
|
||||||
std::queue<runnable> postRunnables;
|
std::queue<runnable> postRunnables;
|
||||||
void actMouse();
|
|
||||||
|
float doubleClickTimer = 0.0f;
|
||||||
|
float doubleClickDelay = 0.5f;
|
||||||
|
bool doubleClicked = false;
|
||||||
|
|
||||||
|
void actMouse(float delta);
|
||||||
void actFocused();
|
void actFocused();
|
||||||
public:
|
public:
|
||||||
GUI();
|
GUI();
|
||||||
@ -121,6 +126,9 @@ namespace gui {
|
|||||||
void onAssetsLoad(Assets* assets);
|
void onAssetsLoad(Assets* assets);
|
||||||
|
|
||||||
void postRunnable(runnable callback);
|
void postRunnable(runnable callback);
|
||||||
|
|
||||||
|
void setDoubleClickDelay(float delay);
|
||||||
|
float getDoubleClickDelay() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -294,6 +294,41 @@ int TextBox::calcIndexAt(int x, int y) const {
|
|||||||
return std::min(offset+label->getTextLineOffset(line), input.length());
|
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) {
|
void TextBox::click(GUI*, int x, int y) {
|
||||||
int index = normalizeIndex(calcIndexAt(x, y));
|
int index = normalizeIndex(calcIndexAt(x, y));
|
||||||
selectionStart = index;
|
selectionStart = index;
|
||||||
|
|||||||
@ -47,6 +47,7 @@ namespace gui {
|
|||||||
bool eraseSelected();
|
bool eraseSelected();
|
||||||
void resetSelection();
|
void resetSelection();
|
||||||
void extendSelection(int index);
|
void extendSelection(int index);
|
||||||
|
void tokenSelectAt(int index);
|
||||||
size_t getLineLength(uint line) const;
|
size_t getLineLength(uint line) const;
|
||||||
|
|
||||||
/// @brief Get total length of the selection
|
/// @brief Get total length of the selection
|
||||||
@ -141,6 +142,7 @@ namespace gui {
|
|||||||
|
|
||||||
virtual void onFocus(GUI*) override;
|
virtual void onFocus(GUI*) override;
|
||||||
virtual void refresh() override;
|
virtual void refresh() override;
|
||||||
|
virtual void doubleClick(GUI*, int x, int y) override;
|
||||||
virtual void click(GUI*, int, int) override;
|
virtual void click(GUI*, int, int) override;
|
||||||
virtual void mouseMove(GUI*, int x, int y) override;
|
virtual void mouseMove(GUI*, int x, int y) override;
|
||||||
virtual bool isFocuskeeper() const override {return true;}
|
virtual bool isFocuskeeper() const override {return true;}
|
||||||
|
|||||||
@ -64,10 +64,24 @@ UINode* UINode::listenAction(onaction action) {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINode* UINode::listenDoubleClick(onaction action) {
|
||||||
|
doubleClickCallbacks.push_back(action);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
void UINode::click(GUI*, int, int) {
|
void UINode::click(GUI*, int, int) {
|
||||||
pressed = true;
|
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) {
|
void UINode::mouseRelease(GUI* gui, int x, int y) {
|
||||||
pressed = false;
|
pressed = false;
|
||||||
if (isInside(glm::vec2(x, y))) {
|
if (isInside(glm::vec2(x, y))) {
|
||||||
|
|||||||
@ -88,6 +88,8 @@ namespace gui {
|
|||||||
vec2supplier sizefunc = nullptr;
|
vec2supplier sizefunc = nullptr;
|
||||||
/// @brief 'onclick' callbacks
|
/// @brief 'onclick' callbacks
|
||||||
std::vector<onaction> actions;
|
std::vector<onaction> actions;
|
||||||
|
/// @brief 'ondoubleclick' callbacks
|
||||||
|
std::vector<onaction> doubleClickCallbacks;
|
||||||
|
|
||||||
UINode(glm::vec2 size);
|
UINode(glm::vec2 size);
|
||||||
public:
|
public:
|
||||||
@ -138,8 +140,10 @@ namespace gui {
|
|||||||
int getZIndex() const;
|
int getZIndex() const;
|
||||||
|
|
||||||
virtual UINode* listenAction(onaction action);
|
virtual UINode* listenAction(onaction action);
|
||||||
|
virtual UINode* listenDoubleClick(onaction action);
|
||||||
|
|
||||||
virtual void onFocus(GUI*) {focused = true;}
|
virtual void onFocus(GUI*) {focused = true;}
|
||||||
|
virtual void doubleClick(GUI*, int x, int y);
|
||||||
virtual void click(GUI*, int x, int y);
|
virtual void click(GUI*, int x, int y);
|
||||||
virtual void clicked(GUI*, mousecode button) {}
|
virtual void clicked(GUI*, mousecode button) {}
|
||||||
virtual void mouseMove(GUI*, int x, int y) {};
|
virtual void mouseMove(GUI*, int x, int y) {};
|
||||||
|
|||||||
@ -123,15 +123,25 @@ static void _readUINode(UiXmlReader& reader, xml::xmlelement element, UINode& no
|
|||||||
std::string text = element->attr("onclick").getText();
|
std::string text = element->attr("onclick").getText();
|
||||||
if (!text.empty()) {
|
if (!text.empty()) {
|
||||||
auto callback = scripting::create_runnable(
|
auto callback = scripting::create_runnable(
|
||||||
reader.getEnvironment(),
|
reader.getEnvironment(), text, reader.getFilename()
|
||||||
text,
|
|
||||||
reader.getFilename()
|
|
||||||
);
|
);
|
||||||
node.listenAction([callback](GUI*) {
|
node.listenAction([callback](GUI*) {
|
||||||
callback();
|
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) {
|
static void _readContainer(UiXmlReader& reader, xml::xmlelement element, Container& container) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user