| 1 | /******************************************************************************* | |
| 2 | * Copyhacked (H) 2012-2025. | |
| 3 | * This program and the accompanying materials | |
| 4 | * are made available under no term at all, use it like | |
| 5 | * you want, but share and discuss it | |
| 6 | * every time possible with every body. | |
| 7 | * | |
| 8 | * Contributors: | |
| 9 | * ron190 at ymail dot com - initial implementation | |
| 10 | ******************************************************************************/ | |
| 11 | package com.jsql.view.swing.list; | |
| 12 | ||
| 13 | import com.formdev.flatlaf.util.SystemFileChooser; | |
| 14 | import com.jsql.util.I18nUtil; | |
| 15 | import com.jsql.util.LogLevelUtil; | |
| 16 | import com.jsql.view.swing.util.I18nViewUtil; | |
| 17 | import com.jsql.view.swing.util.MediatorHelper; | |
| 18 | import org.apache.logging.log4j.LogManager; | |
| 19 | import org.apache.logging.log4j.Logger; | |
| 20 | ||
| 21 | import javax.swing.*; | |
| 22 | import java.awt.*; | |
| 23 | import java.awt.event.*; | |
| 24 | import java.io.IOException; | |
| 25 | import java.util.AbstractMap.SimpleEntry; | |
| 26 | import java.util.Arrays; | |
| 27 | import java.util.stream.Stream; | |
| 28 | ||
| 29 | /** | |
| 30 | * A Mouse action to display a popupmenu on a JList. | |
| 31 | */ | |
| 32 | public class MouseAdapterMenuAction extends MouseAdapter { | |
| 33 | | |
| 34 | private static final Logger LOGGER = LogManager.getRootLogger(); | |
| 35 | | |
| 36 | /** | |
| 37 | * JList to add popupmenu. | |
| 38 | */ | |
| 39 | private final DnDList dndList; | |
| 40 | | |
| 41 | /** | |
| 42 | * Create a popup menu for current JList item. | |
| 43 | * @param dndList List with action | |
| 44 | */ | |
| 45 | public MouseAdapterMenuAction(DnDList dndList) { | |
| 46 | this.dndList = dndList; | |
| 47 | } | |
| 48 | | |
| 49 | /** | |
| 50 | * Displays a popup menu for JList. | |
| 51 | * @param mouseEvent Mouse event | |
| 52 | */ | |
| 53 | @SuppressWarnings("unchecked") | |
| 54 | public void showPopup(final MouseEvent mouseEvent) { | |
| 55 |
1
1. showPopup : negated conditional → NO_COVERAGE |
if (mouseEvent.isPopupTrigger()) { |
| 56 | JList<ItemList> list = (JList<ItemList>) mouseEvent.getSource(); | |
| 57 | ||
| 58 | JPopupMenu popupMenuList = this.initMenu(mouseEvent); | |
| 59 |
1
1. showPopup : removed call to javax/swing/JPopupMenu::applyComponentOrientation → NO_COVERAGE |
popupMenuList.applyComponentOrientation(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale())); |
| 60 | // Fix #26274: IllegalComponentStateException on show() | |
| 61 | try { | |
| 62 |
1
1. showPopup : removed call to javax/swing/JPopupMenu::show → NO_COVERAGE |
popupMenuList.show( |
| 63 | list, | |
| 64 |
1
1. showPopup : negated conditional → NO_COVERAGE |
ComponentOrientation.RIGHT_TO_LEFT.equals(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale())) |
| 65 |
1
1. showPopup : Replaced integer subtraction with addition → NO_COVERAGE |
? mouseEvent.getX() - popupMenuList.getWidth() |
| 66 | : mouseEvent.getX(), | |
| 67 | mouseEvent.getY() | |
| 68 | ); | |
| 69 | } catch (IllegalComponentStateException e) { | |
| 70 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e); | |
| 71 | } | |
| 72 | | |
| 73 |
1
1. showPopup : removed call to javax/swing/JPopupMenu::setLocation → NO_COVERAGE |
popupMenuList.setLocation( |
| 74 |
1
1. showPopup : negated conditional → NO_COVERAGE |
ComponentOrientation.RIGHT_TO_LEFT.equals(ComponentOrientation.getOrientation(I18nUtil.getCurrentLocale())) |
| 75 |
1
1. showPopup : Replaced integer subtraction with addition → NO_COVERAGE |
? mouseEvent.getXOnScreen() - popupMenuList.getWidth() |
| 76 | : mouseEvent.getXOnScreen(), | |
| 77 | mouseEvent.getYOnScreen() | |
| 78 | ); | |
| 79 | } | |
| 80 | } | |
| 81 | ||
| 82 | private JPopupMenu initMenu(final MouseEvent mouseEvent) { | |
| 83 | var popupMenuList = new JPopupMenu(); | |
| 84 | | |
| 85 | boolean isNonUbuntu = I18nViewUtil.isNonUbuntu(I18nUtil.getCurrentLocale()); | |
| 86 | | |
| 87 | JMenuItem menuImport = new JMenuItem(); | |
| 88 | JMenuItem menuExport = new JMenuItem(); | |
| 89 | JMenuItem menuCut = new JMenuItem(); | |
| 90 | JMenuItem menuCopy = new JMenuItem(); | |
| 91 | JMenuItem menuPaste = new JMenuItem(); | |
| 92 | JMenuItem menuDelete = new JMenuItem(); | |
| 93 | JMenuItem menuNew = new JMenuItem(); | |
| 94 | JMenuItem menuRestoreDefault = new JMenuItem(); | |
| 95 | JMenuItem menuSelectAll = new JMenuItem(); | |
| 96 | | |
| 97 | Stream.of( | |
| 98 | new SimpleEntry<>(menuImport, "LIST_IMPORT_CONFIRM_TITLE"), | |
| 99 | new SimpleEntry<>(menuExport, "LIST_EXPORT_TITLE"), | |
| 100 | new SimpleEntry<>(menuCut, "LIST_CUT"), | |
| 101 | new SimpleEntry<>(menuCopy, "CONTEXT_MENU_COPY"), | |
| 102 | new SimpleEntry<>(menuPaste, "LIST_PASTE"), | |
| 103 | new SimpleEntry<>(menuDelete, "LIST_DELETE"), | |
| 104 | new SimpleEntry<>(menuNew, "LIST_NEW_VALUE"), | |
| 105 | new SimpleEntry<>(menuRestoreDefault, "LIST_RESTORE_DEFAULT"), | |
| 106 | new SimpleEntry<>(menuSelectAll, "CONTEXT_MENU_SELECT_ALL") | |
| 107 | ) | |
| 108 |
1
1. initMenu : removed call to java/util/stream/Stream::forEach → NO_COVERAGE |
.forEach(entry -> { |
| 109 |
1
1. lambda$initMenu$0 : removed call to javax/swing/JMenuItem::setText → NO_COVERAGE |
entry.getKey().setText( |
| 110 |
1
1. lambda$initMenu$0 : negated conditional → NO_COVERAGE |
isNonUbuntu |
| 111 | ? I18nViewUtil.valueByKey(entry.getValue()) | |
| 112 | : I18nUtil.valueByKey(entry.getValue()) | |
| 113 | ); | |
| 114 |
1
1. lambda$initMenu$0 : removed call to javax/swing/JMenuItem::setName → NO_COVERAGE |
entry.getKey().setName(entry.getValue()); |
| 115 |
1
1. lambda$initMenu$0 : removed call to com/jsql/view/swing/util/I18nViewUtil::addComponentForKey → NO_COVERAGE |
I18nViewUtil.addComponentForKey(entry.getValue(), entry.getKey()); |
| 116 | }); | |
| 117 | ||
| 118 |
1
1. initMenu : removed call to javax/swing/JMenuItem::setAccelerator → NO_COVERAGE |
menuCut.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_DOWN_MASK)); |
| 119 |
1
1. initMenu : removed call to javax/swing/JMenuItem::setAccelerator → NO_COVERAGE |
menuCopy.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)); |
| 120 |
1
1. initMenu : removed call to javax/swing/JMenuItem::setAccelerator → NO_COVERAGE |
menuPaste.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK)); |
| 121 |
1
1. initMenu : removed call to javax/swing/JMenuItem::setAccelerator → NO_COVERAGE |
menuSelectAll.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_DOWN_MASK)); |
| 122 | | |
| 123 | final var importFileDialog = new SystemFileChooser(MediatorHelper.model().getMediatorUtils().preferencesUtil().getPathFile()); | |
| 124 |
1
1. initMenu : removed call to com/formdev/flatlaf/util/SystemFileChooser::setDialogTitle → NO_COVERAGE |
importFileDialog.setDialogTitle(I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_TITLE")); |
| 125 |
1
1. initMenu : removed call to com/formdev/flatlaf/util/SystemFileChooser::setMultiSelectionEnabled → NO_COVERAGE |
importFileDialog.setMultiSelectionEnabled(true); |
| 126 | ||
| 127 |
1
1. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE |
menuNew.addActionListener(new MenuActionNewValue(this.dndList)); |
| 128 | ||
| 129 |
1
1. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE |
menuImport.addActionListener(actionEvent -> { |
| 130 | var choice = 0; | |
| 131 | // Fix #1896: NullPointerException on showOpenDialog() | |
| 132 | // Fix #42831: ClassCastException on showOpenDialog() | |
| 133 | try { | |
| 134 | choice = importFileDialog.showOpenDialog(this.dndList.getTopLevelAncestor()); | |
| 135 |
1
1. lambda$initMenu$1 : negated conditional → NO_COVERAGE |
if (choice == JFileChooser.APPROVE_OPTION) { |
| 136 |
1
1. lambda$initMenu$1 : removed call to com/jsql/view/swing/list/DnDList::dropPasteFile → NO_COVERAGE |
this.dndList.dropPasteFile( |
| 137 | Arrays.asList(importFileDialog.getSelectedFiles()), | |
| 138 | this.dndList.locationToIndex(mouseEvent.getPoint()) | |
| 139 | ); | |
| 140 | } | |
| 141 | } catch (ClassCastException | NullPointerException | IOException e) { | |
| 142 | LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e); | |
| 143 | } | |
| 144 | }); | |
| 145 | ||
| 146 |
1
1. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE |
menuCopy.addActionListener(actionEvent -> { |
| 147 | var action = this.dndList.getActionMap().get(TransferHandler.getCopyAction().getValue(Action.NAME)); | |
| 148 |
1
1. lambda$initMenu$2 : negated conditional → NO_COVERAGE |
if (action != null) { |
| 149 |
1
1. lambda$initMenu$2 : removed call to javax/swing/Action::actionPerformed → NO_COVERAGE |
action.actionPerformed( |
| 150 | new ActionEvent(this.dndList, ActionEvent.ACTION_PERFORMED, null) | |
| 151 | ); | |
| 152 | } | |
| 153 | }); | |
| 154 | ||
| 155 |
1
1. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE |
menuCut.addActionListener(actionEvent -> { |
| 156 | var action = this.dndList.getActionMap().get(TransferHandler.getCutAction().getValue(Action.NAME)); | |
| 157 |
1
1. lambda$initMenu$3 : negated conditional → NO_COVERAGE |
if (action != null) { |
| 158 |
1
1. lambda$initMenu$3 : removed call to javax/swing/Action::actionPerformed → NO_COVERAGE |
action.actionPerformed( |
| 159 | new ActionEvent(this.dndList, ActionEvent.ACTION_PERFORMED, null) | |
| 160 | ); | |
| 161 | } | |
| 162 | }); | |
| 163 | ||
| 164 |
1
1. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE |
menuPaste.addActionListener(actionEvent -> { |
| 165 | var action = this.dndList.getActionMap().get(TransferHandler.getPasteAction().getValue(Action.NAME)); | |
| 166 |
1
1. lambda$initMenu$4 : negated conditional → NO_COVERAGE |
if (action != null) { |
| 167 |
1
1. lambda$initMenu$4 : removed call to javax/swing/Action::actionPerformed → NO_COVERAGE |
action.actionPerformed( |
| 168 | new ActionEvent(this.dndList, ActionEvent.ACTION_PERFORMED, null) | |
| 169 | ); | |
| 170 | } | |
| 171 | }); | |
| 172 | ||
| 173 |
2
1. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE 2. lambda$initMenu$5 : removed call to com/jsql/view/swing/list/DnDList::removeSelectedItem → NO_COVERAGE |
menuDelete.addActionListener(actionEvent -> this.dndList.removeSelectedItem()); |
| 174 |
1
1. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE |
menuExport.addActionListener(new MenuActionExport(this.dndList)); |
| 175 |
2
1. initMenu : removed call to javax/swing/JMenuItem::setEnabled → NO_COVERAGE 2. initMenu : negated conditional → NO_COVERAGE |
menuExport.setEnabled(!this.dndList.listModel.isEmpty()); |
| 176 |
2
1. lambda$initMenu$6 : removed call to com/jsql/view/swing/list/DnDList::restore → NO_COVERAGE 2. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE |
menuRestoreDefault.addActionListener(actionEvent -> this.dndList.restore()); |
| 177 |
1
1. initMenu : removed call to javax/swing/JMenuItem::addActionListener → NO_COVERAGE |
menuSelectAll.addActionListener(actionEvent -> { |
| 178 | var start = 0; | |
| 179 |
1
1. lambda$initMenu$7 : Replaced integer subtraction with addition → NO_COVERAGE |
int end = this.dndList.getModel().getSize() - 1; |
| 180 |
2
1. lambda$initMenu$7 : changed conditional boundary → NO_COVERAGE 2. lambda$initMenu$7 : negated conditional → NO_COVERAGE |
if (end >= 0) { |
| 181 |
1
1. lambda$initMenu$7 : removed call to com/jsql/view/swing/list/DnDList::setSelectionInterval → NO_COVERAGE |
this.dndList.setSelectionInterval(start, end); |
| 182 | } | |
| 183 | }); | |
| 184 | ||
| 185 | popupMenuList.add(menuNew); | |
| 186 | popupMenuList.add(new JSeparator()); | |
| 187 | popupMenuList.add(menuCut); | |
| 188 | popupMenuList.add(menuCopy); | |
| 189 | popupMenuList.add(menuPaste); | |
| 190 | popupMenuList.add(menuDelete); | |
| 191 | popupMenuList.add(new JSeparator()); | |
| 192 | popupMenuList.add(menuSelectAll); | |
| 193 | popupMenuList.add(new JSeparator()); | |
| 194 | popupMenuList.add(menuImport); | |
| 195 | popupMenuList.add(menuExport); | |
| 196 | popupMenuList.add(new JSeparator()); | |
| 197 | popupMenuList.add(menuRestoreDefault); | |
| 198 |
1
1. initMenu : replaced return value with null for com/jsql/view/swing/list/MouseAdapterMenuAction::initMenu → NO_COVERAGE |
return popupMenuList; |
| 199 | } | |
| 200 | ||
| 201 | @Override | |
| 202 | public void mousePressed(MouseEvent e) { | |
| 203 |
1
1. mousePressed : negated conditional → NO_COVERAGE |
if (SwingUtilities.isRightMouseButton(e)) { |
| 204 | int clickIndex = this.dndList.locationToIndex(e.getPoint()); | |
| 205 | var containsIndex = false; | |
| 206 | for (int currentIndex: this.dndList.getSelectedIndices()) { | |
| 207 |
1
1. mousePressed : negated conditional → NO_COVERAGE |
if (currentIndex == clickIndex) { |
| 208 | containsIndex = true; | |
| 209 | break; | |
| 210 | } | |
| 211 | } | |
| 212 |
1
1. mousePressed : negated conditional → NO_COVERAGE |
if (!containsIndex) { |
| 213 |
1
1. mousePressed : removed call to com/jsql/view/swing/list/DnDList::setSelectedIndex → NO_COVERAGE |
this.dndList.setSelectedIndex(clickIndex); |
| 214 | } | |
| 215 | } | |
| 216 |
1
1. mousePressed : removed call to com/jsql/view/swing/list/MouseAdapterMenuAction::showPopup → NO_COVERAGE |
this.showPopup(e); |
| 217 | } | |
| 218 | ||
| 219 | @Override | |
| 220 | public void mouseReleased(MouseEvent e) { | |
| 221 |
1
1. mouseReleased : removed call to com/jsql/view/swing/list/MouseAdapterMenuAction::showPopup → NO_COVERAGE |
this.showPopup(e); |
| 222 | } | |
| 223 | } | |
Mutations | ||
| 55 |
1.1 |
|
| 59 |
1.1 |
|
| 62 |
1.1 |
|
| 64 |
1.1 |
|
| 65 |
1.1 |
|
| 73 |
1.1 |
|
| 74 |
1.1 |
|
| 75 |
1.1 |
|
| 108 |
1.1 |
|
| 109 |
1.1 |
|
| 110 |
1.1 |
|
| 114 |
1.1 |
|
| 115 |
1.1 |
|
| 118 |
1.1 |
|
| 119 |
1.1 |
|
| 120 |
1.1 |
|
| 121 |
1.1 |
|
| 124 |
1.1 |
|
| 125 |
1.1 |
|
| 127 |
1.1 |
|
| 129 |
1.1 |
|
| 135 |
1.1 |
|
| 136 |
1.1 |
|
| 146 |
1.1 |
|
| 148 |
1.1 |
|
| 149 |
1.1 |
|
| 155 |
1.1 |
|
| 157 |
1.1 |
|
| 158 |
1.1 |
|
| 164 |
1.1 |
|
| 166 |
1.1 |
|
| 167 |
1.1 |
|
| 173 |
1.1 2.2 |
|
| 174 |
1.1 |
|
| 175 |
1.1 2.2 |
|
| 176 |
1.1 2.2 |
|
| 177 |
1.1 |
|
| 179 |
1.1 |
|
| 180 |
1.1 2.2 |
|
| 181 |
1.1 |
|
| 198 |
1.1 |
|
| 203 |
1.1 |
|
| 207 |
1.1 |
|
| 212 |
1.1 |
|
| 213 |
1.1 |
|
| 216 |
1.1 |
|
| 221 |
1.1 |