Prompt to confirm the overwrite when saving over the existing building blocks; When saving building blocks, present a drop down list with most recently used building blocks

This commit is contained in:
Bane Stojkovic
2026-09-03 16:33:15 +02:00
parent a2bd8524ae
commit a44b349705
2 changed files with 86 additions and 6 deletions
@@ -378,9 +378,17 @@
<description>Added ability to set node name (or names) for some connectivity components (e.g. Solder Pad, Eyelet, PCB Terminal Block, etc); when combined into building blocks, these names will become node names of the composite component stamped from the building block</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<changeType>IMPROVEMENT</changeType>
<description>Include building blocks in the Recently Used category</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>When saving building blocks, present a drop down list with most recently used building blocks for quick selection</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Prompt to confirm the overwrite when saving over the existing building blocks</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType>
<description>Percentage values such as transparency Alpha, image Scale, etc, can have decimal values and not just integers</description>
@@ -1,9 +1,18 @@
package org.diylc.swing.actions.edit;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.swing.AbstractAction;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.common.IBlockProcessor;
import org.diylc.common.IPlugInPort;
import org.diylc.swing.ActionFactory;
import org.diylc.utils.IconLoader;
@@ -12,6 +21,9 @@ public class SaveAsBlockAction extends AbstractAction {
private static final long serialVersionUID = 1L;
/** How many recently used building blocks to offer in the name drop-down. */
private static final int MAX_RECENT_BLOCKS = 10;
private IPlugInPort plugInPort;
public SaveAsBlockAction(IPlugInPort plugInPort) {
@@ -24,10 +36,70 @@ public class SaveAsBlockAction extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
ActionFactory.LOG.info("Save as building block triggered");
String templateName = JOptionPane.showInputDialog(null, "Block name:",
"Save as Building Block", JOptionPane.PLAIN_MESSAGE);
if (templateName != null && !templateName.trim().isEmpty()) {
plugInPort.saveSelectionAsBlock(templateName);
JComboBox<String> nameBox =
new JComboBox<String>(getRecentBlockNames().toArray(new String[0]));
nameBox.setEditable(true);
// Start empty so an existing block is never overwritten by accident. The drop-down still
// offers the most recently used blocks (most recent first), so a user editing a block can
// pick its name back with a single click instead of retyping it.
nameBox.setSelectedItem("");
JPanel panel = new JPanel(new BorderLayout(5, 5));
panel.add(new JLabel("Block name:"), BorderLayout.NORTH);
panel.add(nameBox, BorderLayout.CENTER);
// Loop so that declining the overwrite prompt returns to the name dialog (with whatever was
// typed still in it) rather than cancelling the whole action.
while (true) {
int result = JOptionPane.showConfirmDialog(null, panel, "Save as Building Block",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result != JOptionPane.OK_OPTION)
return;
// getEditor().getItem() captures in-progress typing as well as a picked item
Object selected = nameBox.getEditor().getItem();
String blockName = selected == null ? null : selected.toString().trim();
if (blockName == null || blockName.isEmpty())
return;
if (blockExists(blockName)) {
int overwrite = JOptionPane.showConfirmDialog(null,
"A building block named \"" + blockName + "\" already exists. Overwrite it?",
"Save as Building Block", JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.WARNING_MESSAGE);
if (overwrite == JOptionPane.NO_OPTION)
continue; // back to the name dialog
if (overwrite != JOptionPane.YES_OPTION)
return; // Cancel or dialog closed
}
plugInPort.saveSelectionAsBlock(blockName);
return;
}
}
}
@SuppressWarnings("unchecked")
private boolean blockExists(String blockName) {
Map<String, ?> blocks = (Map<String, ?>) ConfigurationManager.getInstance()
.readObject(IBlockProcessor.BLOCKS_KEY, null);
return blocks != null && blocks.containsKey(blockName);
}
@SuppressWarnings("unchecked")
private List<String> getRecentBlockNames() {
List<String> recent = (List<String>) ConfigurationManager.getInstance()
.readObject(IPlugInPort.RECENT_COMPONENTS_KEY, null);
List<String> blockNames = new ArrayList<String>();
if (recent != null) {
for (String identifier : recent) {
if (identifier.startsWith(IBlockProcessor.BLOCK_PREFIX)) {
blockNames.add(identifier.substring(IBlockProcessor.BLOCK_PREFIX.length()));
if (blockNames.size() >= MAX_RECENT_BLOCKS)
break;
}
}
}
return blockNames;
}
}