mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-09-23 05:18:08 +08:00
Checkbox button debounce (#774)
This fixes: https://github.com/ArthurSonzogni/FTXUI/issues/773 Dragging the mouse with the left button pressed now avoids activating multiple checkboxes. Add support for detecting mouse press transition. Added: ```cpp // The previous mouse event. Mouse Mouse::previous; // Return whether the mouse transitionned from: // released to pressed => IsPressed() // pressed to pressed => IsHeld() // pressed to released => IsReleased() bool Mouse::IsPressed(Button button) const; bool Mouse::IsHeld(Button button) const; bool Mouse::IsReleased(Button button) const; ``` A couple of components are now activated when the mouse is pressed, as opposed to released. Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
This commit is contained in:
@@ -124,8 +124,7 @@ class ButtonBase : public ComponentBase, public ButtonOption {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Pressed) {
|
||||
if (event.mouse().IsPressed()) {
|
||||
TakeFocus();
|
||||
OnClick();
|
||||
return true;
|
||||
|
@@ -69,8 +69,7 @@ class CheckboxBase : public ComponentBase, public CheckboxOption {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Pressed) {
|
||||
if (event.mouse().IsPressed()) {
|
||||
*checked = !*checked;
|
||||
on_change();
|
||||
return true;
|
||||
|
@@ -466,8 +466,7 @@ class InputBase : public ComponentBase, public InputOption {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.mouse().button != Mouse::Left ||
|
||||
event.mouse().motion != Mouse::Pressed) {
|
||||
if (!event.mouse().IsPressed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -318,8 +318,7 @@ class MenuBase : public ComponentBase, public MenuOption {
|
||||
|
||||
TakeFocus();
|
||||
focused_entry() = i;
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Released) {
|
||||
if (event.mouse().IsPressed()) {
|
||||
if (selected() != i) {
|
||||
selected() = i;
|
||||
selected_previous_ = selected();
|
||||
@@ -683,8 +682,7 @@ Component MenuEntry(MenuEntryOption option) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Released) {
|
||||
if (event.mouse().IsPressed()) {
|
||||
TakeFocus();
|
||||
return true;
|
||||
}
|
||||
|
36
src/ftxui/component/mouse.cpp
Normal file
36
src/ftxui/component/mouse.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
// Copyright 2023 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
#include "ftxui/component/mouse.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
namespace {
|
||||
bool IsDown(const Mouse* mouse, Mouse::Button btn) {
|
||||
return mouse->button == btn && mouse->motion == Mouse::Pressed;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
/// Return whether the mouse transitionned from released to pressed.
|
||||
/// This is useful to detect a click.
|
||||
/// @arg btn The button to check.
|
||||
bool Mouse::IsPressed(Button btn) const {
|
||||
return IsDown(this, btn) && (!previous || !IsDown(previous, btn));
|
||||
}
|
||||
|
||||
/// Return whether the mouse is currently held.
|
||||
/// This is useful to detect a drag.
|
||||
/// @arg btn The button to check.
|
||||
bool Mouse::IsHeld(Button btn) const {
|
||||
return IsDown(this, btn) && previous && IsDown(previous, btn);
|
||||
}
|
||||
|
||||
/// Return whether the mouse transitionned from pressed to released.
|
||||
/// This is useful to detect a click.
|
||||
/// @arg btn The button to check.
|
||||
bool Mouse::IsReleased(Button btn) const {
|
||||
return !IsDown(this, btn) && (previous && IsDown(previous, btn));
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
@@ -123,8 +123,7 @@ class RadioboxBase : public ComponentBase, public RadioboxOption {
|
||||
|
||||
TakeFocus();
|
||||
focused_entry() = i;
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Released) {
|
||||
if (event.mouse().IsPressed()) {
|
||||
if (selected() != i) {
|
||||
selected() = i;
|
||||
on_change();
|
||||
|
@@ -42,8 +42,7 @@ class ResizableSplitBase : public ComponentBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Pressed &&
|
||||
if (event.mouse().IsPressed() &&
|
||||
separator_box_.Contain(event.mouse().x, event.mouse().y) &&
|
||||
!captured_mouse_) {
|
||||
captured_mouse_ = CaptureMouse(event);
|
||||
|
@@ -689,11 +689,17 @@ void ScreenInteractive::HandleTask(Component component, Task& task) {
|
||||
if (arg.is_mouse()) {
|
||||
arg.mouse().x -= cursor_x_;
|
||||
arg.mouse().y -= cursor_y_;
|
||||
arg.mouse().previous = &latest_mouse_event_;
|
||||
}
|
||||
|
||||
arg.screen_ = this;
|
||||
component->OnEvent(arg);
|
||||
frame_valid_ = false;
|
||||
|
||||
if (arg.is_mouse()) {
|
||||
latest_mouse_event_ = arg.mouse();
|
||||
latest_mouse_event_.previous = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -174,8 +174,7 @@ class SliderBase : public ComponentBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.mouse().button != Mouse::Left ||
|
||||
event.mouse().motion != Mouse::Pressed) {
|
||||
if (!event.mouse().IsPressed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -225,8 +225,7 @@ class WindowImpl : public ComponentBase, public WindowOptions {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.mouse().button != Mouse::Left ||
|
||||
event.mouse().motion != Mouse::Pressed) {
|
||||
if (!event.mouse().IsPressed()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user