Add a lot more CursorIcon's
This commit is contained in:
parent
ee1fcf1ead
commit
958aea922f
8 changed files with 216 additions and 48 deletions
|
@ -74,19 +74,118 @@ impl OpenUrl {
|
||||||
/// A mouse cursor icon.
|
/// A mouse cursor icon.
|
||||||
///
|
///
|
||||||
/// egui emits a [`CursorIcon`] in [`Output`] each frame as a request to the integration.
|
/// egui emits a [`CursorIcon`] in [`Output`] each frame as a request to the integration.
|
||||||
#[derive(Clone, Copy, PartialEq)]
|
///
|
||||||
|
/// Loosely based on <https://developer.mozilla.org/en-US/docs/Web/CSS/cursor>.
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum CursorIcon {
|
pub enum CursorIcon {
|
||||||
|
/// Normal cursor icon, whatever that is.
|
||||||
Default,
|
Default,
|
||||||
|
|
||||||
|
/// Show no cursor
|
||||||
|
None,
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
// Links and status:
|
||||||
|
/// A context menu is available
|
||||||
|
ContextMenu,
|
||||||
|
|
||||||
|
/// Question mark
|
||||||
|
Help,
|
||||||
|
|
||||||
/// Pointing hand, used for e.g. web links
|
/// Pointing hand, used for e.g. web links
|
||||||
PointingHand,
|
PointingHand,
|
||||||
ResizeHorizontal,
|
|
||||||
ResizeNeSw,
|
/// Shows that processing is being done, but that the program is still interactive.
|
||||||
ResizeNwSe,
|
Progress,
|
||||||
ResizeVertical,
|
|
||||||
|
/// Not yet ready, try later.
|
||||||
|
Wait,
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
// Selection:
|
||||||
|
/// Hover a cell in a table
|
||||||
|
Cell,
|
||||||
|
|
||||||
|
/// For precision work
|
||||||
|
Crosshair,
|
||||||
|
|
||||||
|
/// Text caret, e.g. "Click here to edit text"
|
||||||
Text,
|
Text,
|
||||||
/// Used when moving
|
|
||||||
|
/// Vertical text caret, e.g. "Click here to edit vertical text"
|
||||||
|
VerticalText,
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
// Drag-and-drop:
|
||||||
|
/// Indicated an alias, e.g. a shortcut
|
||||||
|
Alias,
|
||||||
|
|
||||||
|
/// Indicate that a copy will be made
|
||||||
|
Copy,
|
||||||
|
|
||||||
|
/// Omnidirectional move icon (e.g. arrows in all cardinal directions)
|
||||||
|
Move,
|
||||||
|
|
||||||
|
/// Can't drop here
|
||||||
|
NoDrop,
|
||||||
|
|
||||||
|
/// Forbidden
|
||||||
|
NotAllowed,
|
||||||
|
|
||||||
|
/// The thing you are hovering can be grabbed
|
||||||
Grab,
|
Grab,
|
||||||
|
|
||||||
|
/// You are grabbing the thing you are hovering
|
||||||
Grabbing,
|
Grabbing,
|
||||||
|
|
||||||
|
// ------------------------------------
|
||||||
|
// Resizing and scrolling
|
||||||
|
/// Something can be scrolled in any direction (panned).
|
||||||
|
AllScroll,
|
||||||
|
|
||||||
|
/// Horizontal resize `-` to make something wider or more narrow (left to/from right)
|
||||||
|
ResizeHorizontal,
|
||||||
|
/// Diagonal resize `/` (right-up to/from left-down)
|
||||||
|
ResizeNeSw,
|
||||||
|
/// Diagonal resize `\` (left-up to/from right-down)
|
||||||
|
ResizeNwSe,
|
||||||
|
/// Vertical resize `|` (up-down or down-up)
|
||||||
|
ResizeVertical,
|
||||||
|
|
||||||
|
/// Enhance!
|
||||||
|
ZoomIn,
|
||||||
|
/// Let's get a better overview
|
||||||
|
ZoomOut,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CursorIcon {
|
||||||
|
pub const ALL: [CursorIcon; 25] = [
|
||||||
|
CursorIcon::Default,
|
||||||
|
CursorIcon::None,
|
||||||
|
CursorIcon::ContextMenu,
|
||||||
|
CursorIcon::Help,
|
||||||
|
CursorIcon::PointingHand,
|
||||||
|
CursorIcon::Progress,
|
||||||
|
CursorIcon::Wait,
|
||||||
|
CursorIcon::Cell,
|
||||||
|
CursorIcon::Crosshair,
|
||||||
|
CursorIcon::Text,
|
||||||
|
CursorIcon::VerticalText,
|
||||||
|
CursorIcon::Alias,
|
||||||
|
CursorIcon::Copy,
|
||||||
|
CursorIcon::Move,
|
||||||
|
CursorIcon::NoDrop,
|
||||||
|
CursorIcon::NotAllowed,
|
||||||
|
CursorIcon::Grab,
|
||||||
|
CursorIcon::Grabbing,
|
||||||
|
CursorIcon::AllScroll,
|
||||||
|
CursorIcon::ResizeHorizontal,
|
||||||
|
CursorIcon::ResizeNeSw,
|
||||||
|
CursorIcon::ResizeNwSe,
|
||||||
|
CursorIcon::ResizeVertical,
|
||||||
|
CursorIcon::ZoomIn,
|
||||||
|
CursorIcon::ZoomOut,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CursorIcon {
|
impl Default for CursorIcon {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
emath::{lerp, Align, Pos2, Rect, Vec2},
|
emath::{lerp, Align, Pos2, Rect, Vec2},
|
||||||
PointerButton, NUM_POINTER_BUTTONS,
|
CursorIcon, PointerButton, NUM_POINTER_BUTTONS,
|
||||||
};
|
};
|
||||||
use crate::{CtxRef, Id, LayerId, Sense, Ui};
|
use crate::{CtxRef, Id, LayerId, Sense, Ui};
|
||||||
|
|
||||||
|
@ -302,6 +302,14 @@ impl Response {
|
||||||
self.on_hover_text(text)
|
self.on_hover_text(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// When hovered, use this icon for the mouse cursor.
|
||||||
|
pub fn on_hover_cursor(self, cursor: CursorIcon) -> Self {
|
||||||
|
if self.hovered() {
|
||||||
|
self.ctx.output().cursor_icon = cursor;
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Check for more interactions (e.g. sense clicks on a `Response` returned from a label).
|
/// Check for more interactions (e.g. sense clicks on a `Response` returned from a label).
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -475,7 +475,7 @@ impl Widget for Plot {
|
||||||
prepared.ui(ui, &response);
|
prepared.ui(ui, &response);
|
||||||
}
|
}
|
||||||
|
|
||||||
response
|
response.on_hover_cursor(CursorIcon::Crosshair)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ impl Default for Demos {
|
||||||
Box::new(super::window_options::WindowOptions::default()),
|
Box::new(super::window_options::WindowOptions::default()),
|
||||||
Box::new(super::tests::WindowResizeTest::default()),
|
Box::new(super::tests::WindowResizeTest::default()),
|
||||||
// Tests:
|
// Tests:
|
||||||
|
Box::new(super::tests::CursorTest::default()),
|
||||||
Box::new(super::tests::IdTest::default()),
|
Box::new(super::tests::IdTest::default()),
|
||||||
Box::new(super::tests::InputTest::default()),
|
Box::new(super::tests::InputTest::default()),
|
||||||
Box::new(super::layout_test::LayoutTest::default()),
|
Box::new(super::layout_test::LayoutTest::default()),
|
||||||
|
|
|
@ -1,3 +1,34 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct CursorTest {}
|
||||||
|
|
||||||
|
impl super::Demo for CursorTest {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"Cursor Test"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show(&mut self, ctx: &egui::CtxRef, open: &mut bool) {
|
||||||
|
egui::Window::new(self.name()).open(open).show(ctx, |ui| {
|
||||||
|
use super::View;
|
||||||
|
self.ui(ui);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl super::View for CursorTest {
|
||||||
|
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
|
ui.heading("Hover to switch cursor icon:");
|
||||||
|
ui.vertical_centered_justified(|ui| {
|
||||||
|
for &cursor_icon in &egui::CursorIcon::ALL {
|
||||||
|
let _ = ui
|
||||||
|
.button(format!("{:?}", cursor_icon))
|
||||||
|
.on_hover_cursor(cursor_icon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct IdTest {}
|
pub struct IdTest {}
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
||||||
let mut previous_frame_time = None;
|
let mut previous_frame_time = None;
|
||||||
let mut painter = Painter::new(&display);
|
let mut painter = Painter::new(&display);
|
||||||
let mut clipboard = init_clipboard();
|
let mut clipboard = init_clipboard();
|
||||||
let mut previous_cursor_icon = None;
|
let mut current_cursor_icon = CursorIcon::Default;
|
||||||
|
|
||||||
#[cfg(feature = "persistence")]
|
#[cfg(feature = "persistence")]
|
||||||
let mut last_auto_save = Instant::now();
|
let mut last_auto_save = Instant::now();
|
||||||
|
@ -209,14 +209,10 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
||||||
ctx.clear_animations();
|
ctx.clear_animations();
|
||||||
|
|
||||||
let (egui_output, _shapes) = ctx.end_frame();
|
let (egui_output, _shapes) = ctx.end_frame();
|
||||||
let new_cursor_icon = egui_output.cursor_icon;
|
|
||||||
handle_output(egui_output, clipboard.as_mut());
|
|
||||||
|
|
||||||
display
|
set_cursor_icon(&display, egui_output.cursor_icon);
|
||||||
.gl_window()
|
current_cursor_icon = egui_output.cursor_icon;
|
||||||
.window()
|
handle_output(egui_output, clipboard.as_mut());
|
||||||
.set_cursor_icon(translate_cursor(new_cursor_icon));
|
|
||||||
previous_cursor_icon = Some(new_cursor_icon);
|
|
||||||
|
|
||||||
// TODO: handle app_output
|
// TODO: handle app_output
|
||||||
// eprintln!("Warmed up in {} ms", warm_up_start.elapsed().as_millis())
|
// eprintln!("Warmed up in {} ms", warm_up_start.elapsed().as_millis())
|
||||||
|
@ -285,18 +281,13 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_reader.speak(&egui_output.events_description());
|
screen_reader.speak(&egui_output.events_description());
|
||||||
let new_cursor_icon = egui_output.cursor_icon;
|
if current_cursor_icon != egui_output.cursor_icon {
|
||||||
handle_output(egui_output, clipboard.as_mut());
|
|
||||||
|
|
||||||
if Some(new_cursor_icon) != previous_cursor_icon {
|
|
||||||
// call only when changed to prevent flickering near frame boundary
|
// call only when changed to prevent flickering near frame boundary
|
||||||
// when Windows OS tries to control cursor icon for window resizing
|
// when Windows OS tries to control cursor icon for window resizing
|
||||||
display
|
set_cursor_icon(&display, egui_output.cursor_icon);
|
||||||
.gl_window()
|
current_cursor_icon = egui_output.cursor_icon;
|
||||||
.window()
|
|
||||||
.set_cursor_icon(translate_cursor(new_cursor_icon));
|
|
||||||
previous_cursor_icon = Some(new_cursor_icon);
|
|
||||||
}
|
}
|
||||||
|
handle_output(egui_output, clipboard.as_mut());
|
||||||
|
|
||||||
#[cfg(feature = "persistence")]
|
#[cfg(feature = "persistence")]
|
||||||
if let Some(storage) = &mut storage {
|
if let Some(storage) = &mut storage {
|
||||||
|
|
|
@ -263,17 +263,43 @@ pub fn translate_virtual_key_code(key: VirtualKeyCode) -> Option<egui::Key> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn translate_cursor(cursor_icon: egui::CursorIcon) -> glutin::window::CursorIcon {
|
fn translate_cursor(cursor_icon: egui::CursorIcon) -> Option<glutin::window::CursorIcon> {
|
||||||
match cursor_icon {
|
match cursor_icon {
|
||||||
CursorIcon::Default => glutin::window::CursorIcon::Default,
|
CursorIcon::None => None,
|
||||||
CursorIcon::PointingHand => glutin::window::CursorIcon::Hand,
|
|
||||||
CursorIcon::ResizeHorizontal => glutin::window::CursorIcon::EwResize,
|
CursorIcon::Alias => Some(glutin::window::CursorIcon::Alias),
|
||||||
CursorIcon::ResizeNeSw => glutin::window::CursorIcon::NeswResize,
|
CursorIcon::AllScroll => Some(glutin::window::CursorIcon::AllScroll),
|
||||||
CursorIcon::ResizeNwSe => glutin::window::CursorIcon::NwseResize,
|
CursorIcon::Cell => Some(glutin::window::CursorIcon::Cell),
|
||||||
CursorIcon::ResizeVertical => glutin::window::CursorIcon::NsResize,
|
CursorIcon::ContextMenu => Some(glutin::window::CursorIcon::ContextMenu),
|
||||||
CursorIcon::Text => glutin::window::CursorIcon::Text,
|
CursorIcon::Copy => Some(glutin::window::CursorIcon::Copy),
|
||||||
CursorIcon::Grab => glutin::window::CursorIcon::Grab,
|
CursorIcon::Crosshair => Some(glutin::window::CursorIcon::Crosshair),
|
||||||
CursorIcon::Grabbing => glutin::window::CursorIcon::Grabbing,
|
CursorIcon::Default => Some(glutin::window::CursorIcon::Default),
|
||||||
|
CursorIcon::Grab => Some(glutin::window::CursorIcon::Grab),
|
||||||
|
CursorIcon::Grabbing => Some(glutin::window::CursorIcon::Grabbing),
|
||||||
|
CursorIcon::Help => Some(glutin::window::CursorIcon::Help),
|
||||||
|
CursorIcon::Move => Some(glutin::window::CursorIcon::Move),
|
||||||
|
CursorIcon::NoDrop => Some(glutin::window::CursorIcon::NoDrop),
|
||||||
|
CursorIcon::NotAllowed => Some(glutin::window::CursorIcon::NotAllowed),
|
||||||
|
CursorIcon::PointingHand => Some(glutin::window::CursorIcon::Hand),
|
||||||
|
CursorIcon::Progress => Some(glutin::window::CursorIcon::Progress),
|
||||||
|
CursorIcon::ResizeHorizontal => Some(glutin::window::CursorIcon::EwResize),
|
||||||
|
CursorIcon::ResizeNeSw => Some(glutin::window::CursorIcon::NeswResize),
|
||||||
|
CursorIcon::ResizeNwSe => Some(glutin::window::CursorIcon::NwseResize),
|
||||||
|
CursorIcon::ResizeVertical => Some(glutin::window::CursorIcon::NsResize),
|
||||||
|
CursorIcon::Text => Some(glutin::window::CursorIcon::Text),
|
||||||
|
CursorIcon::VerticalText => Some(glutin::window::CursorIcon::VerticalText),
|
||||||
|
CursorIcon::Wait => Some(glutin::window::CursorIcon::Wait),
|
||||||
|
CursorIcon::ZoomIn => Some(glutin::window::CursorIcon::ZoomIn),
|
||||||
|
CursorIcon::ZoomOut => Some(glutin::window::CursorIcon::ZoomOut),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_cursor_icon(display: &glium::backend::glutin::Display, cursor_icon: egui::CursorIcon) {
|
||||||
|
if let Some(cursor_icon) = translate_cursor(cursor_icon) {
|
||||||
|
display.gl_window().window().set_cursor_visible(true);
|
||||||
|
display.gl_window().window().set_cursor_icon(cursor_icon);
|
||||||
|
} else {
|
||||||
|
display.gl_window().window().set_cursor_visible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -283,20 +283,32 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor_web_name(cursor: egui::CursorIcon) -> &'static str {
|
fn cursor_web_name(cursor: egui::CursorIcon) -> &'static str {
|
||||||
use egui::CursorIcon::*;
|
|
||||||
match cursor {
|
match cursor {
|
||||||
Default => "default",
|
egui::CursorIcon::Alias => "alias",
|
||||||
PointingHand => "pointer",
|
egui::CursorIcon::AllScroll => "all-scroll",
|
||||||
ResizeHorizontal => "ew-resize",
|
egui::CursorIcon::Cell => "cell",
|
||||||
ResizeNeSw => "nesw-resize",
|
egui::CursorIcon::ContextMenu => "context-menu",
|
||||||
ResizeNwSe => "nwse-resize",
|
egui::CursorIcon::Copy => "copy",
|
||||||
ResizeVertical => "ns-resize",
|
egui::CursorIcon::Crosshair => "crosshair",
|
||||||
Text => "text",
|
egui::CursorIcon::Default => "default",
|
||||||
Grab => "grab",
|
egui::CursorIcon::Grab => "grab",
|
||||||
Grabbing => "grabbing",
|
egui::CursorIcon::Grabbing => "grabbing",
|
||||||
// "no-drop"
|
egui::CursorIcon::Help => "help",
|
||||||
// "not-allowed"
|
egui::CursorIcon::Move => "move",
|
||||||
// default, help, pointer, progress, wait, cell, crosshair, text, alias, copy, move
|
egui::CursorIcon::NoDrop => "no-drop",
|
||||||
|
egui::CursorIcon::None => "none",
|
||||||
|
egui::CursorIcon::NotAllowed => "not-allowed",
|
||||||
|
egui::CursorIcon::PointingHand => "pointer",
|
||||||
|
egui::CursorIcon::Progress => "progress",
|
||||||
|
egui::CursorIcon::ResizeHorizontal => "ew-resize",
|
||||||
|
egui::CursorIcon::ResizeNeSw => "nesw-resize",
|
||||||
|
egui::CursorIcon::ResizeNwSe => "nwse-resize",
|
||||||
|
egui::CursorIcon::ResizeVertical => "ns-resize",
|
||||||
|
egui::CursorIcon::Text => "text",
|
||||||
|
egui::CursorIcon::VerticalText => "vertical-text",
|
||||||
|
egui::CursorIcon::Wait => "wait",
|
||||||
|
egui::CursorIcon::ZoomIn => "zoom-in",
|
||||||
|
egui::CursorIcon::ZoomOut => "zoom-out",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue