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 b72e1ef4e6452dffe276efd2004d56850fcf61fa
Author: Andrus Adamchik <[email protected]>
AuthorDate: Sat May 23 10:32:00 2026 -0400

    Unifying combobix editors
---
 .../toolkit/combobox/CMComboBoxCellEditor.java     | 17 ++---
 .../properties/DbAttributePathComboBoxEditor.java  | 18 ++---
 .../DbRelationshipPathComboBoxEditor.java          | 14 ++--
 .../properties/PathChooserComboBoxCellEditor.java  | 82 +++++++++++-----------
 4 files changed, 65 insertions(+), 66 deletions(-)

diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/CMComboBoxCellEditor.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/CMComboBoxCellEditor.java
index ecc06b238..d1d858278 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/CMComboBoxCellEditor.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/CMComboBoxCellEditor.java
@@ -38,7 +38,7 @@ public class CMComboBoxCellEditor extends AbstractCellEditor 
implements TableCel
     // Auto-complete combos collide with DefaultCellEditor's stop-editing flow,
     // so they need a custom action-listener-based path. This client property
     // is read by Swing's combo UI to keep the popup behavior table-friendly.
-    static final String IS_TABLE_CELL_EDITOR_PROPERTY = 
"JComboBox.isTableCellEditor";
+    private static final String IS_TABLE_CELL_EDITOR_PROPERTY = 
"JComboBox.isTableCellEditor";
 
     private final JComboBox<?> comboBox;
     private final boolean autocomplete;
@@ -78,17 +78,18 @@ public class CMComboBoxCellEditor extends 
AbstractCellEditor implements TableCel
         return true;
     }
 
-    @Override
-    public boolean isCellEditable(EventObject e) {
-        if (e instanceof MouseEvent) {
-            MouseEvent me = (MouseEvent) e;
-            if (me.isControlDown() || me.isShiftDown()) {
-                return false;
-            }
+    public static boolean isTableCellEditable(EventObject e) {
+        if (e instanceof MouseEvent me) {
+            return !me.isControlDown() && !me.isShiftDown();
         }
         return true;
     }
 
+    @Override
+    public boolean isCellEditable(EventObject e) {
+        return isTableCellEditable(e);
+    }
+
     @Override
     public void actionPerformed(ActionEvent e) {
         // Selecting an item produces "comboBoxChanged" — ignore.
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxEditor.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxEditor.java
index 4f6e817df..bcf08e06b 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxEditor.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbAttributePathComboBoxEditor.java
@@ -64,9 +64,9 @@ class DbAttributePathComboBoxEditor extends 
PathChooserComboBoxCellEditor<ObjAtt
         }
         initializeCombo(model, row, table);
 
-        String dbAttributePath = ((JTextComponent) 
(comboBoxPathChooser).getEditor().getEditorComponent()).getText();
+        String dbAttributePath = ((JTextComponent) 
(pathChooser).getEditor().getEditorComponent()).getText();
         previousEmbeddedLevel = Util.countMatches(dbAttributePath, ".");
-        return comboBoxPathChooser;
+        return pathChooser;
     }
 
     @Override
@@ -77,7 +77,7 @@ class DbAttributePathComboBoxEditor extends 
PathChooserComboBoxCellEditor<ObjAtt
     @Override
     protected void initializeCombo(ObjAttributeTableModel model, int row, 
final JTable table) {
         super.initializeCombo(model, row, table);
-        
comboBoxPathChooser.setSelectedItem(model.getAttribute(row).getDbAttributePath());
+        
pathChooser.setSelectedItem(model.getAttribute(row).getDbAttributePath());
         savePath = this.model.getAttribute(row).getDbAttributePath().value();
     }
 
@@ -99,7 +99,7 @@ class DbAttributePathComboBoxEditor extends 
PathChooserComboBoxCellEditor<ObjAtt
 
     @Override
     protected void enterPressed(JTable table) {
-        String dbAttributePath = ((JTextComponent) comboBoxPathChooser.
+        String dbAttributePath = ((JTextComponent) pathChooser.
                 getEditor().getEditorComponent()).getText();
         Object currentNode = getCurrentNode(dbAttributePath);
         String[] pathStrings = dbAttributePath.split(Pattern.quote("."));
@@ -123,14 +123,14 @@ class DbAttributePathComboBoxEditor extends 
PathChooserComboBoxCellEditor<ObjAtt
             if (dbAttributePath.charAt(dbAttributePath.length() - 1) != '.') {
                 dbAttributePath = dbAttributePath + '.';
                 previousEmbeddedLevel = Util.countMatches(dbAttributePath, 
".");
-                ((JTextComponent) (comboBoxPathChooser).
+                ((JTextComponent) (pathChooser).
                         
getEditor().getEditorComponent()).setText(dbAttributePath);
             }
             List<String> currentNodeChildren = new 
ArrayList<>(getChildren(getCurrentNode(dbAttributePath), dbAttributePath));
-            comboBoxPathChooser.setModel(new 
DefaultComboBoxModel<>(currentNodeChildren.toArray(new String[0])));
-            comboBoxPathChooser.setSelectedItem(dbAttributePath);
-            comboBoxPathChooser.showPopup();
-            comboBoxPathChooser.setPopupVisible(true);
+            pathChooser.setModel(new 
DefaultComboBoxModel<>(currentNodeChildren.toArray(new String[0])));
+            pathChooser.setSelectedItem(dbAttributePath);
+            pathChooser.showPopup();
+            pathChooser.setPopupVisible(true);
         }
     }
 
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbRelationshipPathComboBoxEditor.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbRelationshipPathComboBoxEditor.java
index 9969f61bc..525a0bf51 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbRelationshipPathComboBoxEditor.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/DbRelationshipPathComboBoxEditor.java
@@ -60,10 +60,10 @@ class DbRelationshipPathComboBoxEditor extends 
PathChooserComboBoxCellEditor<Obj
         }
         initializeCombo(model, row, table);
 
-        String dbRelationshipPath = ((JTextComponent) (comboBoxPathChooser).
+        String dbRelationshipPath = ((JTextComponent) (pathChooser).
                 getEditor().getEditorComponent()).getText();
         previousEmbeddedLevel = 
dbRelationshipPath.split(Pattern.quote(".")).length;
-        return comboBoxPathChooser;
+        return pathChooser;
     }
 
     @Override
@@ -74,11 +74,11 @@ class DbRelationshipPathComboBoxEditor extends 
PathChooserComboBoxCellEditor<Obj
     @Override
     protected void initializeCombo(ObjRelationshipTableModel model, int row, 
final JTable table) {
         super.initializeCombo(model, row, table);
-        
comboBoxPathChooser.setSelectedItem(model.getRelationship(row).getDbRelationshipPath());
+        
pathChooser.setSelectedItem(model.getRelationship(row).getDbRelationshipPath());
 
         enterPressedCount = 0;
-        comboBoxPathChooser.setToolTipText("To choose relationship press enter 
two times.To choose next relationship press dot.");
-        JTextComponent textEditor = (JTextComponent) (comboBoxPathChooser).
+        pathChooser.setToolTipText("To choose relationship press enter two 
times.To choose next relationship press dot.");
+        JTextComponent textEditor = (JTextComponent) (pathChooser).
                 getEditor().getEditorComponent();
         textEditor.addFocusListener(this);
         savePath = 
this.model.getRelationship(row).getDbRelationshipPath().value();
@@ -86,7 +86,7 @@ class DbRelationshipPathComboBoxEditor extends 
PathChooserComboBoxCellEditor<Obj
 
     @Override
     protected void enterPressed(JTable table) {
-        String dbRelationshipPath = ((JTextComponent) (comboBoxPathChooser).
+        String dbRelationshipPath = ((JTextComponent) (pathChooser).
                 getEditor().getEditorComponent()).getText();
         changeObjEntity(dbRelationshipPath);
         Object currentNode = getCurrentNode(dbRelationshipPath);
@@ -130,7 +130,7 @@ class DbRelationshipPathComboBoxEditor extends 
PathChooserComboBoxCellEditor<Obj
     @Override
     protected void parsePathString(char lastEnteredCharacter) {
         super.parsePathString(lastEnteredCharacter);
-        String dbRelationshipPath = ((JTextComponent) (comboBoxPathChooser).
+        String dbRelationshipPath = ((JTextComponent) (pathChooser).
                 getEditor().getEditorComponent()).getText();
         changeObjEntity(dbRelationshipPath);
         enterPressedCount = 0;
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/PathChooserComboBoxCellEditor.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/PathChooserComboBoxCellEditor.java
index 7c78caabf..1dee114bf 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/PathChooserComboBoxCellEditor.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/PathChooserComboBoxCellEditor.java
@@ -19,14 +19,12 @@
 
 package org.apache.cayenne.modeler.ui.project.editor.objentity.properties;
 
-import org.apache.cayenne.map.MappingNamespace;
-
-import java.util.function.Supplier;
-
 import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.MappingNamespace;
 import org.apache.cayenne.modeler.toolkit.Renderers;
 import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion;
 import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox;
+import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor;
 import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxPopupResizer;
 import org.apache.cayenne.modeler.toolkit.icon.IconFactory;
 import org.apache.cayenne.modeler.toolkit.table.CMTableModel;
@@ -44,7 +42,9 @@ import java.awt.event.ActionListener;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 import java.util.ArrayList;
+import java.util.EventObject;
 import java.util.List;
+import java.util.function.Supplier;
 import java.util.regex.Pattern;
 
 /**
@@ -52,12 +52,12 @@ import java.util.regex.Pattern;
  */
 abstract class PathChooserComboBoxCellEditor<T extends CMTableModel<?>> 
extends AbstractCellEditor implements TableCellEditor, ActionListener, 
PopupMenuListener {
 
-    protected JComboBox<String> comboBoxPathChooser;
-    protected int previousEmbeddedLevel = 0;
+    private final Supplier<MappingNamespace> namespaceSupplier;
+    protected JComboBox<String> pathChooser;
+    protected int previousEmbeddedLevel;
     protected EntityTreeModel treeModel;
     protected int row;
     private JTable table;
-    private final Supplier<MappingNamespace> namespaceSupplier;
 
     protected PathChooserComboBoxCellEditor(Supplier<MappingNamespace> 
namespaceSupplier) {
         this.namespaceSupplier = namespaceSupplier;
@@ -76,9 +76,9 @@ abstract class PathChooserComboBoxCellEditor<T extends 
CMTableModel<?>> extends
         String dbAttributePath = getPathToInitializeCombo(model, row);
         List<String> nodeChildren = getChildren(currentNode, dbAttributePath);
         this.table = table;
-        comboBoxPathChooser = new CMComboBox<>(nodeChildren);
-        comboBoxPathChooser.addPopupMenuListener(new 
CMComboBoxPopupResizer(comboBoxPathChooser));
-        
comboBoxPathChooser.getEditor().getEditorComponent().addKeyListener(new 
KeyAdapter() {
+        pathChooser = new CMComboBox<>(nodeChildren);
+        pathChooser.addPopupMenuListener(new 
CMComboBoxPopupResizer(pathChooser));
+        pathChooser.getEditor().getEditorComponent().addKeyListener(new 
KeyAdapter() {
             @Override
             public void keyReleased(KeyEvent event) {
                 if (event.getKeyCode() == KeyEvent.VK_ENTER) {
@@ -88,25 +88,23 @@ abstract class PathChooserComboBoxCellEditor<T extends 
CMTableModel<?>> extends
                 parsePathString(event.getKeyChar());
             }
         });
-        AutoCompletion.enable(comboBoxPathChooser, true, true, 
namespaceSupplier);
-        ((JComponent) 
comboBoxPathChooser.getEditor().getEditorComponent()).setBorder(null);
-        comboBoxPathChooser.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 
0));
-        comboBoxPathChooser.setRenderer(new PathChooserComboBoxCellRenderer());
-        comboBoxPathChooser.addActionListener(this);
-        comboBoxPathChooser.addPopupMenuListener(this);
+        AutoCompletion.enable(pathChooser, true, true, namespaceSupplier);
+        pathChooser.setRenderer(new PathChooserComboBoxCellRenderer());
+        pathChooser.addActionListener(this);
+        pathChooser.addPopupMenuListener(this);
     }
 
     private void setComboModelAccordingToPath(String pathString) {
         List<String> currentNodeChildren = new 
ArrayList<>(getChildren(getCurrentNode(pathString), pathString));
-        comboBoxPathChooser.setModel(new 
DefaultComboBoxModel<>(currentNodeChildren.toArray(new String[0])));
-        comboBoxPathChooser.setSelectedItem(pathString);
+        pathChooser.setModel(new 
DefaultComboBoxModel<>(currentNodeChildren.toArray(new String[0])));
+        pathChooser.setSelectedItem(pathString);
         if (!pathString.isEmpty()) {
-            comboBoxPathChooser.showPopup();
+            pathChooser.showPopup();
         }
     }
 
     protected void parsePathString(char lastEnteredCharacter) {
-        JTextComponent editorComponent = (JTextComponent) 
(comboBoxPathChooser).getEditor().getEditorComponent();
+        JTextComponent editorComponent = (JTextComponent) 
(pathChooser).getEditor().getEditorComponent();
         String pathString = editorComponent.getText();
         if (pathString != null && pathString.isEmpty()) {
             setComboModelAccordingToPath("");
@@ -128,13 +126,13 @@ abstract class PathChooserComboBoxCellEditor<T extends 
CMTableModel<?>> extends
             String saveDbAttributePath = pathString;
             pathString = pathString.replaceAll(lastStringInPath + "$", "");
             List<String> currentNodeChildren = new 
ArrayList<>(getChildren(getCurrentNode(pathString), pathString));
-            comboBoxPathChooser.setModel(new 
DefaultComboBoxModel<>(currentNodeChildren.toArray(new String[0])));
-            comboBoxPathChooser.setSelectedItem(saveDbAttributePath);
+            pathChooser.setModel(new 
DefaultComboBoxModel<>(currentNodeChildren.toArray(new String[0])));
+            pathChooser.setSelectedItem(saveDbAttributePath);
         }
     }
 
     protected void processDotEntered() {
-        JTextComponent editorComponent = (JTextComponent) 
(comboBoxPathChooser).getEditor().getEditorComponent();
+        JTextComponent editorComponent = (JTextComponent) 
(pathChooser).getEditor().getEditorComponent();
 
         String dbAttributePath = editorComponent.getText();
         if (".".equals(dbAttributePath)) {
@@ -168,12 +166,6 @@ abstract class PathChooserComboBoxCellEditor<T extends 
CMTableModel<?>> extends
         }
     }
 
-    /**
-     * find current node by path
-     *
-     * @param pathString db path
-     * @return last node in path which matches DbRelationship or DbAttribute
-     */
     protected Object getCurrentNode(String pathString) {
         //case for new attribute
         if (pathString == null || pathString.isEmpty()) {
@@ -194,11 +186,6 @@ abstract class PathChooserComboBoxCellEditor<T extends 
CMTableModel<?>> extends
         return root;
     }
 
-    /**
-     * @param node       for which we will find children
-     * @param pathString string which will be added to each child to make 
right autocomplete
-     * @return list with children , which will be used to autocomplete
-     */
     protected List<String> getChildren(Object node, String pathString) {
         List<String> currentNodeChildren = new ArrayList<>();
         for (int j = 0; j < treeModel.getChildCount(node); j++) {
@@ -209,20 +196,31 @@ abstract class PathChooserComboBoxCellEditor<T extends 
CMTableModel<?>> extends
         return currentNodeChildren;
     }
 
+    @Override
+    public boolean isCellEditable(EventObject e) {
+        return CMComboBoxCellEditor.isTableCellEditable(e);
+    }
+
+    @Override
+    public boolean stopCellEditing() {
+        pathChooser.actionPerformed(new ActionEvent(this, 0, ""));
+        fireEditingStopped();
+        return true;
+    }
+
     @Override
     public void actionPerformed(ActionEvent e) {
         //for some reason comboBoxPathChooser don't load selected item text, 
so we made it by hand
-        if (comboBoxPathChooser.getSelectedIndex() != (-1)) {
-            ((JTextComponent) (comboBoxPathChooser).
-                    
getEditor().getEditorComponent()).setText(comboBoxPathChooser.getSelectedItem().toString());
+        if (pathChooser.getSelectedIndex() != (-1)) {
+            ((JTextComponent) (pathChooser).
+                    
getEditor().getEditorComponent()).setText(pathChooser.getSelectedItem().toString());
         }
     }
 
     @Override
     public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
-        if (comboBoxPathChooser.getSelectedIndex() != -1 &&
-                !((JTextComponent) (comboBoxPathChooser).
-                        getEditor().getEditorComponent()).getText().isEmpty()) 
{
+        if (pathChooser.getSelectedIndex() != -1
+                && !((JTextComponent) 
(pathChooser).getEditor().getEditorComponent()).getText().isEmpty()) {
             enterPressed(table);
         }
     }
@@ -240,8 +238,8 @@ abstract class PathChooserComboBoxCellEditor<T extends 
CMTableModel<?>> extends
         private final ImageIcon rightArrow = 
IconFactory.buildIcon("icon-arrow-closed.png");
 
         @Override
-        public Component getListCellRendererComponent(JList<?> list, Object 
value, int index,
-                                                      boolean isSelected, 
boolean cellHasFocus) {
+        public Component getListCellRendererComponent(
+                JList<?> list, Object value, int index, boolean isSelected, 
boolean cellHasFocus) {
 
             JPanel panel = new JPanel(new BorderLayout());
             JLabel label = new JLabel(value.toString());

Reply via email to