mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
ability to change hash map key from inspector
This commit is contained in:
@@ -377,12 +377,80 @@ pub fn make_command(
|
||||
PropertyAction::RemoveItemByKey { .. } => {
|
||||
todo!()
|
||||
}
|
||||
PropertyAction::KeyChanged { .. } => {
|
||||
todo!()
|
||||
PropertyAction::KeyChanged { old_key, new_key } => {
|
||||
Some(Command::new(ChangeHashMapKeyCommand {
|
||||
old_key,
|
||||
new_key,
|
||||
path: property_changed.path(),
|
||||
entity_getter,
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ChangeHashMapKeyCommand<F: EntityGetter> {
|
||||
old_key: Box<dyn Reflect>,
|
||||
new_key: Box<dyn Reflect>,
|
||||
path: String,
|
||||
entity_getter: F,
|
||||
}
|
||||
|
||||
impl<F: EntityGetter> ChangeHashMapKeyCommand<F> {
|
||||
fn swap(&mut self, ctx: &mut dyn CommandContext) {
|
||||
let entity = some_or_return!((self.entity_getter)(ctx));
|
||||
entity.resolve_path_mut(&self.path, &mut |result| match result {
|
||||
Ok(entity) => match entity.as_hash_map_mut() {
|
||||
Some(hash_map) => {
|
||||
match hash_map.reflect_replace_key(
|
||||
&*self.old_key,
|
||||
self.new_key
|
||||
.try_clone_box()
|
||||
.expect("the key must be cloneable"),
|
||||
) {
|
||||
Ok(_) => {
|
||||
std::mem::swap(&mut self.new_key, &mut self.old_key);
|
||||
}
|
||||
Err(new_key) => {
|
||||
self.new_key = new_key;
|
||||
err!("cannot insert a key because it is occupied!")
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
err!("not a hash map")
|
||||
}
|
||||
},
|
||||
Err(reason) => {
|
||||
err!(
|
||||
"Failed to set property {}! Invalid path {:?}!",
|
||||
self.path,
|
||||
reason
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: EntityGetter> Debug for ChangeHashMapKeyCommand<F> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "ChangeHashMapKeyCommand")
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: EntityGetter> CommandTrait for ChangeHashMapKeyCommand<F> {
|
||||
fn name(&mut self, _context: &dyn CommandContext) -> String {
|
||||
format!("Change {} Hash Map Key", self.path)
|
||||
}
|
||||
|
||||
fn execute(&mut self, context: &mut dyn CommandContext) {
|
||||
self.swap(context)
|
||||
}
|
||||
|
||||
fn revert(&mut self, context: &mut dyn CommandContext) {
|
||||
self.swap(context)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_modify_property<F>(entity: &mut dyn Reflect, path: &str, func: F)
|
||||
where
|
||||
F: FnOnce(&mut dyn Reflect),
|
||||
|
||||
@@ -39,13 +39,16 @@ pub enum HashMapPropertyEditorMessage {
|
||||
key: ObjectValue,
|
||||
message: UiMessage,
|
||||
},
|
||||
KeyChanged {
|
||||
key: ObjectValue,
|
||||
message: UiMessage,
|
||||
},
|
||||
}
|
||||
impl MessageData for HashMapPropertyEditorMessage {}
|
||||
|
||||
#[derive(Debug, Reflect, Visit, Clone, PartialEq)]
|
||||
#[reflect(type_uuid = "1440dacb-19ae-425b-a1f4-9d73a1009e6a")]
|
||||
pub struct Entry<K: HashMapKey> {
|
||||
pub key_hash: u64,
|
||||
#[visit(skip)]
|
||||
pub key: K,
|
||||
pub key_editor: PropertyEditorInstance,
|
||||
@@ -76,12 +79,18 @@ impl<K: HashMapKey> DerefMut for HashMapPropertyEditor<K> {
|
||||
|
||||
impl<K: HashMapKey> Control for HashMapPropertyEditor<K> {
|
||||
fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
|
||||
if let Some(_key_editor) = self
|
||||
if let Some(key_editor_entry) = self
|
||||
.entries
|
||||
.iter()
|
||||
.find(|e| message.destination() == e.key_editor.editor())
|
||||
{
|
||||
// TODO.
|
||||
ui.post(
|
||||
self.handle(),
|
||||
HashMapPropertyEditorMessage::KeyChanged {
|
||||
key: ObjectValue::new(key_editor_entry.key.clone()),
|
||||
message: message.clone(),
|
||||
},
|
||||
)
|
||||
} else if let Some(value_editor_entry) = self
|
||||
.entries
|
||||
.iter()
|
||||
|
||||
@@ -40,7 +40,6 @@ use crate::{
|
||||
},
|
||||
message::UiMessage,
|
||||
};
|
||||
use std::hash::Hasher;
|
||||
use std::{
|
||||
any::TypeId,
|
||||
collections::HashMap,
|
||||
@@ -210,11 +209,7 @@ where
|
||||
let entries = hash_map
|
||||
.iter()
|
||||
.filter_map(|(key, value)| {
|
||||
let mut hasher = hash_map.hasher().build_hasher();
|
||||
key.hash(&mut hasher);
|
||||
let key_hash = hasher.finish();
|
||||
Some(Entry {
|
||||
key_hash,
|
||||
key: key.clone(),
|
||||
key_editor: create_key_editor(key, &mut ctx)?,
|
||||
value_editor: create_value_editor(value, &mut ctx)?,
|
||||
@@ -240,29 +235,62 @@ where
|
||||
|
||||
fn translate_message(&self, ctx: PropertyEditorTranslationContext) -> Option<PropertyChanged> {
|
||||
if ctx.message.direction() == MessageDirection::FromWidget {
|
||||
if let Some(HashMapPropertyEditorMessage::ValueChanged { key, message }) =
|
||||
ctx.message.data()
|
||||
{
|
||||
if let Some(definition) = ctx
|
||||
.definition_container
|
||||
.definitions()
|
||||
.get(&TypeId::of::<V>())
|
||||
{
|
||||
return Some(PropertyChanged {
|
||||
name: ctx.name.to_string(),
|
||||
action: FieldAction::HashMapAction(Box::new(HashMapAction::ValueChanged {
|
||||
key: key.clone(),
|
||||
action: definition
|
||||
.property_editor
|
||||
.translate_message(PropertyEditorTranslationContext {
|
||||
environment: ctx.environment.clone(),
|
||||
name: "",
|
||||
message,
|
||||
definition_container: ctx.definition_container.clone(),
|
||||
})?
|
||||
.action,
|
||||
})),
|
||||
});
|
||||
if let Some(msg) = ctx.message.data::<HashMapPropertyEditorMessage>() {
|
||||
match msg {
|
||||
HashMapPropertyEditorMessage::ValueChanged { key, message } => {
|
||||
if let Some(definition) = ctx
|
||||
.definition_container
|
||||
.definitions()
|
||||
.get(&TypeId::of::<V>())
|
||||
{
|
||||
return Some(PropertyChanged {
|
||||
name: ctx.name.to_string(),
|
||||
action: FieldAction::HashMapAction(Box::new(
|
||||
HashMapAction::ValueChanged {
|
||||
key: key.clone(),
|
||||
action: definition
|
||||
.property_editor
|
||||
.translate_message(PropertyEditorTranslationContext {
|
||||
environment: ctx.environment.clone(),
|
||||
name: "",
|
||||
message,
|
||||
definition_container: ctx
|
||||
.definition_container
|
||||
.clone(),
|
||||
})?
|
||||
.action,
|
||||
},
|
||||
)),
|
||||
});
|
||||
}
|
||||
}
|
||||
HashMapPropertyEditorMessage::KeyChanged { key, message } => {
|
||||
if let Some(definition) = ctx
|
||||
.definition_container
|
||||
.definitions()
|
||||
.get(&TypeId::of::<K>())
|
||||
{
|
||||
return Some(PropertyChanged {
|
||||
name: ctx.name.to_string(),
|
||||
action: FieldAction::HashMapAction(Box::new(
|
||||
HashMapAction::KeyChanged {
|
||||
key: key.clone(),
|
||||
action: definition
|
||||
.property_editor
|
||||
.translate_message(PropertyEditorTranslationContext {
|
||||
environment: ctx.environment.clone(),
|
||||
name: "",
|
||||
message,
|
||||
definition_container: ctx
|
||||
.definition_container
|
||||
.clone(),
|
||||
})?
|
||||
.action,
|
||||
},
|
||||
)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ impl PropertyAction {
|
||||
.value
|
||||
.try_clone_box()
|
||||
.expect("the key must be cloneable!");
|
||||
let key_action = PropertyAction::from_field_action(&action);
|
||||
let key_action = PropertyAction::from_field_action(action);
|
||||
key_action.apply_on_result(Ok(&mut *new_key), &mut |result| {
|
||||
Log::verify(result);
|
||||
});
|
||||
@@ -491,9 +491,9 @@ impl PropertyChanged {
|
||||
}
|
||||
FieldAction::ObjectAction(_) | FieldAction::InheritableAction { .. } => {}
|
||||
FieldAction::HashMapAction(ref action) => match **action {
|
||||
HashMapAction::KeyChanged { .. } => {}
|
||||
HashMapAction::Insert { ref key, .. }
|
||||
| HashMapAction::Remove { ref key }
|
||||
| HashMapAction::KeyChanged { ref key, .. }
|
||||
| HashMapAction::ValueChanged { ref key, .. } => {
|
||||
path += format!("[{}]", reflect::make_hash_map_key(&*key.value)).as_ref();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user