1 package edu.jiangxin.apktoolbox.swing.extend;
2
3 import edu.jiangxin.apktoolbox.utils.Constants;
4 import org.apache.logging.log4j.LogManager;
5 import org.apache.logging.log4j.Logger;
6
7 import javax.swing.*;
8 import java.awt.*;
9 import java.awt.datatransfer.DataFlavor;
10 import java.awt.datatransfer.Transferable;
11 import java.awt.datatransfer.UnsupportedFlavorException;
12 import java.awt.event.ActionEvent;
13 import java.awt.event.ActionListener;
14 import java.io.File;
15 import java.io.IOException;
16 import java.io.Serial;
17 import java.util.ArrayList;
18 import java.util.List;
19
20 public class FileListPanel extends JPanel {
21 @Serial
22 private static final long serialVersionUID = 1L;
23
24 private static final Logger LOGGER = LogManager.getLogger(FileListPanel.class.getSimpleName());
25
26 private JPanel leftPanel;
27
28 private JPanel rightPanel;
29
30 private JList<File> fileList;
31
32 private DefaultListModel<File> fileListModel;
33
34 public FileListPanel() {
35 super();
36 }
37
38
39 public void initialize() {
40 initUI();
41 }
42
43 public List<File> getFileList() {
44 List<File> fileList = new ArrayList<>();
45 Object[] objectArray = fileListModel.toArray();
46 for (Object obj : objectArray) {
47 if (obj instanceof File) {
48 fileList.add((File) obj);
49 }
50 }
51 return fileList;
52 }
53
54 private void initUI() {
55 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
56
57 createLeftPanel();
58 add(leftPanel);
59
60 add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
61
62 createRightPanel();
63 add(rightPanel);
64 }
65
66 private void createLeftPanel() {
67 fileList = new JList<>();
68 fileListModel = new DefaultListModel<>();
69 fileList.setModel(fileListModel);
70
71 JScrollPane scrollPane = new JScrollPane(fileList);
72 scrollPane.setPreferredSize(new Dimension(Constants.DEFAULT_SCROLL_PANEL_WIDTH, Constants.DEFAULT_SCROLL_PANEL_HEIGHT));
73
74 leftPanel = new JPanel();
75 leftPanel.setBorder(BorderFactory.createTitledBorder("File List"));
76 leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
77 leftPanel.setTransferHandler(new FileListTransferHandler());
78 leftPanel.add(scrollPane);
79 }
80
81 private void createRightPanel() {
82 rightPanel = new JPanel();
83 rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
84
85 JPanel rightContentPanel = new JPanel();
86 rightPanel.add(Box.createVerticalGlue());
87 rightPanel.add(rightContentPanel);
88 rightPanel.add(Box.createVerticalGlue());
89
90 rightContentPanel.setLayout(new GridLayout(6, 1, 0, Constants.DEFAULT_Y_BORDER));
91
92 JButton addFileButton = new JButton("Add File");
93 addFileButton.addActionListener(new AddFileButtonActionListener());
94 rightContentPanel.add(addFileButton);
95
96 JButton addDirectoryButton = new JButton("Add Directory");
97 addDirectoryButton.addActionListener(new AddDirectoryButtonActionListener());
98 rightContentPanel.add(addDirectoryButton);
99
100 JButton removeSelectedButton = new JButton("Remove Selected");
101 removeSelectedButton.addActionListener(new RemoveSelectedButtonActionListener());
102 rightContentPanel.add(removeSelectedButton);
103
104 JButton clearButton = new JButton("Clear All");
105 clearButton.addActionListener(new ClearButtonActionListener());
106 rightContentPanel.add(clearButton);
107
108 JButton selectAllButton = new JButton("Select All");
109 selectAllButton.addActionListener(new SelectAllButtonActionListener());
110 rightContentPanel.add(selectAllButton);
111
112 JButton inverseSelectedButton = new JButton("Inverse Selected");
113 inverseSelectedButton.addActionListener(new InverseSelectedButtonActionListener());
114 rightContentPanel.add(inverseSelectedButton);
115
116 for (Component component : rightContentPanel.getComponents()) {
117 component.setPreferredSize(new Dimension(Constants.DEFAULT_BUTTON_WIDTH, Constants.DEFAULT_BUTTON_HEIGHT));
118 }
119 }
120
121 private final class FileListTransferHandler extends TransferHandler {
122 @Serial
123 private static final long serialVersionUID = 1L;
124
125 @Override
126 public boolean importData(JComponent comp, Transferable t) {
127 try {
128 @SuppressWarnings("unchecked")
129 List<File> files = (List<File>) (t.getTransferData(DataFlavor.javaFileListFlavor));
130 for (File file : files) {
131 fileListModel.addElement(file);
132 }
133 return true;
134 } catch (IOException e) {
135 LOGGER.error("importData failed: IOException");
136 } catch (UnsupportedFlavorException e) {
137 LOGGER.error("importData failed: UnsupportedFlavorException");
138 }
139 return false;
140 }
141
142 @Override
143 public boolean canImport(JComponent jComponent, DataFlavor[] dataFlavors) {
144 for (DataFlavor dataFlavor : dataFlavors) {
145 if (DataFlavor.javaFileListFlavor.equals(dataFlavor)) {
146 return true;
147 }
148 }
149 return false;
150 }
151 }
152
153 private final class AddFileButtonActionListener implements ActionListener {
154 @Override
155 public void actionPerformed(ActionEvent e) {
156 JFileChooser jfc = new JFileChooser();
157 jfc.setFileSelectionMode(JFileChooser.FILES_ONLY);
158 jfc.setDialogTitle("Select A File");
159 int ret = jfc.showDialog(new JLabel(), null);
160 if (ret == JFileChooser.APPROVE_OPTION) {
161 File file = jfc.getSelectedFile();
162 fileListModel.addElement(file);
163 }
164 }
165 }
166
167 private final class AddDirectoryButtonActionListener implements ActionListener {
168 @Override
169 public void actionPerformed(ActionEvent e) {
170 JFileChooser jfc = new JFileChooser();
171 jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
172 jfc.setDialogTitle("Select A Directory");
173 int ret = jfc.showDialog(new JLabel(), null);
174 if (ret == JFileChooser.APPROVE_OPTION) {
175 File file = jfc.getSelectedFile();
176 fileListModel.addElement(file);
177 }
178
179 }
180 }
181
182 private final class RemoveSelectedButtonActionListener implements ActionListener {
183 @Override
184 public void actionPerformed(ActionEvent e) {
185 List<File> files = fileList.getSelectedValuesList();
186 for (File file : files) {
187 fileListModel.removeElement(file);
188 }
189 }
190 }
191
192 private final class ClearButtonActionListener implements ActionListener {
193 @Override
194 public void actionPerformed(ActionEvent e) {
195 fileListModel.removeAllElements();
196 }
197 }
198
199 private final class SelectAllButtonActionListener implements ActionListener {
200 @Override
201 public void actionPerformed(ActionEvent e) {
202 int[] selectedIndices = new int[fileListModel.getSize()];
203 for (int i = 0; i < selectedIndices.length; i++) {
204 selectedIndices[i] = i;
205 }
206 fileList.clearSelection();
207 fileList.setSelectedIndices(selectedIndices);
208 }
209 }
210
211 private final class InverseSelectedButtonActionListener implements ActionListener {
212 @Override
213 public void actionPerformed(ActionEvent e) {
214 int[] newIndices = new int[fileListModel.getSize() - fileList.getSelectedIndices().length];
215 for (int i = 0, j = 0; i < fileListModel.getSize(); ++i) {
216 if (!fileList.isSelectedIndex(i)) {
217 newIndices[j++] = i;
218 }
219 }
220 fileList.clearSelection();
221 fileList.setSelectedIndices(newIndices);
222 }
223 }
224
225 }