From a04f0ac88b362172d0be72a181533b0b975b08e6 Mon Sep 17 00:00:00 2001 From: John Lewin Date: Wed, 1 Jun 2016 14:00:47 -0700 Subject: [PATCH] Decouple make/model droplists - Fixes #833 --- .../PrinterConnections/PrinterChooser.cs | 149 ++++-------------- .../SetupStepMakeModelName.cs | 142 ++++++++--------- SettingsManagement/OemSettings.cs | 79 ++++++---- Submodules/agg-sharp | 2 +- .../MatterControl/PrinterChooserUnitTests.cs | 37 +++-- 5 files changed, 162 insertions(+), 247 deletions(-) diff --git a/PrinterControls/PrinterConnections/PrinterChooser.cs b/PrinterControls/PrinterConnections/PrinterChooser.cs index 3076bd181..e77188bc4 100644 --- a/PrinterControls/PrinterConnections/PrinterChooser.cs +++ b/PrinterControls/PrinterConnections/PrinterChooser.cs @@ -37,134 +37,41 @@ using System.Linq; namespace MatterHackers.MatterControl { - public class PrinterChooser : GuiWidget + public class BoundDropList : StyledDropDownList { - public StyledDropDownList ManufacturerDropList; - private int countOfMakes = 0; - private string manufacturer; + private List> listSource; - public int CountOfMakes { get { return countOfMakes; } } - - public PrinterChooser(string selectedMake = null) + public BoundDropList(string noSelectionString, int maxHeight = 0) + : base(noSelectionString, maxHeight: maxHeight) { - string defaultManufacturerLabel = LocalizedString.Get("Select Make"); - string defaultManufacturerLabelFull = string.Format("- {0} -", defaultManufacturerLabel); - ManufacturerDropList = new StyledDropDownList(defaultManufacturerLabelFull, maxHeight: 200); - ManufacturerDropList.Name = "Select Make"; - bool addOther = false; - string[] printerWhiteListStrings = OemSettings.Instance.PrinterWhiteList.ToArray(); - List manufacturerNameMappings = OemSettings.Instance.ManufacturerNameMappings; - string pathToManufacturers = "PrinterSettings"; - if (StaticData.Instance.DirectoryExists(pathToManufacturers)) - { - int index = 0; - int preselectIndex = -1; - foreach (string manufacturerDirectory in StaticData.Instance.GetDirectories(pathToManufacturers)) - { - string folderName = Path.GetFileName(manufacturerDirectory.TrimEnd(new[] { '/', '\\' })); - - // Apply whitelist - if (!printerWhiteListStrings.Contains(folderName)) - { - continue; - } - - // Set manufacturer name to the directory name - this.manufacturer = Path.GetFileName(manufacturerDirectory); - - // Override the manufacturer name if a manufacturerNameMappings exists - foreach (ManufacturerNameMapping nameMapping in manufacturerNameMappings) - { - if(nameMapping.NameOnDisk == folderName) - { - this.manufacturer = nameMapping.NameToDisplay; - break; - } - } - - if (this.manufacturer == "Other") - { - addOther = true; - } - else - { - ManufacturerDropList.AddItem(manufacturer, folderName); - if (selectedMake != null) - { - if (this.manufacturer == selectedMake) - { - preselectIndex = index; - } - } - index++; - } - countOfMakes += 1; - } - - if (addOther) - { - if (selectedMake != null && preselectIndex == -1) - { - preselectIndex = index; - } - ManufacturerDropList.AddItem(LocalizedString.Get("Other")); - } - if (preselectIndex != -1) - { - ManufacturerDropList.SelectedIndex = preselectIndex; - } - } - - if (ManufacturerDropList.MenuItems.Count == 1) - { - ManufacturerDropList.SelectedIndex = 0; - } - - AddChild(ManufacturerDropList); - - HAnchor = HAnchor.FitToChildren; - VAnchor = VAnchor.FitToChildren; - } - } - - public class ModelChooser : GuiWidget - { - public StyledDropDownList ModelDropList; - private int countOfModels = 0; - - public int CountOfModels { get { return countOfModels; } } - - public ModelChooser(string manufacturer) - { - string defaultModelDropDownLabel = LocalizedString.Get("Select Model"); - string defaultModelDropDownLabelFull = string.Format("- {0} -", defaultModelDropDownLabel); - ModelDropList = new StyledDropDownList(defaultModelDropDownLabelFull, maxHeight: 200); - ModelDropList.Name = defaultModelDropDownLabel; - - string pathToModels = Path.Combine("PrinterSettings", manufacturer); - if (StaticData.Instance.DirectoryExists((pathToModels))) - { - foreach (string manufacturerDirectory in StaticData.Instance.GetDirectories(pathToModels)) - { - string model = Path.GetFileName(manufacturerDirectory); - ModelDropList.AddItem(model); - countOfModels += 1; - } - } - - ModelDropList.AddItem(LocalizedString.Get("Other")); - AddChild(ModelDropList); - - HAnchor = HAnchor.FitToChildren; - VAnchor = VAnchor.FitToChildren; } - public void SelectIfOnlyOneModel() + public List> ListSource { - if (ModelDropList.MenuItems.Count == 2) + get { - ModelDropList.SelectedIndex = 0; + return listSource; + } + set + { + if (listSource == value) + { + return; + } + + MenuItems.Clear(); + SelectedIndex = -1; + + listSource = value; + + foreach (var keyValue in listSource) + { + AddItem(keyValue.Key, keyValue.Value); + } + + Invalidate(); } } } -} \ No newline at end of file +} + \ No newline at end of file diff --git a/PrinterControls/PrinterConnections/SetupStepMakeModelName.cs b/PrinterControls/PrinterConnections/SetupStepMakeModelName.cs index 1d854c2eb..2ecdb796d 100644 --- a/PrinterControls/PrinterConnections/SetupStepMakeModelName.cs +++ b/PrinterControls/PrinterConnections/SetupStepMakeModelName.cs @@ -8,6 +8,8 @@ using System.Collections.Generic; using System.Linq; using MatterHackers.MatterControl.CustomWidgets; using MatterHackers.MatterControl.SlicerConfiguration; +using MatterHackers.Agg.PlatformAbstract; +using System.IO; namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections { @@ -16,46 +18,68 @@ namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections { private FlowLayoutWidget printerModelContainer; private FlowLayoutWidget printerMakeContainer; - private FlowLayoutWidget printerNameContainer; private MHTextEditWidget printerNameInput; private TextWidget printerNameError; - private TextWidget printerModelError; - private TextWidget printerMakeError; - - private PrinterChooser printerManufacturerSelector; private Button nextButton; private bool usingDefaultName; + private static BorderDouble elementMargin = new BorderDouble(top: 3); + + private BoundDropList printerManufacturerSelector; + private BoundDropList printerModelSelector; + public SetupStepMakeModelName(ConnectionWizard windowController) : base(windowController) { + var allManufacturers = StaticData.Instance.GetDirectories("PrinterSettings").Select(p => Path.GetFileName(p.TrimEnd(new[] { '/', '\\' }))); + //Construct inputs - printerNameContainer = createPrinterNameContainer(); - printerMakeContainer = createPrinterMakeContainer(); - - if (printerManufacturerSelector.CountOfMakes == 1) + printerManufacturerSelector = new BoundDropList(string.Format("- {0} -", "Select Make".Localize()), maxHeight: 200) { - ActivePrinter.Make = printerManufacturerSelector.ManufacturerDropList.SelectedValue; + HAnchor = HAnchor.ParentLeftRight, + Margin = elementMargin, + Name = "Select Make", + ListSource = OemSettings.Instance.AllManufacturers + }; - printerMakeContainer.Visible = false; - printerModelContainer = createPrinterModelContainer(printerManufacturerSelector.ManufacturerDropList.SelectedValue); - printerModelContainer.Visible = true; - } - else + printerManufacturerSelector.SelectionChanged += ManufacturerDropList_SelectionChanged; + + printerMakeContainer = CreateSelectionContainer( + "Make".Localize() + ":", + "Select the printer manufacturer".Localize(), + printerManufacturerSelector); + + if (printerManufacturerSelector.MenuItems.Count == 1) { - printerModelContainer = createPrinterModelContainer(); + ActivePrinter.Make = printerManufacturerSelector.SelectedValue; } + printerModelSelector = new BoundDropList(string.Format("- {0} -", "Select Model".Localize()), maxHeight: 200) + { + Name = "Select Model", + HAnchor = HAnchor.ParentLeftRight, + Margin = elementMargin, + }; + printerModelSelector.SelectionChanged += ModelDropList_SelectionChanged; + + if (printerModelSelector.MenuItems.Count == 1) + { + // SelectIfOnlyOneModel + printerModelSelector.SelectedIndex = 0; + } + + printerModelContainer = CreateSelectionContainer("Model".Localize(), "Select the printer model".Localize(), printerModelSelector); + //Add inputs to main container - contentRow.AddChild(printerNameContainer); + contentRow.AddChild(createPrinterNameContainer()); contentRow.AddChild(printerMakeContainer); contentRow.AddChild(printerModelContainer); //Construct buttons - nextButton = textImageButtonFactory.Generate(LocalizedString.Get("Save & Continue")); + nextButton = textImageButtonFactory.Generate("Save & Continue".Localize()); nextButton.Name = "Save & Continue Button"; nextButton.Click += (s, e) => { @@ -114,73 +138,36 @@ namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections return container; } - private FlowLayoutWidget createPrinterMakeContainer() + private FlowLayoutWidget CreateSelectionContainer(string labelText, string validationMessage, DropDownList selector) { - BorderDouble elementMargin = new BorderDouble(top: 3); - - TextWidget printerManufacturerLabel = new TextWidget("Make".Localize() + ":", 0, 0, 12) + var sectionLabel = new TextWidget(labelText, 0, 0, 12) { TextColor = ActiveTheme.Instance.PrimaryTextColor, HAnchor = HAnchor.ParentLeftRight, Margin = elementMargin }; - printerManufacturerSelector = new PrinterChooser() - { - HAnchor = HAnchor.ParentLeftRight, - Margin = elementMargin - }; - printerManufacturerSelector.ManufacturerDropList.SelectionChanged += ManufacturerDropList_SelectionChanged; - - printerMakeError = new TextWidget("Select the printer manufacturer".Localize(), 0, 0, 10) + var validationTextWidget = new TextWidget(validationMessage, 0, 0, 10) { TextColor = ActiveTheme.Instance.SecondaryAccentColor, HAnchor = HAnchor.ParentLeftRight, Margin = elementMargin }; - FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom); - container.Margin = new BorderDouble(0, 5); - container.AddChild(printerManufacturerLabel); - container.AddChild(printerManufacturerSelector); - container.AddChild(printerMakeError); - container.HAnchor = HAnchor.ParentLeftRight; - - return container; - } - - private FlowLayoutWidget createPrinterModelContainer(string make = "Other") - { - BorderDouble elementMargin = new BorderDouble(top: 3); - - TextWidget printerModelLabel = new TextWidget("Model".Localize() + ":", 0, 0, 12) + selector.SelectionChanged += (s, e) => { - TextColor = ActiveTheme.Instance.PrimaryTextColor, - HAnchor = HAnchor.ParentLeftRight, - Margin = elementMargin + validationTextWidget.Visible = selector.SelectedLabel.StartsWith("-"); // The default values have "- Title -" }; - ModelChooser printerModelSelector = new ModelChooser(make) + var container = new FlowLayoutWidget(FlowDirection.TopToBottom) { - HAnchor = HAnchor.ParentLeftRight, - Margin = elementMargin - }; - printerModelSelector.ModelDropList.SelectionChanged += new EventHandler(ModelDropList_SelectionChanged); - printerModelSelector.SelectIfOnlyOneModel(); - - printerModelError = new TextWidget("Select the printer model".Localize(), 0, 0, 10) - { - TextColor = ActiveTheme.Instance.SecondaryAccentColor, - HAnchor = HAnchor.ParentLeftRight, - Margin = elementMargin + Margin = new BorderDouble(0, 5), + HAnchor = HAnchor.ParentLeftRight }; - FlowLayoutWidget container = new FlowLayoutWidget(FlowDirection.TopToBottom); - container.Margin = new BorderDouble(0, 5); - container.AddChild(printerModelLabel); - container.AddChild(printerModelSelector); - container.AddChild(printerModelError); - container.HAnchor = HAnchor.ParentLeftRight; + container.AddChild(sectionLabel); + container.AddChild(selector); + container.AddChild(validationTextWidget); return container; } @@ -189,35 +176,30 @@ namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections { ActivePrinter.Make = ((DropDownList)sender).SelectedValue; ActivePrinter.Model = null; - ReconstructModelSelector(); - SetElementVisibility(); - } - private void ReconstructModelSelector() - { - //reconstruct model selector - int currentIndex = contentRow.GetChildIndex(printerModelContainer); - contentRow.RemoveChild(printerModelContainer); + // ReconstructModelSelector + string pathToModels = Path.Combine("PrinterSettings", ActivePrinter.Make); + var models = StaticData.Instance.GetDirectories(pathToModels).Select(p => Path.GetFileName(p.TrimEnd(new[] { '/', '\\' }))); + + printerModelSelector.ListSource = models.Select(modelName => new KeyValuePair(modelName, modelName)).ToList(); - printerModelContainer = createPrinterModelContainer(ActivePrinter.Make); - contentRow.AddChild(printerModelContainer, currentIndex); contentRow.Invalidate(); - printerMakeError.Visible = false; + SetElementVisibility(); } private void ModelDropList_SelectionChanged(object sender, EventArgs e) { UiThread.RunOnIdle(() => { - ActivePrinter.Model = ((DropDownList)sender).SelectedLabel; + StyledDropDownList dropList = (StyledDropDownList) sender; + ActivePrinter.Model = dropList.SelectedLabel; - printerModelError.Visible = false; SetElementVisibility(); if (usingDefaultName) { // Use ManufacturerDropList.SelectedLabel instead of ActivePrinter.Make to ensure the mapped Unicode values are picked up - string mappedMakeText = printerManufacturerSelector.ManufacturerDropList.SelectedLabel; + string mappedMakeText = printerManufacturerSelector.SelectedLabel; string printerInputName = String.Format("{0} {1}", mappedMakeText, this.ActivePrinter.Model); var names = ActiveSliceSettings.ProfileData.Profiles.Where(p => p.Name.StartsWith(printerInputName)).Select(p => p.Name).ToList(); diff --git a/SettingsManagement/OemSettings.cs b/SettingsManagement/OemSettings.cs index ef3788aac..ee315873e 100644 --- a/SettingsManagement/OemSettings.cs +++ b/SettingsManagement/OemSettings.cs @@ -30,7 +30,10 @@ either expressed or implied, of the FreeBSD Project. using MatterHackers.Agg.PlatformAbstract; using Newtonsoft.Json; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.IO; +using System.Linq; +using System.Runtime.Serialization; namespace MatterHackers.MatterControl.SettingsManagement { @@ -46,13 +49,6 @@ namespace MatterHackers.MatterControl.SettingsManagement { string oemSettings = StaticData.Instance.ReadAllText(Path.Combine("OEMSettings", "Settings.json")); instance = JsonConvert.DeserializeObject(oemSettings) as OemSettings; -#if false - string output = JsonConvert.SerializeObject(instance, Formatting.Indented); - using (StreamWriter outfile = new StreamWriter("Settings.json")) - { - outfile.Write(output); - } -#endif } return instance; @@ -71,45 +67,68 @@ namespace MatterHackers.MatterControl.SettingsManagement public bool CheckForUpdatesOnFirstRun = false; - private List printerWhiteList = new List(); - - public List PrinterWhiteList { get { return printerWhiteList; } } + public List PrinterWhiteList { get; private set; } = new List(); public List ManufacturerNameMappings { get; set; } - // TODO: Is this ever initialized and if so, how, given there's no obvious references and only one use of the property - private List preloadedLibraryFiles = new List(); + public List PreloadedLibraryFiles { get; } = new List(); - public List PreloadedLibraryFiles { get { return preloadedLibraryFiles; } } + internal void SetManufacturers(List> manufacturers, List whitelist = null) + { + if (whitelist != null) + { + this.PrinterWhiteList = whitelist; + } + // Apply whitelist + var whiteListedItems = manufacturers?.Where(keyValue => PrinterWhiteList.Contains(keyValue.Key)); + if (whiteListedItems == null) + { + AllManufacturers = new List>(); + return; + } + + var newItems = new List>(); + + // Apply manufacturer name mappings + foreach (var keyValue in whiteListedItems) + { + string labelText = keyValue.Value; + + // Override the manufacturer name if a manufacturerNameMappings exists + string mappedName = ManufacturerNameMappings.Where(m => m.NameOnDisk == keyValue.Key).FirstOrDefault()?.NameOnDisk; + if (!string.IsNullOrEmpty(mappedName)) + { + labelText = mappedName; + } + + newItems.Add(new KeyValuePair(keyValue.Key, labelText)); + } + + AllManufacturers = newItems; + } + + public List> AllManufacturers { get; private set; } + [OnDeserialized] + private void Deserialized(StreamingContext context) + { + var manufacturers = StaticData.Instance.GetDirectories("PrinterSettings").Select(p => Path.GetFileName(p.TrimEnd(new[] { '/', '\\' }))); + + SetManufacturers(manufacturers.Select(m => new KeyValuePair(m, m)).ToList()); + } private OemSettings() { -#if false // test saving the file - printerWhiteList.Add("one"); - printerWhiteList.Add("two"); - PreloadedLibraryFiles.Add("uno"); - PreloadedLibraryFiles.Add("dos"); - AffiliateCode = "testcode"; - string pathToOemSettings = Path.Combine(".", "OEMSettings", "Settings.json"); - File.WriteAllText(pathToOemSettings, JsonConvert.SerializeObject(this, Formatting.Indented)); -#endif this.ManufacturerNameMappings = new List(); } } public class ManufacturerNameMapping { - public string NameOnDisk - { - get; set; - } + public string NameOnDisk { get; set; } - public string NameToDisplay - { - get; set; - } + public string NameToDisplay { get; set; } } } diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 98192b406..e8c232b5e 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 98192b406f2b6659e1d8ba27af75d6ccb7a1ca93 +Subproject commit e8c232b5ee5763e4168a527c05ad9ec9b4df2c86 diff --git a/Tests/MatterControl.Tests/MatterControl/PrinterChooserUnitTests.cs b/Tests/MatterControl.Tests/MatterControl/PrinterChooserUnitTests.cs index 5dd0bef6a..ef8732ada 100644 --- a/Tests/MatterControl.Tests/MatterControl/PrinterChooserUnitTests.cs +++ b/Tests/MatterControl.Tests/MatterControl/PrinterChooserUnitTests.cs @@ -23,19 +23,31 @@ namespace MatterControl.Tests.MatterControl MatterControlUtilities.OverrideAppDataLocation(); + var manufacturers = new string[] { "3D Factory", "3D Stuffmaker", "Airwolf 3D", "BCN", "BeeVeryCreative", "Blue Eagle Labs", "Deezmaker", "FlashForge", "gCreate", "IRA3D", "JumpStart", "Leapfrog", "Lulzbot", "MAKEiT", "Maker's Tool Works", "MakerBot", "MakerGear", "Me3D", "OpenBeam", "Organic Thinking System", "Other", "Portabee", "Printrbot", "PrintSpace", "Revolution 3D Printers", "ROBO 3D", "SeeMeCNC", "Solidoodle", "Tosingraf", "Type A Machines", "Ultimaker", "Velleman", "Wanhao" }; + + var allManufacturers = manufacturers.Select(m => new KeyValuePair(m, m)).ToList(); + + BoundDropList dropList; + // Whitelist on non-OEM builds should contain all printers - var printChooser = new PrinterChooser(); - - Assert.IsTrue(printChooser.CountOfMakes > 15); + dropList = new BoundDropList("Test"); + dropList.ListSource = allManufacturers; + Assert.Greater(dropList.MenuItems.Count, 20); - // Set private member to override settings.json values for this test - SetPrivatePrinterWhiteListMember(new List() { "3D Stuffmaker" }); - printChooser = new PrinterChooser(); - Assert.IsTrue(printChooser.CountOfMakes == 1); + var whitelist = new List { "3D Stuffmaker" }; - SetPrivatePrinterWhiteListMember(new List() { "Airwolf 3D", "3D Stuffmaker" }); - printChooser = new PrinterChooser(); - Assert.IsTrue(printChooser.CountOfMakes == 2); + OemSettings.Instance.SetManufacturers(allManufacturers, whitelist); + + dropList = new BoundDropList("Test"); + dropList.ListSource = OemSettings.Instance.AllManufacturers; + Assert.AreEqual(1, dropList.MenuItems.Count); + + whitelist.Add("Airwolf 3D"); + OemSettings.Instance.SetManufacturers(allManufacturers, whitelist); + + dropList = new BoundDropList("Test"); + dropList.ListSource = OemSettings.Instance.AllManufacturers; + Assert.AreEqual(2, dropList.MenuItems.Count); /* * Disable Esagono tests @@ -58,10 +70,5 @@ namespace MatterControl.Tests.MatterControl */ } - private static void SetPrivatePrinterWhiteListMember(List newValue) - { - var fieldInfo = typeof(OemSettings).GetField("printerWhiteList", BindingFlags.Instance | BindingFlags.NonPublic); - fieldInfo.SetValue(OemSettings.Instance, newValue); - } } }