View Javadoc
1   package edu.jiangxin.apktoolbox.pdf.pic2pdf;
2   
3   import edu.jiangxin.apktoolbox.pdf.PdfUtils;
4   import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
5   import edu.jiangxin.apktoolbox.swing.extend.FileListPanel;
6   import edu.jiangxin.apktoolbox.swing.extend.filepanel.FilePanel;
7   import edu.jiangxin.apktoolbox.utils.Constants;
8   import edu.jiangxin.apktoolbox.utils.FileUtils;
9   
10  import javax.swing.*;
11  import java.awt.event.ActionEvent;
12  import java.awt.event.ActionListener;
13  import java.io.File;
14  import java.io.Serial;
15  import java.util.List;
16  import java.util.Set;
17  import java.util.TreeSet;
18  import java.util.concurrent.ExecutorService;
19  import java.util.concurrent.Executors;
20  
21  public class Pic2PdfPanel  extends EasyPanel {
22      @Serial
23      private static final long serialVersionUID = 1L;
24  
25      private FileListPanel fileListPanel;
26  
27      private JCheckBox isRecursiveSearched;
28  
29      private FilePanel targetDirPanel;
30  
31      private JButton startButton;
32      private JButton cancelButton;
33  
34      private transient WorkderThread convertThread;
35  
36      @Override
37      public void initUI() {
38          BoxLayout boxLayout = new BoxLayout(this, BoxLayout.Y_AXIS);
39          setLayout(boxLayout);
40  
41          createInputPanel();
42          add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
43  
44          createOutputPanel();
45          add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
46  
47          createOptionPanel();
48          add(Box.createVerticalStrut(Constants.DEFAULT_Y_BORDER));
49  
50          createOperationPanel();
51      }
52  
53      private void createInputPanel() {
54          fileListPanel = new FileListPanel();
55          fileListPanel.initialize();
56          add(fileListPanel);
57      }
58  
59      private void createOutputPanel() {
60          targetDirPanel = new FilePanel("Target Directory");
61          targetDirPanel.initialize();
62          targetDirPanel.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
63          add(targetDirPanel);
64      }
65  
66      private void createOptionPanel() {
67          JPanel optionPanel = new JPanel();
68          optionPanel.setLayout(new BoxLayout(optionPanel, BoxLayout.X_AXIS));
69          optionPanel.setBorder(BorderFactory.createTitledBorder("Options"));
70  
71          isRecursiveSearched = new JCheckBox("Recursive Search");
72          isRecursiveSearched.setSelected(true);
73          optionPanel.add(isRecursiveSearched);
74          optionPanel.add(Box.createHorizontalGlue());
75  
76          add(optionPanel);
77      }
78  
79      private void createOperationPanel() {
80          JPanel operationPanel = new JPanel();
81          operationPanel.setLayout(new BoxLayout(operationPanel, BoxLayout.X_AXIS));
82          operationPanel.setBorder(BorderFactory.createTitledBorder("Operations"));
83  
84          startButton = new JButton("Start");
85          cancelButton = new JButton("Cancel");
86          cancelButton.setEnabled(false);
87          startButton.addActionListener(new OperationButtonActionListener());
88          cancelButton.addActionListener(new OperationButtonActionListener());
89          operationPanel.add(startButton);
90          operationPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
91          operationPanel.add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
92          operationPanel.add(cancelButton);
93          operationPanel.add(Box.createHorizontalGlue());
94  
95          add(operationPanel);
96      }
97  
98      private void processFile(File encryptedFile, File targetDir) {
99          try {
100             if (Thread.currentThread().isInterrupted()) {
101                 return;
102             }
103             PdfUtils.removePasswordWithIText(encryptedFile, targetDir);
104         } catch (Throwable t) {
105             logger.error("Process file failed: {}", encryptedFile.getAbsolutePath(), t);
106         }
107     }
108 
109     class OperationButtonActionListener implements ActionListener {
110         @Override
111         public void actionPerformed(ActionEvent e) {
112             Object source = e.getSource();
113             if (source.equals(startButton)) {
114                 startButton.setEnabled(false);
115                 cancelButton.setEnabled(true);
116                 convertThread = new WorkderThread(isRecursiveSearched.isSelected());
117                 convertThread.start();
118             } else if (source.equals(cancelButton)) {
119                 startButton.setEnabled(true);
120                 cancelButton.setEnabled(false);
121                 if (convertThread.isAlive()) {
122                     convertThread.interrupt();
123                     convertThread.executorService.shutdownNow();
124                 }
125             }
126 
127         }
128     }
129 
130     class WorkderThread extends Thread {
131         public final ExecutorService executorService;
132         private final boolean isRecursiveSearched;
133 
134         public WorkderThread(boolean isRecursiveSearched) {
135             super();
136             this.isRecursiveSearched = isRecursiveSearched;
137             this.executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
138         }
139 
140         @Override
141         public void run() {
142             try {
143                 List<File> fileList = fileListPanel.getFileList();
144                 Set<File> fileSet = new TreeSet<>();
145                 String[] extensions = new String[]{"jpg", "jpeg", "png"};
146                 for (File file : fileList) {
147                     fileSet.addAll(FileUtils.listFiles(file, extensions, isRecursiveSearched));
148                 }
149 
150                 PdfUtils.imagesToPdf(fileSet, new File(targetDirPanel.getFile(), "result.pdf"));
151             } catch (Exception e) {
152                 logger.error("Remove process failed", e);
153             } finally {
154                 executorService.shutdown();
155                 SwingUtilities.invokeLater(() -> {
156                     startButton.setEnabled(true);
157                     cancelButton.setEnabled(false);
158                 });
159             }
160         }
161     }
162 }