mirror of
https://github.com/griffi-gh/hUI.git
synced 2024-11-25 00:18:41 -06:00
update interactable
This commit is contained in:
parent
01b30c5979
commit
bd0364bde9
|
@ -41,10 +41,7 @@ ui_main!(
|
||||||
Text::new("-")
|
Text::new("-")
|
||||||
.add_child(ui);
|
.add_child(ui);
|
||||||
})
|
})
|
||||||
.into_interactable()
|
.on_click(CounterSignal::Increment)
|
||||||
.on_click(|| {
|
|
||||||
println!("clicked");
|
|
||||||
})
|
|
||||||
.add_child(ui);
|
.add_child(ui);
|
||||||
Text::new(counter.to_string())
|
Text::new(counter.to_string())
|
||||||
.with_color(color::BLACK)
|
.with_color(color::BLACK)
|
||||||
|
@ -58,10 +55,7 @@ ui_main!(
|
||||||
Text::new("+")
|
Text::new("+")
|
||||||
.add_child(ui);
|
.add_child(ui);
|
||||||
})
|
})
|
||||||
.into_interactable()
|
.on_click(CounterSignal::Decrement)
|
||||||
.on_click(|| {
|
|
||||||
println!("clicked");
|
|
||||||
})
|
|
||||||
.add_child(ui);
|
.add_child(ui);
|
||||||
})
|
})
|
||||||
.add_root(ui, size);
|
.add_root(ui, size);
|
||||||
|
|
|
@ -5,51 +5,43 @@
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
element::{MeasureContext, ProcessContext, UiElement},
|
element::{MeasureContext, ProcessContext, UiElement},
|
||||||
signal::{DummySignal, UiSignal},
|
signal::UiSignal,
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
#[non_exhaustive]
|
||||||
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
|
||||||
|
pub enum InteractableEvent {
|
||||||
|
#[default]
|
||||||
|
Click,
|
||||||
|
Hover,
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper that allows adding click and hover events to any element
|
/// Wrapper that allows adding click and hover events to any element
|
||||||
pub struct Interactable<H: UiSignal + 'static = DummySignal, C: UiSignal + 'static = DummySignal> {
|
pub struct Interactable<C: UiSignal + 'static> {
|
||||||
/// The wrapped element that will be interactable
|
/// The wrapped element that will be interactable
|
||||||
pub element: Box<dyn UiElement>,
|
pub element: Box<dyn UiElement>,
|
||||||
|
|
||||||
/// Signal that will be called if the element is hovered in the current frame
|
/// Event to listen for
|
||||||
///
|
pub event: InteractableEvent,
|
||||||
/// Will be consumed after the first time it's called
|
|
||||||
pub hovered: RefCell<Option<H>>,
|
|
||||||
|
|
||||||
/// Signal that will be called if the element was clicked in the current frame
|
/// Signal that will be called if the element was clicked in the current frame
|
||||||
///
|
///
|
||||||
/// Will be consumed after the first time it's called
|
/// Will be consumed after the first time it's called
|
||||||
pub clicked: RefCell<Option<C>>,
|
pub signal: RefCell<Option<C>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<H: UiSignal, C: UiSignal> Interactable<H, C> {
|
impl<C: UiSignal + 'static> Interactable<C> {
|
||||||
pub fn new(element: Box<dyn UiElement>) -> Self {
|
pub fn new(element: Box<dyn UiElement>, event: InteractableEvent, signal: C) -> Self {
|
||||||
Self {
|
Self {
|
||||||
element,
|
element,
|
||||||
hovered: RefCell::new(None),
|
event: InteractableEvent::Click,
|
||||||
clicked: RefCell::new(None),
|
signal: RefCell::new(Some(signal)),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_hover(self, hover: H) -> Self {
|
|
||||||
Self {
|
|
||||||
hovered: RefCell::new(Some(hover)),
|
|
||||||
..self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_click(self, clicked: C) -> Self {
|
|
||||||
Self {
|
|
||||||
clicked: RefCell::new(Some(clicked)),
|
|
||||||
..self
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiElement for Interactable {
|
impl<C: UiSignal + 'static> UiElement for Interactable<C> {
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"Interactable"
|
"Interactable"
|
||||||
}
|
}
|
||||||
|
@ -62,9 +54,8 @@ impl UiElement for Interactable {
|
||||||
let rect = ctx.measure.rect(ctx.layout.position);
|
let rect = ctx.measure.rect(ctx.layout.position);
|
||||||
|
|
||||||
//XXX: should we do this AFTER normal process call of wrapped element?
|
//XXX: should we do this AFTER normal process call of wrapped element?
|
||||||
//TODO other events...
|
|
||||||
if ctx.input.check_click(rect) {
|
if ctx.input.check_click(rect) {
|
||||||
if let Some(sig) = self.clicked.take() {
|
if let Some(sig) = self.signal.take() {
|
||||||
//ctx.signal.push(sig);
|
//ctx.signal.push(sig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,11 +65,21 @@ impl UiElement for Interactable {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ElementInteractableExt: UiElement {
|
pub trait ElementInteractableExt: UiElement {
|
||||||
fn into_interactable(self) -> Interactable;
|
fn into_interactable<C: UiSignal + 'static>(self, event: InteractableEvent, signal: C) -> Interactable<C>;
|
||||||
|
fn on_click<C: UiSignal + 'static>(self, signal: C) -> Interactable<C>;
|
||||||
|
fn on_hover<C: UiSignal + 'static>(self, signal: C) -> Interactable<C>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: UiElement + 'static> ElementInteractableExt for T {
|
impl<T: UiElement + 'static> ElementInteractableExt for T {
|
||||||
fn into_interactable(self) -> Interactable {
|
fn into_interactable<C: UiSignal + 'static>(self, event: InteractableEvent, signal: C) -> Interactable<C> {
|
||||||
Interactable::new(Box::new(self))
|
Interactable::new(Box::new(self), event, signal)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_click<C: UiSignal + 'static>(self, signal: C) -> Interactable<C> {
|
||||||
|
self.into_interactable(InteractableEvent::Click, signal)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_hover<C: UiSignal + 'static>(self, signal: C) -> Interactable<C> {
|
||||||
|
self.into_interactable(InteractableEvent::Hover, signal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue