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.
|
||||
///
|
||||
/// 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 {
|
||||
/// Normal cursor icon, whatever that is.
|
||||
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
|
||||
PointingHand,
|
||||
ResizeHorizontal,
|
||||
ResizeNeSw,
|
||||
ResizeNwSe,
|
||||
ResizeVertical,
|
||||
|
||||
/// Shows that processing is being done, but that the program is still interactive.
|
||||
Progress,
|
||||
|
||||
/// 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,
|
||||
/// 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,
|
||||
|
||||
/// You are grabbing the thing you are hovering
|
||||
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 {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
emath::{lerp, Align, Pos2, Rect, Vec2},
|
||||
PointerButton, NUM_POINTER_BUTTONS,
|
||||
CursorIcon, PointerButton, NUM_POINTER_BUTTONS,
|
||||
};
|
||||
use crate::{CtxRef, Id, LayerId, Sense, Ui};
|
||||
|
||||
|
@ -302,6 +302,14 @@ impl Response {
|
|||
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).
|
||||
///
|
||||
/// ```
|
||||
|
|
|
@ -475,7 +475,7 @@ impl Widget for Plot {
|
|||
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::tests::WindowResizeTest::default()),
|
||||
// Tests:
|
||||
Box::new(super::tests::CursorTest::default()),
|
||||
Box::new(super::tests::IdTest::default()),
|
||||
Box::new(super::tests::InputTest::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)]
|
||||
pub struct IdTest {}
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
|||
let mut previous_frame_time = None;
|
||||
let mut painter = Painter::new(&display);
|
||||
let mut clipboard = init_clipboard();
|
||||
let mut previous_cursor_icon = None;
|
||||
let mut current_cursor_icon = CursorIcon::Default;
|
||||
|
||||
#[cfg(feature = "persistence")]
|
||||
let mut last_auto_save = Instant::now();
|
||||
|
@ -209,14 +209,10 @@ pub fn run(mut app: Box<dyn epi::App>) -> ! {
|
|||
ctx.clear_animations();
|
||||
|
||||
let (egui_output, _shapes) = ctx.end_frame();
|
||||
let new_cursor_icon = egui_output.cursor_icon;
|
||||
handle_output(egui_output, clipboard.as_mut());
|
||||
|
||||
display
|
||||
.gl_window()
|
||||
.window()
|
||||
.set_cursor_icon(translate_cursor(new_cursor_icon));
|
||||
previous_cursor_icon = Some(new_cursor_icon);
|
||||
set_cursor_icon(&display, egui_output.cursor_icon);
|
||||
current_cursor_icon = egui_output.cursor_icon;
|
||||
handle_output(egui_output, clipboard.as_mut());
|
||||
|
||||
// TODO: handle app_output
|
||||
// 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());
|
||||
let new_cursor_icon = egui_output.cursor_icon;
|
||||
handle_output(egui_output, clipboard.as_mut());
|
||||
|
||||
if Some(new_cursor_icon) != previous_cursor_icon {
|
||||
if current_cursor_icon != egui_output.cursor_icon {
|
||||
// call only when changed to prevent flickering near frame boundary
|
||||
// when Windows OS tries to control cursor icon for window resizing
|
||||
display
|
||||
.gl_window()
|
||||
.window()
|
||||
.set_cursor_icon(translate_cursor(new_cursor_icon));
|
||||
previous_cursor_icon = Some(new_cursor_icon);
|
||||
set_cursor_icon(&display, egui_output.cursor_icon);
|
||||
current_cursor_icon = egui_output.cursor_icon;
|
||||
}
|
||||
handle_output(egui_output, clipboard.as_mut());
|
||||
|
||||
#[cfg(feature = "persistence")]
|
||||
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 {
|
||||
CursorIcon::Default => glutin::window::CursorIcon::Default,
|
||||
CursorIcon::PointingHand => glutin::window::CursorIcon::Hand,
|
||||
CursorIcon::ResizeHorizontal => glutin::window::CursorIcon::EwResize,
|
||||
CursorIcon::ResizeNeSw => glutin::window::CursorIcon::NeswResize,
|
||||
CursorIcon::ResizeNwSe => glutin::window::CursorIcon::NwseResize,
|
||||
CursorIcon::ResizeVertical => glutin::window::CursorIcon::NsResize,
|
||||
CursorIcon::Text => glutin::window::CursorIcon::Text,
|
||||
CursorIcon::Grab => glutin::window::CursorIcon::Grab,
|
||||
CursorIcon::Grabbing => glutin::window::CursorIcon::Grabbing,
|
||||
CursorIcon::None => None,
|
||||
|
||||
CursorIcon::Alias => Some(glutin::window::CursorIcon::Alias),
|
||||
CursorIcon::AllScroll => Some(glutin::window::CursorIcon::AllScroll),
|
||||
CursorIcon::Cell => Some(glutin::window::CursorIcon::Cell),
|
||||
CursorIcon::ContextMenu => Some(glutin::window::CursorIcon::ContextMenu),
|
||||
CursorIcon::Copy => Some(glutin::window::CursorIcon::Copy),
|
||||
CursorIcon::Crosshair => Some(glutin::window::CursorIcon::Crosshair),
|
||||
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 {
|
||||
use egui::CursorIcon::*;
|
||||
match cursor {
|
||||
Default => "default",
|
||||
PointingHand => "pointer",
|
||||
ResizeHorizontal => "ew-resize",
|
||||
ResizeNeSw => "nesw-resize",
|
||||
ResizeNwSe => "nwse-resize",
|
||||
ResizeVertical => "ns-resize",
|
||||
Text => "text",
|
||||
Grab => "grab",
|
||||
Grabbing => "grabbing",
|
||||
// "no-drop"
|
||||
// "not-allowed"
|
||||
// default, help, pointer, progress, wait, cell, crosshair, text, alias, copy, move
|
||||
egui::CursorIcon::Alias => "alias",
|
||||
egui::CursorIcon::AllScroll => "all-scroll",
|
||||
egui::CursorIcon::Cell => "cell",
|
||||
egui::CursorIcon::ContextMenu => "context-menu",
|
||||
egui::CursorIcon::Copy => "copy",
|
||||
egui::CursorIcon::Crosshair => "crosshair",
|
||||
egui::CursorIcon::Default => "default",
|
||||
egui::CursorIcon::Grab => "grab",
|
||||
egui::CursorIcon::Grabbing => "grabbing",
|
||||
egui::CursorIcon::Help => "help",
|
||||
egui::CursorIcon::Move => "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