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 23e72ed19cbd8e026386878bcf08d070d15a373d Author: Andrus Adamchik <[email protected]> AuthorDate: Sat May 23 10:11:14 2026 -0400 CMComboBoxCellEditor refactoring --- .../toolkit/combobox/CMComboBoxCellEditor.java | 100 +++++++++++++++++++++ .../CMComboBoxPopupResizer.java} | 90 +++---------------- .../ui/dbrelationship/DbRelationshipDialog.java | 2 +- .../dbentity/properties/DbAttributePanel.java | 2 +- .../dbentity/properties/DbRelationshipPanel.java | 2 +- .../attributes/EmbeddableAttributesView.java | 2 +- .../duplicates/DuplicatedAttributesDialog.java | 2 +- .../objentity/properties/ObjAttributePanel.java | 2 +- .../objentity/properties/ObjRelationshipPanel.java | 2 +- .../editor/procedure/ProcedureParameterTab.java | 2 +- 10 files changed, 122 insertions(+), 84 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 new file mode 100644 index 000000000..ecc06b238 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/CMComboBoxCellEditor.java @@ -0,0 +1,100 @@ +/***************************************************************** + * 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.toolkit.combobox; + +import javax.swing.*; +import javax.swing.table.TableCellEditor; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.io.Serializable; +import java.util.EventObject; + +/** + * Combo box cell editor for the modeler. Handles both auto-completion-aware + * and plain combos uniformly. Editing is suppressed for ctrl/shift-clicks so + * the user can extend a multi-row selection without opening the editor. + */ +public class CMComboBoxCellEditor extends AbstractCellEditor implements TableCellEditor, ActionListener, Serializable { + + // 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 final JComboBox<?> comboBox; + private final boolean autocomplete; + + public CMComboBoxCellEditor(JComboBox<?> comboBox) { + this.comboBox = comboBox; + this.autocomplete = Boolean.TRUE.equals( + comboBox.getClientProperty(AutoCompletion.AUTOCOMPLETION_PROPERTY)); + + if (autocomplete) { + comboBox.putClientProperty(IS_TABLE_CELL_EDITOR_PROPERTY, Boolean.TRUE); + comboBox.addActionListener(this); + } + + comboBox.addPopupMenuListener(new CMComboBoxPopupResizer(comboBox)); + } + + @Override + public Object getCellEditorValue() { + return comboBox.getSelectedItem(); + } + + @Override + public Component getTableCellEditorComponent( + JTable table, Object value, boolean isSelected, int row, int column) { + comboBox.setSelectedItem(value); + return comboBox; + } + + @Override + public boolean stopCellEditing() { + if (autocomplete && comboBox.isEditable()) { + // Notify the combo box that editing has stopped (e.g. user pressed F2). + comboBox.actionPerformed(new ActionEvent(this, 0, "")); + } + fireEditingStopped(); + return true; + } + + @Override + public boolean isCellEditable(EventObject e) { + if (e instanceof MouseEvent) { + MouseEvent me = (MouseEvent) e; + if (me.isControlDown() || me.isShiftDown()) { + return false; + } + } + return true; + } + + @Override + public void actionPerformed(ActionEvent e) { + // Selecting an item produces "comboBoxChanged" — ignore. + // Hitting enter produces "comboBoxEdited" — stop editing. + if (autocomplete && "comboBoxEdited".equals(e.getActionCommand())) { + stopCellEditing(); + } + } +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/CMComboBoxCellEditor.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/CMComboBoxPopupResizer.java similarity index 54% rename from modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/CMComboBoxCellEditor.java rename to modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/CMComboBoxPopupResizer.java index e7961afd4..6a8dce424 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/table/CMComboBoxCellEditor.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/CMComboBoxPopupResizer.java @@ -17,71 +17,39 @@ * under the License. ****************************************************************/ -package org.apache.cayenne.modeler.toolkit.table; - -import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion; -import org.apache.cayenne.modeler.toolkit.combobox.ComboBoxPopup; +package org.apache.cayenne.modeler.toolkit.combobox; import javax.swing.*; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; -import javax.swing.table.TableCellEditor; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseEvent; -import java.io.Serializable; -import java.util.EventObject; /** - * Combo box cell editor for the modeler. Handles both auto-completion-aware - * and plain combos uniformly. Editing is suppressed for ctrl/shift-clicks so - * the user can extend a multi-row selection without opening the editor. + * Widens a combo box drop-down to fit its content, up to {@link ComboBoxPopup#MAX_WIDTH}. + * Handles both heavyweight (own Window) and lightweight (embedded) popups correctly. */ -public class CMComboBoxCellEditor extends AbstractCellEditor - implements TableCellEditor, ActionListener, Serializable { - - // 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"; +public class CMComboBoxPopupResizer implements PopupMenuListener { private final JComboBox<?> comboBox; - private final boolean autocomplete; - public CMComboBoxCellEditor(JComboBox<?> comboBox) { + public CMComboBoxPopupResizer(JComboBox<?> comboBox) { this.comboBox = comboBox; - this.autocomplete = Boolean.TRUE.equals( - comboBox.getClientProperty(AutoCompletion.AUTOCOMPLETION_PROPERTY)); - - if (autocomplete) { - comboBox.putClientProperty(IS_TABLE_CELL_EDITOR_PROPERTY, Boolean.TRUE); - comboBox.addActionListener(this); - } + } - comboBox.addPopupMenuListener(new PopupMenuListener() { - @Override - public void popupMenuWillBecomeVisible(PopupMenuEvent e) { - // BasicComboPopup.show() calls getPopupLocation() after this listener fires, - // constraining the popup to the column width. Adjust on the next EDT cycle — - // invokeLater lands ahead of the first WM_PAINT, so no flash occurs. - SwingUtilities.invokeLater(() -> adjustPopupWidth()); - } - @Override public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} - @Override public void popupMenuCanceled(PopupMenuEvent e) {} - }); + @Override + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + // BasicComboPopup.show() calls getPopupLocation() after this listener fires, + // constraining the popup to the column width. Adjust on the next EDT cycle — + // invokeLater lands ahead of the first WM_PAINT, so no flash occurs. + SwingUtilities.invokeLater(this::adjustPopupWidth); } @Override - public Object getCellEditorValue() { - return comboBox.getSelectedItem(); + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { } @Override - public Component getTableCellEditorComponent(JTable table, Object value, - boolean isSelected, int row, int column) { - comboBox.setSelectedItem(value); - return comboBox; + public void popupMenuCanceled(PopupMenuEvent e) { } private void adjustPopupWidth() { @@ -145,34 +113,4 @@ public class CMComboBoxCellEditor extends AbstractCellEditor } return null; } - - @Override - public boolean stopCellEditing() { - if (autocomplete && comboBox.isEditable()) { - // Notify the combo box that editing has stopped (e.g. user pressed F2). - comboBox.actionPerformed(new ActionEvent(this, 0, "")); - } - fireEditingStopped(); - return true; - } - - @Override - public boolean isCellEditable(EventObject e) { - if (e instanceof MouseEvent) { - MouseEvent me = (MouseEvent) e; - if (me.isControlDown() || me.isShiftDown()) { - return false; - } - } - return true; - } - - @Override - public void actionPerformed(ActionEvent e) { - // Selecting an item produces "comboBoxChanged" — ignore. - // Hitting enter produces "comboBoxEdited" — stop editing. - if (autocomplete && "comboBoxEdited".equals(e.getActionCommand())) { - stopCellEditing(); - } - } } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialog.java index ddb77346d..3fb61a545 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialog.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/dbrelationship/DbRelationshipDialog.java @@ -36,7 +36,7 @@ import org.apache.cayenne.modeler.project.DbRelationshipOps; import org.apache.cayenne.modeler.toolkit.buttons.CMButtonPanel; import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion; import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox; -import org.apache.cayenne.modeler.toolkit.table.CMComboBoxCellEditor; +import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor; import org.apache.cayenne.modeler.toolkit.table.CMTable; import org.apache.cayenne.modeler.pref.adapters.CMTablePrefs; import org.apache.cayenne.modeler.toolkit.ProjectDialog; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java index 0e6d80dd5..35b9459c1 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbAttributePanel.java @@ -33,7 +33,7 @@ import org.apache.cayenne.modeler.toolkit.ProjectPanel; import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion; import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox; import org.apache.cayenne.modeler.toolkit.table.BoardTableCellRenderer; -import org.apache.cayenne.modeler.toolkit.table.CMComboBoxCellEditor; +import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor; import org.apache.cayenne.modeler.toolkit.table.CMTable; import org.apache.cayenne.modeler.toolkit.table.CMTablePanel; import org.apache.cayenne.modeler.pref.adapters.CMTablePrefs; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java index c28b7e093..42b6136ba 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/dbentity/properties/DbRelationshipPanel.java @@ -45,7 +45,7 @@ import org.apache.cayenne.modeler.toolkit.table.CMTablePanel; 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.table.CMComboBoxCellEditor; +import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor; import javax.swing.*; import javax.swing.event.ListSelectionEvent; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java index e3ca0b3e3..a122547a0 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/embeddable/attributes/EmbeddableAttributesView.java @@ -34,7 +34,7 @@ import org.apache.cayenne.modeler.service.action.GlobalActions; import org.apache.cayenne.modeler.toolkit.valuetype.ValueTypes; import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion; import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox; -import org.apache.cayenne.modeler.toolkit.table.CMComboBoxCellEditor; +import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor; import org.apache.cayenne.modeler.toolkit.table.CMTable; import org.apache.cayenne.modeler.toolkit.table.CMTablePanel; import org.apache.cayenne.modeler.pref.adapters.CMTablePrefs; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/duplicates/DuplicatedAttributesDialog.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/duplicates/DuplicatedAttributesDialog.java index b4375d8bc..4287871e5 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/duplicates/DuplicatedAttributesDialog.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/duplicates/DuplicatedAttributesDialog.java @@ -25,7 +25,7 @@ import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.modeler.Application; import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox; -import org.apache.cayenne.modeler.toolkit.table.CMComboBoxCellEditor; +import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor; import org.apache.cayenne.modeler.toolkit.AppDialog; import org.apache.cayenne.modeler.project.ProjectSession; import org.apache.cayenne.modeler.toolkit.table.CMTableModel; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java index da3b6fca6..0dcfce0cb 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjAttributePanel.java @@ -39,7 +39,7 @@ import org.apache.cayenne.modeler.project.ObjEntityOps; import org.apache.cayenne.modeler.service.action.GlobalActions; import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion; import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox; -import org.apache.cayenne.modeler.toolkit.table.CMComboBoxCellEditor; +import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor; import org.apache.cayenne.modeler.toolkit.icon.IconFactory; import org.apache.cayenne.modeler.toolkit.table.CMTable; import org.apache.cayenne.modeler.toolkit.table.CMTableModel; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java index bc62df29f..368379df2 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/objentity/properties/ObjRelationshipPanel.java @@ -27,7 +27,7 @@ import org.apache.cayenne.modeler.event.model.ObjEntityListener; import org.apache.cayenne.modeler.event.model.ObjRelationshipListener; import org.apache.cayenne.modeler.toolkit.ProjectPanel; import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox; -import org.apache.cayenne.modeler.toolkit.table.CMComboBoxCellEditor; +import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor; import org.apache.cayenne.modeler.toolkit.icon.IconFactory; import org.apache.cayenne.modeler.project.ProjectSession; import org.apache.cayenne.modeler.service.action.GlobalActions; diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java index f071f1f44..1ecbd0c31 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/ui/project/editor/procedure/ProcedureParameterTab.java @@ -37,7 +37,7 @@ import org.apache.cayenne.modeler.toolkit.ProjectPanel; import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion; import org.apache.cayenne.modeler.toolkit.combobox.CMComboBox; import org.apache.cayenne.modeler.toolkit.icon.IconFactory; -import org.apache.cayenne.modeler.toolkit.table.CMComboBoxCellEditor; +import org.apache.cayenne.modeler.toolkit.combobox.CMComboBoxCellEditor; import org.apache.cayenne.modeler.toolkit.table.CMTable; import org.apache.cayenne.modeler.toolkit.table.CMTablePanel; import org.apache.cayenne.modeler.pref.adapters.CMTablePrefs;
