Is it possible to code something to stop a function while it is running by pressing the “esc” key?
Can I assume this is for an extension you have written yourself? If so, you need to implement the Tool method #onCancel.
Yes, my extension shows and hide items in an order but it could take more time than expected or you could want to stop the process becasuse you don’t need to cotinue.
Thanks @slbaumgartner
Yes, as Steve said, currently only an active Tool
can receive keystrokes if the main application has focus.
However, if it’s an UI::HtmlDialog
that has the focus, then it can receive the ESC keystroke in JavaScript and fire off a Ruby callback to set some Ruby-side state variable that a timer could check periodically to decide whether to continue some operation.
The process is: I press an icon in an UI::HtmlDialog
which run a Ruby callback that run a Ruby function. The last function is the one I need to stop while running, it doesn’t send any data to the UI::HtmlDialog
while running.
Well, after the HTML icon is clicked, but just before calling the Ruby callback, you can attach a JavaScript event handler to the button waiting for an ESC keypress. If it happens it can call a “bailout” dialog callback.
Periodically, your processing can check a Ruby-side state variable to continue. The “bailout” callback can set this Ruby state variable to false
.
At some point the Ruby-side should call a JS-side reset()
function.
Here is some example code …not tested (Take it for what it’s worth. Ie, an idea.)
I think that the button must remain having the focus for the keyboard “keyup” event to fire.
module Rtches
module SomeExtensionName
extend self
# Returns the HTML for the dialog.
def html()
js = %[
var clicked = false;
function setup() {
var button = document.getElementById('clickme');
button.addEventListener("click", (event) => {
if (clicked) {
return;
} else {
clicked = true;
watchForEscape(this);
sketchup.clicked;
}
});
document.removeEventListener("DOMContentLoaded", setup);
sketchup.load_complete;
}
function handleEscape(event) {
if (event.code === 'Escape') {
sketchup.bailout;
// The Ruby side will need to call reset on the JS side!
};
}
function watchForEscape(button) {
button.addEventListener("keyup", handleEscape);
}
function stopWatchingForEscape() {
var button = document.getElementById('clickme');
button.removeEventListener("keyup", handleEscape);
}
// Needs to be called from the Ruby-side after porcessing is
// complete or a baliout condition has been set via ESC.
function reset() {
stopWatchingForEscape();
clicked = false;
}
document.addEventListener("DOMContentLoaded", setup);
]
html = %[
<!DOCTYPE html>
<html>
<head>
<script>
#{js}
</script>
</head>
<body>
<button id="clickme" tabindex="0" autofocus>Click Me</button>
</body>
</html>
]
end # html()
end # extension submodule
end # top level namespace
I’ll try to test something like that. Thanks @DanRathbun
Whoops, the clicked
JS variable needs to be global. (Moved it outside the setup()
function.)