wayvr/wlx-overlay-s/src/overlays/edit/sprite_tab.rs

130 lines
4.0 KiB
Rust

use std::{collections::HashMap, rc::Rc};
use wgui::{
components::button::ComponentButton, event::CallbackDataCommon, layout::WidgetID,
parser::Fetchable, renderer_vk::text::custom_glyph::CustomGlyphData,
widget::sprite::WidgetSprite,
};
use crate::{backend::task::ModifyOverlayTask, overlays::edit::EditModeWrapPanel};
pub trait SpriteTabKey {
fn to_tab_key(&self) -> &'static str;
fn from_tab_key(key: &str) -> Self;
}
struct SpriteTabButtonState<S> {
name: &'static str,
sprite: CustomGlyphData,
component: Rc<ComponentButton>,
state: S,
}
pub type SpriteTabHighlightChanged<S> = dyn Fn(&mut CallbackDataCommon, &S);
pub type SpriteTabButtonClicked<S> = dyn Fn(&mut CallbackDataCommon, &S) -> Box<ModifyOverlayTask>;
#[derive(Default)]
pub(super) struct SpriteTabHandler<S> {
top_sprite_id: WidgetID,
buttons: HashMap<&'static str, Rc<SpriteTabButtonState<S>>>,
active_button: Option<Rc<SpriteTabButtonState<S>>>,
on_highlight_changed: Option<Box<SpriteTabHighlightChanged<S>>>,
on_button_clicked: Option<Box<SpriteTabButtonClicked<S>>>,
}
impl<S> SpriteTabHandler<S>
where
S: SpriteTabKey,
{
pub fn new(
panel: &mut EditModeWrapPanel,
prefix: &str,
names: &[&'static str],
on_button_clicked: Box<SpriteTabButtonClicked<S>>,
on_highlight_changed: Option<Box<SpriteTabHighlightChanged<S>>>,
) -> anyhow::Result<Self> {
let mut buttons = HashMap::new();
for name in names {
let button_id = format!("{prefix}_{name}");
let component = panel.parser_state.fetch_component_as(&button_id)?;
let sprite_id = format!("{button_id}_sprite");
let id = panel.parser_state.get_widget_id(&sprite_id)?;
let sprite_w = panel
.layout
.state
.widgets
.get_as::<WidgetSprite>(id)
.ok_or_else(|| {
anyhow::anyhow!("Element with id=\"{sprite_id}\" must be a <sprite>")
})?;
let sprite = sprite_w.params.glyph_data.clone().ok_or_else(|| {
anyhow::anyhow!("Element with id=\"{sprite_id}\" must have a valid src!")
})?;
let state = S::from_tab_key(name);
buttons.insert(
*name,
Rc::new(SpriteTabButtonState {
name,
sprite,
component,
state,
}),
);
}
let top_sprite_id = panel
.parser_state
.get_widget_id(&format!("top_{prefix}_sprite"))?;
Ok(Self {
buttons,
active_button: None,
top_sprite_id,
on_highlight_changed,
on_button_clicked: Some(on_button_clicked),
})
}
fn change_highlight(&mut self, common: &mut CallbackDataCommon, key: &str) {
if let Some(old) = self.active_button.take() {
old.component.set_sticky_state(common, false);
}
let new = self.buttons.get_mut(key).unwrap();
new.component.set_sticky_state(common, true);
self.active_button = Some(new.clone());
if let Some(highlight_changed) = self.on_highlight_changed.as_ref() {
highlight_changed(common, &new.state);
}
// change top sprite
if let Some(mut sprite) = common
.state
.widgets
.get_as::<WidgetSprite>(self.top_sprite_id)
{
sprite.params.glyph_data = Some(new.sprite.clone());
}
}
pub fn button_clicked(
&mut self,
common: &mut CallbackDataCommon,
key: &str,
) -> Box<ModifyOverlayTask> {
self.change_highlight(common, key);
let state = S::from_tab_key(key);
self.on_button_clicked.as_ref().unwrap()(common, &state)
}
pub fn reset(&mut self, common: &mut CallbackDataCommon, state: &S) {
let key = state.to_tab_key();
self.change_highlight(common, key);
}
}