218 lines
6 KiB
Rust
218 lines
6 KiB
Rust
use std::sync::Arc;
|
|
|
|
use crate::{math::Rect, Context, Ui};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/// What Egui emits each frame.
|
|
/// The backend should use this.
|
|
#[derive(Clone, Default)]
|
|
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
|
pub struct Output {
|
|
/// Set the cursor to this icon.
|
|
pub cursor_icon: CursorIcon,
|
|
|
|
/// If set, open this url.
|
|
pub open_url: Option<String>,
|
|
|
|
/// Response to Event::Copy or Event::Cut. Ignore if empty.
|
|
pub copied_text: String,
|
|
|
|
/// If `true`, Egui or a user is indicating that the UI needs immediate repaint (e.g. on the next frame).
|
|
/// This happens for instance when there is an animation, or if a user has called `Context::request_repaint()`.
|
|
/// Don't set this manually, but call `Context::request_repaint()` instead.
|
|
pub needs_repaint: bool,
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
|
// #[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
|
pub enum CursorIcon {
|
|
Default,
|
|
/// Pointing hand, used for e.g. web links
|
|
PointingHand,
|
|
ResizeHorizontal,
|
|
ResizeNeSw,
|
|
ResizeNwSe,
|
|
ResizeVertical,
|
|
Text,
|
|
}
|
|
|
|
impl Default for CursorIcon {
|
|
fn default() -> Self {
|
|
Self::Default
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/// The result of adding a widget to an `Ui`.
|
|
///
|
|
/// This lets you know whether or not a widget has been clicked this frame.
|
|
/// It also lets you easily show a tooltip on hover.
|
|
#[derive(Clone)]
|
|
pub struct Response {
|
|
// CONTEXT:
|
|
/// Used for optionally showing a tooltip
|
|
pub ctx: Arc<Context>,
|
|
|
|
// IN:
|
|
/// The area of the screen we are talking about
|
|
pub rect: Rect,
|
|
|
|
/// The senses (click or drag) that the widget is interested in (if any).
|
|
pub sense: Sense,
|
|
|
|
// OUT:
|
|
/// The mouse is hovering above this
|
|
pub hovered: bool,
|
|
|
|
/// The mouse clicked this thing this frame
|
|
pub clicked: bool,
|
|
|
|
/// The thing was double-clicked
|
|
pub double_clicked: bool,
|
|
|
|
/// The mouse is interacting with this thing (e.g. dragging it)
|
|
pub active: bool,
|
|
|
|
/// This widget has the keyboard focus (i.e. is receiving key pressed)
|
|
pub has_kb_focus: bool,
|
|
}
|
|
|
|
impl std::fmt::Debug for Response {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.debug_struct("Response")
|
|
.field("rect", &self.rect)
|
|
.field("sense", &self.sense)
|
|
.field("hovered", &self.hovered)
|
|
.field("clicked", &self.clicked)
|
|
.field("double_clicked", &self.double_clicked)
|
|
.field("active", &self.active)
|
|
.field("has_kb_focus", &self.has_kb_focus)
|
|
.finish()
|
|
}
|
|
}
|
|
|
|
impl Response {
|
|
/// Show this UI if the item was hovered (i.e. a tooltip)
|
|
pub fn on_hover_ui(self, add_contents: impl FnOnce(&mut Ui)) -> Self {
|
|
if self.hovered {
|
|
crate::containers::show_tooltip(&self.ctx, add_contents);
|
|
}
|
|
self
|
|
}
|
|
|
|
/// Show this text if the item was hovered (i.e. a tooltip)
|
|
pub fn on_hover_text(self, text: impl Into<String>) -> Self {
|
|
self.on_hover_ui(|ui| {
|
|
ui.add(crate::widgets::Label::new(text));
|
|
})
|
|
}
|
|
|
|
#[deprecated = "Deprecated 2020-10-01: use `on_hover_text` instead."]
|
|
pub fn tooltip_text(self, text: impl Into<String>) -> Self {
|
|
self.on_hover_text(text)
|
|
}
|
|
}
|
|
|
|
impl Response {
|
|
/// A logical "or" operation.
|
|
/// For instance `a.union(b).hovered` means "was either a or b hovered?".
|
|
pub fn union(&self, other: Self) -> Self {
|
|
assert!(Arc::ptr_eq(&self.ctx, &other.ctx));
|
|
Self {
|
|
ctx: other.ctx,
|
|
rect: self.rect.union(other.rect),
|
|
sense: self.sense.union(other.sense),
|
|
hovered: self.hovered || other.hovered,
|
|
clicked: self.clicked || other.clicked,
|
|
double_clicked: self.double_clicked || other.double_clicked,
|
|
active: self.active || other.active,
|
|
has_kb_focus: self.has_kb_focus || other.has_kb_focus,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// To summarize the response from many widgets you can use this pattern:
|
|
///
|
|
/// ```
|
|
/// use egui::*;
|
|
/// fn draw_vec2(ui: &mut Ui, v: &mut Vec2) -> Response {
|
|
/// ui.add(DragValue::f32(&mut v.x)) | ui.add(DragValue::f32(&mut v.y))
|
|
/// }
|
|
/// ```
|
|
///
|
|
/// Now `draw_vec2(ui, foo).hovered` is true if either `DragValue` were hovered.
|
|
impl std::ops::BitOr for Response {
|
|
type Output = Self;
|
|
fn bitor(self, rhs: Self) -> Self {
|
|
self.union(rhs)
|
|
}
|
|
}
|
|
|
|
/// To summarize the response from many widgets you can use this pattern:
|
|
///
|
|
/// ``` ignore
|
|
/// let mut response = ui.add(some_widget);
|
|
/// response |= ui.add(some_other_widget);
|
|
/// response |= ui.add(some_widget);
|
|
/// if response.active { ui.label("You are interacting with one of the widgets"); }
|
|
/// ```
|
|
impl std::ops::BitOrAssign for Response {
|
|
fn bitor_assign(&mut self, rhs: Self) {
|
|
*self = self.union(rhs);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
/// What sort of interaction is a widget sensitive to?
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
// #[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
|
pub struct Sense {
|
|
/// buttons, sliders, windows ...
|
|
pub click: bool,
|
|
|
|
/// sliders, windows, scroll bars, scroll areas ...
|
|
pub drag: bool,
|
|
}
|
|
|
|
impl Sense {
|
|
pub fn nothing() -> Self {
|
|
Self {
|
|
click: false,
|
|
drag: false,
|
|
}
|
|
}
|
|
|
|
pub fn click() -> Self {
|
|
Self {
|
|
click: true,
|
|
drag: false,
|
|
}
|
|
}
|
|
|
|
pub fn drag() -> Self {
|
|
Self {
|
|
click: false,
|
|
drag: true,
|
|
}
|
|
}
|
|
|
|
/// e.g. a slider or window
|
|
pub fn click_and_drag() -> Self {
|
|
Self {
|
|
click: true,
|
|
drag: true,
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn union(self, other: Self) -> Self {
|
|
Self {
|
|
click: self.click | other.click,
|
|
drag: self.drag | other.drag,
|
|
}
|
|
}
|
|
}
|