use egui::{
Button, Color32, Frame, InnerResponse, KeyboardShortcut, Response, Stroke, Ui, UiBuilder,
};
use gled_model::asset::scene::grid::GridLocation;
pub(crate) mod animation_editor;
pub(crate) mod asset;
pub(crate) mod asset_preview;
pub(crate) mod asset_tree;
pub(crate) mod color;
pub(crate) mod curve_editor;
pub(crate) mod effect;
pub(crate) mod file_pick;
pub(crate) mod frame_requests;
pub(crate) mod gled_slider;
pub(crate) mod input;
pub(crate) mod layout_selection;
pub(crate) mod local_action;
pub(crate) mod logo;
pub(crate) mod multiplied_curve;
pub(crate) mod pills;
pub(crate) mod project_edits;
pub(crate) mod scene_effect_editor;
pub(crate) mod scene_instance;
pub mod temperature;
#[cfg(not(debug_assertions))]
#[cfg(not(target_arch = "wasm32"))]
pub mod update_check;
pub mod window_common;
pub(crate) mod windows;
pub(crate) static FRAME_STROKE: Stroke = Stroke {
width: 0.3,
color: Color32::WHITE,
};
pub(crate) trait ChangeButton {
fn change_button(&mut self, ui: &mut Ui) -> bool;
}
impl ChangeButton for f32 {
fn change_button(&mut self, ui: &mut Ui) -> bool {
let mut changed = false;
let response = ui.add(egui::Slider::new(self, 0.0..=1.0));
if response.changed() {
changed = true;
}
changed
}
}
pub(crate) trait OverwriteChangeButton: Default + ChangeButton {
const NAME: &'static str;
}
impl<T: OverwriteChangeButton> ChangeButton for Option<T> {
fn change_button(&mut self, ui: &mut Ui) -> bool {
let mut changed = false;
let mut overwrite = self.is_some();
ui.checkbox(&mut overwrite, format!("Overwrite {}", T::NAME));
if self.is_none() && overwrite {
*self = Some(T::default());
changed = true;
} else if self.is_some() && !overwrite {
*self = None;
changed = true;
}
if let Some(asset_id) = self {
ui.vertical_centered_justified(|ui| {
changed |= asset_id.change_button(ui);
});
}
changed
}
}
pub(crate) fn row_cell_width(ui: &Ui, cells: usize, margin: f32) -> f32 {
let cells = cells.max(1) as f32;
let spacing = ui.spacing().item_spacing.x * (cells - 1.0);
((ui.available_width() - spacing) / cells - 2.0 * margin)
.floor()
.max(0.0)
}
pub(crate) fn scoped_frame<T>(
ui: &mut Ui,
ui_builder: UiBuilder,
frame: Frame,
add_contents: impl FnOnce(&mut Ui) -> T,
) -> InnerResponse<T> {
ui.scope_builder(ui_builder, |ui| {
frame
.show(ui, |ui| {
ui.take_available_space();
add_contents(ui)
})
.inner
})
}
#[derive(Debug)]
pub(crate) struct ContextMenuAction {
pub(crate) keyboard_shortcut: KeyboardShortcut,
pub(crate) description: String,
pub(crate) ctx_action: fn(GridLocation),
pub(crate) key_action: fn(),
}
#[derive(Debug, Default)]
pub(crate) struct ContextMenuBuilder {
actions: Vec<ContextMenuAction>,
}
impl ContextMenuBuilder {
pub(crate) fn add_action(mut self, action: ContextMenuAction) -> Self {
self.actions.push(action);
self
}
pub(crate) fn show(self, response: &mut Response, location: GridLocation) {
response.context_menu(|ctx_menu_ui| {
for action in &self.actions {
let context_button = Button::new(action.description.to_string())
.shortcut_text(ctx_menu_ui.ctx().format_shortcut(&action.keyboard_shortcut));
if ctx_menu_ui.add(context_button).clicked() {
(action.ctx_action)(location);
return;
}
}
});
for action in &self.actions {
if !response.ctx.egui_wants_keyboard_input()
&& response
.ctx
.input_mut(|i| i.consume_shortcut(&action.keyboard_shortcut))
{
(action.key_action)();
}
}
}
}