1
2
3
4
5
6
7
8
9
10
11 package com.jsql.view.swing.list;
12
13 import com.jsql.util.I18nUtil;
14 import com.jsql.util.LogLevelUtil;
15 import org.apache.commons.io.FilenameUtils;
16 import org.apache.commons.lang3.StringUtils;
17 import org.apache.logging.log4j.LogManager;
18 import org.apache.logging.log4j.Logger;
19
20 import javax.swing.*;
21 import java.awt.event.*;
22 import java.io.BufferedReader;
23 import java.io.File;
24 import java.io.FileReader;
25 import java.io.IOException;
26 import java.nio.charset.StandardCharsets;
27 import java.util.ArrayList;
28 import java.util.List;
29
30
31
32
33 public class DnDList extends JList<ItemList> {
34
35 private static final Logger LOGGER = LogManager.getRootLogger();
36
37
38
39
40 protected final DefaultListModel<ItemList> listModel;
41
42
43
44
45 private final transient List<ItemList> defaultList;
46
47
48
49
50
51 public DnDList(List<ItemList> newList) {
52 this.defaultList = newList;
53 this.listModel = new DefaultListModel<>();
54
55 for (ItemList path: newList) {
56 this.listModel.addElement(path);
57 }
58
59 this.setModel(this.listModel);
60 this.initActionMap();
61 this.initListener();
62 this.setDragEnabled(true);
63 this.setDropMode(DropMode.INSERT);
64 this.setTransferHandler(new ListTransfertHandler());
65 }
66
67 private void initListener() {
68 this.addMouseListener(new MouseAdapterMenuAction(this));
69 this.addFocusListener(new FocusListener() {
70 @Override
71 public void focusLost(FocusEvent focusEvent) {
72 DnDList.this.repaint();
73 }
74 @Override
75 public void focusGained(FocusEvent focusEvent) {
76 DnDList.this.repaint();
77 }
78 });
79 this.addKeyListener(new KeyAdapter() {
80 @Override
81 public void keyPressed(KeyEvent keyEvent) {
82 if (keyEvent.getKeyCode() == KeyEvent.VK_DELETE) {
83 DnDList.this.removeSelectedItem();
84 }
85 }
86 });
87 }
88
89 private void initActionMap() {
90 var listActionMap = this.getActionMap();
91 listActionMap.put(TransferHandler.getCutAction().getValue(Action.NAME), new AbstractAction() {
92 @Override
93 public void actionPerformed(ActionEvent e) {
94 if (DnDList.this.getSelectedValuesList().isEmpty()) {
95 return;
96 }
97
98 List<ItemList> selectedValues = DnDList.this.getSelectedValuesList();
99 List<ItemList> siblings = new ArrayList<>();
100 for (ItemList value: selectedValues) {
101 int valueIndex = DnDList.this.listModel.indexOf(value);
102 if (valueIndex < DnDList.this.listModel.size() - 1) {
103 siblings.add(DnDList.this.listModel.get(valueIndex + 1));
104 } else if (valueIndex > 0) {
105 siblings.add(DnDList.this.listModel.get(valueIndex - 1));
106 }
107 }
108
109 TransferHandler.getCutAction().actionPerformed(e);
110
111 for (ItemList sibling: siblings) {
112 DnDList.this.setSelectedValue(sibling, true);
113 }
114 }
115 });
116
117 listActionMap.put(
118 TransferHandler.getCopyAction().getValue(Action.NAME),
119 TransferHandler.getCopyAction()
120 );
121 listActionMap.put(
122 TransferHandler.getPasteAction().getValue(Action.NAME),
123 TransferHandler.getPasteAction()
124 );
125 }
126
127
128
129
130 public void removeSelectedItem() {
131 if (this.getSelectedValuesList().isEmpty()) {
132 return;
133 }
134
135 List<ItemList> selectedValues = this.getSelectedValuesList();
136 for (ItemList itemSelected: selectedValues) {
137 int indexOfItemSelected = this.listModel.indexOf(itemSelected);
138 this.listModel.removeElement(itemSelected);
139 if (indexOfItemSelected == this.listModel.getSize()) {
140 this.setSelectedIndex(indexOfItemSelected - 1);
141 } else {
142 this.setSelectedIndex(indexOfItemSelected);
143 }
144 }
145
146 try {
147 var rectangle = this.getCellBounds(
148 this.getMinSelectionIndex(),
149 this.getMaxSelectionIndex()
150 );
151 if (rectangle != null) {
152 this.scrollRectToVisible(
153 this.getCellBounds(
154 this.getMinSelectionIndex(),
155 this.getMaxSelectionIndex()
156 )
157 );
158 }
159 } catch (NullPointerException e) {
160
161 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
162 }
163 }
164
165
166
167
168 public void dropPasteFile(final List<File> filesToImport, int position) {
169 if (filesToImport.isEmpty()) {
170 return;
171 }
172
173 for (File fileToImport : filesToImport) {
174
175 if (
176 !FilenameUtils
177 .getExtension(fileToImport.getPath())
178 .matches("txt|csv|ini")
179 ) {
180
181 try {
182 JOptionPane.showMessageDialog(
183 this.getTopLevelAncestor(),
184 I18nUtil.valueByKey("LIST_IMPORT_ERROR_LABEL"),
185 I18nUtil.valueByKey("LIST_IMPORT_ERROR_TITLE"),
186 JOptionPane.ERROR_MESSAGE
187 );
188 } catch (ClassCastException e) {
189 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e.getMessage(), e);
190 }
191 return;
192 }
193 }
194
195 var options = new String[] {
196 I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_REPLACE"),
197 I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_ADD"),
198 I18nUtil.valueByKey("LIST_ADD_VALUE_CANCEL")
199 };
200 int answer = JOptionPane.showOptionDialog(
201 this.getTopLevelAncestor(),
202 I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_LABEL"),
203 I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_TITLE"),
204 JOptionPane.YES_NO_CANCEL_OPTION,
205 JOptionPane.QUESTION_MESSAGE,
206 null,
207 options,
208 options[2]
209 );
210 if (answer != JOptionPane.YES_OPTION && answer != JOptionPane.NO_OPTION) {
211 return;
212 }
213
214 int startPosition = position;
215 if (answer == JOptionPane.YES_OPTION) {
216 this.listModel.clear();
217 startPosition = 0;
218 }
219 int startPositionFinal = startPosition;
220 SwingUtilities.invokeLater(() -> this.addItems(filesToImport, startPositionFinal));
221 }
222
223 private void addItems(final List<File> filesToImport, int startPosition) {
224 int endPosition = startPosition;
225 for (File file: filesToImport) {
226 endPosition = this.initItems(endPosition, file);
227 }
228 if (!this.listModel.isEmpty()) {
229 this.setSelectionInterval(startPosition, endPosition - 1);
230 }
231
232 try {
233 this.scrollRectToVisible(
234 this.getCellBounds(
235 this.getMinSelectionIndex(),
236 this.getMaxSelectionIndex()
237 )
238 );
239 } catch (NullPointerException e) {
240
241 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e.getMessage(), e);
242 }
243 }
244
245 private int initItems(int startPosition, File file) {
246 int endPosition = startPosition;
247
248 try (
249 var fileReader = new FileReader(file, StandardCharsets.UTF_8);
250 var bufferedReader = new BufferedReader(fileReader)
251 ) {
252 String line;
253 while ((line = bufferedReader.readLine()) != null) {
254 if (
255 StringUtils.isNotEmpty(line)
256
257 && 0 <= endPosition
258 && endPosition <= this.listModel.size()
259 ) {
260 this.addItem(endPosition++, line);
261 }
262 }
263 } catch (IOException e) {
264 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e.getMessage(), e);
265 }
266
267 return endPosition;
268 }
269
270 public void restore() {
271 this.listModel.clear();
272 for (ItemList path: this.defaultList) {
273 this.listModel.addElement(path);
274 }
275 }
276
277 public void addItem(int endPosition, String line) {
278 this.listModel.add(endPosition, new ItemList(line.replace("\\", "/")));
279 }
280 }