mod management;
#[cfg(not(target_arch = "wasm32"))]
mod persistence;
mod rendering;
#[cfg(not(target_arch = "wasm32"))]
pub use persistence::format_window_title;
use super::behavior::TileBehavior;
use super::config::MosaicConfig;
use super::project::WindowLayout;
use super::widget::{Pane, Widget};
use nightshade::prelude::*;
#[cfg(not(target_arch = "wasm32"))]
pub enum LayoutEvent {
Switched(String),
Created(String),
Saved(String),
Deleted(String),
Reset,
Renamed(String),
}
pub struct Mosaic<W: Widget<C, M>, C = (), M = ()> {
tile_tree: Option<egui_tiles::Tree<Pane<W>>>,
pub config: MosaicConfig,
pub(crate) behavior: TileBehavior<W, C, M>,
layout_modified: bool,
viewport_texture_overrides: Option<Vec<egui::TextureId>>,
pub is_active_window: bool,
pending_messages: Vec<M>,
incoming_messages: std::collections::HashMap<egui_tiles::TileId, Vec<M>>,
layouts: Vec<WindowLayout<W>>,
active_layout_index: usize,
editing_layout_index: Option<usize>,
layout_name_edit_buffer: String,
}
impl<W: Widget<C, M>, C, M> Default for Mosaic<W, C, M> {
fn default() -> Self {
Self {
tile_tree: None,
config: MosaicConfig::default(),
behavior: TileBehavior::default(),
layout_modified: false,
viewport_texture_overrides: None,
is_active_window: true,
pending_messages: Vec::new(),
incoming_messages: std::collections::HashMap::new(),
layouts: Vec::new(),
active_layout_index: 0,
editing_layout_index: None,
layout_name_edit_buffer: String::new(),
}
}
}
impl<W: Widget<C, M>, C, M> Mosaic<W, C, M> {
pub fn with_tree(tree: egui_tiles::Tree<Pane<W>>) -> Self {
Self {
tile_tree: Some(tree),
..Self::default()
}
}
pub fn set_tree(&mut self, tree: egui_tiles::Tree<Pane<W>>) {
self.tile_tree = Some(tree);
self.layout_modified = true;
}
pub fn current_tree(&self) -> Option<&egui_tiles::Tree<Pane<W>>> {
self.tile_tree.as_ref()
}
pub fn take_layout_modified(&mut self) -> bool {
let modified = self.layout_modified;
self.layout_modified = false;
modified
}
pub fn viewport_rects(&self) -> &std::collections::HashMap<egui_tiles::TileId, egui::Rect> {
&self.behavior.viewport_rects
}
pub fn clear_required_cameras(world: &mut World) {
world.resources.user_interface.required_cameras.clear();
world.resources.user_interface.required_camera_sizes.clear();
}
pub fn find_widget(&self, predicate: impl Fn(&W) -> bool) -> Option<egui_tiles::TileId> {
if let Some(tree) = &self.tile_tree {
for (tile_id, tile) in tree.tiles.iter() {
if let egui_tiles::Tile::Pane(pane) = tile
&& predicate(&pane.widget)
{
return Some(*tile_id);
}
}
}
None
}
pub fn get_widget_mut(&mut self, tile_id: egui_tiles::TileId) -> Option<&mut W> {
if let Some(tree) = &mut self.tile_tree
&& let Some(egui_tiles::Tile::Pane(pane)) = tree.tiles.get_mut(tile_id)
{
return Some(&mut pane.widget);
}
None
}
pub fn insert_pane(&mut self, widget: W) -> Option<egui_tiles::TileId> {
if let Some(tree) = &mut self.tile_tree {
let new_tile_id = tree.tiles.insert_pane(Pane::new(widget));
if let Some(root) = tree.root {
Self::add_to_container(&mut tree.tiles, root, new_tile_id);
}
self.layout_modified = true;
Some(new_tile_id)
} else {
let mut tiles = egui_tiles::Tiles::default();
let pane_id = tiles.insert_pane(Pane::new(widget));
let root = tiles.insert_tab_tile(vec![pane_id]);
self.tile_tree = Some(egui_tiles::Tree::new("mosaic_tree", root, tiles));
self.layout_modified = true;
Some(pane_id)
}
}
pub(crate) fn add_to_container(
tiles: &mut egui_tiles::Tiles<Pane<W>>,
container_id: egui_tiles::TileId,
child_id: egui_tiles::TileId,
) {
match tiles.get_mut(container_id) {
Some(egui_tiles::Tile::Container(egui_tiles::Container::Tabs(tabs))) => {
tabs.add_child(child_id);
tabs.set_active(child_id);
}
Some(egui_tiles::Tile::Container(egui_tiles::Container::Linear(linear))) => {
linear.add_child(child_id);
}
Some(egui_tiles::Tile::Container(egui_tiles::Container::Grid(grid))) => {
grid.add_child(child_id);
}
_ => {}
}
}
pub fn drain_messages(&mut self) -> Vec<M> {
self.pending_messages.drain(..).collect()
}
}