Basic text input support
This commit is contained in:
parent
89823ab617
commit
14db237b1d
|
|
@ -95,6 +95,26 @@ dependencies = [
|
||||||
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clipboard"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"clipboard-win 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"x11-clipboard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clipboard-win"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cloudabi"
|
name = "cloudabi"
|
||||||
version = "0.0.3"
|
version = "0.0.3"
|
||||||
|
|
@ -189,6 +209,7 @@ dependencies = [
|
||||||
name = "example_glium"
|
name = "example_glium"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"clipboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"emigui 0.1.0",
|
"emigui 0.1.0",
|
||||||
"emigui_glium 0.1.0",
|
"emigui_glium 0.1.0",
|
||||||
"glium 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"glium 0.24.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
@ -436,6 +457,24 @@ dependencies = [
|
||||||
"malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc-foundation"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"block 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "objc_id"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ordered-float"
|
name = "ordered-float"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
|
@ -915,6 +954,14 @@ dependencies = [
|
||||||
"x11-dl 2.18.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"x11-dl 2.18.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x11-clipboard"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x11-dl"
|
name = "x11-dl"
|
||||||
version = "2.18.5"
|
version = "2.18.5"
|
||||||
|
|
@ -926,6 +973,15 @@ dependencies = [
|
||||||
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xcb"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.69 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xdg"
|
name = "xdg"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
|
@ -951,6 +1007,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
|
"checksum cc 1.0.52 (registry+https://github.com/rust-lang/crates.io-index)" = "c3d87b23d6a92cd03af510a5ade527033f6aa6fa92161e2d5863a907d4c5e31d"
|
||||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
"checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49"
|
"checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49"
|
||||||
|
"checksum clipboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25a904646c0340239dcf7c51677b33928bf24fdf424b79a57909c0109075b2e7"
|
||||||
|
"checksum clipboard-win 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b"
|
||||||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||||
"checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54"
|
"checksum cocoa 0.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1706996401131526e36b3b49f0c4d912639ce110996f3ca144d78946727bce54"
|
||||||
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
|
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
|
||||||
|
|
@ -985,6 +1043,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||||
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||||
"checksum objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
"checksum objc 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||||
|
"checksum objc-foundation 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||||
|
"checksum objc_id 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||||
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
|
"checksum ordered-float 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
|
||||||
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
|
"checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b"
|
||||||
"checksum parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
|
"checksum parking_lot 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e"
|
||||||
|
|
@ -1041,6 +1101,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
|
||||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
"checksum winit 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e96eb4bb472fa43e718e8fa4aef82f86cd9deac9483a1e1529230babdb394a8"
|
"checksum winit 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e96eb4bb472fa43e718e8fa4aef82f86cd9deac9483a1e1529230babdb394a8"
|
||||||
|
"checksum x11-clipboard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "89bd49c06c9eb5d98e6ba6536cf64ac9f7ee3a009b2f53996d405b3944f6bcea"
|
||||||
"checksum x11-dl 2.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
|
"checksum x11-dl 2.18.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
|
||||||
|
"checksum xcb 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de"
|
||||||
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
"checksum xdg 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
||||||
"checksum xml-rs 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bb76e5c421bbbeb8924c60c030331b345555024d56261dae8f3e786ed817c23"
|
"checksum xml-rs 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2bb76e5c421bbbeb8924c60c030331b345555024d56261dae8f3e786ed817c23"
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,11 @@
|
||||||
An immediate mode GUI library written in Rust. For web apps or native apps.
|
An immediate mode GUI library written in Rust. For web apps or native apps.
|
||||||
|
|
||||||
## Goals:
|
## Goals:
|
||||||
* Easy to use
|
* Lightweight
|
||||||
|
* Short, conveniant syntax
|
||||||
|
* Responsive (60 Hz without breaking a sweat)
|
||||||
|
* Portable
|
||||||
* Platform independent (the same code works on the web and as a native app)
|
* Platform independent (the same code works on the web and as a native app)
|
||||||
* Responsive
|
|
||||||
|
|
||||||
## How it works:
|
## How it works:
|
||||||
Loop:
|
Loop:
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@
|
||||||
var g_is_touch = false; // we don't know yet
|
var g_is_touch = false; // we don't know yet
|
||||||
var g_scroll_delta_x = 0;
|
var g_scroll_delta_x = 0;
|
||||||
var g_scroll_delta_y = 0;
|
var g_scroll_delta_y = 0;
|
||||||
|
var g_events = [];
|
||||||
|
|
||||||
function pixels_per_point() {
|
function pixels_per_point() {
|
||||||
return window.devicePixelRatio || 1.0;
|
return window.devicePixelRatio || 1.0;
|
||||||
|
|
@ -106,9 +107,11 @@
|
||||||
screen_size: { x: window.innerWidth, y: window.innerHeight },
|
screen_size: { x: window.innerWidth, y: window.innerHeight },
|
||||||
pixels_per_point: pixels_per_point(),
|
pixels_per_point: pixels_per_point(),
|
||||||
time: window.performance.now() / 1000.0,
|
time: window.performance.now() / 1000.0,
|
||||||
|
events: g_events,
|
||||||
};
|
};
|
||||||
g_scroll_delta_x = 0;
|
g_scroll_delta_x = 0;
|
||||||
g_scroll_delta_y = 0;
|
g_scroll_delta_y = 0;
|
||||||
|
g_events = [];
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -210,6 +213,37 @@
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keydown", function (event) {
|
||||||
|
console.log(`keydown: '${event.key}'`);
|
||||||
|
var key = translate_key(event.key);
|
||||||
|
if (key) {
|
||||||
|
g_events.push({ "key": { "key": key, 'pressed': true } });
|
||||||
|
} else {
|
||||||
|
g_events.push({ "text": event.key });
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
// document.addEventListener("keypress", function (event) {
|
||||||
|
// console.log(`keypress: ${event.key} ${JSON.stringify(event)}`);
|
||||||
|
// invalidate();
|
||||||
|
// event.stopPropagation();
|
||||||
|
// event.preventDefault();
|
||||||
|
// });
|
||||||
|
|
||||||
|
document.addEventListener("keyup", function (event) {
|
||||||
|
// console.log(`keyup: ${event.key} ${JSON.stringify(event)}`);
|
||||||
|
var key = translate_key(event.key);
|
||||||
|
if (key) {
|
||||||
|
g_events.push({ "key": { "key": key, 'pressed': false } });
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
if (!ANIMATION_FRAME) {
|
if (!ANIMATION_FRAME) {
|
||||||
window.addEventListener("load", invalidate);
|
window.addEventListener("load", invalidate);
|
||||||
window.addEventListener("pagehide", invalidate);
|
window.addEventListener("pagehide", invalidate);
|
||||||
|
|
@ -219,6 +253,29 @@
|
||||||
|
|
||||||
paint_and_schedule();
|
paint_and_schedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function translate_key(key) {
|
||||||
|
if (key == "Alt") { return "alt"; }
|
||||||
|
if (key == "Backspace") { return "backspace"; }
|
||||||
|
if (key == "Control") { return "control"; }
|
||||||
|
if (key == "Delete") { return "delete"; }
|
||||||
|
if (key == "ArrowDown") { return "down"; }
|
||||||
|
if (key == "End") { return "end"; }
|
||||||
|
if (key == "Escape") { return "escape"; }
|
||||||
|
if (key == "Home") { return "home"; }
|
||||||
|
if (key == "Help") { return "insert"; }
|
||||||
|
if (key == "ArrowLeft") { return "left"; }
|
||||||
|
if (key == "Meta") { return "logo"; }
|
||||||
|
if (key == "PageDown") { return "page_down"; }
|
||||||
|
if (key == "PageUp") { return "page_up"; }
|
||||||
|
if (key == "Enter") { return "return"; }
|
||||||
|
if (key == "ArrowRight") { return "right"; }
|
||||||
|
if (key == "Shift") { return "shift"; }
|
||||||
|
// if (key == " ") { return "space"; }
|
||||||
|
if (key == "Tab") { return "tab"; }
|
||||||
|
if (key == "ArrowUp") { return "up"; }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<!-- We later make this cover the entire screen even when resized -->
|
<!-- We later make this cover the entire screen even when resized -->
|
||||||
<canvas id="canvas" width="1024" height="1024"></canvas>
|
<canvas id="canvas" width="1024" height="1024"></canvas>
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,14 @@ This is the core library crate Emigui. It is fully platform independent without
|
||||||
* [ ] Kinetic scrolling
|
* [ ] Kinetic scrolling
|
||||||
* [x] Add support for clicking links
|
* [x] Add support for clicking links
|
||||||
* [ ] Menu bar (File, Edit, etc)
|
* [ ] Menu bar (File, Edit, etc)
|
||||||
* [ ] One-line TextField
|
* [ ] Text input
|
||||||
|
* [x] Input events (key presses)
|
||||||
|
* [x] Text focus
|
||||||
|
* [ ] Cursor movement
|
||||||
|
* [ ] Text selection
|
||||||
* [ ] Clipboard copy/paste
|
* [ ] Clipboard copy/paste
|
||||||
|
* [ ] Move focus with tab
|
||||||
|
* [ ] Handle leading/trailing space
|
||||||
* [ ] Color picker
|
* [ ] Color picker
|
||||||
* [ ] Style editor
|
* [ ] Style editor
|
||||||
* [ ] Table with resizable columns
|
* [ ] Table with resizable columns
|
||||||
|
|
@ -45,6 +51,7 @@ Add extremely quick animations for some things, maybe 2-3 frames. For instance:
|
||||||
* [x] Use clip rectangles when painting
|
* [x] Use clip rectangles when painting
|
||||||
* [x] Use clip rectangles when interacting
|
* [x] Use clip rectangles when interacting
|
||||||
* [x] Adjust clip rects so edges of child widgets aren't clipped
|
* [x] Adjust clip rects so edges of child widgets aren't clipped
|
||||||
|
* [ ] Use HW clip rects
|
||||||
|
|
||||||
### Modularity
|
### Modularity
|
||||||
* [x] `trait Widget` (`Label`, `Slider`, `Checkbox`, ...)
|
* [x] `trait Widget` (`Label`, `Slider`, `Checkbox`, ...)
|
||||||
|
|
|
||||||
|
|
@ -149,15 +149,16 @@ fn font_definitions_ui(font_definitions: &mut FontDefinitions, region: &mut Regi
|
||||||
impl RawInput {
|
impl RawInput {
|
||||||
pub fn ui(&self, region: &mut Region) {
|
pub fn ui(&self, region: &mut Region) {
|
||||||
// TODO: simpler way to show values, e.g. `region.value("Mouse Pos:", self.mouse_pos);
|
// TODO: simpler way to show values, e.g. `region.value("Mouse Pos:", self.mouse_pos);
|
||||||
|
// TODO: easily change default font!
|
||||||
region.add(label!("mouse_down: {}", self.mouse_down));
|
region.add(label!("mouse_down: {}", self.mouse_down));
|
||||||
region.add(label!("mouse_pos: {:.1?}", self.mouse_pos));
|
region.add(label!("mouse_pos: {:.1?}", self.mouse_pos));
|
||||||
region.add(label!("scroll_delta: {:?}", self.scroll_delta));
|
region.add(label!("scroll_delta: {:?}", self.scroll_delta));
|
||||||
region.add(label!("screen_size: {:?}", self.screen_size));
|
region.add(label!("screen_size: {:?}", self.screen_size));
|
||||||
region.add(label!("pixels_per_point: {}", self.pixels_per_point));
|
region.add(label!("pixels_per_point: {}", self.pixels_per_point));
|
||||||
region.add(label!("time: {:.3} s", self.time));
|
region.add(label!("time: {:.3} s", self.time));
|
||||||
region.add(label!("text: {:?}", self.text));
|
region.add(label!("events: {:?}", self.events));
|
||||||
// region.add(label!("dropped_files: {}", self.dropped_files));
|
region.add(label!("dropped_files: {:?}", self.dropped_files));
|
||||||
// region.add(label!("hovered_files: {}", self.hovered_files));
|
region.add(label!("hovered_files: {:?}", self.hovered_files));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,8 +173,8 @@ impl GuiInput {
|
||||||
region.add(label!("screen_size: {:?}", self.screen_size));
|
region.add(label!("screen_size: {:?}", self.screen_size));
|
||||||
region.add(label!("pixels_per_point: {}", self.pixels_per_point));
|
region.add(label!("pixels_per_point: {}", self.pixels_per_point));
|
||||||
region.add(label!("time: {}", self.time));
|
region.add(label!("time: {}", self.time));
|
||||||
region.add(label!("text: {:?}", self.text));
|
region.add(label!("events: {:?}", self.events));
|
||||||
// region.add(label!("dropped_files: {}", self.dropped_files));
|
region.add(label!("dropped_files: {:?}", self.dropped_files));
|
||||||
// region.add(label!("hovered_files: {}", self.hovered_files));
|
region.add(label!("hovered_files: {:?}", self.hovered_files));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ pub struct ExampleApp {
|
||||||
checked: bool,
|
checked: bool,
|
||||||
count: usize,
|
count: usize,
|
||||||
radio: usize,
|
radio: usize,
|
||||||
|
text_inputs: [String; 3],
|
||||||
|
|
||||||
size: Vec2,
|
size: Vec2,
|
||||||
corner_radius: f32,
|
corner_radius: f32,
|
||||||
|
|
@ -24,6 +25,8 @@ impl Default for ExampleApp {
|
||||||
checked: true,
|
checked: true,
|
||||||
radio: 0,
|
radio: 0,
|
||||||
count: 0,
|
count: 0,
|
||||||
|
text_inputs: Default::default(),
|
||||||
|
|
||||||
size: vec2(100.0, 50.0),
|
size: vec2(100.0, 50.0),
|
||||||
corner_radius: 5.0,
|
corner_radius: 5.0,
|
||||||
stroke_width: 2.0,
|
stroke_width: 2.0,
|
||||||
|
|
@ -52,7 +55,7 @@ impl ExampleApp {
|
||||||
});
|
});
|
||||||
|
|
||||||
CollapsingHeader::new("Widgets")
|
CollapsingHeader::new("Widgets")
|
||||||
// .default_open()
|
.default_open()
|
||||||
.show(region, |region| {
|
.show(region, |region| {
|
||||||
region.horizontal(Align::Min, |region| {
|
region.horizontal(Align::Min, |region| {
|
||||||
region.add(label!("Text can have").text_color(srgba(110, 255, 110, 255)));
|
region.add(label!("Text can have").text_color(srgba(110, 255, 110, 255)));
|
||||||
|
|
@ -94,6 +97,13 @@ impl ExampleApp {
|
||||||
if region.add(Button::new("Double it")).clicked {
|
if region.add(Button::new("Double it")).clicked {
|
||||||
self.slider_value *= 2;
|
self.slider_value *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i, text) in self.text_inputs.iter_mut().enumerate() {
|
||||||
|
region.horizontal(Align::Min, |region|{
|
||||||
|
region.add(label!("Text input {}: ", i));
|
||||||
|
region.add(TextEdit::new(text).id(i));
|
||||||
|
}); // TODO: .tooltip_text("Enter text to edit me")
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
region.collapsing("Layouts", |region| {
|
region.collapsing("Layouts", |region| {
|
||||||
|
|
@ -151,7 +161,7 @@ impl ExampleApp {
|
||||||
.show(region, |region| self.painting.ui(region));
|
.show(region, |region| self.painting.ui(region));
|
||||||
|
|
||||||
CollapsingHeader::new("Resize")
|
CollapsingHeader::new("Resize")
|
||||||
.default_open()
|
// .default_open()
|
||||||
.show(region, |region| {
|
.show(region, |region| {
|
||||||
Resize::default()
|
Resize::default()
|
||||||
.default_height(200.0)
|
.default_height(200.0)
|
||||||
|
|
|
||||||
|
|
@ -40,4 +40,5 @@ pub use {
|
||||||
style::Style,
|
style::Style,
|
||||||
texture_atlas::Texture,
|
texture_atlas::Texture,
|
||||||
types::*,
|
types::*,
|
||||||
|
widgets::Widget,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ pub struct Memory {
|
||||||
/// The widget being interacted with (e.g. dragged, in case of a slider).
|
/// The widget being interacted with (e.g. dragged, in case of a slider).
|
||||||
pub(crate) active_id: Option<Id>,
|
pub(crate) active_id: Option<Id>,
|
||||||
|
|
||||||
|
/// The widget with keyboard focus (i.e. a text input field).
|
||||||
|
pub(crate) kb_focus_id: Option<Id>,
|
||||||
|
|
||||||
// states of various types of widgets
|
// states of various types of widgets
|
||||||
pub(crate) collapsing_headers: HashMap<Id, collapsing_header::State>,
|
pub(crate) collapsing_headers: HashMap<Id, collapsing_header::State>,
|
||||||
pub(crate) scroll_areas: HashMap<Id, scroll_area::State>,
|
pub(crate) scroll_areas: HashMap<Id, scroll_area::State>,
|
||||||
|
|
|
||||||
|
|
@ -143,6 +143,10 @@ impl Region {
|
||||||
self.ctx.memory.lock()
|
self.ctx.memory.lock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn output(&self) -> parking_lot::MutexGuard<Output> {
|
||||||
|
self.ctx.output.lock()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fonts(&self) -> &Fonts {
|
pub fn fonts(&self) -> &Fonts {
|
||||||
&*self.ctx.fonts
|
&*self.ctx.fonts
|
||||||
}
|
}
|
||||||
|
|
@ -281,7 +285,7 @@ impl Region {
|
||||||
};
|
};
|
||||||
add_contents(&mut child_region);
|
add_contents(&mut child_region);
|
||||||
let size = child_region.bounding_size();
|
let size = child_region.bounding_size();
|
||||||
self.reserve_space_without_padding(size);
|
self.reserve_space(size, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start a region with horizontal layout
|
/// Start a region with horizontal layout
|
||||||
|
|
@ -356,6 +360,14 @@ impl Region {
|
||||||
self.ctx.contains_mouse(self.layer, &self.clip_rect, rect)
|
self.ctx.contains_mouse(self.layer, &self.clip_rect, rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_kb_focus(&self, id: Id) -> bool {
|
||||||
|
self.memory().kb_focus_id == Some(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_kb_focus(&self, id: Id) {
|
||||||
|
self.memory().kb_focus_id = Some(id);
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
pub fn add(&mut self, widget: impl Widget) -> GuiResponse {
|
pub fn add(&mut self, widget: impl Widget) -> GuiResponse {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ pub struct Style {
|
||||||
/// For stuff like check marks in check boxes.
|
/// For stuff like check marks in check boxes.
|
||||||
pub line_width: f32,
|
pub line_width: f32,
|
||||||
|
|
||||||
|
pub cursor_blink_hz: f32,
|
||||||
|
pub text_cursor_width: f32,
|
||||||
|
|
||||||
// TODO: add ability to disable animations!
|
// TODO: add ability to disable animations!
|
||||||
/// How many seconds a typical animation should last
|
/// How many seconds a typical animation should last
|
||||||
pub animation_time: f32,
|
pub animation_time: f32,
|
||||||
|
|
@ -50,6 +53,8 @@ impl Default for Style {
|
||||||
clickable_diameter: 22.0,
|
clickable_diameter: 22.0,
|
||||||
start_icon_width: 16.0,
|
start_icon_width: 16.0,
|
||||||
line_width: 1.0,
|
line_width: 1.0,
|
||||||
|
cursor_blink_hz: 1.0,
|
||||||
|
text_cursor_width: 2.0,
|
||||||
animation_time: 1.0 / 20.0,
|
animation_time: 1.0 / 20.0,
|
||||||
window: Window::default(),
|
window: Window::default(),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,17 +30,17 @@ pub struct RawInput {
|
||||||
/// Time in seconds. Relative to whatever. Used for animation.
|
/// Time in seconds. Relative to whatever. Used for animation.
|
||||||
pub time: f64,
|
pub time: f64,
|
||||||
|
|
||||||
/// Text input, e.g. via keyboard or paste action
|
|
||||||
pub text: String,
|
|
||||||
|
|
||||||
/// Files has been dropped into the window.
|
/// Files has been dropped into the window.
|
||||||
pub dropped_files: Vec<std::path::PathBuf>,
|
pub dropped_files: Vec<std::path::PathBuf>,
|
||||||
|
|
||||||
/// Someone is threatening to drop these on us.
|
/// Someone is threatening to drop these on us.
|
||||||
pub hovered_files: Vec<std::path::PathBuf>,
|
pub hovered_files: Vec<std::path::PathBuf>,
|
||||||
|
|
||||||
|
/// In-order events received this frame
|
||||||
|
pub events: Vec<Event>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// What the gui maintains
|
/// What emigui maintains
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct GuiInput {
|
pub struct GuiInput {
|
||||||
/// Is the button currently down?
|
/// Is the button currently down?
|
||||||
|
|
@ -73,14 +73,52 @@ pub struct GuiInput {
|
||||||
/// Time in seconds. Relative to whatever. Used for animation.
|
/// Time in seconds. Relative to whatever. Used for animation.
|
||||||
pub time: f64,
|
pub time: f64,
|
||||||
|
|
||||||
/// Text input, e.g. via keyboard or paste action
|
|
||||||
pub text: String,
|
|
||||||
|
|
||||||
/// Files has been dropped into the window.
|
/// Files has been dropped into the window.
|
||||||
pub dropped_files: Vec<std::path::PathBuf>,
|
pub dropped_files: Vec<std::path::PathBuf>,
|
||||||
|
|
||||||
/// Someone is threatening to drop these on us.
|
/// Someone is threatening to drop these on us.
|
||||||
pub hovered_files: Vec<std::path::PathBuf>,
|
pub hovered_files: Vec<std::path::PathBuf>,
|
||||||
|
|
||||||
|
/// In-order events received this frame
|
||||||
|
pub events: Vec<Event>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum Event {
|
||||||
|
Copy,
|
||||||
|
Cut,
|
||||||
|
/// Text input, e.g. via keyboard or paste action
|
||||||
|
Text(String),
|
||||||
|
Key {
|
||||||
|
key: Key,
|
||||||
|
pressed: bool,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum Key {
|
||||||
|
Alt,
|
||||||
|
Backspace,
|
||||||
|
Control,
|
||||||
|
Delete,
|
||||||
|
Down,
|
||||||
|
End,
|
||||||
|
Escape,
|
||||||
|
Home,
|
||||||
|
Insert,
|
||||||
|
Left,
|
||||||
|
/// Windows key or Mac Command key
|
||||||
|
Logo,
|
||||||
|
PageDown,
|
||||||
|
PageUp,
|
||||||
|
Return,
|
||||||
|
Right,
|
||||||
|
Shift,
|
||||||
|
// Space,
|
||||||
|
Tab,
|
||||||
|
Up,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GuiInput {
|
impl GuiInput {
|
||||||
|
|
@ -99,9 +137,9 @@ impl GuiInput {
|
||||||
screen_size: new.screen_size,
|
screen_size: new.screen_size,
|
||||||
pixels_per_point: new.pixels_per_point,
|
pixels_per_point: new.pixels_per_point,
|
||||||
time: new.time,
|
time: new.time,
|
||||||
text: new.text.clone(),
|
|
||||||
dropped_files: new.dropped_files.clone(),
|
dropped_files: new.dropped_files.clone(),
|
||||||
hovered_files: new.hovered_files.clone(),
|
hovered_files: new.hovered_files.clone(),
|
||||||
|
events: new.events.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -109,8 +147,12 @@ impl GuiInput {
|
||||||
#[derive(Clone, Default, Serialize)]
|
#[derive(Clone, Default, Serialize)]
|
||||||
pub struct Output {
|
pub struct Output {
|
||||||
pub cursor_icon: CursorIcon,
|
pub cursor_icon: CursorIcon,
|
||||||
|
|
||||||
/// If set, open this url.
|
/// If set, open this url.
|
||||||
pub open_url: Option<String>,
|
pub open_url: Option<String>,
|
||||||
|
|
||||||
|
/// Response to Event::Copy or Event::Cut. Ignore if empty.
|
||||||
|
pub copied_text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Serialize)]
|
#[derive(Clone, Copy, Serialize)]
|
||||||
|
|
@ -120,6 +162,7 @@ pub enum CursorIcon {
|
||||||
/// Pointing hand, used for e.g. web links
|
/// Pointing hand, used for e.g. web links
|
||||||
PointingHand,
|
PointingHand,
|
||||||
ResizeNwSe,
|
ResizeNwSe,
|
||||||
|
Text,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CursorIcon {
|
impl Default for CursorIcon {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ use crate::{
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod text_edit;
|
||||||
|
pub use text_edit::*;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Anything implementing Widget can be added to a Region with Region::add
|
/// Anything implementing Widget can be added to a Region with Region::add
|
||||||
|
|
@ -336,7 +339,6 @@ impl<'a> Slider<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: use range syntax
|
|
||||||
pub fn f32(value: &'a mut f32, range: RangeInclusive<f32>) -> Self {
|
pub fn f32(value: &'a mut f32, range: RangeInclusive<f32>) -> Self {
|
||||||
Slider {
|
Slider {
|
||||||
precision: 3,
|
precision: 3,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TextEdit<'t> {
|
||||||
|
text: &'t mut String,
|
||||||
|
id: Option<Id>,
|
||||||
|
text_style: TextStyle, // TODO: Option<TextStyle>, where None means "use the default for the region"
|
||||||
|
text_color: Option<Color>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t> TextEdit<'t> {
|
||||||
|
pub fn new(text: &'t mut String) -> Self {
|
||||||
|
TextEdit {
|
||||||
|
text,
|
||||||
|
id: None,
|
||||||
|
text_style: TextStyle::Body,
|
||||||
|
text_color: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn id(mut self, id_source: impl std::hash::Hash) -> Self {
|
||||||
|
self.id = Some(Id::new(id_source));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_style(mut self, text_style: TextStyle) -> Self {
|
||||||
|
self.text_style = text_style;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text_color(mut self, text_color: Color) -> Self {
|
||||||
|
self.text_color = Some(text_color);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t> Widget for TextEdit<'t> {
|
||||||
|
fn add_to(self, region: &mut Region) -> GuiResponse {
|
||||||
|
let id = region.make_child_id(self.id);
|
||||||
|
|
||||||
|
let font = ®ion.fonts()[self.text_style];
|
||||||
|
let line_spacing = font.line_spacing();
|
||||||
|
let (text, text_size) = font.layout_multiline(self.text.as_str(), region.available_width());
|
||||||
|
let desired_size = text_size.max(vec2(region.available_width(), line_spacing));
|
||||||
|
let interact = region.reserve_space(desired_size, Some(id));
|
||||||
|
|
||||||
|
if interact.clicked {
|
||||||
|
region.request_kb_focus(id);
|
||||||
|
}
|
||||||
|
if interact.hovered {
|
||||||
|
region.output().cursor_icon = CursorIcon::Text;
|
||||||
|
}
|
||||||
|
let has_kb_focus = region.has_kb_focus(id);
|
||||||
|
|
||||||
|
if has_kb_focus {
|
||||||
|
for event in ®ion.input().events {
|
||||||
|
match event {
|
||||||
|
Event::Copy | Event::Cut => {
|
||||||
|
// TODO: cut
|
||||||
|
region.ctx().output.lock().copied_text = self.text.clone();
|
||||||
|
}
|
||||||
|
Event::Text(text) => {
|
||||||
|
if text == "\u{7f}" {
|
||||||
|
// backspace
|
||||||
|
} else {
|
||||||
|
*self.text += text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Event::Key { key, pressed: true } => {
|
||||||
|
match key {
|
||||||
|
Key::Backspace => {
|
||||||
|
self.text.pop(); // TODO: unicode aware
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
region.add_paint_cmd(PaintCmd::Rect {
|
||||||
|
rect: interact.rect,
|
||||||
|
corner_radius: 0.0,
|
||||||
|
// fill_color: Some(color::BLACK),
|
||||||
|
fill_color: region.style().interact_fill_color(&interact),
|
||||||
|
// fill_color: Some(region.style().background_fill_color()),
|
||||||
|
outline: None, //Some(Outline::new(1.0, color::WHITE)),
|
||||||
|
});
|
||||||
|
|
||||||
|
if has_kb_focus {
|
||||||
|
let cursor_blink_hz = region.style().cursor_blink_hz;
|
||||||
|
let show_cursor =
|
||||||
|
(region.input().time * cursor_blink_hz as f64 * 3.0).floor() as i64 % 3 != 0;
|
||||||
|
if show_cursor {
|
||||||
|
let cursor_pos = if let Some(last) = text.last() {
|
||||||
|
interact.rect.min + vec2(last.max_x(), last.y_offset)
|
||||||
|
} else {
|
||||||
|
interact.rect.min
|
||||||
|
};
|
||||||
|
region.add_paint_cmd(PaintCmd::line_segment(
|
||||||
|
(cursor_pos, cursor_pos + vec2(0.0, line_spacing)),
|
||||||
|
color::WHITE,
|
||||||
|
region.style().text_cursor_width,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
region.add_text(interact.rect.min, self.text_style, text, self.text_color);
|
||||||
|
|
||||||
|
region.response(interact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,5 +8,6 @@ edition = "2018"
|
||||||
emigui = { path = "../emigui" }
|
emigui = { path = "../emigui" }
|
||||||
emigui_glium = { path = "../emigui_glium" }
|
emigui_glium = { path = "../emigui_glium" }
|
||||||
|
|
||||||
|
clipboard = "0.5"
|
||||||
glium = "0.24"
|
glium = "0.24"
|
||||||
webbrowser = "0.5"
|
webbrowser = "0.5"
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,14 @@
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use {
|
use {
|
||||||
|
clipboard::{ClipboardContext, ClipboardProvider},
|
||||||
emigui::{containers::*, example_app::ExampleApp, widgets::*, *},
|
emigui::{containers::*, example_app::ExampleApp, widgets::*, *},
|
||||||
emigui_glium::Painter,
|
emigui_glium::Painter,
|
||||||
glium::glutin,
|
glium::glutin::{self, VirtualKeyCode},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: move more code into emigui_glium care
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut events_loop = glutin::EventsLoop::new();
|
let mut events_loop = glutin::EventsLoop::new();
|
||||||
let window = glutin::WindowBuilder::new().with_title("Emigui example");
|
let window = glutin::WindowBuilder::new().with_title("Emigui example");
|
||||||
|
|
@ -47,6 +50,14 @@ fn main() {
|
||||||
|
|
||||||
let mut example_app = ExampleApp::default();
|
let mut example_app = ExampleApp::default();
|
||||||
|
|
||||||
|
let mut clipboard: Option<ClipboardContext> = match ClipboardContext::new() {
|
||||||
|
Ok(clipboard) => Some(clipboard),
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Failed to initialize clipboard: {}", err);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
while running {
|
while running {
|
||||||
{
|
{
|
||||||
// Keep smooth frame rate. TODO: proper vsync
|
// Keep smooth frame rate. TODO: proper vsync
|
||||||
|
|
@ -60,12 +71,15 @@ fn main() {
|
||||||
{
|
{
|
||||||
raw_input.time = start_time.elapsed().as_nanos() as f64 * 1e-9;
|
raw_input.time = start_time.elapsed().as_nanos() as f64 * 1e-9;
|
||||||
raw_input.scroll_delta = vec2(0.0, 0.0);
|
raw_input.scroll_delta = vec2(0.0, 0.0);
|
||||||
raw_input.text.clear();
|
|
||||||
raw_input.dropped_files.clear();
|
raw_input.dropped_files.clear();
|
||||||
raw_input.hovered_files.clear();
|
raw_input.hovered_files.clear();
|
||||||
events_loop.poll_events(|event| input_event(event, &mut raw_input, &mut running));
|
raw_input.events.clear();
|
||||||
|
events_loop.poll_events(|event| {
|
||||||
|
input_event(event, clipboard.as_mut(), &mut raw_input, &mut running)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let emigui_start = Instant::now();
|
||||||
emigui.begin_frame(raw_input.clone()); // TODO: avoid clone
|
emigui.begin_frame(raw_input.clone()); // TODO: avoid clone
|
||||||
let mut region = emigui.background_region();
|
let mut region = emigui.background_region();
|
||||||
let mut region = region.centered_column(region.available_width().min(480.0));
|
let mut region = region.centered_column(region.available_width().min(480.0));
|
||||||
|
|
@ -117,6 +131,7 @@ fn main() {
|
||||||
CursorIcon::Default => glutin::MouseCursor::Default,
|
CursorIcon::Default => glutin::MouseCursor::Default,
|
||||||
CursorIcon::PointingHand => glutin::MouseCursor::Hand,
|
CursorIcon::PointingHand => glutin::MouseCursor::Hand,
|
||||||
CursorIcon::ResizeNwSe => glutin::MouseCursor::NwseResize,
|
CursorIcon::ResizeNwSe => glutin::MouseCursor::NwseResize,
|
||||||
|
CursorIcon::Text => glutin::MouseCursor::Text,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(url) = output.open_url {
|
if let Some(url) = output.open_url {
|
||||||
|
|
@ -125,11 +140,24 @@ fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !output.copied_text.is_empty() {
|
||||||
|
if let Some(clipboard) = clipboard.as_mut() {
|
||||||
|
if let Err(err) = clipboard.set_contents(output.copied_text) {
|
||||||
|
eprintln!("Copy/Cut error: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
display.gl_window().set_cursor(cursor);
|
display.gl_window().set_cursor(cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input_event(event: glutin::Event, raw_input: &mut RawInput, running: &mut bool) {
|
fn input_event(
|
||||||
|
event: glutin::Event,
|
||||||
|
clipboard: Option<&mut ClipboardContext>,
|
||||||
|
raw_input: &mut RawInput,
|
||||||
|
running: &mut bool,
|
||||||
|
) {
|
||||||
use glutin::WindowEvent::*;
|
use glutin::WindowEvent::*;
|
||||||
match event {
|
match event {
|
||||||
glutin::Event::WindowEvent { event, .. } => match event {
|
glutin::Event::WindowEvent { event, .. } => match event {
|
||||||
|
|
@ -151,12 +179,39 @@ fn input_event(event: glutin::Event, raw_input: &mut RawInput, running: &mut boo
|
||||||
raw_input.mouse_pos = None;
|
raw_input.mouse_pos = None;
|
||||||
}
|
}
|
||||||
ReceivedCharacter(ch) => {
|
ReceivedCharacter(ch) => {
|
||||||
raw_input.text.push(ch);
|
raw_input.events.push(Event::Text(ch.to_string()));
|
||||||
}
|
}
|
||||||
KeyboardInput { input, .. } => {
|
KeyboardInput { input, .. } => {
|
||||||
if input.virtual_keycode == Some(glutin::VirtualKeyCode::Q) && input.modifiers.logo
|
if let Some(virtual_keycode) = input.virtual_keycode {
|
||||||
{
|
// TODO: If mac
|
||||||
*running = false;
|
if input.modifiers.logo && virtual_keycode == VirtualKeyCode::Q {
|
||||||
|
*running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match virtual_keycode {
|
||||||
|
VirtualKeyCode::Paste => {
|
||||||
|
if let Some(clipboard) = clipboard {
|
||||||
|
match clipboard.get_contents() {
|
||||||
|
Ok(contents) => {
|
||||||
|
raw_input.events.push(Event::Text(contents));
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
eprintln!("Paste error: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
VirtualKeyCode::Copy => raw_input.events.push(Event::Copy),
|
||||||
|
VirtualKeyCode::Cut => raw_input.events.push(Event::Cut),
|
||||||
|
_ => {
|
||||||
|
if let Some(key) = translate_virtual_key_code(virtual_keycode) {
|
||||||
|
raw_input.events.push(Event::Key {
|
||||||
|
key,
|
||||||
|
pressed: input.state == glutin::ElementState::Pressed,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MouseWheel { delta, .. } => {
|
MouseWheel { delta, .. } => {
|
||||||
|
|
@ -178,3 +233,34 @@ fn input_event(event: glutin::Event, raw_input: &mut RawInput, running: &mut boo
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn translate_virtual_key_code(key: glutin::VirtualKeyCode) -> Option<emigui::Key> {
|
||||||
|
use VirtualKeyCode::*;
|
||||||
|
|
||||||
|
Some(match key {
|
||||||
|
Escape => Key::Escape,
|
||||||
|
Insert => Key::Insert,
|
||||||
|
Home => Key::Home,
|
||||||
|
Delete => Key::Delete,
|
||||||
|
End => Key::End,
|
||||||
|
PageDown => Key::PageDown,
|
||||||
|
PageUp => Key::PageUp,
|
||||||
|
Left => Key::Left,
|
||||||
|
Up => Key::Up,
|
||||||
|
Right => Key::Right,
|
||||||
|
Down => Key::Down,
|
||||||
|
Back => Key::Backspace,
|
||||||
|
Return => Key::Return,
|
||||||
|
// Space => Key::Space,
|
||||||
|
Tab => Key::Tab,
|
||||||
|
|
||||||
|
LAlt | RAlt => Key::Alt,
|
||||||
|
LShift | RShift => Key::Shift,
|
||||||
|
LControl | RControl => Key::Control,
|
||||||
|
LWin | RWin => Key::Logo,
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue