use crate::{
fyrox::{
core::{log::Log, pool::Handle},
fxhash::FxHashMap,
graph::constructor::{VariantConstructor, VariantResult},
gui::{
constructor::WidgetConstructorContainer, menu::MenuItemMessage, message::UiMessage,
BuildContext, UiNode, UserInterface,
},
},
menu::create_menu_item,
message::MessageSender,
scene::Selection,
ui_scene::{commands::graph::AddWidgetCommand, UiScene},
};
use fyrox::core::{uuid, Uuid};
use fyrox::gui::menu::{MenuItem, SortingPredicate};
pub struct UiMenu {
pub menu: Handle<MenuItem>,
constructor_views: FxHashMap<Handle<MenuItem>, VariantConstructor<UiNode, UserInterface>>,
}
impl UiMenu {
pub const MENU: Uuid = uuid!("3a3f7035-529e-4d79-a413-a4d887d5e32e");
pub fn new(
constructors: &WidgetConstructorContainer,
name: &str,
ctx: &mut BuildContext,
) -> Self {
let mut root_items = vec![];
let mut groups = FxHashMap::default();
let mut constructor_views = FxHashMap::default();
let constructors = constructors.map();
for constructor in constructors.values() {
for variant in constructor.variants.iter() {
let item = create_menu_item(&variant.name, Uuid::new_v4(), vec![], ctx);
constructor_views.insert(item, variant.constructor.clone());
if constructor.group.is_empty() {
root_items.push(item);
} else {
let group = *groups.entry(constructor.group).or_insert_with(|| {
let group =
create_menu_item(constructor.group, Uuid::new_v4(), vec![], ctx);
root_items.push(group);
group
});
ctx.inner().send(group, MenuItemMessage::AddItem(item));
}
}
}
let menu = create_menu_item(name, Self::MENU, root_items.clone(), ctx);
for root_item in root_items.iter().chain(&[menu]) {
ctx.inner().send(
*root_item,
MenuItemMessage::Sort(SortingPredicate::sort_by_text()),
)
}
Self {
menu,
constructor_views,
}
}
pub fn handle_ui_message(
&mut self,
sender: &MessageSender,
message: &UiMessage,
scene: &mut UiScene,
selection: &Selection,
) {
if let Some(MenuItemMessage::Click) = message.data::<MenuItemMessage>() {
if let Some(constructor) = self
.constructor_views
.get_mut(&message.destination().to_variant())
{
if let VariantResult::Handle(ui_node_handle) = constructor(&mut scene.ui) {
let sub_graph = scene.ui.take_reserve_sub_graph(ui_node_handle);
let parent = if let Some(selection) = selection.as_ui() {
selection.widgets.first().cloned().unwrap_or_default()
} else {
Handle::NONE
};
sender.do_command(AddWidgetCommand::new(sub_graph, parent, true));
} else {
Log::err("Unsupported");
}
}
}
}
}