mirror of
https://github.com/FyroxEngine/Fyrox.git
synced 2026-10-12 02:02:20 +00:00
refactored hash map property editor
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
use crate::inspector::editors::PropertyEditorBuildContext;
|
||||
use crate::{
|
||||
button::{Button, ButtonBuilder, ButtonMessage},
|
||||
core::{pool::Handle, reflect::prelude::*, visitor::prelude::*},
|
||||
@@ -29,62 +30,70 @@ use crate::{
|
||||
SelectHashMapKeyDialogWindow, SelectHashMapKeyDialogWindowBuilder,
|
||||
SelectHashMapKeyDialogWindowMessage,
|
||||
},
|
||||
HashMapKey,
|
||||
HashMapKey, HashMapState, HashMapValue,
|
||||
},
|
||||
PropertyEditorDefinitionContainer, PropertyEditorInstance,
|
||||
},
|
||||
InspectorEnvironmentContainer, ObjectValue,
|
||||
InspectorEnvironmentContainer,
|
||||
},
|
||||
message::{MessageData, UiMessage},
|
||||
widget::{Widget, WidgetBuilder},
|
||||
window::{WindowAlignment, WindowBuilder, WindowMessage, WindowTitle},
|
||||
BuildContext, Control, UiNode, UserInterface,
|
||||
Control, UiNode, UserInterface, VerticalAlignment,
|
||||
};
|
||||
use fxhash::FxHashSet;
|
||||
use fyrox_core::reflect;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ops::{Deref, DerefMut},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub enum HashMapPropertyEditorMessage {
|
||||
ValueChanged {
|
||||
key: ObjectValue,
|
||||
message: UiMessage,
|
||||
},
|
||||
KeyChanged {
|
||||
key: ObjectValue,
|
||||
message: UiMessage,
|
||||
},
|
||||
Remove {
|
||||
key: ObjectValue,
|
||||
},
|
||||
InsertDefault {
|
||||
key: ObjectValue,
|
||||
},
|
||||
pub enum HashMapPropertyEditorMessage<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
V: HashMapValue,
|
||||
S: HashMapState,
|
||||
{
|
||||
Update { hash_map: HashMap<K, V, S> },
|
||||
ValueChanged { key: K, message: UiMessage },
|
||||
KeyChanged { key: K, message: UiMessage },
|
||||
Remove { key: K },
|
||||
InsertDefault { key: K },
|
||||
}
|
||||
impl<K, V, S> MessageData for HashMapPropertyEditorMessage<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
V: HashMapValue,
|
||||
S: HashMapState,
|
||||
{
|
||||
}
|
||||
impl MessageData for HashMapPropertyEditorMessage {}
|
||||
|
||||
#[derive(Debug, Reflect, Visit, Clone, PartialEq)]
|
||||
#[reflect(
|
||||
derived_type = "UiNode",
|
||||
type_uuid = "1440dacb-19ae-425b-a1f4-9d73a1009e6a"
|
||||
)]
|
||||
pub struct Entry<K: HashMapKey> {
|
||||
#[visit(skip)]
|
||||
pub key: K,
|
||||
pub key_hash: u64,
|
||||
#[reflect(type_uuid = "1440dacb-19ae-425b-a1f4-9d73a1009e6a")]
|
||||
pub struct Entry<V: HashMapValue> {
|
||||
pub key_editor: PropertyEditorInstance,
|
||||
pub value_editor: PropertyEditorInstance,
|
||||
pub remove: Handle<Button>,
|
||||
#[visit(skip)]
|
||||
pub value: V,
|
||||
}
|
||||
|
||||
#[derive(Debug, Reflect, Visit, Clone)]
|
||||
#[reflect(type_uuid = "a36ed236-e6f6-4d98-a22e-73e6af38c29d", non_comparable)]
|
||||
pub struct HashMapPropertyEditor<K: HashMapKey> {
|
||||
#[reflect(
|
||||
derived_type = "UiNode",
|
||||
type_uuid = "a36ed236-e6f6-4d98-a22e-73e6af38c29d",
|
||||
non_comparable,
|
||||
ignore_generics_type_uuid
|
||||
)]
|
||||
pub struct HashMapPropertyEditor<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
V: HashMapValue,
|
||||
S: HashMapState,
|
||||
{
|
||||
widget: Widget,
|
||||
#[visit(skip)]
|
||||
entries: Vec<Entry<K>>,
|
||||
add: Handle<Button>,
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
@@ -93,9 +102,17 @@ pub struct HashMapPropertyEditor<K: HashMapKey> {
|
||||
#[reflect(hidden)]
|
||||
environment: Option<InspectorEnvironmentContainer>,
|
||||
dialog: Handle<SelectHashMapKeyDialogWindow<K>>,
|
||||
#[visit(skip)]
|
||||
#[reflect(hidden)]
|
||||
hash_map: HashMap<K, Entry<V>, S>,
|
||||
}
|
||||
|
||||
impl<K: HashMapKey> Deref for HashMapPropertyEditor<K> {
|
||||
impl<K, V, S> Deref for HashMapPropertyEditor<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
V: HashMapValue,
|
||||
S: HashMapState,
|
||||
{
|
||||
type Target = Widget;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
@@ -103,37 +120,45 @@ impl<K: HashMapKey> Deref for HashMapPropertyEditor<K> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: HashMapKey> DerefMut for HashMapPropertyEditor<K> {
|
||||
impl<K, V, S> DerefMut for HashMapPropertyEditor<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
V: HashMapValue,
|
||||
S: HashMapState,
|
||||
{
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.widget
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: HashMapKey> Control for HashMapPropertyEditor<K> {
|
||||
impl<K, V, S> Control for HashMapPropertyEditor<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
V: HashMapValue,
|
||||
S: HashMapState,
|
||||
{
|
||||
fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
|
||||
for entry in self.entries.iter() {
|
||||
for (key, entry) in self.hash_map.iter() {
|
||||
if message.destination() == entry.key_editor.editor() {
|
||||
ui.post(
|
||||
self.handle(),
|
||||
HashMapPropertyEditorMessage::KeyChanged {
|
||||
key: ObjectValue::new(entry.key.clone()),
|
||||
HashMapPropertyEditorMessage::<K, V, S>::KeyChanged {
|
||||
key: key.clone(),
|
||||
message: message.clone(),
|
||||
},
|
||||
)
|
||||
} else if message.destination() == entry.value_editor.editor() {
|
||||
ui.post(
|
||||
self.handle(),
|
||||
HashMapPropertyEditorMessage::ValueChanged {
|
||||
key: ObjectValue::new(entry.key.clone()),
|
||||
HashMapPropertyEditorMessage::<K, V, S>::ValueChanged {
|
||||
key: key.clone(),
|
||||
message: message.clone(),
|
||||
},
|
||||
)
|
||||
} else if let Some(ButtonMessage::Click) = message.data_from(entry.remove) {
|
||||
ui.post(
|
||||
self.handle(),
|
||||
HashMapPropertyEditorMessage::Remove {
|
||||
key: ObjectValue::new(entry.key.clone()),
|
||||
},
|
||||
HashMapPropertyEditorMessage::<K, V, S>::Remove { key: key.clone() },
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -147,12 +172,12 @@ impl<K: HashMapKey> Control for HashMapPropertyEditor<K> {
|
||||
self.property_editors.clone(),
|
||||
K::default(),
|
||||
)
|
||||
.with_existing_keys(
|
||||
self.entries
|
||||
.iter()
|
||||
.map(|e| e.key_hash)
|
||||
.collect::<FxHashSet<_>>(),
|
||||
)
|
||||
.with_existing_keys({
|
||||
self.hash_map
|
||||
.keys()
|
||||
.map(|e| self.hash_map.hasher().hash_one(e))
|
||||
.collect::<FxHashSet<_>>()
|
||||
})
|
||||
.with_environment(self.environment.clone())
|
||||
.build(&mut ui.build_ctx());
|
||||
|
||||
@@ -164,6 +189,11 @@ impl<K: HashMapKey> Control for HashMapPropertyEditor<K> {
|
||||
focus_content: true,
|
||||
},
|
||||
);
|
||||
} else if let Some(HashMapPropertyEditorMessage::<K, V, S>::Update { hash_map: _ }) =
|
||||
message.data_for(self.handle)
|
||||
{
|
||||
// TODO. Sync entries.
|
||||
// self.hash_map = hash_map.clone();
|
||||
}
|
||||
|
||||
self.widget.handle_routed_message(ui, message)
|
||||
@@ -175,87 +205,209 @@ impl<K: HashMapKey> Control for HashMapPropertyEditor<K> {
|
||||
{
|
||||
ui.post(
|
||||
self.handle(),
|
||||
HashMapPropertyEditorMessage::InsertDefault {
|
||||
key: ObjectValue::new(key.clone()),
|
||||
},
|
||||
HashMapPropertyEditorMessage::<K, V, S>::InsertDefault { key: key.clone() },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HashMapPropertyEditorBuilder<K: HashMapKey> {
|
||||
pub struct HashMapPropertyEditorBuilder<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
V: HashMapValue,
|
||||
S: HashMapState,
|
||||
{
|
||||
widget_builder: WidgetBuilder,
|
||||
entries: Vec<Entry<K>>,
|
||||
property_editors: Arc<PropertyEditorDefinitionContainer>,
|
||||
environment: Option<InspectorEnvironmentContainer>,
|
||||
hash_map: HashMap<K, V, S>,
|
||||
}
|
||||
|
||||
impl<K: HashMapKey> HashMapPropertyEditorBuilder<K> {
|
||||
pub fn new(
|
||||
widget_builder: WidgetBuilder,
|
||||
property_editors: Arc<PropertyEditorDefinitionContainer>,
|
||||
) -> Self {
|
||||
fn create_key_editor<K>(
|
||||
key: &K,
|
||||
ctx: &mut PropertyEditorBuildContext,
|
||||
) -> Option<PropertyEditorInstance>
|
||||
where
|
||||
K: HashMapKey,
|
||||
{
|
||||
let key_property_editor = ctx.definition_container.get::<K>()?;
|
||||
|
||||
let property_info = ctx.property_info;
|
||||
|
||||
let key_name = reflect::make_hash_map_key(key);
|
||||
|
||||
let key_property_info = FieldRef {
|
||||
metadata: &FieldMetadata {
|
||||
name: &key_name,
|
||||
display_name: &key_name,
|
||||
read_only: property_info.read_only,
|
||||
immutable_collection: property_info.immutable_collection,
|
||||
min_value: property_info.min_value,
|
||||
max_value: property_info.max_value,
|
||||
step: property_info.step,
|
||||
precision: property_info.precision,
|
||||
tag: property_info.tag,
|
||||
doc: property_info.doc,
|
||||
},
|
||||
value: key,
|
||||
};
|
||||
|
||||
key_property_editor
|
||||
.property_editor
|
||||
.create_instance(PropertyEditorBuildContext {
|
||||
build_context: ctx.build_context,
|
||||
property_info: &key_property_info,
|
||||
environment: ctx.environment.clone(),
|
||||
definition_container: ctx.definition_container.clone(),
|
||||
layer_index: ctx.layer_index,
|
||||
generate_property_string_values: ctx.generate_property_string_values,
|
||||
filter: ctx.filter.clone(),
|
||||
name_column_width: ctx.name_column_width,
|
||||
hide_name_column: ctx.hide_name_column,
|
||||
base_path: ctx.base_path.clone(),
|
||||
has_parent_object: ctx.has_parent_object,
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
fn create_value_editor<V>(
|
||||
key: &V,
|
||||
ctx: &mut PropertyEditorBuildContext,
|
||||
) -> Option<PropertyEditorInstance>
|
||||
where
|
||||
V: HashMapValue,
|
||||
{
|
||||
let value_property_editor = ctx.definition_container.get::<V>()?;
|
||||
|
||||
let property_info = ctx.property_info;
|
||||
|
||||
let value_property_info = FieldRef {
|
||||
metadata: &FieldMetadata {
|
||||
name: property_info.name,
|
||||
display_name: property_info.display_name,
|
||||
read_only: property_info.read_only,
|
||||
immutable_collection: property_info.immutable_collection,
|
||||
min_value: property_info.min_value,
|
||||
max_value: property_info.max_value,
|
||||
step: property_info.step,
|
||||
precision: property_info.precision,
|
||||
tag: property_info.tag,
|
||||
doc: property_info.doc,
|
||||
},
|
||||
value: key,
|
||||
};
|
||||
|
||||
value_property_editor
|
||||
.property_editor
|
||||
.create_instance(PropertyEditorBuildContext {
|
||||
build_context: ctx.build_context,
|
||||
property_info: &value_property_info,
|
||||
environment: ctx.environment.clone(),
|
||||
definition_container: ctx.definition_container.clone(),
|
||||
layer_index: ctx.layer_index,
|
||||
generate_property_string_values: ctx.generate_property_string_values,
|
||||
filter: ctx.filter.clone(),
|
||||
name_column_width: ctx.name_column_width,
|
||||
hide_name_column: ctx.hide_name_column,
|
||||
base_path: ctx.base_path.clone(),
|
||||
has_parent_object: ctx.has_parent_object,
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
impl<K, V, S> HashMapPropertyEditorBuilder<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
V: HashMapValue,
|
||||
S: HashMapState,
|
||||
{
|
||||
pub fn new(widget_builder: WidgetBuilder) -> Self {
|
||||
Self {
|
||||
widget_builder,
|
||||
entries: Default::default(),
|
||||
property_editors,
|
||||
environment: None,
|
||||
hash_map: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_entries(mut self, entries: Vec<Entry<K>>) -> Self {
|
||||
self.entries = entries;
|
||||
pub fn with_hash_map(mut self, hash_map: HashMap<K, V, S>) -> Self {
|
||||
self.hash_map = hash_map;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_environment(mut self, environment: InspectorEnvironmentContainer) -> Self {
|
||||
self.environment = Some(environment);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self, ctx: &mut BuildContext) -> Handle<HashMapPropertyEditor<K>> {
|
||||
pub fn build(
|
||||
self,
|
||||
ctx: &mut PropertyEditorBuildContext,
|
||||
) -> Handle<HashMapPropertyEditor<K, V, S>> {
|
||||
let add = ButtonBuilder::new(WidgetBuilder::new().on_row(0).on_column(0))
|
||||
.with_text("Add...")
|
||||
.build(ctx);
|
||||
.build(ctx.build_context);
|
||||
|
||||
let children = self
|
||||
.entries
|
||||
.iter()
|
||||
let hash_map = self
|
||||
.hash_map
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.flat_map(|(i, e)| {
|
||||
.filter_map(|(i, (key, value))| {
|
||||
let key_editor_instance = create_key_editor(&key, ctx)?;
|
||||
let value_editor_instance = create_value_editor(&value, ctx)?;
|
||||
let remove = ButtonBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_width(24.0)
|
||||
.with_height(24.0)
|
||||
.with_vertical_alignment(VerticalAlignment::Center),
|
||||
)
|
||||
.with_text("-")
|
||||
.build(ctx.build_context);
|
||||
|
||||
let row = i + 1; // "add" button occupies the first row
|
||||
let key_editor = e.key_editor.editor();
|
||||
let key_editor_ref = &mut ctx[key_editor];
|
||||
let key_editor = key_editor_instance.editor();
|
||||
let key_editor_ref = &mut ctx.build_context[key_editor];
|
||||
key_editor_ref.set_row(row);
|
||||
key_editor_ref.set_column(0);
|
||||
let value_editor = e.value_editor.editor();
|
||||
let value_editor_ref = &mut ctx[value_editor];
|
||||
let value_editor = value_editor_instance.editor();
|
||||
let value_editor_ref = &mut ctx.build_context[value_editor];
|
||||
value_editor_ref.set_row(row);
|
||||
value_editor_ref.set_column(1);
|
||||
let remove_ref = &mut ctx[e.remove];
|
||||
let remove_ref = &mut ctx.build_context[remove];
|
||||
remove_ref.set_row(row);
|
||||
remove_ref.set_column(2);
|
||||
[key_editor, value_editor, e.remove.to_base()]
|
||||
Some((
|
||||
key,
|
||||
Entry {
|
||||
key_editor: key_editor_instance,
|
||||
value_editor: value_editor_instance,
|
||||
remove,
|
||||
value,
|
||||
},
|
||||
))
|
||||
})
|
||||
.collect::<HashMap<K, Entry<V>, S>>();
|
||||
|
||||
let children = hash_map
|
||||
.values()
|
||||
.flat_map(|entry| {
|
||||
Some([
|
||||
entry.key_editor.editor(),
|
||||
entry.value_editor.editor(),
|
||||
entry.remove.to_base(),
|
||||
])
|
||||
})
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let grid = GridBuilder::new(WidgetBuilder::new().with_child(add).with_children(children))
|
||||
.add_row(Row::auto())
|
||||
.add_rows(self.entries.iter().map(|_| Row::auto()).collect::<Vec<_>>())
|
||||
.add_rows(hash_map.iter().map(|_| Row::auto()).collect::<Vec<_>>())
|
||||
.add_columns(vec![Column::auto(), Column::stretch(), Column::auto()])
|
||||
.build(ctx);
|
||||
.build(ctx.build_context);
|
||||
|
||||
ctx.add(HashMapPropertyEditor {
|
||||
ctx.build_context.add(HashMapPropertyEditor {
|
||||
widget: self
|
||||
.widget_builder
|
||||
.with_child(grid)
|
||||
.with_preview_messages(true)
|
||||
.build(ctx),
|
||||
entries: self.entries,
|
||||
.build(ctx.build_context),
|
||||
add,
|
||||
property_editors: self.property_editors,
|
||||
environment: self.environment,
|
||||
property_editors: ctx.definition_container.clone(),
|
||||
environment: ctx.environment.clone(),
|
||||
dialog: Default::default(),
|
||||
hash_map,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,24 +21,18 @@
|
||||
mod dialog;
|
||||
pub mod editor;
|
||||
|
||||
use crate::inspector::ObjectValue;
|
||||
use crate::{
|
||||
button::ButtonBuilder,
|
||||
core::{
|
||||
reflect::{self, prelude::*, FieldMetadata, FieldRef},
|
||||
PhantomDataSendSync,
|
||||
},
|
||||
core::{reflect::prelude::*, PhantomDataSendSync},
|
||||
inspector::{
|
||||
editors::{
|
||||
hashmap::editor::{Entry, HashMapPropertyEditorBuilder, HashMapPropertyEditorMessage},
|
||||
hashmap::editor::{HashMapPropertyEditorBuilder, HashMapPropertyEditorMessage},
|
||||
PropertyEditorBuildContext, PropertyEditorDefinition, PropertyEditorInstance,
|
||||
PropertyEditorMessageContext, PropertyEditorTranslationContext,
|
||||
},
|
||||
FieldAction, HashMapAction, InspectorError, PropertyChanged,
|
||||
FieldAction, HashMapAction, InspectorError, ObjectValue, PropertyChanged,
|
||||
},
|
||||
message::{MessageDirection, UiMessage},
|
||||
widget::WidgetBuilder,
|
||||
VerticalAlignment,
|
||||
};
|
||||
use std::{
|
||||
any::TypeId,
|
||||
@@ -53,8 +47,8 @@ impl<T: Reflect + Send + Eq + Hash + Clone + PartialEq + Default> HashMapKey for
|
||||
pub trait HashMapValue: Reflect + Clone + PartialEq + Default + Send {}
|
||||
impl<T: Reflect + Clone + PartialEq + Default + Send> HashMapValue for T {}
|
||||
|
||||
pub trait HashMapState: BuildHasher + Clone + Debug + 'static {}
|
||||
impl<T: BuildHasher + Clone + Debug + 'static> HashMapState for T {}
|
||||
pub trait HashMapState: BuildHasher + Clone + Debug + PartialEq + Default + Send + 'static {}
|
||||
impl<T: BuildHasher + Clone + Debug + Send + PartialEq + Default + 'static> HashMapState for T {}
|
||||
|
||||
pub struct HashMapPropertyEditorDefinition<K, V, S>
|
||||
where
|
||||
@@ -96,98 +90,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
fn create_key_editor<K>(
|
||||
key: &K,
|
||||
ctx: &mut PropertyEditorBuildContext,
|
||||
) -> Option<PropertyEditorInstance>
|
||||
where
|
||||
K: HashMapKey,
|
||||
{
|
||||
let key_property_editor = ctx.definition_container.get::<K>()?;
|
||||
|
||||
let property_info = ctx.property_info;
|
||||
|
||||
let key_name = reflect::make_hash_map_key(key);
|
||||
|
||||
let key_property_info = FieldRef {
|
||||
metadata: &FieldMetadata {
|
||||
name: &key_name,
|
||||
display_name: &key_name,
|
||||
read_only: property_info.read_only,
|
||||
immutable_collection: property_info.immutable_collection,
|
||||
min_value: property_info.min_value,
|
||||
max_value: property_info.max_value,
|
||||
step: property_info.step,
|
||||
precision: property_info.precision,
|
||||
tag: property_info.tag,
|
||||
doc: property_info.doc,
|
||||
},
|
||||
value: key,
|
||||
};
|
||||
|
||||
key_property_editor
|
||||
.property_editor
|
||||
.create_instance(PropertyEditorBuildContext {
|
||||
build_context: ctx.build_context,
|
||||
property_info: &key_property_info,
|
||||
environment: ctx.environment.clone(),
|
||||
definition_container: ctx.definition_container.clone(),
|
||||
layer_index: ctx.layer_index,
|
||||
generate_property_string_values: ctx.generate_property_string_values,
|
||||
filter: ctx.filter.clone(),
|
||||
name_column_width: ctx.name_column_width,
|
||||
hide_name_column: ctx.hide_name_column,
|
||||
base_path: ctx.base_path.clone(),
|
||||
has_parent_object: ctx.has_parent_object,
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
fn create_value_editor<V>(
|
||||
key: &V,
|
||||
ctx: &mut PropertyEditorBuildContext,
|
||||
) -> Option<PropertyEditorInstance>
|
||||
where
|
||||
V: HashMapValue,
|
||||
{
|
||||
let value_property_editor = ctx.definition_container.get::<V>()?;
|
||||
|
||||
let property_info = ctx.property_info;
|
||||
|
||||
let value_property_info = FieldRef {
|
||||
metadata: &FieldMetadata {
|
||||
name: property_info.name,
|
||||
display_name: property_info.display_name,
|
||||
read_only: property_info.read_only,
|
||||
immutable_collection: property_info.immutable_collection,
|
||||
min_value: property_info.min_value,
|
||||
max_value: property_info.max_value,
|
||||
step: property_info.step,
|
||||
precision: property_info.precision,
|
||||
tag: property_info.tag,
|
||||
doc: property_info.doc,
|
||||
},
|
||||
value: key,
|
||||
};
|
||||
|
||||
value_property_editor
|
||||
.property_editor
|
||||
.create_instance(PropertyEditorBuildContext {
|
||||
build_context: ctx.build_context,
|
||||
property_info: &value_property_info,
|
||||
environment: ctx.environment.clone(),
|
||||
definition_container: ctx.definition_container.clone(),
|
||||
layer_index: ctx.layer_index,
|
||||
generate_property_string_values: ctx.generate_property_string_values,
|
||||
filter: ctx.filter.clone(),
|
||||
name_column_width: ctx.name_column_width,
|
||||
hide_name_column: ctx.hide_name_column,
|
||||
base_path: ctx.base_path.clone(),
|
||||
has_parent_object: ctx.has_parent_object,
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
impl<K, V, S> PropertyEditorDefinition for HashMapPropertyEditorDefinition<K, V, S>
|
||||
where
|
||||
K: HashMapKey,
|
||||
@@ -204,48 +106,33 @@ where
|
||||
) -> Result<PropertyEditorInstance, InspectorError> {
|
||||
let hash_map = ctx.property_info.cast_value::<HashMap<K, V, S>>()?;
|
||||
|
||||
let entries = hash_map
|
||||
.iter()
|
||||
.filter_map(|(key, value)| {
|
||||
Some(Entry {
|
||||
key: key.clone(),
|
||||
key_hash: hash_map.hasher().hash_one(key),
|
||||
key_editor: create_key_editor(key, &mut ctx)?,
|
||||
value_editor: create_value_editor(value, &mut ctx)?,
|
||||
remove: ButtonBuilder::new(
|
||||
WidgetBuilder::new()
|
||||
.with_width(24.0)
|
||||
.with_height(24.0)
|
||||
.with_vertical_alignment(VerticalAlignment::Center),
|
||||
)
|
||||
.with_text("-")
|
||||
.build(ctx.build_context),
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let editor = HashMapPropertyEditorBuilder::new(
|
||||
WidgetBuilder::new(),
|
||||
ctx.definition_container.clone(),
|
||||
)
|
||||
.with_entries(entries)
|
||||
.build(ctx.build_context)
|
||||
.to_base();
|
||||
let editor = HashMapPropertyEditorBuilder::<K, V, S>::new(WidgetBuilder::new())
|
||||
.with_hash_map(hash_map.clone())
|
||||
.build(&mut ctx)
|
||||
.to_base();
|
||||
|
||||
Ok(PropertyEditorInstance::Simple { editor })
|
||||
}
|
||||
|
||||
fn create_message(
|
||||
&self,
|
||||
_ctx: PropertyEditorMessageContext,
|
||||
ctx: PropertyEditorMessageContext,
|
||||
) -> Result<Option<UiMessage>, InspectorError> {
|
||||
// TODO
|
||||
Ok(None)
|
||||
let hash_map = ctx.property_info.cast_value::<HashMap<K, V, S>>()?;
|
||||
|
||||
// TODO: Very unoptimal solution. It is probably better to access the editor instance and
|
||||
// see which entries it has and update/remove/add respective.
|
||||
Ok(Some(UiMessage::for_widget(
|
||||
ctx.instance,
|
||||
HashMapPropertyEditorMessage::Update {
|
||||
hash_map: hash_map.clone(),
|
||||
},
|
||||
)))
|
||||
}
|
||||
|
||||
fn translate_message(&self, ctx: PropertyEditorTranslationContext) -> Option<PropertyChanged> {
|
||||
if ctx.message.direction() == MessageDirection::FromWidget {
|
||||
if let Some(msg) = ctx.message.data::<HashMapPropertyEditorMessage>() {
|
||||
if let Some(msg) = ctx.message.data::<HashMapPropertyEditorMessage<K, V, S>>() {
|
||||
match msg {
|
||||
HashMapPropertyEditorMessage::ValueChanged { key, message } => {
|
||||
if let Some(definition) = ctx.definition_container.get::<V>() {
|
||||
@@ -253,7 +140,7 @@ where
|
||||
name: ctx.name.to_string(),
|
||||
action: FieldAction::HashMapAction(Box::new(
|
||||
HashMapAction::ValueChanged {
|
||||
key: key.clone(),
|
||||
key: ObjectValue::new(key.clone()),
|
||||
action: definition
|
||||
.property_editor
|
||||
.translate_message(PropertyEditorTranslationContext {
|
||||
@@ -276,7 +163,7 @@ where
|
||||
name: ctx.name.to_string(),
|
||||
action: FieldAction::HashMapAction(Box::new(
|
||||
HashMapAction::KeyChanged {
|
||||
key: key.clone(),
|
||||
key: ObjectValue::new(key.clone()),
|
||||
action: definition
|
||||
.property_editor
|
||||
.translate_message(PropertyEditorTranslationContext {
|
||||
@@ -297,7 +184,7 @@ where
|
||||
return Some(PropertyChanged {
|
||||
name: ctx.name.to_string(),
|
||||
action: FieldAction::HashMapAction(Box::new(HashMapAction::Remove {
|
||||
key: key.clone(),
|
||||
key: ObjectValue::new(key.clone()),
|
||||
})),
|
||||
});
|
||||
}
|
||||
@@ -305,11 +192,14 @@ where
|
||||
return Some(PropertyChanged {
|
||||
name: ctx.name.to_string(),
|
||||
action: FieldAction::HashMapAction(Box::new(HashMapAction::Insert {
|
||||
key: key.clone(),
|
||||
key: ObjectValue::new(key.clone()),
|
||||
value: ObjectValue::new(V::default()),
|
||||
})),
|
||||
});
|
||||
}
|
||||
HashMapPropertyEditorMessage::Update { .. } => {
|
||||
// Sync only.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user