This is an automated email from the ASF dual-hosted git repository. asf-gitbox-commits pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 8ebc2132f341b16d0b014d19f809d26b875c60fa Author: Andrus Adamchik <[email protected]> AuthorDate: Sat Aug 29 18:14:55 2026 -0400 Modeler: cleaning up cgen toolbar --- .../apache/cayenne/modeler/project/CgenOps.java | 21 +++++++ .../ui/confirmremove/ConfirmRemoveDialog.java | 3 +- .../ui/project/editor/datamap/cgen/CgenPanel.java | 47 +++++++++++++-- .../datamap/cgen/action/AddCgenConfigAction.java | 24 +++----- .../cgen/action/RemoveCgenConfigAction.java | 22 +++---- .../cayenne/modeler/project/CgenOpsTest.java | 70 ++++++++++++++++++++++ 6 files changed, 147 insertions(+), 40 deletions(-) diff --git a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/CgenOps.java b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/CgenOps.java index 59546f255..c1063c792 100644 --- a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/CgenOps.java +++ b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/project/CgenOps.java @@ -19,6 +19,8 @@ package org.apache.cayenne.modeler.project; +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.gen.CgenConfigList; import org.apache.cayenne.gen.CgenConfiguration; import org.apache.cayenne.gen.internal.Utils; import org.apache.cayenne.map.DataMap; @@ -35,6 +37,25 @@ import java.util.Optional; public class CgenOps { + static final int MAX_NAME_ATTEMPTS = 1000; + + /** + * Returns a name for a new configuration that doesn't clash with the existing ones, following the + * same "Default", "Default1", "Default2" pattern used for newly created ObjEntities. Gives up with + * an exception after {@link #MAX_NAME_ATTEMPTS} suffixes. + */ + public static String createUniqueConfigName(CgenConfigList configurations) { + String name = CgenConfigList.DEFAULT_CONFIG_NAME; + for (int i = 1; configurations.isExist(name); i++) { + if (i > MAX_NAME_ATTEMPTS) { + throw new CayenneRuntimeException("Can't create a unique cgen configuration name after %d attempts", + MAX_NAME_ATTEMPTS); + } + name = CgenConfigList.DEFAULT_CONFIG_NAME + i; + } + return name; + } + public static CgenConfiguration createDefaultCgenConfiguration(DataMap map, ProjectSession session) { CgenConfiguration configuration = CgenConfiguration.createDefault(map, baseDir(session).orElse(null)); diff --git a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/confirmremove/ConfirmRemoveDialog.java b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/confirmremove/ConfirmRemoveDialog.java index 50fb321ba..71ae3c88f 100644 --- a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/confirmremove/ConfirmRemoveDialog.java +++ b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/confirmremove/ConfirmRemoveDialog.java @@ -60,8 +60,7 @@ public class ConfirmRemoveDialog { shouldDelete = DELETE.equals(pane.getValue()); - // If the user clicks "cancel" or window close button, we'll just ignore whatever's in the checkbox because - // it's non-sensical. + // If the user clicks "cancel" or window close button, we'll just ignore whatever's in the checkbox if (shouldDelete) { new GeneralPrefs(application.getPrefsLocator().appNode(GeneralPrefs.NODE)).setNoDeletePrompt(neverPromptAgainBox.isSelected()); } diff --git a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPanel.java b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPanel.java index a076ab93f..47e33a489 100644 --- a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPanel.java +++ b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/CgenPanel.java @@ -55,6 +55,8 @@ import org.slf4j.LoggerFactory; import org.slf4j.helpers.NOPLogger; import javax.swing.*; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; import java.awt.*; import java.nio.file.Path; import java.util.Collection; @@ -82,6 +84,7 @@ public class CgenPanel extends ProjectPanel implements ObjEntityListener, Embedd private final JComboBox<String> configurationsComboBox; private final JButton addConfigBtn; private final JButton editConfigBtn; + private final RemoveCgenConfigAction removeConfigAction; private final JButton removeConfigBtn; private CgenConfigList cgenConfigList; @@ -105,7 +108,8 @@ public class CgenPanel extends ProjectPanel implements ObjEntityListener, Embedd this.configurationsComboBox = new JComboBox<>(); this.addConfigBtn = new AddCgenConfigAction(app, configurationsComboBox, () -> cgenConfigList).buildButton(); this.editConfigBtn = new EditCgenConfigAction(app, configurationsComboBox, () -> cgenConfigList, () -> configuration).buildButton(); - this.removeConfigBtn = new RemoveCgenConfigAction(app, configurationsComboBox, () -> cgenConfigList, () -> configuration).buildButton(); + this.removeConfigAction = new RemoveCgenConfigAction(app, configurationsComboBox, () -> cgenConfigList, () -> configuration); + this.removeConfigBtn = removeConfigAction.buildButton(); this.cgenConfigPanel = new CgenConfigPanel(session, this); this.classesSelector = new CgenArtifactSelectorPanel(this); @@ -200,6 +204,13 @@ public class CgenPanel extends ProjectPanel implements ObjEntityListener, Embedd return modified; } + /** + * The last configuration can't be removed, so the button is only active when there is a choice. + */ + private void updateRemoveConfigButton() { + removeConfigAction.setEnabled(configurationsComboBox.getItemCount() > 1); + } + public void updateGenerateButton() { boolean isOutputPathValid = cgenConfigPanel.isDataValid(); generateButton.setEnabled(!selectionModel.isModelEmpty() && isOutputPathValid); @@ -288,14 +299,15 @@ public class CgenPanel extends ProjectPanel implements ObjEntityListener, Embedd private JPanel buildConfigurationsPanel() { FormLayout layout = new FormLayout( - "109dlu,$lcgap,pref,$lcgap,pref,$lcgap,pref", + "pref,$lcgap,109dlu,$lcgap,pref,$lcgap,pref,$lcgap,pref", "p"); PanelBuilder builder = new PanelBuilder(layout); CellConstraints cc = new CellConstraints(); - builder.add(configurationsComboBox, cc.xy(1, 1)); - builder.add(addConfigBtn, cc.xy(3, 1)); - builder.add(editConfigBtn, cc.xy(5, 1)); - builder.add(removeConfigBtn, cc.xy(7, 1)); + builder.addLabel("Cgen Configuration:", cc.xy(1, 1)); + builder.add(configurationsComboBox, cc.xy(3, 1)); + builder.add(addConfigBtn, cc.xy(5, 1)); + builder.add(editConfigBtn, cc.xy(7, 1)); + builder.add(removeConfigBtn, cc.xy(9, 1)); return builder.getPanel(); } @@ -330,6 +342,8 @@ public class CgenPanel extends ProjectPanel implements ObjEntityListener, Embedd private void initBindings() { generateButton.addActionListener(e -> generateAction()); + configurationsComboBox.getModel().addListDataListener(new ConfigCountListener()); + updateRemoveConfigButton(); configurationsComboBox.addActionListener(e -> { // ignore events fired while initFromModel() is rebuilding the combo box if (initFromModel) { @@ -540,6 +554,27 @@ public class CgenPanel extends ProjectPanel implements ObjEntityListener, Embedd } } + /** + * Keeps the "remove configuration" button in sync with the number of configurations. + */ + private final class ConfigCountListener implements ListDataListener { + + @Override + public void intervalAdded(ListDataEvent e) { + updateRemoveConfigButton(); + } + + @Override + public void intervalRemoved(ListDataEvent e) { + updateRemoveConfigButton(); + } + + @Override + public void contentsChanged(ListDataEvent e) { + updateRemoveConfigButton(); + } + } + private final Predicate<ConfigurationNode> defaultPredicate = o -> o.acceptVisitor(new BaseConfigurationNodeVisitor<Boolean>() { @Override public Boolean visitDataMap(DataMap dataMap) { diff --git a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/action/AddCgenConfigAction.java b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/action/AddCgenConfigAction.java index a8487f8af..e8d6098f8 100644 --- a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/action/AddCgenConfigAction.java +++ b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/action/AddCgenConfigAction.java @@ -26,7 +26,6 @@ import org.apache.cayenne.modeler.project.ProjectSession; import org.apache.cayenne.modeler.toolkit.AppAction; import javax.swing.JComboBox; -import javax.swing.JOptionPane; import java.awt.event.ActionEvent; import java.util.function.Supplier; @@ -50,23 +49,14 @@ public class AddCgenConfigAction extends AppAction { @Override public void performAction(ActionEvent e) { - String name = JOptionPane.showInputDialog( - app.getFrame(), - "Type the name for new cgenConfiguration", - configurationsComboBox.getSelectedItem()); ProjectSession session = app.getFrame().getProjectSession(); + CgenConfigList cgenConfigList = cgenConfigListProvider.get(); + CgenConfiguration configuration = CgenOps.createDefaultCgenConfiguration(session.getSelectedDataMap(), session); - if (name != null) { - CgenConfigList cgenConfigList = cgenConfigListProvider.get(); - if (!cgenConfigList.isExist(name) && !name.isEmpty()) { - configuration.setName(name); - cgenConfigList.add(configuration); - configurationsComboBox.addItem(name); - configurationsComboBox.setSelectedItem(name); - } else { - JOptionPane.showMessageDialog(app.getFrame(), - "Can't create new configuration, same name is already exist or empty"); - } - } + configuration.setName(CgenOps.createUniqueConfigName(cgenConfigList)); + cgenConfigList.add(configuration); + + configurationsComboBox.addItem(configuration.getName()); + configurationsComboBox.setSelectedItem(configuration.getName()); } } diff --git a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/action/RemoveCgenConfigAction.java b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/action/RemoveCgenConfigAction.java index a2641dacc..8f33cdb55 100644 --- a/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/action/RemoveCgenConfigAction.java +++ b/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/datamap/cgen/action/RemoveCgenConfigAction.java @@ -22,9 +22,9 @@ import org.apache.cayenne.gen.CgenConfigList; import org.apache.cayenne.gen.CgenConfiguration; import org.apache.cayenne.modeler.Application; import org.apache.cayenne.modeler.toolkit.AppAction; +import org.apache.cayenne.modeler.ui.confirmremove.ConfirmRemoveDialog; import javax.swing.JComboBox; -import javax.swing.JOptionPane; import java.awt.event.ActionEvent; import java.util.function.Supplier; @@ -41,7 +41,6 @@ public class RemoveCgenConfigAction extends AppAction { this.configurationsComboBox = configurationsComboBox; this.cgenConfigListProvider = cgenConfigListProvider; this.cgenConfigurationProvider = cgenConfigurationProvider; - setAlwaysOn(true); } @Override @@ -51,19 +50,12 @@ public class RemoveCgenConfigAction extends AppAction { @Override public void performAction(ActionEvent e) { - int result = JOptionPane.showConfirmDialog(app.getFrame(), - "Configuration will be removed\n Are you sure?", - "Delete cgenConfiguration", - JOptionPane.YES_NO_OPTION); - if (result == JOptionPane.OK_OPTION) { - if (configurationsComboBox.getItemCount() > 1) { - CgenConfigList cgenConfigList = cgenConfigListProvider.get(); - cgenConfigList.removeByName(cgenConfigurationProvider.get().getName()); - configurationsComboBox.removeItem(configurationsComboBox.getSelectedItem()); - configurationsComboBox.setSelectedIndex(0); - } else { - JOptionPane.showMessageDialog(app.getFrame(), "At least one configuration must exist"); - } + CgenConfiguration configuration = cgenConfigurationProvider.get(); + if (new ConfirmRemoveDialog(app, true).shouldDelete("Cgen Configuration", configuration.getName())) { + CgenConfigList cgenConfigList = cgenConfigListProvider.get(); + cgenConfigList.removeByName(configuration.getName()); + configurationsComboBox.removeItem(configurationsComboBox.getSelectedItem()); + configurationsComboBox.setSelectedIndex(0); } } } diff --git a/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/project/CgenOpsTest.java b/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/project/CgenOpsTest.java new file mode 100644 index 000000000..324697ce4 --- /dev/null +++ b/cayenne-modeler/src/test/java/org/apache/cayenne/modeler/project/CgenOpsTest.java @@ -0,0 +1,70 @@ +/***************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + ****************************************************************/ + +package org.apache.cayenne.modeler.project; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.gen.CgenConfigList; +import org.apache.cayenne.gen.CgenConfiguration; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class CgenOpsTest { + + @Test + public void uniqueConfigNameForEmptyList() { + assertEquals("Default", CgenOps.createUniqueConfigName(new CgenConfigList())); + } + + @Test + public void uniqueConfigNameSkipsExisting() { + CgenConfigList configurations = new CgenConfigList(); + configurations.add(configuration("Default")); + assertEquals("Default1", CgenOps.createUniqueConfigName(configurations)); + + configurations.add(configuration("Default1")); + assertEquals("Default2", CgenOps.createUniqueConfigName(configurations)); + } + + @Test + public void uniqueConfigNameIgnoresUnrelatedNames() { + CgenConfigList configurations = new CgenConfigList(); + configurations.add(configuration("client")); + assertEquals("Default", CgenOps.createUniqueConfigName(configurations)); + } + + @Test + public void uniqueConfigNameGivesUp() { + CgenConfigList configurations = new CgenConfigList(); + configurations.add(configuration(CgenConfigList.DEFAULT_CONFIG_NAME)); + for (int i = 1; i <= CgenOps.MAX_NAME_ATTEMPTS; i++) { + configurations.add(configuration(CgenConfigList.DEFAULT_CONFIG_NAME + i)); + } + + assertThrows(CayenneRuntimeException.class, () -> CgenOps.createUniqueConfigName(configurations)); + } + + private CgenConfiguration configuration(String name) { + CgenConfiguration configuration = new CgenConfiguration(); + configuration.setName(name); + return configuration; + } +}
