From 74db968eee32d6701c5637d44d52eb9874b109bb Mon Sep 17 00:00:00 2001 From: MatterHackers Date: Sun, 3 Dec 2023 19:00:41 -0800 Subject: [PATCH] We can read extra fonts from the system. --- .../ApplicationView/Application.cs | 9 - .../ApplicationView/ApplicationController.cs | 140 +++++--- .../Attributes/FontSelectorAttribute.cs | 38 +++ .../Attributes/MultiLineEditAttribute.cs | 4 +- .../DesignTools/Braille/BrailleObject3D.cs | 4 +- .../OpenSCAD/OpenScadScriptObject3D.cs | 2 +- .../Primitives/TemperatureTowerObject3D.cs | 2 +- .../DesignTools/Primitives/TextObject3D.cs | 7 +- .../DesignTools/PropertyEditor.cs | 9 +- .../DesignTools/StringPropertyEditor.cs | 319 ++++++++++-------- .../PartPreviewWindow/MarkdownEditPage.cs | 2 +- .../PrinterControls/MacroDetailPage.cs | 2 +- .../TerminalWindow/TerminalWidget.cs | 2 +- .../TerminalWindow/TextScrollWidget.cs | 2 +- .../SlicerConfiguration/UIFields/EnumField.cs | 2 +- .../UIFields/FontSelectorField.cs | 29 +- .../UIFields/MultilineStringField.cs | 2 +- 17 files changed, 334 insertions(+), 241 deletions(-) create mode 100644 MatterControlLib/DesignTools/Attributes/FontSelectorAttribute.cs diff --git a/MatterControlLib/ApplicationView/Application.cs b/MatterControlLib/ApplicationView/Application.cs index 18b926e49..cf8bbc634 100644 --- a/MatterControlLib/ApplicationView/Application.cs +++ b/MatterControlLib/ApplicationView/Application.cs @@ -71,15 +71,6 @@ namespace MatterHackers.MatterControl { timer = Stopwatch.StartNew(); - if (false) - { - // set the default font - AggContext.DefaultFont = ApplicationController.GetTypeFace(NamedTypeFace.Nunito_Regular); - AggContext.DefaultFontBold = ApplicationController.GetTypeFace(NamedTypeFace.Nunito_Bold); - AggContext.DefaultFontItalic = ApplicationController.GetTypeFace(NamedTypeFace.Nunito_Italic); - AggContext.DefaultFontBoldItalic = ApplicationController.GetTypeFace(NamedTypeFace.Nunito_Bold_Italic); - } - var rootSystemWindow = new RootSystemWindow(width, height); var overlay = new GuiWidget() diff --git a/MatterControlLib/ApplicationView/ApplicationController.cs b/MatterControlLib/ApplicationView/ApplicationController.cs index a5e2567b2..983c5db9a 100644 --- a/MatterControlLib/ApplicationView/ApplicationController.cs +++ b/MatterControlLib/ApplicationView/ApplicationController.cs @@ -68,12 +68,14 @@ using MatterHackers.MatterControl.PrintHistory; using MatterHackers.MatterControl.PrintQueue; using MatterHackers.MatterControl.SettingsManagement; using MatterHackers.MatterControl.SlicerConfiguration; +using MatterHackers.Pathfinding; using MatterHackers.PolygonMesh; using MatterHackers.PolygonMesh.Processors; using MatterHackers.VectorMath; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; +using Typography.OpenFont; [assembly: InternalsVisibleTo("MatterControl.Tests")] [assembly: InternalsVisibleTo("MatterControl.AutomationTests")] @@ -81,36 +83,35 @@ using Newtonsoft.Json.Linq; namespace MatterHackers.MatterControl { - [JsonConverter(typeof(StringEnumConverter))] - public enum NamedTypeFace - { - Alfa_Slab, - Audiowide, - Bangers, - Courgette, - Damion, - Firefly_Sung, - Fredoka, - Great_Vibes, - Liberation_Mono, - Liberation_Sans, - Liberation_Sans_Bold, - Lobster, - Nunito_Regular, - Nunito_Bold, - Nunito_Bold_Italic, - Nunito_Italic, - Pacifico, - Poppins, - Questrial, - Righteous, - Russo, - Titan, - Titillium, - } - public class ApplicationController { + public Dictionary TypeFaceCache = new Dictionary() + { + {"Alfa_Slab", null}, + {"Audiowide", null}, + {"Bangers", null}, + {"Courgette", null}, + {"Damion", null}, + {"Firefly_Sung", null}, + {"Fredoka", null}, + {"Great_Vibes", null}, + {"Liberation_Mono", TypeFace.LoadFrom(StaticData.Instance.ReadAllText(Path.Combine("Fonts", "LiberationMono.svg"))) }, + {"Liberation_Sans", LiberationSansFont.Instance}, + {"Liberation_Sans_Bold", LiberationSansBoldFont.Instance}, + {"Lobster", null}, + {"Nunito_Regular", null}, + {"Nunito_Bold", null}, + {"Nunito_Bold_Italic", null}, + {"Nunito_Italic", null}, + {"Pacifico", null}, + {"Poppins", null}, + {"Questrial", null}, + {"Righteous", null}, + {"Russo", null}, + {"Titan", null}, + {"Titillium", null} + }; + public event EventHandler ApplicationError; public event EventHandler ApplicationEvent; @@ -1367,21 +1368,52 @@ namespace MatterHackers.MatterControl } } - private static readonly Dictionary TypeFaceCache = new Dictionary() - { - [NamedTypeFace.Liberation_Sans] = LiberationSansFont.Instance, - [NamedTypeFace.Liberation_Sans_Bold] = LiberationSansBoldFont.Instance, - [NamedTypeFace.Liberation_Mono] = TypeFace.LoadFrom(StaticData.Instance.ReadAllText(Path.Combine("Fonts", "LiberationMono.svg"))) - }; - private static object locker = new object(); - public static TypeFace GetTypeFace(NamedTypeFace namedTypeFace) + bool addedWindowsFonts = false; + + public TypeFace GetTypeFace(string namedTypeFace) { lock (locker) { + if (!addedWindowsFonts) + { + addedWindowsFonts = true; + + // add all the windows fonts + // get all the files with the extension .ttf in the windows/fonts directory + var ttfs = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "*.ttf"); + var otf = Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), "*.otf"); + var fonts = ttfs.Concat(otf); + // add all the fonts to the cache + foreach (var font in fonts) + { + var fontName = Path.GetFileNameWithoutExtension(font); + if (!TypeFaceCache.ContainsKey(fontName)) + { + var stream2 = File.OpenRead(font); + var typeFace = new TypeFace(); + if (stream2 != null + && typeFace.LoadTTF(stream2)) + { + TypeFaceCache.Add(fontName, typeFace); + } + else + { + TypeFaceCache.Add(fontName, null); + } + } + } + } + if (!TypeFaceCache.ContainsKey(namedTypeFace)) { + // add it + TypeFaceCache.Add(namedTypeFace, null); + } + else if (TypeFaceCache[namedTypeFace] == null) + { + // try and load it from the cache var typeFace = new TypeFace(); var path = Path.Combine("Fonts", $"{namedTypeFace}.ttf"); var exists = StaticData.Instance.FileExists(path); @@ -1389,7 +1421,7 @@ namespace MatterHackers.MatterControl if (stream != null && typeFace.LoadTTF(stream)) { - TypeFaceCache.Add(namedTypeFace, typeFace); + TypeFaceCache[namedTypeFace] = typeFace; } else { @@ -1399,13 +1431,31 @@ namespace MatterHackers.MatterControl typeFace = exists ? TypeFace.LoadFrom(StaticData.Instance.ReadAllText(path)) : null; if (typeFace != null) { - TypeFaceCache.Add(namedTypeFace, typeFace); + TypeFaceCache[namedTypeFace] = typeFace; } else { - // assign it to the default - TypeFaceCache.Add(namedTypeFace, TypeFaceCache[NamedTypeFace.Liberation_Sans]); - } + var extensionsToTry = new string[] { ".ttf", ".otf" }; + // try and load it from windows + // check if the there is a font with the given name and an extension of ttf in the windows/fonts directory + foreach (var extension in extensionsToTry) + { + var fontPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts), $"{namedTypeFace}{extension}"); + var stream2 = exists ? StaticData.Instance.OpenStream(fontPath) : null; + if (stream2 != null + && typeFace.LoadTTF(stream2)) + { + TypeFaceCache[namedTypeFace] = typeFace; + } + } + + // if we did not find it in windows/fonts set it to the default + if (typeFace == null) + { + // assign it to the default + TypeFaceCache[namedTypeFace] = TypeFaceCache["Liberation_Sans"]; + } + } } stream?.Dispose(); @@ -2180,10 +2230,10 @@ namespace MatterHackers.MatterControl if (twoLetterIsoLanguageName == "ja" || twoLetterIsoLanguageName == "zh") { - AggContext.DefaultFont = ApplicationController.GetTypeFace(NamedTypeFace.Firefly_Sung); - AggContext.DefaultFontBold = ApplicationController.GetTypeFace(NamedTypeFace.Firefly_Sung); - AggContext.DefaultFontItalic = ApplicationController.GetTypeFace(NamedTypeFace.Firefly_Sung); - AggContext.DefaultFontBoldItalic = ApplicationController.GetTypeFace(NamedTypeFace.Firefly_Sung); + AggContext.DefaultFont = ApplicationController.Instance.GetTypeFace("Firefly_Sung"); + AggContext.DefaultFontBold = ApplicationController.Instance.GetTypeFace("Firefly_Sung"); + AggContext.DefaultFontItalic = ApplicationController.Instance.GetTypeFace("Firefly_Sung"); + AggContext.DefaultFontBoldItalic = ApplicationController.Instance.GetTypeFace("1Firefly_Sung"); } else { diff --git a/MatterControlLib/DesignTools/Attributes/FontSelectorAttribute.cs b/MatterControlLib/DesignTools/Attributes/FontSelectorAttribute.cs new file mode 100644 index 000000000..02d85e406 --- /dev/null +++ b/MatterControlLib/DesignTools/Attributes/FontSelectorAttribute.cs @@ -0,0 +1,38 @@ +/* +Copyright (c) 2023, 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 System; + +namespace MatterHackers.MatterControl.DesignTools +{ + [AttributeUsage(AttributeTargets.Property)] + public class FontSelectorAttribute : Attribute + { + } +} \ No newline at end of file diff --git a/MatterControlLib/DesignTools/Attributes/MultiLineEditAttribute.cs b/MatterControlLib/DesignTools/Attributes/MultiLineEditAttribute.cs index 2cdc5e32a..1b76b462a 100644 --- a/MatterControlLib/DesignTools/Attributes/MultiLineEditAttribute.cs +++ b/MatterControlLib/DesignTools/Attributes/MultiLineEditAttribute.cs @@ -1,5 +1,5 @@ /* -Copyright (c) 2018, Lars Brubaker, John Lewin +Copyright (c) 2023, Lars Brubaker, John Lewin All rights reserved. Redistribution and use in source and binary forms, with or without @@ -32,7 +32,7 @@ using System; namespace MatterHackers.MatterControl.DesignTools { - [AttributeUsage(AttributeTargets.Property)] + [AttributeUsage(AttributeTargets.Property)] public class MultiLineEditAttribute : Attribute { } diff --git a/MatterControlLib/DesignTools/Braille/BrailleObject3D.cs b/MatterControlLib/DesignTools/Braille/BrailleObject3D.cs index 71f38339f..db6e3b940 100644 --- a/MatterControlLib/DesignTools/Braille/BrailleObject3D.cs +++ b/MatterControlLib/DesignTools/Braille/BrailleObject3D.cs @@ -127,7 +127,7 @@ namespace MatterHackers.MatterControl.DesignTools } else { - textPrinter = new TypeFacePrinter(brailleText, new StyledTypeFace(ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono), pointSize)); + textPrinter = new TypeFacePrinter(brailleText, new StyledTypeFace(ApplicationController.Instance.GetTypeFace("Liberation_Mono"), pointSize)); } foreach (var letter in brailleText.ToCharArray()) @@ -180,7 +180,7 @@ namespace MatterHackers.MatterControl.DesignTools } else { - letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono), pointSize)); + letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(ApplicationController.Instance.GetTypeFace("Liberation_Mono"), pointSize)); var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm)); letterObject = new Object3D() { diff --git a/MatterControlLib/DesignTools/OpenSCAD/OpenScadScriptObject3D.cs b/MatterControlLib/DesignTools/OpenSCAD/OpenScadScriptObject3D.cs index 7991506da..dd0d09db0 100644 --- a/MatterControlLib/DesignTools/OpenSCAD/OpenScadScriptObject3D.cs +++ b/MatterControlLib/DesignTools/OpenSCAD/OpenScadScriptObject3D.cs @@ -42,7 +42,7 @@ namespace MatterHackers.MatterControl.Library { public class OpenScadScriptObject3D : Object3D { - [MultiLineEditAttribute] + [MultiLineEdit] public string NameToWrite { get; set; } = "cube([20, 20, 20]);"; public OpenScadScriptObject3D() diff --git a/MatterControlLib/DesignTools/Primitives/TemperatureTowerObject3D.cs b/MatterControlLib/DesignTools/Primitives/TemperatureTowerObject3D.cs index f93cfcd32..ec7d40ae2 100644 --- a/MatterControlLib/DesignTools/Primitives/TemperatureTowerObject3D.cs +++ b/MatterControlLib/DesignTools/Primitives/TemperatureTowerObject3D.cs @@ -168,7 +168,7 @@ namespace MatterHackers.MatterControl.DesignTools // Add temperature text var text = new TextObject3D() { - Font = NamedTypeFace.Fredoka, + Font = "Fredoka", Height = 1, Name = $"{temp:0.##}", PointSize = 10, diff --git a/MatterControlLib/DesignTools/Primitives/TextObject3D.cs b/MatterControlLib/DesignTools/Primitives/TextObject3D.cs index 057e64004..f171ebeaf 100644 --- a/MatterControlLib/DesignTools/Primitives/TextObject3D.cs +++ b/MatterControlLib/DesignTools/Primitives/TextObject3D.cs @@ -113,9 +113,8 @@ namespace MatterHackers.MatterControl.DesignTools [Slider(1, 400, VectorMath.Easing.EaseType.Quadratic, useSnappingGrid: true)] public DoubleOrExpression Height { get; set; } = 3; - [Sortable] - [JsonConverter(typeof(StringEnumConverter))] - public NamedTypeFace Font { get; set; } = NamedTypeFace.Nunito_Bold; + [FontSelector] + public string Font { get; set; } = "Nunito_Bold"; [EnumDisplay(Mode = EnumDisplayAttribute.PresentationMode.Buttons)] public OutputDimensions Output { get; set; } = OutputDimensions.Output3D; @@ -251,7 +250,7 @@ namespace MatterHackers.MatterControl.DesignTools var letterPaths = new List(); foreach (var letter in textToWrite.ToCharArray()) { - var style = new StyledTypeFace(ApplicationController.GetTypeFace(this.Font), pointSize) + var style = new StyledTypeFace(ApplicationController.Instance.GetTypeFace(Font), pointSize) { FlattenCurves = false }; diff --git a/MatterControlLib/DesignTools/PropertyEditor.cs b/MatterControlLib/DesignTools/PropertyEditor.cs index 6b9b4e249..3ab0ba1fa 100644 --- a/MatterControlLib/DesignTools/PropertyEditor.cs +++ b/MatterControlLib/DesignTools/PropertyEditor.cs @@ -1091,14 +1091,7 @@ namespace MatterHackers.MatterControl.DesignTools } else { - if (property.PropertyType == typeof(NamedTypeFace)) - { - field = new FontSelectorField(property, theme); - } - else - { - field = new EnumField(property, theme); - } + field = new EnumField(property, theme); } field.Initialize(ref tabIndex); diff --git a/MatterControlLib/DesignTools/StringPropertyEditor.cs b/MatterControlLib/DesignTools/StringPropertyEditor.cs index bd50125e4..2fa28db6c 100644 --- a/MatterControlLib/DesignTools/StringPropertyEditor.cs +++ b/MatterControlLib/DesignTools/StringPropertyEditor.cs @@ -29,19 +29,18 @@ either expressed or implied, of the FreeBSD Project. using MatterHackers.Agg; using MatterHackers.Agg.Platform; -using MatterHackers.ImageProcessing; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; +using MatterHackers.ImageProcessing; using MatterHackers.Localizations; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.SlicerConfiguration; +using MatterHackers.VectorMath; using System; +using System.ComponentModel; +using System.IO; using System.Linq; using System.Web; -using System.ComponentModel; -using MatterHackers.VectorMath; -using System.IO; -using System.Reflection.Metadata.Ecma335; namespace MatterHackers.MatterControl.DesignTools { @@ -54,41 +53,21 @@ namespace MatterHackers.MatterControl.DesignTools var theme = propertyEditor.Theme; var undoBuffer = propertyEditor.UndoBuffer; - var contextItem = context.Item; - var contextObject3D = contextItem as IObject3D; var propertyIObject3D = property.Source as IObject3D; - var propertyGridModifier = property.Source as IPropertyGridModifier; - - GuiWidget rowContainer = null; + GuiWidget rowContainer; if (property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault() != null) { rowContainer = NewImageSearchWidget(theme); } + if (property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault() != null) + { + rowContainer = InsertFontSelectorField(propertyEditor, property, context, ref tabIndex, stringValue, theme, undoBuffer); + } else if (propertyIObject3D is AssetObject3D assetObject && property.PropertyInfo.Name == "AssetPath") { - // This is the AssetPath property of an asset object, add a button to set the AssetPath from a file - // Change button - var changeButton = new ThemedTextButton(property.Description, theme) - { - BackgroundColor = theme.MinimalShade, - Margin = 3 - }; - - rowContainer = new SettingsRow(property.DisplayName, - null, - changeButton, - theme); - - - changeButton.Click += (sender, e) => - { - UiThread.RunOnIdle(() => - { - ImageObject3D.ShowOpenDialog(assetObject); - }); - }; + rowContainer = InsertEditFieldWithFileButton(property, theme, assetObject); } else { @@ -96,121 +75,17 @@ namespace MatterHackers.MatterControl.DesignTools if (readOnly) { - WrappedTextWidget wrappedTextWidget = null; - if (!string.IsNullOrEmpty(property.DisplayName)) - { - rowContainer = new GuiWidget() - { - HAnchor = HAnchor.Stretch, - VAnchor = VAnchor.Fit, - Margin = 9 - }; - - var displayName = rowContainer.AddChild(new TextWidget(property.DisplayName, - textColor: theme.TextColor, - pointSize: 10) - { - VAnchor = VAnchor.Center, - }); - - var wrapContainer = new GuiWidget() - { - Margin = new BorderDouble(displayName.Width + displayName.Margin.Width + 15, 3, 3, 3), - HAnchor = HAnchor.Stretch, - VAnchor = VAnchor.Fit - }; - wrappedTextWidget = new WrappedTextWidget(stringValue, textColor: theme.TextColor, pointSize: 10) - { - HAnchor = HAnchor.Stretch - }; - wrappedTextWidget.TextWidget.HAnchor = HAnchor.Right; - wrapContainer.AddChild(wrappedTextWidget); - rowContainer.AddChild(wrapContainer); - } - else - { - rowContainer = wrappedTextWidget = new WrappedTextWidget(stringValue, - textColor: theme.TextColor, - pointSize: 10) - { - Margin = 9 - }; - } - - void RefreshField(object s, InvalidateArgs e) - { - if (e.InvalidateType.HasFlag(InvalidateType.DisplayValues)) - { - wrappedTextWidget.Text = property.Value.ToString(); - } - } - - if (propertyIObject3D != null) - { - propertyIObject3D.Invalidated += RefreshField; - wrappedTextWidget.Closed += (s, e) => propertyIObject3D.Invalidated -= RefreshField; - } + rowContainer = InsertReadOnlyTextDisplay(property, stringValue, theme, propertyIObject3D); } else // normal edit row { if (property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault() != null) { - // create a a multi-line string editor - var field = new MultilineStringField(theme, property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault() != null); - field.Initialize(ref tabIndex); - field.SetValue(stringValue, false); - field.ClearUndoHistory(); - field.Content.HAnchor = HAnchor.Stretch; - field.Content.Descendants().FirstOrDefault().MaximumSize = new Vector2(double.MaxValue, 200); - field.Content.Descendants().FirstOrDefault().Parent.VAnchor = VAnchor.Top; - field.Content.MinimumSize = new Vector2(0, 100 * GuiWidget.DeviceScale); - field.Content.Margin = new BorderDouble(0, 0, 0, 5); - PropertyEditor.RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString); - rowContainer = PropertyEditor.CreateSettingsColumn(property, field, fullWidth: true); + rowContainer = InsertMultiLineEdit(property, context, ref tabIndex, stringValue, theme, undoBuffer); } else { - // create a string editor - var field = new TextField(theme); - field.Initialize(ref tabIndex); - field.SetValue(stringValue, false); - field.ClearUndoHistory(); - field.Content.HAnchor = HAnchor.Stretch; - PropertyEditor.RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString); - rowContainer = propertyEditor.CreateSettingsRow(property, field.Content, theme, true); - - // check for DirectoryPathAttribute - var directoryPathAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); - if (directoryPathAttribute != null) - { - // add a browse button - var browseButton = new ThemedIconButton(StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png"), 16, 16).GrayToColor(theme.TextColor), theme) - { - ToolTipText = "Select Folder".Localize(), - }; - browseButton.Click += (s, e) => - { - UiThread.RunOnIdle(() => - { - AggContext.FileDialogs.SelectFolderDialog( - new SelectFolderDialogParams(directoryPathAttribute.Message) - { - ActionButtonLabel = directoryPathAttribute.ActionLabel, - Title = ApplicationController.Instance.ProductName + " - " + "Select A Folder".Localize(), - RootFolder = SelectFolderDialogParams.RootFolderTypes.Specify, - FolderPath = stringValue - }, - (openParams) => - { - if (!string.IsNullOrEmpty(openParams.FolderPath)) - { - field.SetValue(openParams.FolderPath, true); - } - }); - }); - }; - rowContainer.AddChild(browseButton); - } + rowContainer = InsertSingleLineEdit(propertyEditor, property, context, ref tabIndex, stringValue, theme, undoBuffer); } } } @@ -221,6 +96,174 @@ namespace MatterHackers.MatterControl.DesignTools return null; } + private GuiWidget InsertFontSelectorField(PropertyEditor propertyEditor, EditableProperty property, EditorContext context, ref int tabIndex, string stringValue, ThemeConfig theme, UndoBuffer undoBuffer) + { + GuiWidget rowContainer; + var field = new FontSelectorField(property, theme); + + field.Initialize(ref tabIndex); + field.SetValue(stringValue, false); + field.ClearUndoHistory(); + field.Content.HAnchor = HAnchor.Stretch; + PropertyEditor.RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString); + rowContainer = propertyEditor.CreateSettingsRow(property, field.Content, theme, true); + + return rowContainer; + } + + private static GuiWidget InsertSingleLineEdit(PropertyEditor propertyEditor, EditableProperty property, EditorContext context, ref int tabIndex, string stringValue, ThemeConfig theme, UndoBuffer undoBuffer) + { + GuiWidget rowContainer; + // create a string editor + var field = new TextField(theme); + field.Initialize(ref tabIndex); + field.SetValue(stringValue, false); + field.ClearUndoHistory(); + field.Content.HAnchor = HAnchor.Stretch; + PropertyEditor.RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString); + rowContainer = propertyEditor.CreateSettingsRow(property, field.Content, theme, true); + + // check for DirectoryPathAttribute + var directoryPathAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); + if (directoryPathAttribute != null) + { + // add a browse button + var browseButton = new ThemedIconButton(StaticData.Instance.LoadIcon(Path.Combine("Library", "folder.png"), 16, 16).GrayToColor(theme.TextColor), theme) + { + ToolTipText = "Select Folder".Localize(), + }; + browseButton.Click += (s, e) => + { + UiThread.RunOnIdle(() => + { + AggContext.FileDialogs.SelectFolderDialog( + new SelectFolderDialogParams(directoryPathAttribute.Message) + { + ActionButtonLabel = directoryPathAttribute.ActionLabel, + Title = ApplicationController.Instance.ProductName + " - " + "Select A Folder".Localize(), + RootFolder = SelectFolderDialogParams.RootFolderTypes.Specify, + FolderPath = stringValue + }, + (openParams) => + { + if (!string.IsNullOrEmpty(openParams.FolderPath)) + { + field.SetValue(openParams.FolderPath, true); + } + }); + }); + }; + rowContainer.AddChild(browseButton); + } + + return rowContainer; + } + + private static GuiWidget InsertMultiLineEdit(EditableProperty property, EditorContext context, ref int tabIndex, string stringValue, ThemeConfig theme, UndoBuffer undoBuffer) + { + GuiWidget rowContainer; + // create a a multi-line string editor + var field = new MultilineStringField(theme, property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault() != null); + field.Initialize(ref tabIndex); + field.SetValue(stringValue, false); + field.ClearUndoHistory(); + field.Content.HAnchor = HAnchor.Stretch; + field.Content.Descendants().FirstOrDefault().MaximumSize = new Vector2(double.MaxValue, 200); + field.Content.Descendants().FirstOrDefault().Parent.VAnchor = VAnchor.Top; + field.Content.MinimumSize = new Vector2(0, 100 * GuiWidget.DeviceScale); + field.Content.Margin = new BorderDouble(0, 0, 0, 5); + PropertyEditor.RegisterValueChanged(property, undoBuffer, context, field, (valueString) => valueString); + rowContainer = PropertyEditor.CreateSettingsColumn(property, field, fullWidth: true); + return rowContainer; + } + + private static GuiWidget InsertReadOnlyTextDisplay(EditableProperty property, string stringValue, ThemeConfig theme, IObject3D propertyIObject3D) + { + GuiWidget rowContainer; + WrappedTextWidget wrappedTextWidget = null; + if (!string.IsNullOrEmpty(property.DisplayName)) + { + rowContainer = new GuiWidget() + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit, + Margin = 9 + }; + + var displayName = rowContainer.AddChild(new TextWidget(property.DisplayName, + textColor: theme.TextColor, + pointSize: 10) + { + VAnchor = VAnchor.Center, + }); + + var wrapContainer = new GuiWidget() + { + Margin = new BorderDouble(displayName.Width + displayName.Margin.Width + 15, 3, 3, 3), + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit + }; + wrappedTextWidget = new WrappedTextWidget(stringValue, textColor: theme.TextColor, pointSize: 10) + { + HAnchor = HAnchor.Stretch + }; + wrappedTextWidget.TextWidget.HAnchor = HAnchor.Right; + wrapContainer.AddChild(wrappedTextWidget); + rowContainer.AddChild(wrapContainer); + } + else + { + rowContainer = wrappedTextWidget = new WrappedTextWidget(stringValue, + textColor: theme.TextColor, + pointSize: 10) + { + Margin = 9 + }; + } + + void RefreshField(object s, InvalidateArgs e) + { + if (e.InvalidateType.HasFlag(InvalidateType.DisplayValues)) + { + wrappedTextWidget.Text = property.Value.ToString(); + } + } + + if (propertyIObject3D != null) + { + propertyIObject3D.Invalidated += RefreshField; + wrappedTextWidget.Closed += (s, e) => propertyIObject3D.Invalidated -= RefreshField; + } + + return rowContainer; + } + + private static GuiWidget InsertEditFieldWithFileButton(EditableProperty property, ThemeConfig theme, AssetObject3D assetObject) + { + GuiWidget rowContainer; + // This is the AssetPath property of an asset object, add a button to set the AssetPath from a file + // Change button + var changeButton = new ThemedTextButton(property.Description, theme) + { + BackgroundColor = theme.MinimalShade, + Margin = 3 + }; + + rowContainer = new SettingsRow(property.DisplayName, + null, + changeButton, + theme); + + changeButton.Click += (sender, e) => + { + UiThread.RunOnIdle(() => + { + ImageObject3D.ShowOpenDialog(assetObject); + }); + }; + return rowContainer; + } + public static GuiWidget NewImageSearchWidget(ThemeConfig theme, string postPend = "silhouette") { var searchRow = new FlowLayoutWidget() diff --git a/MatterControlLib/PartPreviewWindow/MarkdownEditPage.cs b/MatterControlLib/PartPreviewWindow/MarkdownEditPage.cs index 672dccc98..7fa87d05d 100644 --- a/MatterControlLib/PartPreviewWindow/MarkdownEditPage.cs +++ b/MatterControlLib/PartPreviewWindow/MarkdownEditPage.cs @@ -66,7 +66,7 @@ namespace MatterHackers.MatterControl BackgroundColor = theme.BackgroundColor }; - editWidget = new ThemedTextEditWidget("", theme, multiLine: true, typeFace: ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono)) + editWidget = new ThemedTextEditWidget("", theme, multiLine: true, typeFace: ApplicationController.Instance.GetTypeFace("Liberation_Mono")) { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Stretch, diff --git a/MatterControlLib/PrinterControls/MacroDetailPage.cs b/MatterControlLib/PrinterControls/MacroDetailPage.cs index c4b395e81..5ec1348d0 100644 --- a/MatterControlLib/PrinterControls/MacroDetailPage.cs +++ b/MatterControlLib/PrinterControls/MacroDetailPage.cs @@ -82,7 +82,7 @@ namespace MatterHackers.MatterControl Margin = new BorderDouble(0, 0, 0, 1) }); - macroCommandInput = new ThemedTextEditWidget(gcodeMacro.GCode, theme, pixelHeight: 120, multiLine: true, typeFace: ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono)) + macroCommandInput = new ThemedTextEditWidget(gcodeMacro.GCode, theme, pixelHeight: 120, multiLine: true, typeFace: ApplicationController.Instance.GetTypeFace("Liberation_Mono")) { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Stretch diff --git a/MatterControlLib/PrinterControls/TerminalWindow/TerminalWidget.cs b/MatterControlLib/PrinterControls/TerminalWindow/TerminalWidget.cs index 90a981ebc..39f0f71bc 100644 --- a/MatterControlLib/PrinterControls/TerminalWindow/TerminalWidget.cs +++ b/MatterControlLib/PrinterControls/TerminalWindow/TerminalWidget.cs @@ -181,7 +181,7 @@ namespace MatterHackers.MatterControl }; this.AddChild(inputRow); - manualCommandTextEdit = new ThemedTextEditWidget("", theme, typeFace: ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono)) + manualCommandTextEdit = new ThemedTextEditWidget("", theme, typeFace: ApplicationController.Instance.GetTypeFace("Liberation_Mono")) { Margin = new BorderDouble(right: 3), HAnchor = HAnchor.Stretch, diff --git a/MatterControlLib/PrinterControls/TerminalWindow/TextScrollWidget.cs b/MatterControlLib/PrinterControls/TerminalWindow/TextScrollWidget.cs index 87d1482b3..6ae86bb78 100644 --- a/MatterControlLib/PrinterControls/TerminalWindow/TextScrollWidget.cs +++ b/MatterControlLib/PrinterControls/TerminalWindow/TextScrollWidget.cs @@ -63,7 +63,7 @@ namespace MatterHackers.MatterControl public TextScrollWidget(PrinterConfig printer, TerminalLog terminalLog) { this.printer = printer; - this.typeFacePrinter = new TypeFacePrinter("", new StyledTypeFace(ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono), 12)); + this.typeFacePrinter = new TypeFacePrinter("", new StyledTypeFace(ApplicationController.Instance.GetTypeFace("Liberation_Mono"), 12)); this.typeFacePrinter.DrawFromHintedCache = true; this.terminalLog = terminalLog; this.visibleLines = terminalLog.AllLines().ToList(); diff --git a/MatterControlLib/SlicerConfiguration/UIFields/EnumField.cs b/MatterControlLib/SlicerConfiguration/UIFields/EnumField.cs index 06a904780..d77906f6e 100644 --- a/MatterControlLib/SlicerConfiguration/UIFields/EnumField.cs +++ b/MatterControlLib/SlicerConfiguration/UIFields/EnumField.cs @@ -66,7 +66,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration { Key = enumName, Value = renamedName.Replace('_', ' ') - }; + }; }); dropDownList = new MHDropDownList("Name".Localize(), theme) diff --git a/MatterControlLib/SlicerConfiguration/UIFields/FontSelectorField.cs b/MatterControlLib/SlicerConfiguration/UIFields/FontSelectorField.cs index d8ee2fe49..1a3228984 100644 --- a/MatterControlLib/SlicerConfiguration/UIFields/FontSelectorField.cs +++ b/MatterControlLib/SlicerConfiguration/UIFields/FontSelectorField.cs @@ -50,39 +50,18 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public override void Initialize(ref int tabIndex) { // Enum keyed on name to friendly name - var enumItems = Enum.GetNames(property.PropertyType).Select(enumName => - { - var renamedName = enumName; - - var renameAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); - if (renameAttribute != null) - { - if (renameAttribute.NameMaping.TryGetValue(renamedName, out string value)) - { - renamedName = value; - } - } - - return new - { - Key = enumName, - Value = renamedName.Replace('_', ' ') - }; - }); + var orderedItems = ApplicationController.Instance.TypeFaceCache.OrderBy(n => n.Key); dropDownList = new MHDropDownList("Name".Localize(), theme) { Name = property.DisplayName + " DropDownList" }; - var sortableAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType().FirstOrDefault(); - var orderedItems = sortableAttribute != null ? enumItems.OrderBy(n => n.Value) : enumItems; - foreach (var orderItem in orderedItems) { - Enum.TryParse(orderItem.Key, out NamedTypeFace namedTypeFace); - var typeFace = ApplicationController.GetTypeFace(namedTypeFace); - MenuItem newItem = dropDownList.AddItem(orderItem.Value, orderItem.Key, typeFace); + var namedTypeFace = orderItem.Key; + var typeFace = ApplicationController.Instance.GetTypeFace(namedTypeFace); + MenuItem newItem = dropDownList.AddItem(orderItem.Key, orderItem.Key, typeFace); var localOrderedItem = orderItem; newItem.Selected += (sender, e) => diff --git a/MatterControlLib/SlicerConfiguration/UIFields/MultilineStringField.cs b/MatterControlLib/SlicerConfiguration/UIFields/MultilineStringField.cs index 7c3bfa256..dfca08c2e 100644 --- a/MatterControlLib/SlicerConfiguration/UIFields/MultilineStringField.cs +++ b/MatterControlLib/SlicerConfiguration/UIFields/MultilineStringField.cs @@ -53,7 +53,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration public override void Initialize(ref int tabIndex) { - editWidget = new ThemedTextEditWidget("", theme, pixelWidth: 320, multiLine: true, tabIndex: tabIndex, typeFace: ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono)) + editWidget = new ThemedTextEditWidget("", theme, pixelWidth: 320, multiLine: true, tabIndex: tabIndex, typeFace: ApplicationController.Instance.GetTypeFace("Liberation_Mono")) { HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Fit,