use crate::{lerp, math::Rect, Align, CtxRef, Id, LayerId, Ui};
#[derive(Clone, Default)]
pub struct Output {
pub cursor_icon: CursorIcon,
pub open_url: Option<String>,
pub copied_text: String,
pub needs_repaint: bool,
}
#[derive(Clone, Copy)]
pub enum CursorIcon {
Default,
PointingHand,
ResizeHorizontal,
ResizeNeSw,
ResizeNwSe,
ResizeVertical,
Text,
Grab,
Grabbing,
}
impl Default for CursorIcon {
fn default() -> Self {
Self::Default
}
}
#[derive(Clone)]
pub struct Response {
pub ctx: CtxRef,
pub layer_id: LayerId,
pub id: Id,
pub rect: Rect,
pub sense: Sense,
pub hovered: bool,
pub clicked: bool,
pub double_clicked: bool,
pub active: bool,
pub has_kb_focus: bool,
pub lost_kb_focus: bool,
}
impl std::fmt::Debug for Response {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self {
ctx: _,
layer_id,
id,
rect,
sense,
hovered,
clicked,
double_clicked,
active,
has_kb_focus,
lost_kb_focus,
} = self;
f.debug_struct("Response")
.field("layer_id", layer_id)
.field("id", id)
.field("rect", rect)
.field("sense", sense)
.field("hovered", hovered)
.field("clicked", clicked)
.field("double_clicked", double_clicked)
.field("active", active)
.field("has_kb_focus", has_kb_focus)
.field("lost_kb_focus", lost_kb_focus)
.finish()
}
}
impl Response {
pub fn on_hover_ui(self, add_contents: impl FnOnce(&mut Ui)) -> Self {
if self.hovered || self.ctx.memory().everything_is_visible() {
crate::containers::show_tooltip(&self.ctx, add_contents);
}
self
}
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)
}
pub fn interact(&self, sense: Sense) -> Self {
self.ctx
.interact_with_hovered(self.layer_id, self.id, self.rect, sense, self.hovered)
}
pub fn scroll_to_me(&self, align: Align) {
let scroll_target = lerp(self.rect.y_range(), align.scroll_center_factor());
self.ctx.frame_state().scroll_target = Some((scroll_target, align));
}
}
impl Response {
pub fn union(&self, other: Self) -> Self {
assert!(self.ctx == other.ctx);
debug_assert_eq!(
self.layer_id, other.layer_id,
"It makes no sense to combine Responses from two different layers"
);
Self {
ctx: other.ctx,
layer_id: self.layer_id,
id: self.id,
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,
lost_kb_focus: self.lost_kb_focus || other.lost_kb_focus,
}
}
}
impl std::ops::BitOr for Response {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
self.union(rhs)
}
}
impl std::ops::BitOrAssign for Response {
fn bitor_assign(&mut self, rhs: Self) {
*self = self.union(rhs);
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Sense {
pub click: bool,
pub drag: bool,
}
impl Sense {
pub fn hover() -> Self {
Self {
click: false,
drag: false,
}
}
#[deprecated = "Use hover()"]
pub fn nothing() -> Self {
Sense::hover()
}
pub fn click() -> Self {
Self {
click: true,
drag: false,
}
}
pub fn drag() -> Self {
Self {
click: false,
drag: true,
}
}
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,
}
}
}