diff --git a/CustomWidgets/ColorPicker/RadialColorPicker.cs b/CustomWidgets/ColorPicker/RadialColorPicker.cs new file mode 100644 index 000000000..43a321ff9 --- /dev/null +++ b/CustomWidgets/ColorPicker/RadialColorPicker.cs @@ -0,0 +1,342 @@ +/* +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; +using MatterHackers.Agg.Transform; +using MatterHackers.Agg.UI; +using MatterHackers.Agg.VertexSource; +using MatterHackers.RenderOpenGl; +using MatterHackers.RenderOpenGl.OpenGl; +using MatterHackers.VectorMath; +using System; + +namespace MatterHackers.MatterControl.CustomWidgets.ColorPicker +{ + public static class Graphics2DOverrides + { + public static void Ring(this Graphics2D graphics2D, Vector2 center, double radius, double width, Color color) + { + var ring = new Ellipse(center, radius); + var ringStroke = new Stroke(ring, width); + graphics2D.Render(ringStroke, color); + } + } + + public class RadialColorPicker : GuiWidget + { + private double colorAngle = 0; + private bool mouseDownOnRing; + private Vector2 unitTrianglePosition = new Vector2(0, 1); + + public RadialColorPicker() + { + BackgroundColor = Color.White; + + this.Width = 100; + this.Height = 100; + + if (!TriangleToWidgetTransform(0).Transform(new Vector2(1, .5)).Equals(new Vector2(88, 50), .01)) + { + //throw new Exception("Incorect transform"); + } + if (!TriangleToWidgetTransform(0).InverseTransform(new Vector2(88, 50)).Equals(new Vector2(1, .5), .01)) + { + //throw new Exception("Incorect transform"); + } + if (!TriangleToWidgetTransform(0).Transform(new Vector2(0, .5)).Equals(new Vector2(23.13, 50), .01)) + { + //throw new Exception("Incorect transform"); + } + } + + public bool mouseDownOnTriangle { get; private set; } + public double RingWidth { get => Width / 10; } + + public Color SelectedColor + { + get + { + return ColorF.FromHSL(colorAngle / MathHelper.Tau, 1, .5).ToColor(); + } + } + + public Color SelectedHueColor + { + get + { + return ColorF.FromHSL(colorAngle / MathHelper.Tau, 1, .5).ToColor(); + } + } + + private double InnerRadius + { + get + { + return RingRadius - RingWidth / 2; + } + } + + private double RingRadius + { + get + { + return Width / 2 - RingWidth / 2 - 2; + } + } + + public override void OnDraw(Graphics2D graphics2D) + { + var center = new Vector2(Width / 2, Height / 2); + var radius = new Vector2(RingRadius, RingRadius); + + // draw the big outside ring (color part) + DrawColorRing(graphics2D, RingRadius, RingWidth); + + // draw the inner triangle (color part) + DrawColorTriangle(graphics2D, InnerRadius, SelectedHueColor); + + // draw the big ring outline + graphics2D.Ring(center, RingRadius + RingWidth / 2, 1, Color.Black); + graphics2D.Ring(center, RingRadius - RingWidth / 2, 1, Color.Black); + + // draw the triangle outline + graphics2D.Line(GetTrianglePoint(0, InnerRadius, colorAngle), GetTrianglePoint(1, InnerRadius, colorAngle), Color.Black); + graphics2D.Line(GetTrianglePoint(1, InnerRadius, colorAngle), GetTrianglePoint(2, InnerRadius, colorAngle), Color.Black); + graphics2D.Line(GetTrianglePoint(2, InnerRadius, colorAngle), GetTrianglePoint(0, InnerRadius, colorAngle), Color.Black); + + // draw the color circle on the triangle + var triangleColorCenter = TriangleToWidgetTransform(colorAngle).Transform(unitTrianglePosition); + graphics2D.Circle(triangleColorCenter, + RingWidth / 2 - 2, + SelectedColor); + graphics2D.Ring(triangleColorCenter, + RingWidth / 2 - 2, + 2, + Color.White); + + // draw the color circle on the ring + var ringColorCenter = center + Vector2.Rotate(new Vector2(RingRadius, 0), colorAngle); + graphics2D.Circle(ringColorCenter, + RingWidth / 2 - 2, + SelectedHueColor); + graphics2D.Ring(ringColorCenter, + RingWidth / 2 - 2, + 2, + Color.White); + + base.OnDraw(graphics2D); + } + + public override void OnMouseDown(MouseEventArgs mouseEvent) + { + var center = new Vector2(Width / 2, Height / 2); + var direction = mouseEvent.Position - center; + + if (mouseEvent.Button == MouseButtons.Left) + { + if (direction.Length > RingRadius - RingWidth / 2 + && direction.Length < RingRadius + RingWidth / 2) + { + mouseDownOnRing = true; + + colorAngle = Math.Atan2(direction.Y, direction.X); + if (colorAngle < 0) + { + colorAngle += MathHelper.Tau; + } + Invalidate(); + } + else + { + var trianglePositon = WidgetToUnitTriangle(mouseEvent.Position); + + if (trianglePositon.inside) + { + mouseDownOnTriangle = true; + unitTrianglePosition = trianglePositon.position; + } + Invalidate(); + } + } + + base.OnMouseDown(mouseEvent); + } + + public override void OnMouseMove(MouseEventArgs mouseEvent) + { + if (mouseDownOnRing) + { + var center = new Vector2(Width / 2, Height / 2); + + var direction = mouseEvent.Position - center; + colorAngle = Math.Atan2(direction.Y, direction.X); + if (colorAngle < 0) + { + colorAngle += MathHelper.Tau; + } + Invalidate(); + } + else if (mouseDownOnTriangle) + { + unitTrianglePosition = WidgetToUnitTriangle(mouseEvent.Position).position; + Invalidate(); + } + + base.OnMouseMove(mouseEvent); + } + + public override void OnMouseUp(MouseEventArgs mouseEvent) + { + mouseDownOnRing = false; + mouseDownOnTriangle = false; + + base.OnMouseUp(mouseEvent); + } + + private void DrawColorRing(Graphics2D graphics2D, double radius, double width) + { + if (graphics2D is Graphics2DOpenGL graphicsGL) + { + graphicsGL.PushOrthoProjection(); + + GL.Disable(EnableCap.Texture2D); + GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); + GL.Enable(EnableCap.Blend); + + var outer = radius + width / 2; + var inner = radius - width / 2; + GL.Begin(BeginMode.TriangleStrip); + + for (int i = 0; i <= 360; i++) + { + var color = ColorF.FromHSL(i / 360.0, 1, .5); + var angle = MathHelper.DegreesToRadians(i); + + GL.Color4(color.Red0To255, color.Green0To255, color.Blue0To255, color.Alpha0To255); + GL.Vertex2(GetAtAngle(angle, outer)); + GL.Vertex2(GetAtAngle(angle, inner)); + } + + GL.End(); + + graphicsGL.PopOrthoProjection(); + } + } + + private void DrawColorTriangle(Graphics2D graphics2D, double radius, Color color) + { + if (graphics2D is Graphics2DOpenGL graphicsGL) + { + graphicsGL.PushOrthoProjection(); + + GL.Disable(EnableCap.Texture2D); + GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); + GL.Enable(EnableCap.Blend); + + GL.Begin(BeginMode.Triangles); + GL.Color4(color.Red0To255, color.Green0To255, color.Blue0To255, color.Alpha0To255); + GL.Vertex2(GetTrianglePoint(0, radius, colorAngle)); + GL.Color4(Color.Black); + GL.Vertex2(GetTrianglePoint(1, radius, colorAngle)); + GL.Color4(Color.White); + GL.Vertex2(GetTrianglePoint(2, radius, colorAngle)); + + GL.End(); + + graphicsGL.PopOrthoProjection(); + } + } + + private Vector2 GetAtAngle(double angle, double radius) + { + var start = new Vector2(radius, 0); + + var center = new Vector2(Width / 2, Height / 2); + return center + Vector2.Rotate(start, angle); + } + + private Vector2 GetTrianglePoint(int index, double radius, double pontingAngle) + { + switch (index) + { + case 0: + return GetAtAngle(pontingAngle, radius); + + case 1: + return GetAtAngle(pontingAngle + MathHelper.DegreesToRadians(120), radius); + + case 2: + return GetAtAngle(pontingAngle + MathHelper.DegreesToRadians(240), radius); + } + + return Vector2.Zero; + } + + private Affine TriangleToWidgetTransform(double angle) + { + var center = new Vector2(Width / 2, Height / 2); + var leftSize = .5;// Math.Sqrt(1.0 / 2.0); + var cos30 = Math.Sin(MathHelper.DegreesToRadians(30)); + + Affine total = Affine.NewIdentity(); + // scale to -1 to 1 coordinates + total *= Affine.NewScaling(1 + leftSize, 2); + // center + total *= Affine.NewTranslation(-leftSize, -1); + // rotate to correct color + total *= Affine.NewRotation(angle); + // scale to radius + total *= Affine.NewScaling(InnerRadius); + // move to center + total *= Affine.NewTranslation(center); + return total; + } + + private (bool inside, Vector2 position) WidgetToUnitTriangle(Vector2 widgetPosition) + { + var trianglePosition = TriangleToWidgetTransform(colorAngle) + .InverseTransform(widgetPosition); + + bool inside = false; + if (trianglePosition.X >= 0 + && trianglePosition.X <=1 + && trianglePosition.Y >= 0 + && trianglePosition.Y <= 1) + { + inside = true; + } + + bool changed = false; + agg_basics.Clamp(trianglePosition.X, 0, 1, ref changed); + agg_basics.Clamp(trianglePosition.Y, 0, 1, ref changed); + + return (inside, trianglePosition); + } + } +} \ No newline at end of file diff --git a/DesignTools/Attributes/ShowAsListAttribute.cs b/DesignTools/Attributes/ShowAsListAttribute.cs new file mode 100644 index 000000000..6655661f3 --- /dev/null +++ b/DesignTools/Attributes/ShowAsListAttribute.cs @@ -0,0 +1,38 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +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 System; + +namespace MatterHackers.MatterControl.DesignTools +{ + [AttributeUsage(AttributeTargets.Property)] + public class ShowAsListAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/DesignTools/Operations/AlignObject3D.cs b/DesignTools/Operations/AlignObject3D.cs index d9e51f5f4..df5ade673 100644 --- a/DesignTools/Operations/AlignObject3D.cs +++ b/DesignTools/Operations/AlignObject3D.cs @@ -149,6 +149,10 @@ namespace MatterHackers.MatterControl.DesignTools.Operations Children.Add(item.Clone()); } + [ShowAsList] + [DisplayName("Anchor")] + public ChildrenSelector AnchorObjectSelector { get; set; } = new ChildrenSelector(); + public bool Advanced { get; set; } = false; [DisplayName("X")] @@ -203,6 +207,39 @@ namespace MatterHackers.MatterControl.DesignTools.Operations } } + [JsonIgnore] + private IObject3D AnchorObject + { + get + { + if (AnchorObjectSelector.Count == 1) + { + return this.Children.Where(c => c.ID == AnchorObjectSelector[0]).FirstOrDefault(); + } + + return null; + } + } + + [JsonIgnore] + private int AnchorObjectIndex + { + get + { + int index = 0; + foreach(var child in this.Children) + { + if(child.ID == AnchorObjectSelector[0]) + { + return index; + } + index++; + } + + return -1; + } + } + public static Vector3 GetPositionToAlignTo(IObject3D objectToAlignTo, FaceAlign boundingFacesToAlignTo, Vector3 extraOffset) { Vector3 positionToAlignTo = new Vector3(); @@ -258,6 +295,24 @@ namespace MatterHackers.MatterControl.DesignTools.Operations { this.DebugDepth("Rebuild"); + var childrenIds = Children.Select(c => c.ID).ToArray(); + if(childrenIds.Length == 0) + { + AnchorObjectSelector.Clear(); + } + else if (AnchorObjectSelector.Count != 1 + || !AnchorObjectSelector.Where(i => childrenIds.Contains(i)).Any()) + { + AnchorObjectSelector.Clear(); + AnchorObjectSelector.Add(childrenIds[0]); + } + + // if the count of our children changed clear our cache of the bounds + if (Children.Count != OriginalChildrenBounds.Count) + { + OriginalChildrenBounds.Clear(); + } + using (RebuildLock()) { var aabb = this.GetAxisAlignedBoundingBox(); @@ -274,82 +329,98 @@ namespace MatterHackers.MatterControl.DesignTools.Operations }); } - var currentChildrenBounds = CurrentChildrenBounds; this.Children.Modify(list => { if (list.Count == 0) { return; } - var firstBounds = currentChildrenBounds[0]; + int anchorIndex = AnchorObjectIndex; + var anchorBounds = CurrentChildrenBounds[anchorIndex]; + int i = 0; + // first align the anchor object foreach (var child in list) { - if (i > 0) + if (XAlign == Align.None + || i == anchorIndex) { - if (XAlign == Align.None) + if (i < OriginalChildrenBounds.Count) { - if (i < OriginalChildrenBounds.Count) - { - // make sure it is where it started - AlignAxis(0, Align.Min, OriginalChildrenBounds[i].minXYZ.X, 0, child); - } + // make sure it is where it started + AlignAxis(0, Align.Min, OriginalChildrenBounds[i].minXYZ.X, 0, child); + } + } + + if (YAlign == Align.None + || i == anchorIndex) + { + if (i < OriginalChildrenBounds.Count) + { + AlignAxis(1, Align.Min, OriginalChildrenBounds[i].minXYZ.Y, 0, child); + } + } + + if (ZAlign == Align.None + || i == anchorIndex) + { + if (i < OriginalChildrenBounds.Count) + { + AlignAxis(2, Align.Min, OriginalChildrenBounds[i].minXYZ.Z, 0, child); + } + } + i++; + } + + // the align all the objects to it + i = 0; + foreach (var child in list) + { + if (XAlign != Align.None + && i != anchorIndex) + { + if (XAlign == Align.Origin) + { + // find the origin in world space of the child + var firstOrigin = Vector3.Transform(Vector3.Zero, AnchorObject.WorldMatrix()); + var childOrigin = Vector3.Transform(Vector3.Zero, child.WorldMatrix()); + child.Translate(new Vector3(-(childOrigin - firstOrigin).X + (Advanced ? XOffset : 0), 0, 0)); } else { - if (XAlign == Align.Origin) - { - // find the origin in world space of the child - var firstOrigin = Vector3.Transform(Vector3.Zero, this.Children.First().WorldMatrix()); - var childOrigin = Vector3.Transform(Vector3.Zero, child.WorldMatrix()); - child.Translate(new Vector3(-(childOrigin - firstOrigin).X + (Advanced ? XOffset : 0), 0, 0)); - } - else - { - AlignAxis(0, XAlign, GetAlignToOffset(currentChildrenBounds, 0, (!Advanced || XAlignTo == Align.None) ? XAlign : XAlignTo), XOffset, child); - } + AlignAxis(0, XAlign, GetAlignToOffset(CurrentChildrenBounds, 0, (!Advanced || XAlignTo == Align.None) ? XAlign : XAlignTo), XOffset, child); } - if (YAlign == Align.None) + } + + if (YAlign != Align.None + && i != anchorIndex) + { + if (YAlign == Align.Origin) { - if (i < OriginalChildrenBounds.Count) - { - AlignAxis(1, Align.Min, OriginalChildrenBounds[i].minXYZ.Y, 0, child); - } + // find the origin in world space of the child + var firstOrigin = Vector3.Transform(Vector3.Zero, AnchorObject.WorldMatrix()); + var childOrigin = Vector3.Transform(Vector3.Zero, child.WorldMatrix()); + child.Translate(new Vector3(0, -(childOrigin - firstOrigin).Y + (Advanced ? YOffset : 0), 0)); } else { - if (YAlign == Align.Origin) - { - // find the origin in world space of the child - var firstOrigin = Vector3.Transform(Vector3.Zero, this.Children.First().WorldMatrix()); - var childOrigin = Vector3.Transform(Vector3.Zero, child.WorldMatrix()); - child.Translate(new Vector3(0, -(childOrigin - firstOrigin).Y + (Advanced ? YOffset : 0), 0)); - } - else - { - AlignAxis(1, YAlign, GetAlignToOffset(currentChildrenBounds, 1, (!Advanced || YAlignTo == Align.None) ? YAlign : YAlignTo), YOffset, child); - } + AlignAxis(1, YAlign, GetAlignToOffset(CurrentChildrenBounds, 1, (!Advanced || YAlignTo == Align.None) ? YAlign : YAlignTo), YOffset, child); } - if (ZAlign == Align.None) + } + + if (ZAlign != Align.None + && i != anchorIndex) + { + if (ZAlign == Align.Origin) { - if (i < OriginalChildrenBounds.Count) - { - AlignAxis(2, Align.Min, OriginalChildrenBounds[i].minXYZ.Z, 0, child); - } + // find the origin in world space of the child + var firstOrigin = Vector3.Transform(Vector3.Zero, AnchorObject.WorldMatrix()); + var childOrigin = Vector3.Transform(Vector3.Zero, child.WorldMatrix()); + child.Translate(new Vector3(0, 0, -(childOrigin - firstOrigin).Z + (Advanced ? ZOffset : 0))); } else { - if (ZAlign == Align.Origin) - { - // find the origin in world space of the child - var firstOrigin = Vector3.Transform(Vector3.Zero, this.Children.First().WorldMatrix()); - var childOrigin = Vector3.Transform(Vector3.Zero, child.WorldMatrix()); - child.Translate(new Vector3(0, 0, -(childOrigin - firstOrigin).Z + (Advanced ? ZOffset : 0))); - } - else - { - AlignAxis(2, ZAlign, GetAlignToOffset(currentChildrenBounds, 2, (!Advanced || ZAlignTo == Align.None) ? ZAlign : ZAlignTo), ZOffset, child); - } + AlignAxis(2, ZAlign, GetAlignToOffset(CurrentChildrenBounds, 2, (!Advanced || ZAlignTo == Align.None) ? ZAlign : ZAlignTo), ZOffset, child); } } i++; @@ -440,13 +511,13 @@ namespace MatterHackers.MatterControl.DesignTools.Operations switch (alignTo) { case Align.Min: - return currentChildrenBounds[0].minXYZ[axis]; + return currentChildrenBounds[AnchorObjectIndex].minXYZ[axis]; case Align.Center: - return currentChildrenBounds[0].Center[axis]; + return currentChildrenBounds[AnchorObjectIndex].Center[axis]; case Align.Max: - return currentChildrenBounds[0].maxXYZ[axis]; + return currentChildrenBounds[AnchorObjectIndex].maxXYZ[axis]; default: throw new NotImplementedException(); diff --git a/DesignTools/PublicPropertyEditor.cs b/DesignTools/PublicPropertyEditor.cs index 6c28446c3..b5653699d 100644 --- a/DesignTools/PublicPropertyEditor.cs +++ b/DesignTools/PublicPropertyEditor.cs @@ -401,8 +401,26 @@ namespace MatterHackers.MatterControl.DesignTools } else if (propertyValue is ChildrenSelector childSelector) { - rowContainer = CreateSettingsColumn(property); - rowContainer.AddChild(CreateSelector(childSelector, property.Item, theme)); + var showAsList = property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault() != null; + if (showAsList) + { + UIField field = new ChildrenSelectorListField(property, theme); + + field.Initialize(0); + field.ValueChanged += (s, e) => + { + property.SetValue(new ChildrenSelector() { field.Value }); + object3D?.Invalidate(new InvalidateArgs(context.item, InvalidateType.Properties, undoBuffer)); + propertyGridModifier?.UpdateControls(new PublicPropertyChange(context, property.PropertyInfo.Name)); + }; + + rowContainer = CreateSettingsRow(property, field); + } + else // show the subtarct editor for boolean subtract and subtract and replace + { + rowContainer = CreateSettingsColumn(property); + rowContainer.AddChild(CreateSelector(childSelector, property.Item, theme)); + } } else if (propertyValue is ImageBuffer imageBuffer) { diff --git a/MatterControl.csproj b/MatterControl.csproj index 8a2f0c1c2..af4b767b9 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -84,6 +84,7 @@ + @@ -94,6 +95,7 @@ + @@ -283,6 +285,7 @@ + diff --git a/SlicerConfiguration/UIFields/ChildrenSelectorListField.cs b/SlicerConfiguration/UIFields/ChildrenSelectorListField.cs new file mode 100644 index 000000000..845e72ab0 --- /dev/null +++ b/SlicerConfiguration/UIFields/ChildrenSelectorListField.cs @@ -0,0 +1,107 @@ +/* +Copyright (c) 2018, Lars Brubaker, John Lewin +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 System; +using System.Collections.Generic; +using System.Linq; +using MatterHackers.Agg.UI; +using MatterHackers.DataConverters3D; +using MatterHackers.Localizations; +using MatterHackers.MatterControl.DesignTools; +using MatterHackers.MatterControl.DesignTools.Operations; + +namespace MatterHackers.MatterControl.SlicerConfiguration +{ + public class ChildrenSelectorListField : UIField + { + private EditableProperty property; + private ThemeConfig theme; + private DropDownList dropDownList; + + public ChildrenSelectorListField(EditableProperty property, ThemeConfig theme) + { + this.property = property; + this.theme = theme; + } + + public override void Initialize(int tabIndex) + { + // Enum keyed on name to friendly name + List<(string key, string value)> names = null; + var selectedName = ""; + if (property.source is AlignObject3D item) + { + names = item.Children.Select(child => (child.ID, child.Name)).ToList(); + if (item.AnchorObjectSelector.Count == 1) + { + var selectedKey = item.AnchorObjectSelector[0]; + foreach(var name in names) + { + if(name.key == selectedKey) + { + selectedName = name.value; + } + } + } + } + + dropDownList = new DropDownList("Name".Localize(), theme.Colors.PrimaryTextColor, Direction.Down, pointSize: theme.DefaultFontSize) + { + BorderColor = theme.GetBorderColor(75) + }; + + var orderedItems = names.OrderBy(n => n.value); + + foreach (var orderItem in orderedItems) + { + MenuItem newItem = dropDownList.AddItem(orderItem.value, orderItem.key); + + var localOrderedItem = orderItem; + newItem.Selected += (sender, e) => + { + this.SetValue(localOrderedItem.key, true); + }; + } + + dropDownList.SelectedLabel = selectedName; + + this.Content = dropDownList; + } + + protected override void OnValueChanged(FieldChangedEventArgs fieldChangedEventArgs) + { + if (this.Value != dropDownList.SelectedValue) + { + dropDownList.SelectedValue = this.Value; + } + + base.OnValueChanged(fieldChangedEventArgs); + } + } +} diff --git a/Submodules/MatterSlice b/Submodules/MatterSlice index 4a3abc90d..539644655 160000 --- a/Submodules/MatterSlice +++ b/Submodules/MatterSlice @@ -1 +1 @@ -Subproject commit 4a3abc90d5afc01e784532ddb2fc7da06e75d1da +Subproject commit 53964465593f3611b1aedb6214209b7667f1d9f9 diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 82ca51142..2edd3b61b 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 82ca5114241bb398eca060bd0002e6db25035a8a +Subproject commit 2edd3b61b87d29d1f70e9e0a36c5e25adf266726