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