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.lang3.StringUtils;
16 import org.apache.logging.log4j.LogManager;
17 import org.apache.logging.log4j.Logger;
18
19 import javax.swing.*;
20 import java.awt.event.*;
21 import java.io.BufferedReader;
22 import java.io.File;
23 import java.io.FileReader;
24 import java.io.IOException;
25 import java.nio.charset.StandardCharsets;
26 import java.nio.file.Files;
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) throws IOException {
169 if (filesToImport.isEmpty()) {
170 return;
171 }
172
173 for (File fileToImport : filesToImport) {
174
175 String type = Files.probeContentType(fileToImport.toPath());
176 if (type != null && !type.startsWith("text")) {
177
178 try {
179 JOptionPane.showMessageDialog(
180 this.getTopLevelAncestor(),
181 I18nUtil.valueByKey("LIST_IMPORT_ERROR_LABEL"),
182 I18nUtil.valueByKey("LIST_IMPORT_ERROR_TITLE"),
183 JOptionPane.ERROR_MESSAGE
184 );
185 } catch (ClassCastException e) {
186 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
187 }
188 return;
189 }
190 }
191
192 int answer = JOptionPane.YES_OPTION;
193 if (!this.listModel.isEmpty()) {
194 var options = new String[]{
195 I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_REPLACE"),
196 I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_ADD"),
197 I18nUtil.valueByKey("LIST_ADD_VALUE_CANCEL")
198 };
199 answer = JOptionPane.showOptionDialog(
200 this.getTopLevelAncestor(),
201 I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_LABEL"),
202 I18nUtil.valueByKey("LIST_IMPORT_CONFIRM_TITLE"),
203 JOptionPane.YES_NO_CANCEL_OPTION,
204 JOptionPane.QUESTION_MESSAGE,
205 null,
206 options,
207 options[2]
208 );
209 if (answer != JOptionPane.YES_OPTION && answer != JOptionPane.NO_OPTION) {
210 return;
211 }
212 }
213
214 int startPosition = Math.max(position, 0);
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, 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 && endPosition <= this.listModel.size()
258 ) {
259 this.addItem(endPosition++, line);
260 }
261 }
262 } catch (IOException e) {
263 LOGGER.log(LogLevelUtil.CONSOLE_JAVA, e, e);
264 }
265
266 return endPosition;
267 }
268
269 public void restore() {
270 this.listModel.clear();
271 for (ItemList path: this.defaultList) {
272 this.listModel.addElement(path);
273 }
274 }
275
276 public void addItem(int endPosition, String line) {
277 this.listModel.add(endPosition, new ItemList(line.replace("\\", "/")));
278 }
279 }