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 438f4e3c67b59df3145f911c1910549bed10c9d9 Author: Andrus Adamchik <[email protected]> AuthorDate: Thu May 7 09:55:17 2026 -0400 CAY-2934 Modeler: dropdown data trunction cleanup --- .../modeler/toolkit/combobox/AutoCompletion.java | 67 +++++++++------------- .../modeler/toolkit/combobox/ComboBoxPopup.java | 25 ++++++++ .../modeler/toolkit/combobox/SuggestionList.java | 13 ++--- .../toolkit/table/CMComboBoxCellEditor.java | 15 ++--- 4 files changed, 62 insertions(+), 58 deletions(-) diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/AutoCompletion.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/AutoCompletion.java index e433b646c..b21669905 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/AutoCompletion.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/AutoCompletion.java @@ -36,43 +36,26 @@ import java.util.function.Supplier; * */ public class AutoCompletion implements FocusListener, KeyListener, Runnable { - /** - * Property to mark combobox as 'auto-completing' - */ + public static final String AUTOCOMPLETION_PROPERTY = "JComboBox.autoCompletion"; - /** - * A list with matching items - */ - private final SuggestionList suggestionList; + private final SuggestionList suggestions; - /** - * Combo with auto-completion - */ private final JComboBox comboBox; - private final JTextComponent textEditor; - private final boolean allowsUserValues; protected AutoCompletion(JComboBox comboBox, boolean strict, boolean allowsUserValues, Supplier<MappingNamespace> namespaceSupplier) { this.comboBox = comboBox; - textEditor = ((JTextComponent) comboBox.getEditor().getEditorComponent()); + this.textEditor = ((JTextComponent) comboBox.getEditor().getEditorComponent()); this.allowsUserValues = allowsUserValues; - suggestionList = new SuggestionList(comboBox, strict, namespaceSupplier); + this.suggestions = new SuggestionList(comboBox, strict, namespaceSupplier); - // Marking combobox as auto-completing comboBox.putClientProperty(AUTOCOMPLETION_PROPERTY, Boolean.TRUE); } /** * Enables auto-completion for specified combobox - * - * @param comboBox Combo to be featured - * @param strict Whether strict matching (check 'startWith' or 'contains') should be used - * @param allowsUserValues Whether non-present items are allowed - * @param namespaceSupplier Supplies the {@link MappingNamespace} (typically the currently selected DataMap) - * used to render entity labels. */ public static void enable(JComboBox comboBox, boolean strict, boolean allowsUserValues, Supplier<MappingNamespace> namespaceSupplier) { comboBox.setEditable(true); @@ -98,24 +81,28 @@ public class AutoCompletion implements FocusListener, KeyListener, Runnable { enable(comboBox, true, false, namespaceSupplier); } + @Override public void focusGained(FocusEvent e) { } + @Override public void focusLost(FocusEvent e) { - suggestionList.hide(); + suggestions.hide(); } + @Override public void keyPressed(KeyEvent e) { handleKeyPressed(e); } + @Override public void keyReleased(KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE || e.getKeyCode() == KeyEvent.VK_ENTER) { String text = textEditor.getText(); if (comboBox.isShowing()) { - suggestionList.hide(); - suggestionList.filter(text); - suggestionList.show(); + suggestions.hide(); + suggestions.filter(text); + suggestions.show(); } } } @@ -128,13 +115,13 @@ public class AutoCompletion implements FocusListener, KeyListener, Runnable { //need to hide first because Swing incorrectly updates popups (getSize() returns //dimension not the same as seen on the screen) - suggestionList.hide(); + suggestions.hide(); if (comboBox.isShowing()) { - suggestionList.filter(text); + suggestions.filter(text); - if (suggestionList.getItemCount() > 0) { - suggestionList.show(); + if (suggestions.getItemCount() > 0) { + suggestions.show(); } } } @@ -144,7 +131,7 @@ public class AutoCompletion implements FocusListener, KeyListener, Runnable { * This might affect either suggestion list or original popup */ private void handleKeyPressed(KeyEvent e) { - boolean suggest = suggestionList.isVisible(); + boolean suggest = suggestions.isVisible(); if (suggest) { processKeyPressedWhenSuggestionListIsVisible(e); @@ -195,8 +182,8 @@ public class AutoCompletion implements FocusListener, KeyListener, Runnable { } private void processKeyPressedWhenSuggestionListIsVisible(KeyEvent e) { - int sel = suggestionList.getSelectedIndex(); - int max = suggestionList.getItemCount() - 1; + int sel = suggestions.getSelectedIndex(); + int max = suggestions.getItemCount() - 1; int next; switch (e.getKeyCode()) { case KeyEvent.VK_UP: @@ -223,7 +210,7 @@ public class AutoCompletion implements FocusListener, KeyListener, Runnable { processEnterPressed(); return; case KeyEvent.VK_ESCAPE: - suggestionList.hide(); + suggestions.hide(); return; default: //invoke in end of AWT thread so that information in textEditor would update @@ -235,15 +222,15 @@ public class AutoCompletion implements FocusListener, KeyListener, Runnable { } private void processEnterPressed() { - Object value = suggestionList.getSelectedValue(); - if (!allowsUserValues && value == null && suggestionList.getItemCount() > 0) { - value = suggestionList.getItemAt(0); + Object value = suggestions.getSelectedValue(); + if (!allowsUserValues && value == null && suggestions.getItemCount() > 0) { + value = suggestions.getItemAt(0); } //reset the item (value == null) only if user values are not supported if (value != null || !allowsUserValues) { comboBox.setSelectedItem(value); } - suggestionList.hide(); + suggestions.hide(); } private void handleNavigationKeys(boolean suggest, int next, int sel, int max) { @@ -263,7 +250,7 @@ public class AutoCompletion implements FocusListener, KeyListener, Runnable { if (next != sel) { if (suggest) { - suggestionList.setSelectedIndex(next); + suggestions.setSelectedIndex(next); } else { comboBox.setPopupVisible(true); comboBox.setSelectedIndex(next); @@ -274,8 +261,8 @@ public class AutoCompletion implements FocusListener, KeyListener, Runnable { } private void suggestionListScrolling() { - JList list = suggestionList.getList(); - int selectedIndex = suggestionList.getSelectedIndex(); + JList list = suggestions.getList(); + int selectedIndex = suggestions.getSelectedIndex(); list.ensureIndexIsVisible(selectedIndex); } } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/ComboBoxPopup.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/ComboBoxPopup.java new file mode 100644 index 000000000..15c6d3650 --- /dev/null +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/ComboBoxPopup.java @@ -0,0 +1,25 @@ +/***************************************************************** + * 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; + +public final class ComboBoxPopup { + + public static final int MAX_WIDTH = 450; +} diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/SuggestionList.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/SuggestionList.java index d78f6c42a..513d16337 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/SuggestionList.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/toolkit/combobox/SuggestionList.java @@ -35,22 +35,21 @@ import java.util.function.Supplier; */ class SuggestionList extends BasicComboPopup { - private static final int MAX_POPUP_WIDTH = 450; + private final Supplier<MappingNamespace> namespaceSupplier; /** - * 'Strict' matching, i.e. whether 'startWith' or 'contains' function - * should be used for checking match + * 'Strict' matching, i.e. whether 'startWith' or 'contains' function should be used for checking match */ protected boolean strict; - private final Supplier<MappingNamespace> namespaceSupplier; public SuggestionList(JComboBox cb, boolean strict, Supplier<MappingNamespace> namespaceSupplier) { super(cb); this.strict = strict; this.namespaceSupplier = namespaceSupplier; - list.addMouseListener(new MouseHandler()); + this.list.addMouseListener(new MouseHandler()); + setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY)); } @@ -60,7 +59,7 @@ class SuggestionList extends BasicComboPopup { * @param prefix user-typed string, used to filter */ public void filter(String prefix) { - ComboBoxModel model = comboBox.getModel(); + ComboBoxModel<?> model = comboBox.getModel(); DefaultListModel lm = new DefaultListModel(); for (int i = 0; i < model.getSize(); i++) { @@ -105,7 +104,7 @@ class SuggestionList extends BasicComboPopup { protected Rectangle computePopupBounds(int px, int py, int pw, int ph) { Rectangle bounds = super.computePopupBounds(px, py, pw, ph); int naturalWidth = scroller.getPreferredSize().width; - int targetWidth = Math.min(Math.max(naturalWidth, pw), MAX_POPUP_WIDTH); + int targetWidth = Math.min(Math.max(naturalWidth, pw), ComboBoxPopup.MAX_WIDTH); return new Rectangle(bounds.x, bounds.y, targetWidth, bounds.height); } 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/table/CMComboBoxCellEditor.java index 219bc47d3..1cc28d3b9 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/table/CMComboBoxCellEditor.java @@ -20,18 +20,13 @@ package org.apache.cayenne.modeler.toolkit.table; import org.apache.cayenne.modeler.toolkit.combobox.AutoCompletion; +import org.apache.cayenne.modeler.toolkit.combobox.ComboBoxPopup; -import javax.swing.AbstractCellEditor; -import javax.swing.JComboBox; -import javax.swing.JPopupMenu; -import javax.swing.JScrollPane; -import javax.swing.JTable; +import javax.swing.*; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import javax.swing.table.TableCellEditor; -import java.awt.Component; -import java.awt.Container; -import java.awt.Dimension; +import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; @@ -51,8 +46,6 @@ public class CMComboBoxCellEditor extends AbstractCellEditor // 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 int MAX_POPUP_WIDTH = 450; - private final JComboBox<?> comboBox; private final boolean autocomplete; @@ -108,7 +101,7 @@ public class CMComboBoxCellEditor extends AbstractCellEditor popup.setPreferredSize(null); int naturalWidth = scrollPane.getPreferredSize().width; - int targetWidth = Math.min(Math.max(naturalWidth, comboBox.getWidth()), MAX_POPUP_WIDTH); + int targetWidth = Math.min(Math.max(naturalWidth, comboBox.getWidth()), ComboBoxPopup.MAX_WIDTH); Dimension scrollSize = new Dimension(targetWidth, scrollPane.getPreferredSize().height); scrollPane.setPreferredSize(scrollSize);
