double click support
This commit is contained in:
parent
b6f2456a82
commit
a678eddb77
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;}
|
||||
|
||||
@ -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))) {
|
||||
|
||||
@ -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) {};
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user