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());
