mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 02:32:09 +10:00
added ability to save default model
This commit is contained in:
@@ -43,6 +43,10 @@ public interface IVariantProcessor {
|
||||
void deleteVariant(ComponentType type, String variantName);
|
||||
|
||||
void setDefaultVariant(ComponentType type, String variantName);
|
||||
|
||||
void setDefaultModel(ComponentType type, String[] model);
|
||||
|
||||
boolean isDefaultModel(ComponentType type, String[] model);
|
||||
|
||||
int importVariants(String fileName) throws IOException;
|
||||
|
||||
|
||||
@@ -2868,17 +2868,21 @@ public class Presenter implements IPlugInPort {
|
||||
controlPointMap.clear();
|
||||
}
|
||||
|
||||
// try to find a default template if none is provided
|
||||
if (componentType != null && template == null) {
|
||||
String defaultTemplate = getDefaultVariant(componentType);
|
||||
List<Template> templates = getVariantsFor(componentType);
|
||||
if (templates != null && defaultTemplate != null)
|
||||
for (Template t : templates) {
|
||||
if (t.getName().equals(defaultTemplate)) {
|
||||
template = t;
|
||||
break;
|
||||
// try to find a default model or template if none is provided
|
||||
if (componentType != null && template == null && model == null) {
|
||||
model = variantManager.getDefaultModel(componentType);
|
||||
if (model == null) {
|
||||
String defaultTemplate = getDefaultVariant(componentType);
|
||||
List<Template> templates = getVariantsFor(componentType);
|
||||
if (templates != null && defaultTemplate != null) {
|
||||
for (Template t : templates) {
|
||||
if (t.getName().equals(defaultTemplate)) {
|
||||
template = t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -3064,28 +3068,19 @@ public class Presenter implements IPlugInPort {
|
||||
variantManager.deleteVariant(type, templateName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void setDefaultVariant(ComponentType type, String templateName) {
|
||||
LOG.debug(String.format("setTemplateDefault(%s, %s)", type, templateName));
|
||||
Map<String, String> defaultTemplateMap =
|
||||
(Map<String, String>) configManager.readObject(DEFAULT_TEMPLATES_KEY, null);
|
||||
if (defaultTemplateMap == null)
|
||||
defaultTemplateMap = new HashMap<String, String>();
|
||||
variantManager.setDefaultVariant(type, templateName);
|
||||
}
|
||||
|
||||
// try by class name and then by old category.type format
|
||||
String key1 = type.getInstanceClass().getCanonicalName();
|
||||
String key2 = type.getCategory() + "." + type.getName();
|
||||
@Override
|
||||
public void setDefaultModel(ComponentType type, String[] model) {
|
||||
variantManager.setDefaultModel(type, model);
|
||||
}
|
||||
|
||||
if (templateName.equals(defaultTemplateMap.get(key1)) || templateName.equals(defaultTemplateMap.get(key2))) {
|
||||
defaultTemplateMap.remove(key1);
|
||||
defaultTemplateMap.remove(key2);
|
||||
} else {
|
||||
// get rid of legacy key
|
||||
defaultTemplateMap.remove(key2);
|
||||
defaultTemplateMap.put(key1, templateName);
|
||||
}
|
||||
configManager.writeValue(DEFAULT_TEMPLATES_KEY, defaultTemplateMap);
|
||||
@Override
|
||||
public boolean isDefaultModel(ComponentType type, String[] model) {
|
||||
return variantManager.isDefaultModel(type, model);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,6 +23,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@@ -46,6 +47,9 @@ import org.diylc.serialization.ProjectFileManager;
|
||||
public class VariantManager {
|
||||
|
||||
private static final String VARIANTS_FILE_NAME = "import-defaults/variants.xml";
|
||||
// marks a default that names a datasheet model rather than a variant; older versions find no
|
||||
// variant by that name and simply place the component without a default
|
||||
private static final String DATASHEET_MODEL_PREFIX = "datasheet:";
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(VariantManager.class);
|
||||
|
||||
@@ -261,6 +265,67 @@ public class VariantManager {
|
||||
return defaultTemplateMap.get(key2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the variant the default of its type, replacing whatever variant or model was the
|
||||
* default before, or clears the default if the variant already is it.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setDefaultVariant(ComponentType type, String variantName) {
|
||||
Map<String, String> defaultTemplateMap =
|
||||
(Map<String, String>) configManager.readObject(IPlugInPort.DEFAULT_TEMPLATES_KEY, null);
|
||||
if (defaultTemplateMap == null) {
|
||||
defaultTemplateMap = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
// try by class name and then by old category.type format
|
||||
String key1 = type.getInstanceClass().getCanonicalName();
|
||||
String key2 = type.getCategory() + "." + type.getName();
|
||||
|
||||
if (variantName.equals(defaultTemplateMap.get(key1))
|
||||
|| variantName.equals(defaultTemplateMap.get(key2))) {
|
||||
defaultTemplateMap.remove(key1);
|
||||
defaultTemplateMap.remove(key2);
|
||||
LOG.info(String.format("Cleared default of %s, was %s", type.getName(), variantName));
|
||||
} else {
|
||||
// get rid of legacy key
|
||||
defaultTemplateMap.remove(key2);
|
||||
defaultTemplateMap.put(key1, variantName);
|
||||
LOG.info(String.format("Set default of %s to %s", type.getName(), variantName));
|
||||
}
|
||||
configManager.writeValue(IPlugInPort.DEFAULT_TEMPLATES_KEY, defaultTemplateMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link #setDefaultVariant(ComponentType, String)} for a datasheet model, sharing the
|
||||
* single default slot of the type.
|
||||
*/
|
||||
public void setDefaultModel(ComponentType type, String[] model) {
|
||||
setDefaultVariant(type, encodeModel(type, model));
|
||||
}
|
||||
|
||||
public boolean isDefaultModel(ComponentType type, String[] model) {
|
||||
return encodeModel(type, model).equals(getDefaultVariant(type));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the datasheet row pinned as the default of the type, or null when the default is a
|
||||
* variant, nothing is pinned, or the pinned model is no longer in the datasheet.
|
||||
*/
|
||||
public String[] getDefaultModel(ComponentType type) {
|
||||
String defaultVariant = getDefaultVariant(type);
|
||||
List<String[]> datasheet = type.getDatasheet();
|
||||
if (defaultVariant == null || !defaultVariant.startsWith(DATASHEET_MODEL_PREFIX)
|
||||
|| datasheet == null) {
|
||||
return null;
|
||||
}
|
||||
for (String[] row : datasheet) {
|
||||
if (defaultVariant.equals(encodeModel(type, row))) {
|
||||
return row;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void deleteVariant(ComponentType type, String templateName) {
|
||||
LOG.debug(String.format("deleteTemplate(%s, %s)", type, templateName));
|
||||
@@ -294,4 +359,11 @@ public class VariantManager {
|
||||
}
|
||||
configManager.writeValue(IPlugInPort.TEMPLATES_KEY, templateMap);
|
||||
}
|
||||
|
||||
// a model is identified by its path through the datasheet submenus, the same columns the
|
||||
// toolbox matches when a model is clicked
|
||||
private String encodeModel(ComponentType type, String[] model) {
|
||||
int depth = Math.min(type.getDatasheetCreationStepCount(), model.length);
|
||||
return DATASHEET_MODEL_PREFIX + String.join("|", Arrays.copyOf(model, depth));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -549,6 +549,10 @@
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Added a datasheet to 'Enclosure' with Hammond 1590, 1550, 1441 and 1444 enclosures and the 125B size - more than 130 variations</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>Datasheet models in a component's drop-down menu now have the same pin as saved variants, so a model such as a 2N3904 can be made the default that is placed when the component is clicked; a component has one default, so pinning a model replaces a pinned variant and the other way round</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>IMPROVEMENT</changeType>
|
||||
<description>Re-modeled factory variants of Resistor component type as datasheet in order to make them available to the AI; this will produce more accurate AI-driven edits</description>
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
|
||||
DIY Layout Creator (DIYLC).
|
||||
Copyright (c) 2009-2025 held jointly by the individual authors.
|
||||
|
||||
This file is part of DIYLC.
|
||||
|
||||
DIYLC is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
DIYLC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
package org.diylc.presenter;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.diylc.appframework.miscutils.IConfigListener;
|
||||
import org.diylc.appframework.miscutils.IConfigurationManager;
|
||||
import org.diylc.common.ComponentType;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.core.CreationMethod;
|
||||
import org.diylc.core.annotations.BomPolicy;
|
||||
import org.diylc.core.annotations.KeywordPolicy;
|
||||
import org.diylc.testcomponents.TwoPointTestComponent;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Covers the single default slot that variants and datasheet models share, see
|
||||
* {@code docs/plans/default-datasheet-model.md}.
|
||||
*/
|
||||
public class VariantManagerTest {
|
||||
|
||||
private static final String[] NPN = new String[] {"BJT (NPN)", "2N3904", "BJT_EBC"};
|
||||
private static final String[] PNP = new String[] {"BJT (PNP)", "2N3906", "BJT_EBC"};
|
||||
|
||||
private MapConfigurationManager configManager;
|
||||
private ComponentType type;
|
||||
private VariantManager manager;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
configManager = new MapConfigurationManager();
|
||||
type = createType(new ArrayList<String[]>(Arrays.asList(NPN, PNP)));
|
||||
manager = new VariantManager(configManager, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pinningAModelMakesItTheDefault() {
|
||||
manager.setDefaultModel(type, NPN);
|
||||
|
||||
assertTrue(manager.isDefaultModel(type, NPN));
|
||||
assertFalse(manager.isDefaultModel(type, PNP));
|
||||
assertArrayEquals(NPN, manager.getDefaultModel(type));
|
||||
assertEquals("datasheet:BJT (NPN)|2N3904", manager.getDefaultVariant(type));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pinningTheDefaultModelAgainClearsIt() {
|
||||
manager.setDefaultModel(type, NPN);
|
||||
manager.setDefaultModel(type, NPN);
|
||||
|
||||
assertFalse(manager.isDefaultModel(type, NPN));
|
||||
assertNull(manager.getDefaultModel(type));
|
||||
assertNull(manager.getDefaultVariant(type));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void pinningAnotherModelReplacesTheDefault() {
|
||||
manager.setDefaultModel(type, NPN);
|
||||
manager.setDefaultModel(type, PNP);
|
||||
|
||||
assertFalse(manager.isDefaultModel(type, NPN));
|
||||
assertArrayEquals(PNP, manager.getDefaultModel(type));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modelAndVariantReplaceEachOther() {
|
||||
manager.setDefaultVariant(type, "My variant");
|
||||
manager.setDefaultModel(type, NPN);
|
||||
|
||||
assertArrayEquals(NPN, manager.getDefaultModel(type));
|
||||
|
||||
manager.setDefaultVariant(type, "My variant");
|
||||
|
||||
assertEquals("My variant", manager.getDefaultVariant(type));
|
||||
assertNull(manager.getDefaultModel(type));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void modelMissingFromTheDatasheetIsNoDefault() {
|
||||
manager.setDefaultModel(type, NPN);
|
||||
ComponentType reduced = createType(new ArrayList<String[]>(Arrays.<String[]>asList(PNP)));
|
||||
|
||||
assertNull(manager.getDefaultModel(reduced));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void legacyKeyIsReadAndReplacedOnWrite() {
|
||||
String legacyKey = type.getCategory() + "." + type.getName();
|
||||
Map<String, String> defaults = new HashMap<String, String>();
|
||||
defaults.put(legacyKey, "Old variant");
|
||||
configManager.writeValue(IPlugInPort.DEFAULT_TEMPLATES_KEY, defaults);
|
||||
|
||||
assertEquals("Old variant", manager.getDefaultVariant(type));
|
||||
|
||||
manager.setDefaultModel(type, PNP);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> written = (Map<String, String>) configManager
|
||||
.readObject(IPlugInPort.DEFAULT_TEMPLATES_KEY, null);
|
||||
assertFalse(written.containsKey(legacyKey));
|
||||
assertArrayEquals(PNP, manager.getDefaultModel(type));
|
||||
}
|
||||
|
||||
private static ComponentType createType(List<String[]> datasheet) {
|
||||
return new ComponentType("Test Transistor", "", CreationMethod.SINGLE_CLICK, "Test", "Q", "",
|
||||
null, TwoPointTestComponent.class, 0, false, BomPolicy.SHOW_ALL_NAMES, false, null,
|
||||
KeywordPolicy.NEVER_SHOW, null, false, datasheet, 2);
|
||||
}
|
||||
|
||||
private static class MapConfigurationManager implements IConfigurationManager<Object> {
|
||||
|
||||
private final Map<String, Object> values = new HashMap<String, Object>();
|
||||
|
||||
@Override
|
||||
public void addConfigListener(String key, IConfigListener listener) {}
|
||||
|
||||
@Override
|
||||
public boolean readBoolean(String key, boolean defaultValue) {
|
||||
return (Boolean) readObject(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readString(String key, String defaultValue) {
|
||||
return (String) readObject(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int readInt(String key, int defaultValue) {
|
||||
return (Integer) readObject(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float readFloat(String key, float defaultValue) {
|
||||
return (Float) readObject(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double readDouble(String key, double defaultValue) {
|
||||
return (Double) readObject(key, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readObject(String key, Object defaultValue) {
|
||||
return values.containsKey(key) ? values.get(key) : defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeValue(String key, Object value) {
|
||||
values.put(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getSerializer() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(String appName) {}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user