mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
Merge branch 'master' into popup2
This commit is contained in:
@@ -42,6 +42,7 @@ use crate::{
|
||||
message::MessageSender,
|
||||
send_sync_message,
|
||||
};
|
||||
use fyrox::gui::menu::ContextMenuBuilder;
|
||||
use std::{
|
||||
cell::Cell,
|
||||
fmt::{Debug, Formatter},
|
||||
@@ -486,8 +487,8 @@ impl BlendSpaceFieldBuilder {
|
||||
fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
|
||||
let add_point;
|
||||
let remove_point;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
@@ -500,8 +501,9 @@ impl BlendSpaceFieldBuilder {
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
let field = BlendSpaceField {
|
||||
|
||||
@@ -27,6 +27,7 @@ use crate::{
|
||||
message::MessageSender,
|
||||
scene::{commands::ChangeSelectionCommand, Selection},
|
||||
};
|
||||
use fyrox::gui::menu::ContextMenuBuilder;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use super::fetch_state_node_model_handle;
|
||||
@@ -43,8 +44,8 @@ impl CanvasContextMenu {
|
||||
pub fn new(ctx: &mut BuildContext) -> Self {
|
||||
let create_state;
|
||||
let connect_all_nodes;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(WidgetBuilder::new().with_children([
|
||||
{
|
||||
create_state = create_menu_item("Create State", vec![], ctx);
|
||||
@@ -56,8 +57,9 @@ impl CanvasContextMenu {
|
||||
},
|
||||
]))
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
@@ -145,8 +147,8 @@ impl NodeContextMenu {
|
||||
let set_as_entry_state;
|
||||
let enter_state;
|
||||
let connect_to_all_nodes;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
@@ -176,8 +178,9 @@ impl NodeContextMenu {
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
@@ -319,15 +322,16 @@ pub struct TransitionContextMenu {
|
||||
impl TransitionContextMenu {
|
||||
pub fn new(ctx: &mut BuildContext) -> Self {
|
||||
let remove;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(WidgetBuilder::new().with_child({
|
||||
remove = create_menu_item("Remove Transition", vec![], ctx);
|
||||
remove
|
||||
}))
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
|
||||
@@ -33,6 +33,7 @@ use crate::{
|
||||
message::MessageSender,
|
||||
scene::{commands::ChangeSelectionCommand, Selection},
|
||||
};
|
||||
use fyrox::gui::menu::ContextMenuBuilder;
|
||||
|
||||
pub struct CanvasContextMenu {
|
||||
create_play_animation: Handle<UiNode>,
|
||||
@@ -50,32 +51,35 @@ impl CanvasContextMenu {
|
||||
let create_blend_animations;
|
||||
let create_blend_by_index;
|
||||
let create_blend_space;
|
||||
let menu = PopupBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_enabled(false) // Disabled by default.
|
||||
.with_visibility(false),
|
||||
)
|
||||
.with_content(
|
||||
StackPanelBuilder::new(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
create_play_animation = create_menu_item("Play Animation", vec![], ctx);
|
||||
create_play_animation
|
||||
})
|
||||
.with_child({
|
||||
create_blend_animations = create_menu_item("Blend Animations", vec![], ctx);
|
||||
create_blend_animations
|
||||
})
|
||||
.with_child({
|
||||
create_blend_by_index = create_menu_item("Blend By Index", vec![], ctx);
|
||||
create_blend_by_index
|
||||
})
|
||||
.with_child({
|
||||
create_blend_space = create_menu_item("Blend Space", vec![], ctx);
|
||||
create_blend_space
|
||||
}),
|
||||
.with_enabled(false) // Disabled by default.
|
||||
.with_visibility(false),
|
||||
)
|
||||
.build(ctx),
|
||||
.with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
create_play_animation = create_menu_item("Play Animation", vec![], ctx);
|
||||
create_play_animation
|
||||
})
|
||||
.with_child({
|
||||
create_blend_animations =
|
||||
create_menu_item("Blend Animations", vec![], ctx);
|
||||
create_blend_animations
|
||||
})
|
||||
.with_child({
|
||||
create_blend_by_index = create_menu_item("Blend By Index", vec![], ctx);
|
||||
create_blend_by_index
|
||||
})
|
||||
.with_child({
|
||||
create_blend_space = create_menu_item("Blend Space", vec![], ctx);
|
||||
create_blend_space
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
@@ -187,8 +191,8 @@ impl NodeContextMenu {
|
||||
pub fn new(ctx: &mut BuildContext) -> Self {
|
||||
let remove;
|
||||
let set_as_root;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
@@ -201,8 +205,9 @@ impl NodeContextMenu {
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
@@ -279,15 +284,16 @@ pub struct ConnectionContextMenu {
|
||||
impl ConnectionContextMenu {
|
||||
pub fn new(ctx: &mut BuildContext) -> Self {
|
||||
let remove;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(WidgetBuilder::new().with_child({
|
||||
remove = create_menu_item("Remove Connection", vec![], ctx);
|
||||
remove
|
||||
}))
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
|
||||
@@ -24,6 +24,7 @@ use crate::fyrox::{
|
||||
},
|
||||
};
|
||||
use crate::menu::create_menu_item;
|
||||
use fyrox::gui::menu::ContextMenuBuilder;
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
fmt::{Debug, Formatter},
|
||||
@@ -65,8 +66,8 @@ impl ContextMenu {
|
||||
fn new(ctx: &mut BuildContext) -> Self {
|
||||
let add_signal;
|
||||
let remove_signal;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
@@ -79,8 +80,9 @@ impl ContextMenu {
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
|
||||
@@ -72,6 +72,7 @@ use crate::{
|
||||
},
|
||||
send_sync_message, utils,
|
||||
};
|
||||
use fyrox::gui::menu::ContextMenuBuilder;
|
||||
use std::{
|
||||
any::TypeId,
|
||||
cmp::Ordering,
|
||||
@@ -105,8 +106,8 @@ impl TrackContextMenu {
|
||||
let set_target;
|
||||
let rebind;
|
||||
let duplicate;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
@@ -127,8 +128,9 @@ impl TrackContextMenu {
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
|
||||
@@ -52,6 +52,7 @@ use crate::{
|
||||
Message, Mode,
|
||||
};
|
||||
use fyrox::core::parking_lot::RwLock;
|
||||
use fyrox::gui::menu::ContextMenuBuilder;
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
path::{Path, PathBuf},
|
||||
@@ -111,8 +112,8 @@ impl ContextMenu {
|
||||
let copy_path;
|
||||
let copy_file_name;
|
||||
let dependencies;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new())
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new()).with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
@@ -153,8 +154,9 @@ impl ContextMenu {
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
|
||||
+6
-4
@@ -28,6 +28,7 @@ use crate::{
|
||||
gui::{make_dropdown_list_option, make_image_button_with_tooltip},
|
||||
load_image, Brush, Color, DropdownListBuilder, Engine,
|
||||
};
|
||||
use fyrox::gui::menu::ContextMenuBuilder;
|
||||
use std::sync::mpsc::Receiver;
|
||||
|
||||
struct ContextMenu {
|
||||
@@ -39,8 +40,8 @@ struct ContextMenu {
|
||||
impl ContextMenu {
|
||||
pub fn new(ctx: &mut BuildContext) -> Self {
|
||||
let copy;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new())
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new()).with_content(
|
||||
StackPanelBuilder::new(WidgetBuilder::new().with_child({
|
||||
copy = MenuItemBuilder::new(WidgetBuilder::new())
|
||||
.with_content(MenuItemContent::text("Copy"))
|
||||
@@ -48,8 +49,9 @@ impl ContextMenu {
|
||||
copy
|
||||
}))
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
Self {
|
||||
|
||||
@@ -50,6 +50,7 @@ use crate::{
|
||||
scene::commands::material::{SetMaterialPropertyValueCommand, SetMaterialShaderCommand},
|
||||
send_sync_message, Engine, Message,
|
||||
};
|
||||
use fyrox::gui::menu::ContextMenuBuilder;
|
||||
use std::{path::Path, sync::Arc};
|
||||
|
||||
struct TextureContextMenu {
|
||||
@@ -63,8 +64,8 @@ impl TextureContextMenu {
|
||||
fn new(ctx: &mut BuildContext) -> Self {
|
||||
let show_in_asset_browser;
|
||||
let unassign;
|
||||
let popup = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let popup = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
@@ -81,8 +82,9 @@ impl TextureContextMenu {
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let popup = RcUiNodeHandle::new(popup, ctx.sender());
|
||||
|
||||
Self {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::menu::ContextMenuBuilder;
|
||||
use crate::{
|
||||
brush::Brush,
|
||||
core::{
|
||||
@@ -1310,8 +1311,8 @@ impl CurveEditorBuilder {
|
||||
let key_properties;
|
||||
let key_value;
|
||||
let key_location;
|
||||
let context_menu = PopupBuilder::new(WidgetBuilder::new())
|
||||
.with_content(
|
||||
let context_menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new()).with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_child({
|
||||
@@ -1414,8 +1415,9 @@ impl CurveEditorBuilder {
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let context_menu = RcUiNodeHandle::new(context_menu, ctx.sender());
|
||||
|
||||
if self.widget_builder.foreground.is_none() {
|
||||
|
||||
@@ -6,10 +6,10 @@ use crate::{
|
||||
},
|
||||
draw::DrawingContext,
|
||||
grid::{Column, GridBuilder, Row},
|
||||
menu::{MenuItemBuilder, MenuItemContent, MenuItemMessage},
|
||||
menu::{ContextMenu, ContextMenuBuilder, MenuItemBuilder, MenuItemContent, MenuItemMessage},
|
||||
message::{MessageDirection, OsEvent, UiMessage},
|
||||
messagebox::{MessageBoxBuilder, MessageBoxButtons, MessageBoxMessage, MessageBoxResult},
|
||||
popup::{Placement, Popup, PopupBuilder, PopupMessage},
|
||||
popup::{Placement, PopupBuilder, PopupMessage},
|
||||
stack_panel::StackPanelBuilder,
|
||||
text::{TextBuilder, TextMessage},
|
||||
text_box::TextBoxBuilder,
|
||||
@@ -38,7 +38,7 @@ pub struct FolderNameDialog {
|
||||
#[derive(Clone, Visit, Reflect, Debug, ComponentProvider)]
|
||||
pub struct ItemContextMenu {
|
||||
#[component(include)]
|
||||
pub popup: Popup,
|
||||
pub base_menu: ContextMenu,
|
||||
pub delete: Handle<UiNode>,
|
||||
pub make_folder: Handle<UiNode>,
|
||||
pub delete_message_box: Cell<Handle<UiNode>>,
|
||||
@@ -49,13 +49,13 @@ impl Deref for ItemContextMenu {
|
||||
type Target = Widget;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.popup.widget
|
||||
&self.base_menu.popup.widget
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for ItemContextMenu {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.popup.widget
|
||||
&mut self.base_menu.popup.widget
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,27 +63,27 @@ uuid_provider!(ItemContextMenu = "6a9d597f-6a9f-4bad-b569-4cff1a6deff7");
|
||||
|
||||
impl Control for ItemContextMenu {
|
||||
fn on_remove(&self, sender: &Sender<UiMessage>) {
|
||||
self.popup.on_remove(sender)
|
||||
self.base_menu.on_remove(sender)
|
||||
}
|
||||
|
||||
fn measure_override(&self, ui: &UserInterface, available_size: Vector2<f32>) -> Vector2<f32> {
|
||||
self.popup.measure_override(ui, available_size)
|
||||
self.base_menu.measure_override(ui, available_size)
|
||||
}
|
||||
|
||||
fn arrange_override(&self, ui: &UserInterface, final_size: Vector2<f32>) -> Vector2<f32> {
|
||||
self.popup.arrange_override(ui, final_size)
|
||||
self.base_menu.arrange_override(ui, final_size)
|
||||
}
|
||||
|
||||
fn draw(&self, drawing_context: &mut DrawingContext) {
|
||||
self.popup.draw(drawing_context)
|
||||
self.base_menu.draw(drawing_context)
|
||||
}
|
||||
|
||||
fn update(&mut self, dt: f32, ui: &mut UserInterface) {
|
||||
self.popup.update(dt, ui)
|
||||
self.base_menu.update(dt, ui)
|
||||
}
|
||||
|
||||
fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
|
||||
self.popup.handle_routed_message(ui, message);
|
||||
self.base_menu.handle_routed_message(ui, message);
|
||||
|
||||
if let Some(PopupMessage::Placement(Placement::Cursor(_))) = message.data() {
|
||||
if message.destination() == self.handle {
|
||||
@@ -210,7 +210,7 @@ impl Control for ItemContextMenu {
|
||||
}
|
||||
|
||||
fn preview_message(&self, ui: &UserInterface, message: &mut UiMessage) {
|
||||
self.popup.preview_message(ui, message);
|
||||
self.base_menu.preview_message(ui, message);
|
||||
|
||||
if let Some(MessageBoxMessage::Close(result)) = message.data() {
|
||||
if message.destination() == self.delete_message_box.get() {
|
||||
@@ -286,7 +286,7 @@ impl Control for ItemContextMenu {
|
||||
ui: &mut UserInterface,
|
||||
event: &OsEvent,
|
||||
) {
|
||||
self.popup.handle_os_event(self_handle, ui, event)
|
||||
self.base_menu.handle_os_event(self_handle, ui, event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,38 +294,40 @@ impl ItemContextMenu {
|
||||
pub fn build(ctx: &mut BuildContext) -> Handle<UiNode> {
|
||||
let delete;
|
||||
let make_folder;
|
||||
let popup = PopupBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_preview_messages(true)
|
||||
.with_visibility(false),
|
||||
)
|
||||
.with_content(
|
||||
StackPanelBuilder::new(
|
||||
let base_menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_width(120.0)
|
||||
.with_child({
|
||||
delete = MenuItemBuilder::new(
|
||||
WidgetBuilder::new().with_margin(Thickness::uniform(2.0)),
|
||||
)
|
||||
.with_content(MenuItemContent::text("Delete"))
|
||||
.build(ctx);
|
||||
delete
|
||||
})
|
||||
.with_child({
|
||||
make_folder = MenuItemBuilder::new(
|
||||
WidgetBuilder::new().with_margin(Thickness::uniform(2.0)),
|
||||
)
|
||||
.with_content(MenuItemContent::text("Make Folder"))
|
||||
.build(ctx);
|
||||
make_folder
|
||||
}),
|
||||
.with_preview_messages(true)
|
||||
.with_visibility(false),
|
||||
)
|
||||
.build(ctx),
|
||||
.with_content(
|
||||
StackPanelBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_width(120.0)
|
||||
.with_child({
|
||||
delete = MenuItemBuilder::new(
|
||||
WidgetBuilder::new().with_margin(Thickness::uniform(2.0)),
|
||||
)
|
||||
.with_content(MenuItemContent::text("Delete"))
|
||||
.build(ctx);
|
||||
delete
|
||||
})
|
||||
.with_child({
|
||||
make_folder = MenuItemBuilder::new(
|
||||
WidgetBuilder::new().with_margin(Thickness::uniform(2.0)),
|
||||
)
|
||||
.with_content(MenuItemContent::text("Make Folder"))
|
||||
.build(ctx);
|
||||
make_folder
|
||||
}),
|
||||
)
|
||||
.build(ctx),
|
||||
),
|
||||
)
|
||||
.build_popup(ctx);
|
||||
.build_context_menu(ctx);
|
||||
|
||||
let menu = Self {
|
||||
popup,
|
||||
base_menu,
|
||||
delete,
|
||||
make_folder,
|
||||
delete_message_box: Default::default(),
|
||||
@@ -336,7 +338,7 @@ impl ItemContextMenu {
|
||||
}
|
||||
|
||||
fn item_path(&self, ui: &UserInterface) -> Option<PathBuf> {
|
||||
ui.try_get(self.popup.placement.target())
|
||||
ui.try_get(self.base_menu.popup.placement.target())
|
||||
.and_then(|n| n.user_data_cloned::<PathBuf>())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
//! structure or enumeration recursively. It's primary usage is provide unified and simple way of introspection.
|
||||
//! See [`Inspector`] docs for more info and usage examples.
|
||||
|
||||
use crate::menu::ContextMenuBuilder;
|
||||
use crate::{
|
||||
border::BorderBuilder,
|
||||
check_box::CheckBoxBuilder,
|
||||
@@ -878,8 +879,8 @@ impl InspectorContext {
|
||||
});
|
||||
|
||||
let copy_value_as_string;
|
||||
let menu = PopupBuilder::new(WidgetBuilder::new().with_visibility(false))
|
||||
.with_content(
|
||||
let menu = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_visibility(false)).with_content(
|
||||
StackPanelBuilder::new(WidgetBuilder::new().with_child({
|
||||
copy_value_as_string = MenuItemBuilder::new(WidgetBuilder::new())
|
||||
.with_content(MenuItemContent::text("Copy Value as String"))
|
||||
@@ -887,8 +888,9 @@ impl InspectorContext {
|
||||
copy_value_as_string
|
||||
}))
|
||||
.build(ctx),
|
||||
)
|
||||
.build(ctx);
|
||||
),
|
||||
)
|
||||
.build(ctx);
|
||||
let menu = RcUiNodeHandle::new(menu, ctx.sender());
|
||||
|
||||
let stack_panel = StackPanelBuilder::new(
|
||||
|
||||
+102
-43
@@ -375,6 +375,13 @@ pub struct MenuItem {
|
||||
|
||||
crate::define_widget_deref!(MenuItem);
|
||||
|
||||
impl MenuItem {
|
||||
fn is_opened(&self, ui: &UserInterface) -> bool {
|
||||
ui.try_get_of_type::<ContextMenu>(*self.items_panel)
|
||||
.map_or(false, |items_panel| *items_panel.popup.is_open)
|
||||
}
|
||||
}
|
||||
|
||||
// MenuItem uses popup to show its content, popup can be top-most only if it is
|
||||
// direct child of root canvas of UI. This fact adds some complications to search
|
||||
// of parent menu - we can't just traverse the tree because popup is not a child
|
||||
@@ -383,7 +390,7 @@ crate::define_widget_deref!(MenuItem);
|
||||
fn find_menu(from: Handle<UiNode>, ui: &UserInterface) -> Handle<UiNode> {
|
||||
let mut handle = from;
|
||||
while handle.is_some() {
|
||||
if let Some((_, panel)) = ui.find_component_up::<MenuItemsPanel>(handle) {
|
||||
if let Some((_, panel)) = ui.find_component_up::<ContextMenu>(handle) {
|
||||
// Continue search from parent menu item of popup.
|
||||
handle = panel.parent_menu_item;
|
||||
} else {
|
||||
@@ -413,17 +420,14 @@ fn is_any_menu_item_contains_point(ui: &UserInterface, pt: Vector2<f32>) -> bool
|
||||
fn close_menu_chain(from: Handle<UiNode>, ui: &UserInterface) {
|
||||
let mut handle = from;
|
||||
while handle.is_some() {
|
||||
let popup_handle = ui.find_handle_up(handle, &mut |n| n.has_component::<Popup>());
|
||||
let popup_handle = ui.find_handle_up(handle, &mut |n| n.has_component::<ContextMenu>());
|
||||
|
||||
if popup_handle.is_none() {
|
||||
break;
|
||||
}
|
||||
ui.send_message(PopupMessage::close(
|
||||
popup_handle,
|
||||
MessageDirection::ToWidget,
|
||||
));
|
||||
if let Some(panel) = ui.try_get_of_type::<ContextMenu>(popup_handle) {
|
||||
ui.send_message(PopupMessage::close(
|
||||
popup_handle,
|
||||
MessageDirection::ToWidget,
|
||||
));
|
||||
|
||||
if let Some(panel) = ui.node(popup_handle).query_component::<MenuItemsPanel>() {
|
||||
// Continue search from parent menu item of popup.
|
||||
handle = panel.parent_menu_item;
|
||||
} else {
|
||||
@@ -509,6 +513,15 @@ impl Control for MenuItem {
|
||||
));
|
||||
}
|
||||
}
|
||||
WidgetMessage::MouseLeave => {
|
||||
if !self.is_opened(ui) {
|
||||
ui.send_message(MenuItemMessage::select(
|
||||
self.handle,
|
||||
MessageDirection::ToWidget,
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
WidgetMessage::KeyDown(key_code) => {
|
||||
if !message.handled() && *self.is_selected && *key_code == KeyCode::Enter {
|
||||
ui.send_message(MenuItemMessage::click(
|
||||
@@ -530,16 +543,19 @@ impl Control for MenuItem {
|
||||
MenuItemMessage::Select(selected) => {
|
||||
if *self.is_selected != *selected {
|
||||
self.is_selected.set_value_and_mark_modified(*selected);
|
||||
|
||||
ui.send_message(DecoratorMessage::select(
|
||||
*self.decorator,
|
||||
MessageDirection::ToWidget,
|
||||
*selected,
|
||||
));
|
||||
|
||||
ui.send_message(WidgetMessage::focus(
|
||||
self.handle,
|
||||
MessageDirection::ToWidget,
|
||||
));
|
||||
if *selected {
|
||||
ui.send_message(WidgetMessage::focus(
|
||||
self.handle,
|
||||
MessageDirection::ToWidget,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
MenuItemMessage::Open => {
|
||||
@@ -574,13 +590,23 @@ impl Control for MenuItem {
|
||||
*self.items_panel,
|
||||
MessageDirection::ToWidget,
|
||||
));
|
||||
|
||||
if *deselect && *self.is_selected {
|
||||
ui.send_message(DecoratorMessage::select(
|
||||
*self.decorator,
|
||||
ui.send_message(MenuItemMessage::select(
|
||||
self.handle,
|
||||
MessageDirection::ToWidget,
|
||||
false,
|
||||
));
|
||||
}
|
||||
|
||||
// Recursively deselect everything in the sub-items container.
|
||||
for &item in &*self.items_container.items {
|
||||
ui.send_message(MenuItemMessage::close(
|
||||
item,
|
||||
MessageDirection::ToWidget,
|
||||
true,
|
||||
));
|
||||
}
|
||||
}
|
||||
MenuItemMessage::Click => {}
|
||||
MenuItemMessage::AddItem(item) => {
|
||||
@@ -641,7 +667,7 @@ impl Control for MenuItem {
|
||||
break;
|
||||
} else {
|
||||
let node = ui.node(handle);
|
||||
if let Some(panel) = node.component_ref::<MenuItemsPanel>() {
|
||||
if let Some(panel) = node.component_ref::<ContextMenu>() {
|
||||
// Once we found popup in chain, we must extract handle
|
||||
// of parent menu item to continue search.
|
||||
handle = panel.parent_menu_item;
|
||||
@@ -671,10 +697,7 @@ impl Control for MenuItem {
|
||||
// Allow closing "orphaned" menus by clicking outside of them.
|
||||
if let OsEvent::MouseInput { state, .. } = event {
|
||||
if *state == ButtonState::Pressed {
|
||||
if let Some(panel) = ui
|
||||
.node(*self.items_panel)
|
||||
.query_component::<MenuItemsPanel>()
|
||||
{
|
||||
if let Some(panel) = ui.node(*self.items_panel).query_component::<ContextMenu>() {
|
||||
if *panel.popup.is_open {
|
||||
// Ensure that cursor is outside of any menus.
|
||||
if !is_any_menu_item_contains_point(ui, ui.cursor_position())
|
||||
@@ -959,21 +982,19 @@ impl<'a, 'b> MenuItemBuilder<'a, 'b> {
|
||||
}
|
||||
|
||||
let panel;
|
||||
let popup = PopupBuilder::new(WidgetBuilder::new().with_min_size(Vector2::new(10.0, 10.0)))
|
||||
.with_content({
|
||||
panel = StackPanelBuilder::new(
|
||||
WidgetBuilder::new().with_children(self.items.iter().cloned()),
|
||||
)
|
||||
.build(ctx);
|
||||
panel
|
||||
})
|
||||
// We'll manually control if popup is either open or closed.
|
||||
.stays_open(true)
|
||||
.build_popup(ctx);
|
||||
let items_panel = ctx.add_node(UiNode::new(MenuItemsPanel {
|
||||
popup,
|
||||
parent_menu_item: Default::default(),
|
||||
}));
|
||||
let items_panel = ContextMenuBuilder::new(
|
||||
PopupBuilder::new(WidgetBuilder::new().with_min_size(Vector2::new(10.0, 10.0)))
|
||||
.with_content({
|
||||
panel = StackPanelBuilder::new(
|
||||
WidgetBuilder::new().with_children(self.items.iter().cloned()),
|
||||
)
|
||||
.build(ctx);
|
||||
panel
|
||||
})
|
||||
// We'll manually control if popup is either open or closed.
|
||||
.stays_open(true),
|
||||
)
|
||||
.build(ctx);
|
||||
|
||||
let menu = MenuItem {
|
||||
widget: self
|
||||
@@ -997,7 +1018,7 @@ impl<'a, 'b> MenuItemBuilder<'a, 'b> {
|
||||
let handle = ctx.add_node(UiNode::new(menu));
|
||||
|
||||
// "Link" popup with its parent menu item.
|
||||
if let Some(popup) = ctx[items_panel].cast_mut::<MenuItemsPanel>() {
|
||||
if let Some(popup) = ctx[items_panel].cast_mut::<ContextMenu>() {
|
||||
popup.parent_menu_item = handle;
|
||||
}
|
||||
|
||||
@@ -1009,13 +1030,15 @@ impl<'a, 'b> MenuItemBuilder<'a, 'b> {
|
||||
/// an ability for keyboard navigation.
|
||||
#[derive(Default, Clone, Debug, Visit, Reflect, TypeUuidProvider, ComponentProvider)]
|
||||
#[type_uuid(id = "ad8e9e76-c213-4232-9bab-80ebcabd69fa")]
|
||||
pub struct MenuItemsPanel {
|
||||
pub struct ContextMenu {
|
||||
/// Inner popup widget of the context menu.
|
||||
#[component(include)]
|
||||
popup: Popup,
|
||||
parent_menu_item: Handle<UiNode>,
|
||||
pub popup: Popup,
|
||||
/// Parent menu item of the context menu. Allows you to build chained context menus.
|
||||
pub parent_menu_item: Handle<UiNode>,
|
||||
}
|
||||
|
||||
impl Deref for MenuItemsPanel {
|
||||
impl Deref for ContextMenu {
|
||||
type Target = Widget;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@@ -1023,13 +1046,13 @@ impl Deref for MenuItemsPanel {
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for MenuItemsPanel {
|
||||
impl DerefMut for ContextMenu {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.popup.widget
|
||||
}
|
||||
}
|
||||
|
||||
impl Control for MenuItemsPanel {
|
||||
impl Control for ContextMenu {
|
||||
fn on_remove(&self, sender: &Sender<UiMessage>) {
|
||||
self.popup.on_remove(sender)
|
||||
}
|
||||
@@ -1087,6 +1110,42 @@ impl Control for MenuItemsPanel {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates [`ContextMenu`] widgets.
|
||||
pub struct ContextMenuBuilder {
|
||||
popup_builder: PopupBuilder,
|
||||
parent_menu_item: Handle<UiNode>,
|
||||
}
|
||||
|
||||
impl ContextMenuBuilder {
|
||||
/// Creates new builder instance using an instance of the [`PopupBuilder`].
|
||||
pub fn new(popup_builder: PopupBuilder) -> Self {
|
||||
Self {
|
||||
popup_builder,
|
||||
parent_menu_item: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the desired parent menu item.
|
||||
pub fn with_parent_menu_item(mut self, parent_menu_item: Handle<UiNode>) -> Self {
|
||||
self.parent_menu_item = parent_menu_item;
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes context menu building.
|
||||
pub fn build_context_menu(self, ctx: &mut BuildContext) -> ContextMenu {
|
||||
ContextMenu {
|
||||
popup: self.popup_builder.build_popup(ctx),
|
||||
parent_menu_item: self.parent_menu_item,
|
||||
}
|
||||
}
|
||||
|
||||
/// Finishes context menu building and adds it to the user interface.
|
||||
pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
|
||||
let context_menu = self.build_context_menu(ctx);
|
||||
ctx.add_node(UiNode::new(context_menu))
|
||||
}
|
||||
}
|
||||
|
||||
fn keyboard_navigation(
|
||||
ui: &UserInterface,
|
||||
key_code: KeyCode,
|
||||
|
||||
@@ -21,7 +21,7 @@ use crate::{
|
||||
inspector::Inspector,
|
||||
key::{HotKeyEditor, KeyBindingEditor},
|
||||
list_view::{ListView, ListViewItem},
|
||||
menu::{Menu, MenuItem, MenuItemsPanel},
|
||||
menu::{ContextMenu, Menu, MenuItem},
|
||||
messagebox::MessageBox,
|
||||
nine_patch::NinePatch,
|
||||
numeric::NumericUpDown,
|
||||
@@ -95,7 +95,7 @@ impl WidgetConstructorContainer {
|
||||
container.add::<ListView>();
|
||||
container.add::<Menu>();
|
||||
container.add::<MenuItem>();
|
||||
container.add::<MenuItemsPanel>();
|
||||
container.add::<ContextMenu>();
|
||||
container.add::<MessageBox>();
|
||||
container.add::<NinePatch>();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user