From d6addaa45aa976e48962709a4e729edfcc55a22b Mon Sep 17 00:00:00 2001 From: Lars Brubaker Date: Thu, 12 Apr 2018 17:23:19 -0700 Subject: [PATCH] Improving Package tool Changing public property editor to be able to dynamically add new properties --- DesignTools/Operations/Align3D.cs | 12 +- DesignTools/Operations/Package3D.cs | 95 ++- DesignTools/PublicPropertyEditor.cs | 720 ++++++++++++----------- PartPreviewWindow/SelectedObjectPanel.cs | 4 +- Submodules/MatterSlice | 2 +- Submodules/agg-sharp | 2 +- 6 files changed, 450 insertions(+), 385 deletions(-) diff --git a/DesignTools/Operations/Align3D.cs b/DesignTools/Operations/Align3D.cs index 36b93ea0e..278694520 100644 --- a/DesignTools/Operations/Align3D.cs +++ b/DesignTools/Operations/Align3D.cs @@ -423,12 +423,12 @@ namespace MatterHackers.MatterControl.DesignTools.Operations public void UpdateControls(PublicPropertyEditor editor) { - editor.GetEditRow(nameof(XAlignTo)).Visible = Advanced && XAlign != Align.Origin; - editor.GetEditRow(nameof(XOffset)).Visible = Advanced; - editor.GetEditRow(nameof(YAlignTo)).Visible = Advanced && YAlign != Align.Origin; - editor.GetEditRow(nameof(YOffset)).Visible = Advanced; - editor.GetEditRow(nameof(ZAlignTo)).Visible = Advanced && ZAlign != Align.Origin; - editor.GetEditRow(nameof(ZOffset)).Visible = Advanced; + editor.GetEditRow((this.ID, nameof(XAlignTo))).Visible = Advanced && XAlign != Align.Origin; + editor.GetEditRow((this.ID, nameof(XOffset))).Visible = Advanced; + editor.GetEditRow((this.ID, nameof(YAlignTo))).Visible = Advanced && YAlign != Align.Origin; + editor.GetEditRow((this.ID, nameof(YOffset))).Visible = Advanced; + editor.GetEditRow((this.ID, nameof(ZAlignTo))).Visible = Advanced && ZAlign != Align.Origin; + editor.GetEditRow((this.ID, nameof(ZOffset))).Visible = Advanced; } private static bool IsSet(Face variableToCheck, Face faceToCheckFor, Face faceToAssertNot) diff --git a/DesignTools/Operations/Package3D.cs b/DesignTools/Operations/Package3D.cs index dca900c97..b8e839ef3 100644 --- a/DesignTools/Operations/Package3D.cs +++ b/DesignTools/Operations/Package3D.cs @@ -1,33 +1,73 @@ -using System; -using System.ComponentModel; -using System.Linq; -using System.Threading; -using MatterHackers.Agg.Font; +/* +Copyright (c) 2018, Lars Brubaker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; -using MatterHackers.VectorMath; -using MatterHackers.PolygonMesh; +using Newtonsoft.Json; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; namespace MatterHackers.MatterControl.DesignTools.Operations { public class Package3D : Object3D, IRebuildable { - public string NameToWrite { get; set; } public Package3D() { + } + [JsonIgnore] + private SubProperties _subProperties = new SubProperties(); + [JsonIgnore] + public SubProperties LiftedProperties + { + get + { + _subProperties.Items.Clear(); + foreach (var child in this.Descendants()) + { + PropertyInfo propertyToEdit = child.GetType().GetProperties().First(); + _subProperties.Items.Add(new EditableProperty(propertyToEdit, child)); + } + return _subProperties; + } + + set + { + // only here so it will show up in PublicPropertyEditor + } } public static Package3D Create(IObject3D itemToPackage) { Package3D package = new Package3D(); - var text = itemToPackage.Descendants().FirstOrDefault(); - if (text != null) - { - package.NameToWrite = text.NameToWrite; - } - package.Children.Add(itemToPackage); return package; @@ -35,26 +75,21 @@ namespace MatterHackers.MatterControl.DesignTools.Operations public void Rebuild(UndoBuffer undoBuffer) { - var text = this.Descendants().FirstOrDefault(); - if (text != null) + foreach (var child in this.Descendants()) { - text.NameToWrite = this.NameToWrite; - text.Rebuild(null); - } + child.Rebuild(null); - var fit = this.Descendants().FirstOrDefault(); - if (fit != null) - { - fit.Rebuild(null); - } - - var align = this.Descendants().FirstOrDefault(); - if (align != null) - { - align.Rebuild(null); + foreach (var parent in child.Parents()) + { + if (parent is IRebuildable rebuildable + && parent != this) + { + rebuildable.Rebuild(null); + } + } } return; } } -} +} \ No newline at end of file diff --git a/DesignTools/PublicPropertyEditor.cs b/DesignTools/PublicPropertyEditor.cs index 16adcd6f6..04ed0895c 100644 --- a/DesignTools/PublicPropertyEditor.cs +++ b/DesignTools/PublicPropertyEditor.cs @@ -46,6 +46,45 @@ using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.DesignTools { + public class EditableProperty + { + public IObject3D Item { get; private set; } + public PropertyInfo PropertyInfo { get; private set; } + public EditableProperty(PropertyInfo p, IObject3D item) + { + this.Item = item; + this.PropertyInfo = p; + } + + private string GetDescription(PropertyInfo prop) + { + var nameAttribute = prop.GetCustomAttributes(true).OfType().FirstOrDefault(); + return nameAttribute?.Description ?? null; + } + + public static string GetDisplayName(PropertyInfo prop) + { + var nameAttribute = prop.GetCustomAttributes(true).OfType().FirstOrDefault(); + return nameAttribute?.DisplayName ?? prop.Name.SplitCamelCase(); + } + + public object Value => PropertyInfo.GetGetMethod().Invoke(Item, null); + public string DisplayName => GetDisplayName(PropertyInfo); + public string Description => GetDescription(PropertyInfo); + public Type ptype => PropertyInfo.PropertyType; + } + + public class SubProperties + { + public List Items = new List(); + public virtual IEnumerable GetProperties() + { + foreach (var item in Items) + { + yield return item; + } + } + } public class PublicPropertyEditor : IObject3DEditor { @@ -57,14 +96,14 @@ namespace MatterHackers.MatterControl.DesignTools public IEnumerable SupportedTypes() => new Type[] { typeof(IRebuildable) }; - private Dictionary editRows = new Dictionary(); + private Dictionary<(string id, string propertyName), GuiWidget> editRows = new Dictionary<(string id, string propertyName), GuiWidget>(); private static Type[] allowedTypes = { typeof(double), typeof(int), typeof(char), typeof(string), typeof(bool), typeof(Vector2), typeof(Vector3), typeof(DirectionVector), typeof(DirectionAxis), - typeof(ImageObject3D) + typeof(ImageObject3D), typeof(SubProperties) }; private static Type IObject3DType = typeof(IObject3D); @@ -98,10 +137,10 @@ namespace MatterHackers.MatterControl.DesignTools return mainContainer; } - public GuiWidget GetEditRow(string propertyName) + public GuiWidget GetEditRow((string id, string propertyName) key) { GuiWidget value; - if (editRows.TryGetValue(propertyName, out value)) + if (editRows.TryGetValue(key, out value)) { return value; } @@ -130,35 +169,7 @@ namespace MatterHackers.MatterControl.DesignTools return rowContainer; } - public static string GetDisplayName(PropertyInfo prop) - { - var nameAttribute = prop.GetCustomAttributes(true).OfType().FirstOrDefault(); - return nameAttribute?.DisplayName ?? prop.Name.SplitCamelCase(); - } - - public class EditableProperty - { - public Object Item { get; private set; } - public PropertyInfo PropertyInfo { get; private set; } - public EditableProperty(PropertyInfo p, object item) - { - this.Item = item; - this.PropertyInfo = p; - } - - private string GetDescription(PropertyInfo prop) - { - var nameAttribute = prop.GetCustomAttributes(true).OfType().FirstOrDefault(); - return nameAttribute?.Description ?? null; - } - - public object Value => PropertyInfo.GetGetMethod().Invoke(Item, null); - public string DisplayName => GetDisplayName(PropertyInfo); - public string Description => GetDescription(PropertyInfo); - public Type ptype => PropertyInfo.PropertyType; - } - - public static IEnumerable GetEditablePropreties(Object item) + public static IEnumerable GetEditablePropreties(IObject3D item) { return item.GetType().GetProperties(OwnedPropertiesOnly) .Where(pi => (allowedTypes.Contains(pi.PropertyType) || pi.PropertyType.IsEnum) @@ -182,308 +193,7 @@ namespace MatterHackers.MatterControl.DesignTools foreach (var property in editableProperties) { - GuiWidget rowContainer = null; - - // create a double editor - if (property.Value is double doubleValue) - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var field = new DoubleField(); - field.Initialize(0); - field.DoubleValue = doubleValue; - field.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { field.DoubleValue }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - rowContainer.AddChild(field.Content); - editControlsContainer.AddChild(rowContainer); - } - else if (property.Value is Vector2 vector2) - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var field = new Vector2Field(); - field.Initialize(0); - field.Vector2 = vector2; - field.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { field.Vector2 }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - rowContainer.AddChild(field.Content); - editControlsContainer.AddChild(rowContainer); - } - else if (property.Value is Vector3 vector3) - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var field = new Vector3Field(); - field.Initialize(0); - field.Vector3 = vector3; - field.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { field.Vector3 }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - rowContainer.AddChild(field.Content); - editControlsContainer.AddChild(rowContainer); - } - else if (property.Value is DirectionVector directionVector) - { - bool simpleEdit = true; - if (simpleEdit) - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var dropDownList = new DropDownList("Name".Localize(), theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize) - { - BorderColor = theme.GetBorderColor(75) - }; - - var orderedItems = new string[] { "Right", "Back", "Up" }; - - foreach (var orderItem in orderedItems) - { - MenuItem newItem = dropDownList.AddItem(orderItem); - - var localOredrItem = orderItem; - newItem.Selected += (sender, e) => - { - switch (dropDownList.SelectedValue) - { - case "Right": - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { new DirectionVector() { Normal = Vector3.UnitX } }); - break; - case "Back": - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { new DirectionVector() { Normal = Vector3.UnitY } }); - break; - case "Up": - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { new DirectionVector() { Normal = Vector3.UnitZ } }); - break; - } - - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - } - - dropDownList.SelectedLabel = "Right"; - rowContainer.AddChild(dropDownList); - editControlsContainer.AddChild(rowContainer); - } - else // edit the vector - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var field = new Vector3Field(); - field.Initialize(0); - field.Vector3 = directionVector.Normal; - field.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { new DirectionVector() { Normal = field.Vector3 } }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - rowContainer.AddChild(field.Content); - editControlsContainer.AddChild(rowContainer); - } - } - else if (property.Value is DirectionAxis directionAxis) - { - bool simpleAxis = true; - - if (simpleAxis) - { - // the direction axis - // the distance from the center of the part - // create a double editor - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var field = new DoubleField(); - field.Initialize(0); - field.DoubleValue = directionAxis.Origin.X - item.Children.First().GetAxisAlignedBoundingBox().Center.X; - field.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] - { - new DirectionAxis() - { - Normal = Vector3.UnitZ, Origin = item.Children.First().GetAxisAlignedBoundingBox().Center + new Vector3(field.DoubleValue, 0, 0) - } - }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - rowContainer.AddChild(field.Content); - editControlsContainer.AddChild(rowContainer); - - // update tihs when changed - EventHandler updateData = (object s, EventArgs e) => - { - field.DoubleValue = ((DirectionAxis)property.PropertyInfo.GetGetMethod().Invoke(this.item, null)).Origin.X - item.Children.First().GetAxisAlignedBoundingBox().Center.X; - }; - item.Invalidated += updateData; - editControlsContainer.Closed += (s, e) => - { - item.Invalidated -= updateData; - }; - } - else - { - // add in the position - FlowLayoutWidget originRowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var originField = new Vector3Field(); - originField.Initialize(0); - originField.Vector3 = directionAxis.Origin; - - var normalField = new Vector3Field(); - normalField.Initialize(0); - normalField.Vector3 = directionAxis.Normal; - - originField.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { new DirectionAxis() { Origin = originField.Vector3, Normal = normalField.Vector3 } }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - originRowContainer.AddChild(originField.Content); - editControlsContainer.AddChild(originRowContainer); - - // add in the direction - FlowLayoutWidget directionRowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - normalField.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { new DirectionAxis() { Origin = originField.Vector3, Normal = normalField.Vector3 } }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - directionRowContainer.AddChild(normalField.Content); - editControlsContainer.AddChild(directionRowContainer); - - // update tihs when changed - EventHandler updateData = (object s, EventArgs e) => - { - originField.Vector3 = ((DirectionAxis)property.PropertyInfo.GetGetMethod().Invoke(this.item, null)).Origin; - }; - item.Invalidated += updateData; - editControlsContainer.Closed += (s, e) => - { - item.Invalidated -= updateData; - }; - } - } - // create a int editor - else if (property.Value is int intValue) - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - - var field = new IntField(); - field.Initialize(0); - field.IntValue = intValue; - field.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { field.IntValue }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - rowContainer.AddChild(field.Content); - editControlsContainer.AddChild(rowContainer); - } - // create a bool editor - else if (property.Value is bool boolValue) - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize(), property.Description.Localize()); - - var field = new ToggleboxField(theme); - field.Initialize(0); - field.Checked = boolValue; - field.ValueChanged += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { field.Checked }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - - rowContainer.AddChild(field.Content); - editControlsContainer.AddChild(rowContainer); - } - // create a string editor - else if (property.Value is string stringValue) - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - var textEditWidget = new MHTextEditWidget(stringValue, pixelWidth: 150 * GuiWidget.DeviceScale) - { - SelectAllOnFocus = true, - VAnchor = VAnchor.Center - }; - textEditWidget.ActualTextEditWidget.EditComplete += (s, e) => - { - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { textEditWidget.Text }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - rowContainer.AddChild(textEditWidget); - editControlsContainer.AddChild(rowContainer); - } - // create a char editor - else if (property.Value is char charValue) - { - rowContainer = CreateSettingsRow(property.DisplayName.Localize()); - var textEditWidget = new MHTextEditWidget(charValue.ToString(), pixelWidth: 150 * GuiWidget.DeviceScale) - { - SelectAllOnFocus = true, - VAnchor = VAnchor.Center - }; - textEditWidget.ActualTextEditWidget.EditComplete += (s, e) => - { - if (textEditWidget.Text.Length < 1) - { - textEditWidget.Text = "a"; - } - if (textEditWidget.Text.Length > 1) - { - textEditWidget.Text = textEditWidget.Text.Substring(0, 1); - } - property.PropertyInfo.GetSetMethod().Invoke(this.item, new Object[] { textEditWidget.Text[0] }); - rebuildable?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); - }; - rowContainer.AddChild(textEditWidget); - editControlsContainer.AddChild(rowContainer); - } - // create an enum editor - else if (property.ptype.IsEnum) - { - rowContainer = CreateEnumEditor(rebuildable, - property.PropertyInfo, property.ptype, property.Value, property.DisplayName, - theme, undoBuffer); - editControlsContainer.AddChild(rowContainer); - } - // Use known IObject3D editors - else if (property.Value is IObject3D object3D - && ApplicationController.Instance.GetEditorsForType(property.ptype)?.FirstOrDefault() is IObject3DEditor editor) - { - rowContainer = editor.Create( object3D, view3DWidget, theme); - editControlsContainer.AddChild(rowContainer); - } - - // remember the row name and widget - editRows.Add(property.PropertyInfo.Name, rowContainer); + AddPropertyEditor(this, view3DWidget, editControlsContainer, theme, undoBuffer, rebuildable, propertyGridModifier, property, editRows); } var hideUpdate = item.GetType().GetCustomAttributes(typeof(HideUpdateButtonAttribute), true).FirstOrDefault() as HideUpdateButtonAttribute; @@ -498,10 +208,330 @@ namespace MatterHackers.MatterControl.DesignTools }; editControlsContainer.AddChild(updateButton); } + // make sure the ui is set right to start propertyGridModifier?.UpdateControls(this); } + private static void AddPropertyEditor(PublicPropertyEditor publicPropertyEditor, + View3DWidget view3DWidget, FlowLayoutWidget editControlsContainer, ThemeConfig theme, + UndoBuffer undoBuffer, IRebuildable rebuildable, IPropertyGridModifier propertyGridModifier, + EditableProperty property, Dictionary<(string id, string propertyName), GuiWidget> editRows) + { + GuiWidget rowContainer = null; + + // create a double editor + if (property.Value is double doubleValue) + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + var field = new DoubleField(); + field.Initialize(0); + field.DoubleValue = doubleValue; + field.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { field.DoubleValue }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + rowContainer.AddChild(field.Content); + editControlsContainer.AddChild(rowContainer); + } + else if (property.Value is SubProperties subProperties) + { + foreach(var subProperty in subProperties.GetProperties()) + { + AddPropertyEditor(publicPropertyEditor, view3DWidget, editControlsContainer, theme, undoBuffer, + rebuildable, propertyGridModifier, subProperty, editRows); + } + // don't add a row, they were added for the individual properties + return; + } + else if (property.Value is Vector2 vector2) + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + var field = new Vector2Field(); + field.Initialize(0); + field.Vector2 = vector2; + field.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { field.Vector2 }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + rowContainer.AddChild(field.Content); + editControlsContainer.AddChild(rowContainer); + } + else if (property.Value is Vector3 vector3) + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + var field = new Vector3Field(); + field.Initialize(0); + field.Vector3 = vector3; + field.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { field.Vector3 }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + rowContainer.AddChild(field.Content); + editControlsContainer.AddChild(rowContainer); + } + else if (property.Value is DirectionVector directionVector) + { + bool simpleEdit = true; + if (simpleEdit) + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + var dropDownList = new DropDownList("Name".Localize(), theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize) + { + BorderColor = theme.GetBorderColor(75) + }; + + var orderedItems = new string[] { "Right", "Back", "Up" }; + + foreach (var orderItem in orderedItems) + { + MenuItem newItem = dropDownList.AddItem(orderItem); + + var localOredrItem = orderItem; + newItem.Selected += (sender, e) => + { + switch (dropDownList.SelectedValue) + { + case "Right": + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { new DirectionVector() { Normal = Vector3.UnitX } }); + break; + case "Back": + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { new DirectionVector() { Normal = Vector3.UnitY } }); + break; + case "Up": + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { new DirectionVector() { Normal = Vector3.UnitZ } }); + break; + } + + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + } + + dropDownList.SelectedLabel = "Right"; + rowContainer.AddChild(dropDownList); + editControlsContainer.AddChild(rowContainer); + } + else // edit the vector + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + var field = new Vector3Field(); + field.Initialize(0); + field.Vector3 = directionVector.Normal; + field.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { new DirectionVector() { Normal = field.Vector3 } }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + rowContainer.AddChild(field.Content); + editControlsContainer.AddChild(rowContainer); + } + } + else if (property.Value is DirectionAxis directionAxis) + { + bool simpleAxis = true; + + if (simpleAxis) + { + // the direction axis + // the distance from the center of the part + // create a double editor + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + var field = new DoubleField(); + field.Initialize(0); + field.DoubleValue = directionAxis.Origin.X - property.Item.Children.First().GetAxisAlignedBoundingBox().Center.X; + field.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] + { + new DirectionAxis() + { + Normal = Vector3.UnitZ, Origin = property.Item.Children.First().GetAxisAlignedBoundingBox().Center + new Vector3(field.DoubleValue, 0, 0) + } + }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + rowContainer.AddChild(field.Content); + editControlsContainer.AddChild(rowContainer); + + // update tihs when changed + EventHandler updateData = (object s, EventArgs e) => + { + field.DoubleValue = ((DirectionAxis)property.PropertyInfo.GetGetMethod().Invoke(property.Item, null)).Origin.X - property.Item.Children.First().GetAxisAlignedBoundingBox().Center.X; + }; + property.Item.Invalidated += updateData; + editControlsContainer.Closed += (s, e) => + { + property.Item.Invalidated -= updateData; + }; + } + else + { + // add in the position + FlowLayoutWidget originRowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + var originField = new Vector3Field(); + originField.Initialize(0); + originField.Vector3 = directionAxis.Origin; + + var normalField = new Vector3Field(); + normalField.Initialize(0); + normalField.Vector3 = directionAxis.Normal; + + originField.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { new DirectionAxis() { Origin = originField.Vector3, Normal = normalField.Vector3 } }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + originRowContainer.AddChild(originField.Content); + editControlsContainer.AddChild(originRowContainer); + + // add in the direction + FlowLayoutWidget directionRowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + normalField.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { new DirectionAxis() { Origin = originField.Vector3, Normal = normalField.Vector3 } }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + directionRowContainer.AddChild(normalField.Content); + editControlsContainer.AddChild(directionRowContainer); + + // update tihs when changed + EventHandler updateData = (object s, EventArgs e) => + { + originField.Vector3 = ((DirectionAxis)property.PropertyInfo.GetGetMethod().Invoke(property.Item, null)).Origin; + }; + property.Item.Invalidated += updateData; + editControlsContainer.Closed += (s, e) => + { + property.Item.Invalidated -= updateData; + }; + } + } + // create a int editor + else if (property.Value is int intValue) + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + + var field = new IntField(); + field.Initialize(0); + field.IntValue = intValue; + field.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { field.IntValue }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + rowContainer.AddChild(field.Content); + editControlsContainer.AddChild(rowContainer); + } + // create a bool editor + else if (property.Value is bool boolValue) + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize(), property.Description.Localize()); + + var field = new ToggleboxField(theme.Colors.PrimaryTextColor); + field.Initialize(0); + field.Checked = boolValue; + field.ValueChanged += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { field.Checked }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + + rowContainer.AddChild(field.Content); + editControlsContainer.AddChild(rowContainer); + } + // create a string editor + else if (property.Value is string stringValue) + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + var textEditWidget = new MHTextEditWidget(stringValue, pixelWidth: 150 * GuiWidget.DeviceScale) + { + SelectAllOnFocus = true, + VAnchor = VAnchor.Center + }; + textEditWidget.ActualTextEditWidget.EditComplete += (s, e) => + { + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { textEditWidget.Text }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + rowContainer.AddChild(textEditWidget); + editControlsContainer.AddChild(rowContainer); + } + // create a char editor + else if (property.Value is char charValue) + { + rowContainer = CreateSettingsRow(property.DisplayName.Localize()); + var textEditWidget = new MHTextEditWidget(charValue.ToString(), pixelWidth: 150 * GuiWidget.DeviceScale) + { + SelectAllOnFocus = true, + VAnchor = VAnchor.Center + }; + textEditWidget.ActualTextEditWidget.EditComplete += (s, e) => + { + if (textEditWidget.Text.Length < 1) + { + textEditWidget.Text = "a"; + } + if (textEditWidget.Text.Length > 1) + { + textEditWidget.Text = textEditWidget.Text.Substring(0, 1); + } + property.PropertyInfo.GetSetMethod().Invoke(property.Item, new Object[] { textEditWidget.Text[0] }); + rebuildable?.Rebuild(undoBuffer); + propertyGridModifier?.UpdateControls(publicPropertyEditor); + }; + rowContainer.AddChild(textEditWidget); + editControlsContainer.AddChild(rowContainer); + } + // create an enum editor + else if (property.ptype.IsEnum) + { + rowContainer = CreateEnumEditor(publicPropertyEditor, rebuildable, + property, property.ptype, property.Value, property.DisplayName, + theme, undoBuffer); + editControlsContainer.AddChild(rowContainer); + } + // Use known IObject3D editors + else if (property.Value is IObject3D object3D + && ApplicationController.Instance.GetEditorsForType(property.ptype)?.FirstOrDefault() is IObject3DEditor editor) + { + rowContainer = editor.Create(object3D, view3DWidget, theme); + editControlsContainer.AddChild(rowContainer); + } + + // remember the row name and widget + editRows.Add((property.Item.ID, property.PropertyInfo.Name), rowContainer); + } + private void AddUnlockLinkIfRequired(FlowLayoutWidget editControlsContainer, ThemeConfig theme) { var unlockLink = item.GetType().GetCustomAttributes(typeof(UnlockLinkAttribute), true).FirstOrDefault() as UnlockLinkAttribute; @@ -541,8 +571,8 @@ namespace MatterHackers.MatterControl.DesignTools } } - private GuiWidget CreateEnumEditor(IRebuildable item, - PropertyInfo propertyInfo, Type propertyType, object value, string displayName, + private static GuiWidget CreateEnumEditor(PublicPropertyEditor publicPropertyEditor, IRebuildable item, + EditableProperty property, Type propertyType, object value, string displayName, ThemeConfig theme, UndoBuffer undoBuffer) { @@ -560,7 +590,7 @@ namespace MatterHackers.MatterControl.DesignTools FlowLayoutWidget rowContainer = CreateSettingsRow(displayName); - var iconsAttribute = propertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); + var iconsAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); if (iconsAttribute != null) { int index = 0; @@ -599,11 +629,11 @@ namespace MatterHackers.MatterControl.DesignTools { if (radioButton.Checked) { - propertyInfo.GetSetMethod().Invoke( - this.item, + property.PropertyInfo.GetSetMethod().Invoke( + property.Item, new Object[] { Enum.Parse(propertyType, localItem.Key) }); item?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); + propertyGridModifier?.UpdateControls(publicPropertyEditor); if (localIndex != 0 || !iconsAttribute.Item0IsNone) { @@ -626,7 +656,7 @@ namespace MatterHackers.MatterControl.DesignTools BorderColor = theme.GetBorderColor(75) }; - var sortableAttribute = propertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); + var sortableAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); var orderedItems = sortableAttribute != null ? enumItems.OrderBy(n => n.Value) : enumItems; foreach (var orderItem in orderedItems) @@ -636,11 +666,11 @@ namespace MatterHackers.MatterControl.DesignTools var localOrderedItem = orderItem; newItem.Selected += (sender, e) => { - propertyInfo.GetSetMethod().Invoke( - this.item, + property.PropertyInfo.GetSetMethod().Invoke( + property.Item, new Object[] { Enum.Parse(propertyType, localOrderedItem.Key) }); item?.Rebuild(undoBuffer); - propertyGridModifier?.UpdateControls(this); + propertyGridModifier?.UpdateControls(publicPropertyEditor); }; } diff --git a/PartPreviewWindow/SelectedObjectPanel.cs b/PartPreviewWindow/SelectedObjectPanel.cs index 82544a781..3000be276 100644 --- a/PartPreviewWindow/SelectedObjectPanel.cs +++ b/PartPreviewWindow/SelectedObjectPanel.cs @@ -290,7 +290,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { Type = propertyType, Value = item.GetValue(selectedItem, null) as IObject3D, - DisplayName = PublicPropertyEditor.GetDisplayName(item) + DisplayName = EditableProperty.GetDisplayName(item) }; // Shown known editors for any matching properties @@ -311,7 +311,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { Type = item.PropertyType, Value = item.GetValue(selectedItem, null) as IObject3D, - DisplayName = PublicPropertyEditor.GetDisplayName(item) + DisplayName = EditableProperty.GetDisplayName(item) }; // Shown known editors for any matching properties diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index 5d49759eb..8a12f59f4 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit 5d49759ebee1bcb93be08c4319de4155382b5ed2 +Subproject commit 8a12f59f45d02dfc21a62329d1e15a48e13956d1 diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index bcf6f08b3..b80c97daf 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit bcf6f08b3a27e3aeedf6229cb5a5cc0c9ddb4ae7 +Subproject commit b80c97dafebed4d6566bce4e29897b417d2d9558