diff --git a/ActionBar/TemperatureWidgetBed.cs b/ActionBar/TemperatureWidgetBed.cs index 3842c8d4a..b4ba36252 100644 --- a/ActionBar/TemperatureWidgetBed.cs +++ b/ActionBar/TemperatureWidgetBed.cs @@ -105,8 +105,8 @@ namespace MatterHackers.MatterControl.ActionBar }, enforceGutter: false)); - heatToggle = hotendRow.Descendants().FirstOrDefault(); - heatToggle.Name = "Toggle Heater"; + //heatToggle = hotendRow.Descendants().FirstOrDefault(); + //heatToggle.Name = "Toggle Heater"; int tabIndex = 0; var settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All); diff --git a/ActionBar/TemperatureWidgetExtruder.cs b/ActionBar/TemperatureWidgetExtruder.cs index e877f922c..b7c52a4b5 100644 --- a/ActionBar/TemperatureWidgetExtruder.cs +++ b/ActionBar/TemperatureWidgetExtruder.cs @@ -241,8 +241,8 @@ namespace MatterHackers.MatterControl.ActionBar }, enforceGutter: false)); - heatToggle = hotendRow.Descendants().FirstOrDefault(); - heatToggle.Name = "Toggle Heater"; + //heatToggle = hotendRow.Descendants().OfType().FirstOrDefault(); + //heatToggle.Name = "Toggle Heater"; int tabIndex = 0; var settingsContext = new SettingsContext(printer, null, NamedSettingsLayers.All); diff --git a/ApplicationView/ApplicationController.cs b/ApplicationView/ApplicationController.cs index 26603d516..bfa9f3b76 100644 --- a/ApplicationView/ApplicationController.cs +++ b/ApplicationView/ApplicationController.cs @@ -46,6 +46,7 @@ using System.Collections.ObjectModel; namespace MatterHackers.MatterControl { + using System.ComponentModel; using System.IO.Compression; using System.Net; using System.Reflection; @@ -1686,10 +1687,12 @@ namespace MatterHackers.MatterControl }; container.AddChild(bedButton); + RadioIconButton printAreaButton = null; + if (printer.Bed.BuildHeight > 0 && printer?.ViewState.ViewMode != PartViewMode.Layers2D) { - var printAreaButton = new RadioIconButton(AggContext.StaticData.LoadIcon("print_area.png", IconColor.Theme), theme) + printAreaButton = new RadioIconButton(AggContext.StaticData.LoadIcon("print_area.png", IconColor.Theme), theme) { Name = "Bed Button", ToolTipText = "Show Print Area".Localize(), @@ -1706,9 +1709,40 @@ namespace MatterHackers.MatterControl container.AddChild(printAreaButton); } + this. BindBedOptions(container, bedButton, printAreaButton, printer.Bed.RendererOptions); + return container; } + public void BindBedOptions(GuiWidget container, ICheckbox bedButton, ICheckbox printAreaButton, View3DConfig renderOptions) + { + PropertyChangedEventHandler syncProperties = (s, e) => + { + switch (e.PropertyName) + { + case nameof(renderOptions.RenderBed): + bedButton.Checked = renderOptions.RenderBed; + break; + + case nameof(renderOptions.RenderBuildVolume) when printAreaButton != null: + printAreaButton.Checked = renderOptions.RenderBuildVolume; + break; + } + }; + + renderOptions.PropertyChanged += syncProperties; + + container.Closed += (s, e) => + { + renderOptions.PropertyChanged -= syncProperties; + }; + } + + private void RendererOptions_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + { + throw new NotImplementedException(); + } + public class CloudSyncEventArgs : EventArgs { public bool IsAuthenticated { get; set; } diff --git a/ApplicationView/PrinterModels.cs b/ApplicationView/PrinterModels.cs index 2f72985aa..0449a4ff6 100644 --- a/ApplicationView/PrinterModels.cs +++ b/ApplicationView/PrinterModels.cs @@ -42,6 +42,7 @@ using Newtonsoft.Json; namespace MatterHackers.MatterControl { using System.Collections.Generic; + using System.ComponentModel; using System.Threading; using MatterHackers.Agg; using MatterHackers.DataConverters3D; @@ -77,7 +78,7 @@ namespace MatterHackers.MatterControl public async Task LoadContent(EditContext editContext) { - // Make sure we don't have a selection + // Make sure we don't have a selection this.Scene.SelectedItem = null; // Store @@ -408,7 +409,7 @@ namespace MatterHackers.MatterControl renderType |= RenderType.Retractions; } - if (options.RenderSpeeds) + if (options.GCodeLineColorStyle == "Speeds") { renderType |= RenderType.SpeedColors; } @@ -959,11 +960,11 @@ namespace MatterHackers.MatterControl } } - public class View3DConfig + public class View3DConfig : INotifyPropertyChanged { - public bool IsDirty { get; internal set; } + public event PropertyChangedEventHandler PropertyChanged; - public event EventHandler GCodeOptionsChanged; + public bool IsDirty { get; internal set; } public bool RenderBed { @@ -972,86 +973,102 @@ namespace MatterHackers.MatterControl string value = UserSettings.Instance.get("GcodeViewerRenderGrid"); if (value == null) { - RenderBed = true; return true; } return (value == "True"); } set { - UserSettings.Instance.set("GcodeViewerRenderGrid", value.ToString()); - this.IsDirty = true; + if (this.RenderBed != value) + { + UserSettings.Instance.set("GcodeViewerRenderGrid", value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(RenderBed)); + } } } public bool RenderMoves { - get { return (UserSettings.Instance.get("GcodeViewerRenderMoves") == "True"); } + get => UserSettings.Instance.get("GcodeViewerRenderMoves") == "True"; set { - UserSettings.Instance.set("GcodeViewerRenderMoves", value.ToString()); - this.IsDirty = true; + if (this.RenderMoves != value) + { + UserSettings.Instance.set("GcodeViewerRenderMoves", value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(RenderMoves)); + } } } public bool RenderRetractions { - get { return (UserSettings.Instance.get("GcodeViewerRenderRetractions") == "True"); } + get => UserSettings.Instance.get("GcodeViewerRenderRetractions") == "True"; set { - UserSettings.Instance.set("GcodeViewerRenderRetractions", value.ToString()); - this.IsDirty = true; - } - } - - public bool RenderSpeeds - { - get => this.GCodeLineColorStyle == "Speeds"; - set - { - this.GCodeLineColorStyle = "Speeds"; - GCodeOptionsChanged?.Invoke(this, null); + if (this.RenderRetractions != value) + { + UserSettings.Instance.set("GcodeViewerRenderRetractions", value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(RenderRetractions)); + } } } public string GCodeModelView { - get { return UserSettings.Instance.get("GcodeModelView"); } + get => UserSettings.Instance.get("GcodeModelView"); set { - UserSettings.Instance.set("GcodeModelView", value); - this.IsDirty = true; + if (this.GCodeModelView != value) + { + UserSettings.Instance.set("GcodeModelView", value); + this.IsDirty = true; + this.OnPropertyChanged(nameof(GCodeModelView)); + } } } public string GCodeLineColorStyle { - get { return UserSettings.Instance.get("GCodeLineColorStyle"); } + get => UserSettings.Instance.get("GCodeLineColorStyle"); set { - UserSettings.Instance.set("GCodeLineColorStyle", value); - GCodeOptionsChanged?.Invoke(this, null); - this.IsDirty = true; + if (this.GCodeLineColorStyle != value) + { + UserSettings.Instance.set("GCodeLineColorStyle", value); + this.IsDirty = true; + this.OnPropertyChanged(nameof(GCodeLineColorStyle)); + } } } public bool SimulateExtrusion { - get { return (UserSettings.Instance.get("GcodeViewerSimulateExtrusion") == "True"); } + get => UserSettings.Instance.get("GcodeViewerSimulateExtrusion") == "True"; set { - UserSettings.Instance.set("GcodeViewerSimulateExtrusion", value.ToString()); - this.IsDirty = true; + if (this.SimulateExtrusion != value) + { + UserSettings.Instance.set("GcodeViewerSimulateExtrusion", value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(SimulateExtrusion)); + } } } public bool TransparentExtrusion { - get { return (UserSettings.Instance.get("GcodeViewerTransparentExtrusion") == "True"); } + get => UserSettings.Instance.get("GcodeViewerTransparentExtrusion") == "True"; set { - UserSettings.Instance.set("GcodeViewerTransparentExtrusion", value.ToString()); - this.IsDirty = true; + if (this.TransparentExtrusion != value) + { + UserSettings.Instance.set("GcodeViewerTransparentExtrusion", value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(TransparentExtrusion)); + } } } @@ -1068,8 +1085,12 @@ namespace MatterHackers.MatterControl } set { - UserSettings.Instance.set("GcodeViewerHideExtruderOffsets", value.ToString()); - this.IsDirty = true; + if (this.HideExtruderOffsets != value) + { + UserSettings.Instance.set("GcodeViewerHideExtruderOffsets", value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(HideExtruderOffsets)); + } } } @@ -1078,11 +1099,32 @@ namespace MatterHackers.MatterControl get => UserSettings.Instance.get("LayerViewSyncToPrint") == "True"; set { - UserSettings.Instance.set("LayerViewSyncToPrint", value.ToString()); - this.IsDirty = true; + if (this.SyncToPrint != value) + { + UserSettings.Instance.set("LayerViewSyncToPrint", value.ToString()); + this.IsDirty = true; + this.OnPropertyChanged(nameof(SyncToPrint)); + } } } - public bool RenderBuildVolume { get; set; } + private bool _renderBuildVolume; + public bool RenderBuildVolume + { + get => _renderBuildVolume; + set + { + if (_renderBuildVolume != value) + { + _renderBuildVolume = value; + this.OnPropertyChanged(nameof(RenderBuildVolume)); + } + } + } + + protected void OnPropertyChanged(string name) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); + } } } \ No newline at end of file diff --git a/ConfigurationPage/ApplicationSettings/SettingsItem.cs b/ConfigurationPage/ApplicationSettings/SettingsItem.cs index 182f013db..7e0c63ed1 100644 --- a/ConfigurationPage/ApplicationSettings/SettingsItem.cs +++ b/ConfigurationPage/ApplicationSettings/SettingsItem.cs @@ -52,7 +52,7 @@ namespace MatterHackers.MatterControl.ConfigurationPage } else if (enforceGutter) { - // Add an icon place holder to get consistent label indenting on items lacking icons + // Add an icon placeholder to get consistent label indenting on items lacking icons this.AddChild(new GuiWidget() { Width = 24 + 12, @@ -82,17 +82,21 @@ namespace MatterHackers.MatterControl.ConfigurationPage public GuiWidget SettingsControl { get; } - private static CheckBox CreateToggleSwitch(ToggleSwitchConfig toggleSwitchConfig, Color textColor) + private static GuiWidget CreateToggleSwitch(ToggleSwitchConfig toggleSwitchConfig, Color textColor) { if (toggleSwitchConfig == null) { return null; } - var toggleSwitch = ImageButtonFactory.CreateToggleSwitch(toggleSwitchConfig.Checked, textColor); - toggleSwitch.VAnchor = VAnchor.Center; - toggleSwitch.Name = toggleSwitchConfig.Name; - toggleSwitch.Margin = new BorderDouble(left: 16); + var toggleSwitch = new RoundedToggleSwitch(ApplicationController.Instance.Theme) + { + VAnchor = VAnchor.Center, + Checked = toggleSwitchConfig.Checked, + Name = toggleSwitchConfig.Name, + Margin = new BorderDouble(left: 16), + }; + toggleSwitch.CheckedStateChanged += (sender, e) => { toggleSwitchConfig.ToggleAction?.Invoke(toggleSwitch.Checked); diff --git a/MatterControl.csproj b/MatterControl.csproj index 8aeb1e207..9ac9624ba 100644 --- a/MatterControl.csproj +++ b/MatterControl.csproj @@ -142,6 +142,7 @@ + diff --git a/PartPreviewWindow/GCode3DWidget.cs b/PartPreviewWindow/GCode3DWidget.cs index 5b07ccc75..a143f5f3e 100644 --- a/PartPreviewWindow/GCode3DWidget.cs +++ b/PartPreviewWindow/GCode3DWidget.cs @@ -85,7 +85,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow }, ref unregisterEvents); printer.Bed.LoadedGCodeChanged += Bed_LoadedGCodeChanged; - printer.Bed.RendererOptions.GCodeOptionsChanged += RendererOptions_GCodeOptionsChanged; + printer.Bed.RendererOptions.PropertyChanged += RendererOptions_PropertyChanged; } private void RefreshGCodeDetails(PrinterConfig printer) @@ -109,13 +109,15 @@ namespace MatterHackers.MatterControl.PartPreviewWindow VAnchor = VAnchor.Fit }); + bool renderSpeeds = printer.Bed.RendererOptions.GCodeLineColorStyle == "Speeds"; + loadedGCodeSection.AddChild( speedsWidget = new SectionWidget( "Speeds".Localize(), new SpeedsLegend(sceneContext.LoadedGCode, theme, pointSize: theme.FontSize12) { HAnchor = HAnchor.Stretch, - Visible = sceneContext.RendererOptions.RenderSpeeds, + Visible = renderSpeeds, Padding = new BorderDouble(15, 4) }, theme) @@ -124,7 +126,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow VAnchor = VAnchor.Fit }); - speedsWidget.Visible = printer.Bed.RendererOptions.RenderSpeeds; + speedsWidget.Visible = renderSpeeds; } // Enforce panel padding in sidebar @@ -141,17 +143,18 @@ namespace MatterHackers.MatterControl.PartPreviewWindow UiThread.RunOnIdle(() => this.RefreshGCodeDetails(printer)); } - private void RendererOptions_GCodeOptionsChanged(object sender, EventArgs e) + private void RendererOptions_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { - if (speedsWidget != null) + if (speedsWidget != null + && e.PropertyName == "GCodeLineColorStyle") { - speedsWidget.Visible = printer.Bed.RendererOptions.RenderSpeeds; + speedsWidget.Visible = printer.Bed.RendererOptions.GCodeLineColorStyle == "Speeds"; } } public override void OnClosed(ClosedEventArgs e) { - printer.Bed.RendererOptions.GCodeOptionsChanged -= RendererOptions_GCodeOptionsChanged; + printer.Bed.RendererOptions.PropertyChanged -= RendererOptions_PropertyChanged; printer.Bed.LoadedGCodeChanged -= Bed_LoadedGCodeChanged; unregisterEvents?.Invoke(this, null); diff --git a/PartPreviewWindow/GCodeDetailsView.cs b/PartPreviewWindow/GCodeDetailsView.cs index dda8c7ef3..411eccf00 100644 --- a/PartPreviewWindow/GCodeDetailsView.cs +++ b/PartPreviewWindow/GCodeDetailsView.cs @@ -30,6 +30,7 @@ either expressed or implied, of the FreeBSD Project. using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using MatterHackers.Agg; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; @@ -239,24 +240,53 @@ namespace MatterHackers.MatterControl.PartPreviewWindow }) }); - foreach(var option in viewOptions) + var optionsContainer = new FlowLayoutWidget(FlowDirection.TopToBottom) { - if (option.IsVisible()) + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit + }; + this.AddChild(optionsContainer); + + void BuildMenu() + { + foreach (var option in viewOptions) { - this.AddChild( - new SettingsItem( - option.Title, - theme.Colors.PrimaryTextColor, - new SettingsItem.ToggleSwitchConfig() - { - Name = option.Title + " Toggle", - Checked = option.IsChecked(), - ToggleAction = option.SetValue - }, - enforceGutter: false) - ); + if (option.IsVisible()) + { + optionsContainer.AddChild( + new SettingsItem( + option.Title, + theme.Colors.PrimaryTextColor, + new SettingsItem.ToggleSwitchConfig() + { + Name = option.Title + " Toggle", + Checked = option.IsChecked(), + ToggleAction = option.SetValue + }, + enforceGutter: false) + ); + } } } + + BuildMenu(); + + PropertyChangedEventHandler syncProperties = (s, e) => + { + if (e.PropertyName == nameof(gcodeOptions.RenderBed) + || e.PropertyName == nameof(gcodeOptions.RenderBuildVolume)) + { + optionsContainer.CloseAllChildren(); + BuildMenu(); + } + }; + + gcodeOptions.PropertyChanged += syncProperties; + + optionsContainer.Closed += (s, e) => + { + gcodeOptions.PropertyChanged -= syncProperties; + }; } private void SwitchColorModes_Click(object sender, MouseEventArgs e) diff --git a/PartPreviewWindow/ModelOptionsPanel.cs b/PartPreviewWindow/ModelOptionsPanel.cs new file mode 100644 index 000000000..460148eea --- /dev/null +++ b/PartPreviewWindow/ModelOptionsPanel.cs @@ -0,0 +1,162 @@ +/* +Copyright (c) 2018, 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.Collections.ObjectModel; +using MatterHackers.Agg; +using MatterHackers.Agg.Platform; +using MatterHackers.Agg.UI; +using MatterHackers.Localizations; +using MatterHackers.MatterControl.ConfigurationPage; +using MatterHackers.MatterControl.CustomWidgets; +using MatterHackers.MeshVisualizer; +using MatterHackers.RenderOpenGl; + +namespace MatterHackers.MatterControl.PartPreviewWindow +{ + public class ModelOptionsPanel : FlowLayoutWidget + { + private RadioIconButton shadedViewButton; + private RadioIconButton outlinesViewButton; + private RadioIconButton polygonsViewButton; + private RadioIconButton materialsViewButton; + private RadioIconButton overhangViewButton; + + public ModelOptionsPanel(BedConfig sceneContext, MeshViewerWidget meshViewerWidget, ThemeConfig theme) + : base(FlowDirection.TopToBottom) + { + void switchToRenderType(RenderTypes renderType) + { + meshViewerWidget.RenderType = renderType; + UserSettings.Instance.set(UserSettingsKey.defaultRenderSetting, renderType.ToString()); + } + + var buttonPanel = new FlowLayoutWidget() + { + HAnchor = HAnchor.Fit, + VAnchor = VAnchor.Fit + }; + + var buttonGroup = new ObservableCollection(); + + shadedViewButton = new RadioIconButton(AggContext.StaticData.LoadIcon("view_shaded.png", IconColor.Theme), theme) + { + SiblingRadioButtonList = buttonGroup, + Name = "Shaded Button", + Checked = meshViewerWidget.RenderType == RenderTypes.Shaded, + ToolTipText = "Shaded".Localize(), + Margin = theme.ButtonSpacing + }; + shadedViewButton.Click += (s, e) => switchToRenderType(RenderTypes.Shaded); + buttonGroup.Add(shadedViewButton); + + buttonPanel.AddChild(shadedViewButton); + + outlinesViewButton = new RadioIconButton(AggContext.StaticData.LoadIcon("view_outlines.png", IconColor.Theme), theme) + { + SiblingRadioButtonList = buttonGroup, + Name = "Outlines Button", + Checked = meshViewerWidget.RenderType == RenderTypes.Outlines, + ToolTipText = "Outlines".Localize(), + Margin = theme.ButtonSpacing + }; + outlinesViewButton.Click += (s, e) => switchToRenderType(RenderTypes.Outlines); + buttonGroup.Add(outlinesViewButton); + + buttonPanel.AddChild(outlinesViewButton); + + polygonsViewButton = new RadioIconButton(AggContext.StaticData.LoadIcon("view_polygons.png", IconColor.Theme), theme) + { + SiblingRadioButtonList = buttonGroup, + Name = "Polygons Button", + Checked = meshViewerWidget.RenderType == RenderTypes.Polygons, + ToolTipText = "Polygons".Localize(), + Margin = theme.ButtonSpacing + }; + polygonsViewButton.Click += (s, e) => switchToRenderType(RenderTypes.Polygons); + buttonGroup.Add(polygonsViewButton); + + buttonPanel.AddChild(polygonsViewButton); + + materialsViewButton = new RadioIconButton(AggContext.StaticData.LoadIcon("view_materials.png", IconColor.Raw), theme) + { + SiblingRadioButtonList = buttonGroup, + Name = "Materials Button", + Checked = meshViewerWidget.RenderType == RenderTypes.Materials, + ToolTipText = "Materials".Localize(), + Margin = theme.ButtonSpacing + }; + materialsViewButton.Click += (s, e) => switchToRenderType(RenderTypes.Materials); + buttonGroup.Add(materialsViewButton); + + buttonPanel.AddChild(materialsViewButton); + + overhangViewButton = new RadioIconButton(AggContext.StaticData.LoadIcon("view_overhang.png", IconColor.Raw), theme) + { + SiblingRadioButtonList = buttonGroup, + Name = "Overhang Button", + Checked = meshViewerWidget.RenderType == RenderTypes.Overhang, + ToolTipText = "Overhang".Localize(), + Margin = theme.ButtonSpacing + }; + overhangViewButton.Click += (s, e) => switchToRenderType(RenderTypes.Overhang); + buttonGroup.Add(overhangViewButton); + + buttonPanel.AddChild(overhangViewButton); + + this.AddChild( + new SettingsItem( + "View Style".Localize(), + theme.Colors.PrimaryTextColor, + buttonPanel, + enforceGutter: false) + { + Margin = new BorderDouble(bottom: 2) + }); + + foreach (var option in sceneContext.GetBaseViewOptions()) + { + if (option.IsVisible()) + { + this.AddChild( + new SettingsItem( + option.Title, + theme.Colors.PrimaryTextColor, + new SettingsItem.ToggleSwitchConfig() + { + Name = option.Title + " Toggle", + Checked = option.IsChecked(), + ToggleAction = option.SetValue + }, + enforceGutter: false) + ); + } + } + } + } +} diff --git a/PartPreviewWindow/RoundedToggleSwitch.cs b/PartPreviewWindow/RoundedToggleSwitch.cs new file mode 100644 index 000000000..706990c68 --- /dev/null +++ b/PartPreviewWindow/RoundedToggleSwitch.cs @@ -0,0 +1,172 @@ +/* +Copyright (c) 2018, 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 MatterHackers.Agg; +using MatterHackers.Agg.UI; +using MatterHackers.Agg.VertexSource; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.CustomWidgets +{ + public class RoundedToggleSwitch : GuiWidget, ICheckbox + { + private ThemeConfig theme; + + private Color inactiveBarColor; + private Color activeBarColor; + + private bool mouseIsDown; + + public bool Checked { get; set; } + + public event EventHandler CheckedStateChanged; + + public RoundedToggleSwitch(ThemeConfig theme) + { + this.theme = theme; + //this.DoubleBuffer = true; + inactiveBarColor = theme.ResolveColor(theme.ActiveTabColor, theme.SlightShade); + activeBarColor = new Color(theme.Colors.PrimaryAccentColor, 100); + + this.MinimumSize = new Vector2(50, theme.ButtonHeight); + } + + public override void OnMouseDown(MouseEventArgs mouseEvent) + { + mouseIsDown = true; + base.OnMouseDown(mouseEvent); + + this.Invalidate(); + } + + public override void OnMouseUp(MouseEventArgs mouseEvent) + { + mouseIsDown = false; + base.OnMouseUp(mouseEvent); + + this.Invalidate(); + } + + + public override void OnClick(MouseEventArgs mouseEvent) + { + base.OnClick(mouseEvent); + + bool newValue = !this.Checked; + + bool checkStateChanged = (newValue != this.Checked); + + this.Checked = newValue; + + // After setting CheckedState, fire event if different + if (checkStateChanged) + { + OnCheckStateChanged(); + this.Invalidate(); + } + } + + public virtual void OnCheckStateChanged() + { + CheckedStateChanged?.Invoke(this, null); + } + + public bool ShowBubble { get; set; } + + public override void OnDraw(Graphics2D graphics2D) + { + base.OnDraw(graphics2D); + + var center = this.LocalBounds.Center; + + var toggleRadius = 10; + var bubbleRadius = toggleRadius * 1.7; + + var halfBarHeight = 14 / 2; + var halfBarWidth = 36 / 2; + + //var barRect = new RectangleDouble( + // new Vector2(26, 0), + // new Vector2(0, 14)); + + var left = center.X - halfBarWidth; + var right = center.X + halfBarWidth; + + Color barColor = (this.Checked) ? activeBarColor : inactiveBarColor; + + if (mouseIsDown) + { + if (this.ShowBubble) + { + graphics2D.Render( + new RoundedRect( + new RectangleDouble( + left, + center.Y - halfBarHeight, + right, + center.Y + halfBarHeight), + halfBarHeight), + barColor); + + graphics2D.Circle( + new Vector2( + (this.Checked) ? right : left, + center.Y), + bubbleRadius, + new Color(this.Checked ? theme.Colors.PrimaryAccentColor : Color.Gray, 80)); + } + else + { + barColor = (this.Checked) ? Color.Gray : theme.Colors.PrimaryAccentColor; + } + } + + // Draw bar + graphics2D.Render( + new RoundedRect( + new RectangleDouble( + left, + center.Y - halfBarHeight, + right, + center.Y + halfBarHeight), + halfBarHeight), + barColor); + + // Draw toggle circle + var toggleColor = (this.Checked) ? theme.Colors.PrimaryAccentColor : Color.Gray; + graphics2D.Circle( + new Vector2( + (this.Checked) ? right - halfBarHeight : left + halfBarHeight, + center.Y), + toggleRadius, + toggleColor); + } + } +} \ No newline at end of file diff --git a/PartPreviewWindow/SelectedObjectPanel.cs b/PartPreviewWindow/SelectedObjectPanel.cs index dbd0cdb17..a5662d919 100644 --- a/PartPreviewWindow/SelectedObjectPanel.cs +++ b/PartPreviewWindow/SelectedObjectPanel.cs @@ -33,6 +33,7 @@ using System.Linq; using MatterHackers.Agg; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; +using MatterHackers.Agg.VertexSource; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; using MatterHackers.MatterControl.CustomWidgets; @@ -102,6 +103,12 @@ namespace MatterHackers.MatterControl.PartPreviewWindow } }; + this.AddChild(new RoundedToggleSwitch(theme) + { + Width = 100, + Height = 34 + }); + scrollableContent = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.Stretch,