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;
+    }
+}

Reply via email to