View Javadoc
1   package edu.jiangxin.apktoolbox.main;
2   
3   import edu.jiangxin.apktoolbox.Version;
4   import edu.jiangxin.apktoolbox.android.dumpsys.DumpsysPanel;
5   import edu.jiangxin.apktoolbox.convert.base.BaseConvertPanel;
6   import edu.jiangxin.apktoolbox.convert.color.ColorConvertPanel;
7   import edu.jiangxin.apktoolbox.convert.color.ColorPickerPanel;
8   import edu.jiangxin.apktoolbox.convert.color.ColorTablePanel;
9   import edu.jiangxin.apktoolbox.convert.encoding.AsciiGbViewerPanel;
10  import edu.jiangxin.apktoolbox.convert.encoding.GarbledTextRecoveryPanel;
11  import edu.jiangxin.apktoolbox.convert.protobuf.supervised.SupervisedProtobufConvertPanel;
12  import edu.jiangxin.apktoolbox.convert.protobuf.unsupervised.UnsupervisedProtobufConvertPanel;
13  import edu.jiangxin.apktoolbox.convert.relationship.RelationShipConvertPanel;
14  import edu.jiangxin.apktoolbox.convert.time.TimeConvertPanel;
15  import edu.jiangxin.apktoolbox.convert.zh2unicode.Zh2UnicodeConvertPanel;
16  import edu.jiangxin.apktoolbox.file.batchrename.BatchRenamePanel;
17  import edu.jiangxin.apktoolbox.file.EncodeConvertPanel;
18  import edu.jiangxin.apktoolbox.file.OsConvertPanel;
19  import edu.jiangxin.apktoolbox.file.checksum.ChecksumPanel;
20  import edu.jiangxin.apktoolbox.file.password.recovery.RecoveryPanel;
21  import edu.jiangxin.apktoolbox.file.duplicate.DuplicateSearchPanel;
22  import edu.jiangxin.apktoolbox.file.zhconvert.ZhConvertPanel;
23  import edu.jiangxin.apktoolbox.help.*;
24  import edu.jiangxin.apktoolbox.android.i18n.I18nAddPanel;
25  import edu.jiangxin.apktoolbox.android.i18n.I18nFindLongestPanel;
26  import edu.jiangxin.apktoolbox.android.i18n.I18nRemovePanel;
27  import edu.jiangxin.apktoolbox.android.monkey.MonkeyPanel;
28  import edu.jiangxin.apktoolbox.help.settings.SettingsPanel;
29  import edu.jiangxin.apktoolbox.pdf.finder.PdfFinderPanel;
30  import edu.jiangxin.apktoolbox.pdf.passwordremover.PdfPasswordRemoverPanel;
31  import edu.jiangxin.apktoolbox.pdf.pic2pdf.Pic2PdfPanel;
32  import edu.jiangxin.apktoolbox.pdf.stat.PdfStatPanel;
33  import edu.jiangxin.apktoolbox.reverse.*;
34  import edu.jiangxin.apktoolbox.android.screenshot.ScreenShotPanel;
35  import edu.jiangxin.apktoolbox.reverse.ApktoolPanel;
36  import edu.jiangxin.apktoolbox.swing.extend.EasyFrame;
37  import edu.jiangxin.apktoolbox.swing.extend.EasyPanel;
38  import edu.jiangxin.apktoolbox.swing.extend.listener.ChangeMenuListener;
39  import edu.jiangxin.apktoolbox.swing.extend.listener.ChangeMenuToUrlListener;
40  import edu.jiangxin.apktoolbox.swing.extend.listener.IPreChangeMenuCallBack;
41  import edu.jiangxin.apktoolbox.swing.extend.plugin.ChangeMenuPreparePluginController;
42  import edu.jiangxin.apktoolbox.swing.extend.plugin.PluginPanel;
43  import edu.jiangxin.apktoolbox.swing.keeper.UiStateKeeper;
44  import edu.jiangxin.apktoolbox.utils.Utils;
45  import org.apache.commons.configuration2.Configuration;
46  import org.apache.commons.lang3.StringUtils;
47  import org.apache.logging.log4j.LogManager;
48  import org.apache.logging.log4j.Logger;
49  
50  import javax.swing.*;
51  import javax.swing.border.EmptyBorder;
52  import java.awt.*;
53  import java.awt.event.*;
54  import java.io.Serial;
55  import java.lang.reflect.InvocationTargetException;
56  import java.text.MessageFormat;
57  import java.util.Locale;
58  import java.util.Objects;
59  
60  /**
61   * @author jiangxin
62   * @author 2018-08-19
63   */
64  public final class MainFrame extends EasyFrame {
65  
66      @Serial
67      private static final long serialVersionUID = 1L;
68  
69      private JPanel contentPane;
70      private EasyPanel currentEasyPanel = null;
71      private JMenuBar menuBar;
72  
73      public static void main(String[] args) {
74          final Logger logger = LogManager.getLogger(MainFrame.class.getSimpleName());
75          boolean isEnvironmentOk = Utils.checkAndInitEnvironment();
76          if (!isEnvironmentOk) {
77              logger.error("Environment is not ready, exit");
78              return;
79          }
80          EventQueue.invokeLater(() -> {
81              Configuration conf = Utils.getConfiguration();
82              String lookAndFeelClassName = conf.getString("look.and.feel.class.name");
83              if (StringUtils.isEmpty(lookAndFeelClassName)) {
84                  lookAndFeelClassName = "com.formdev.flatlaf.FlatDarculaLaf";
85                  conf.setProperty("look.and.feel.class.name", lookAndFeelClassName);
86              }
87              try {
88                  UIManager.setLookAndFeel(lookAndFeelClassName);
89              } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) {
90                  logger.error("setLookAndFeel failed, use default instead", e);
91              }
92  
93              String currentLocaleLanguage = conf.getString("locale.language");
94              if (StringUtils.isEmpty(currentLocaleLanguage)) {
95                  currentLocaleLanguage = Locale.ENGLISH.getLanguage();
96                  conf.setProperty("locale.language", currentLocaleLanguage);
97              }
98              Locale.setDefault(Locale.forLanguageTag(currentLocaleLanguage));
99  
100             MainFrame frame = new MainFrame();
101 
102             boolean isAlwaysOnTop = conf.getBoolean("always.on.top", false);
103             conf.setProperty("always.on.top", isAlwaysOnTop);
104             frame.setAlwaysOnTop(isAlwaysOnTop);
105 
106             frame.setVisible(true);
107         });
108     }
109 
110     public MainFrame() {
111         super();
112         initialize();
113         if (SystemTray.isSupported()) {
114             configSystemTray();
115         }
116 
117         setTitle(MessageFormat.format(bundle.getString("main.title"), Version.VERSION));
118         setDefaultCloseOperation(EXIT_ON_CLOSE);
119         setMenuBar();
120         contentPane = new JPanel();
121         contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
122         contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
123         contentPane.add(Box.createVerticalGlue());
124         EasyPanel initPanel = new AboutPanel();
125         initPanel.init();
126         initPanel.setBorder(BorderFactory.createTitledBorder(bundle.getString("help.about.title")));
127         contentPane.add(initPanel);
128         contentPane.add(Box.createVerticalGlue());
129         setContentPane(contentPane);
130         refreshSizeAndLocation();
131     }
132 
133     private void configSystemTray() {
134         SystemTray systemTray = SystemTray.getSystemTray();
135         PopupMenu popupMenu = new PopupMenu();
136         final MenuItem show = new MenuItem("Open");
137         final MenuItem exit = new MenuItem("Close");
138         ActionListener actionListener = e -> {
139             if (e.getSource() == show) {
140                 setExtendedState(NORMAL);
141                 setVisible(true);
142             }
143             if (e.getSource() == exit) {
144                 dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
145             }
146         };
147         exit.addActionListener(actionListener);
148         show.addActionListener(actionListener);
149         popupMenu.add(show);
150         popupMenu.add(exit);
151         TrayIcon trayIcon = new TrayIcon(image, "系统托盘", popupMenu);
152         trayIcon.setImageAutoSize(true);
153         try {
154             systemTray.add(trayIcon);
155         } catch (AWTException e) {
156             logger.error("add icon to tray failed");
157         }
158         trayIcon.addMouseListener(new MouseAdapter() {
159             @Override
160             public void mouseClicked(MouseEvent e) {
161                 if (e.getClickCount() == 2) {
162                     setExtendedState(NORMAL);
163                     setVisible(true);
164                 }
165             }
166         });
167     }
168 
169     private void setMenuBar() {
170         menuBar = new JMenuBar();
171         setJMenuBar(menuBar);
172 
173         createReverseMenu();
174 
175         createAndroidMenu();
176 
177         createPdfMenu();
178 
179         createFileMenu();
180 
181         createConvertMenu();
182 
183         createHelpMenu();
184     }
185 
186     private void createHelpMenu() {
187         JMenu helpMenu = new JMenu(bundle.getString("help.title"));
188         menuBar.add(helpMenu);
189 
190         JMenuItem documentMenuItem = new JMenuItem(bundle.getString("help.document.title"));
191         documentMenuItem.addActionListener(new ChangeMenuToUrlListener(Constant.URL_DOCUMENT));
192         helpMenu.add(documentMenuItem);
193 
194         JMenuItem settingsMenuItem = new JMenuItem(bundle.getString("help.settings.title"));
195         settingsMenuItem.addActionListener(new ChangeMenuToPanelListener(SettingsPanel.class, settingsMenuItem.getText()));
196         helpMenu.add(settingsMenuItem);
197 
198         JMenuItem feedbackMenuItem = new JMenuItem(bundle.getString("help.feedback.title"));
199         feedbackMenuItem.addActionListener(new ChangeMenuToUrlListener(Constant.URL_FEEDBACK));
200         helpMenu.add(feedbackMenuItem);
201 
202         JMenuItem checkUpdateMenuItem = new JMenuItem(bundle.getString("help.checkupdate.title"));
203         checkUpdateMenuItem.addActionListener(new CheckUpdateActionListener(this));
204         helpMenu.add(checkUpdateMenuItem);
205 
206         JMenuItem contributeMenuItem = new JMenuItem(bundle.getString("help.contribute.title"));
207         contributeMenuItem.addActionListener(new ChangeMenuToUrlListener(Constant.URL_CONTRIBUTE));
208         helpMenu.add(contributeMenuItem);
209 
210         JMenuItem aboutMenuItem = new JMenuItem(bundle.getString("help.about.title"));
211         aboutMenuItem.addActionListener(new ChangeMenuToPanelListener(AboutPanel.class, aboutMenuItem.getText()));
212         helpMenu.add(aboutMenuItem);
213     }
214 
215     private void createPdfMenu() {
216         JMenu pdfMenu = new JMenu(bundle.getString("pdf.title"));
217         menuBar.add(pdfMenu);
218 
219         JMenuItem pdfStatMenuItem = new JMenuItem(bundle.getString("pdf.stat.title"));
220         pdfStatMenuItem.addActionListener(new ChangeMenuToPanelListener(PdfStatPanel.class, pdfStatMenuItem.getText()));
221         pdfMenu.add(pdfStatMenuItem);
222 
223         JMenuItem pdfFinderMenuItem = new JMenuItem(bundle.getString("pdf.finder.title"));
224         pdfFinderMenuItem.addActionListener(new ChangeMenuToPanelListener(PdfFinderPanel.class, pdfFinderMenuItem.getText()));
225         pdfMenu.add(pdfFinderMenuItem);
226 
227         JMenuItem pdfPasswordRemoverMenuItem = new JMenuItem(bundle.getString("pdf.password.remover.title"));
228         pdfPasswordRemoverMenuItem.addActionListener(new ChangeMenuToPanelListener(PdfPasswordRemoverPanel.class, pdfPasswordRemoverMenuItem.getText()));
229         pdfMenu.add(pdfPasswordRemoverMenuItem);
230 
231         JMenuItem pic2PdfMenuItem = new JMenuItem(bundle.getString("pictures.to.pdf.title"));
232         pic2PdfMenuItem.addActionListener(new ChangeMenuToPanelListener(Pic2PdfPanel.class, pic2PdfMenuItem.getText()));
233         pdfMenu.add(pic2PdfMenuItem);
234     }
235 
236     private void createFileMenu() {
237         JMenu fileMenu = new JMenu(bundle.getString("file.title"));
238         menuBar.add(fileMenu);
239 
240         JMenuItem osConvertMenuItem = new JMenuItem(bundle.getString("file.os.convert.title"));
241         osConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(OsConvertPanel.class, osConvertMenuItem.getText()));
242         fileMenu.add(osConvertMenuItem);
243 
244         JMenuItem encodeConvertMenuItem = new JMenuItem(bundle.getString("file.encode.convert.title"));
245         encodeConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(EncodeConvertPanel.class, encodeConvertMenuItem.getText()));
246         fileMenu.add(encodeConvertMenuItem);
247 
248         JMenuItem zhConvertMenuItem = new JMenuItem(bundle.getString("file.zh.convert.title"));
249         zhConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(ZhConvertPanel.class, zhConvertMenuItem.getText()));
250         fileMenu.add(zhConvertMenuItem);
251 
252         JMenuItem duplicateFindMenuItem = new JMenuItem(bundle.getString("file.duplicate.title"));
253         duplicateFindMenuItem.addActionListener(new ChangeMenuToPanelListener(DuplicateSearchPanel.class, duplicateFindMenuItem.getText()));
254         fileMenu.add(duplicateFindMenuItem);
255 
256         JMenuItem batchRenameMenuItem = new JMenuItem(bundle.getString("file.batch.rename.title"));
257         batchRenameMenuItem.addActionListener(new ChangeMenuToPanelListener(BatchRenamePanel.class, batchRenameMenuItem.getText()));
258         fileMenu.add(batchRenameMenuItem);
259 
260         JMenuItem checkSumMenuItem = new JMenuItem(bundle.getString("file.check.summary.title"));
261         checkSumMenuItem.addActionListener(new ChangeMenuToPanelListener(ChecksumPanel.class, checkSumMenuItem.getText()));
262         fileMenu.add(checkSumMenuItem);
263 
264         JMenuItem recoveryMenuItem = new JMenuItem(bundle.getString("file.password.recovery.title"));
265         recoveryMenuItem.addActionListener(new ChangeMenuToPanelListener(RecoveryPanel.class, recoveryMenuItem.getText()));
266         fileMenu.add(recoveryMenuItem);
267     }
268 
269     private void createConvertMenu() {
270         JMenu convertMenu = new JMenu(bundle.getString("convert.title"));
271         menuBar.add(convertMenu);
272 
273         JMenuItem timeConvertMenuItem = new JMenuItem(bundle.getString("convert.time.title"));
274         timeConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(TimeConvertPanel.class, timeConvertMenuItem.getText()));
275         convertMenu.add(timeConvertMenuItem);
276 
277         JMenuItem colorConvertMenuItem = new JMenuItem(bundle.getString("convert.color.title"));
278         colorConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(ColorConvertPanel.class, colorConvertMenuItem.getText()));
279         convertMenu.add(colorConvertMenuItem);
280 
281         JMenuItem colorTableMenuItem = new JMenuItem(bundle.getString("table.color.title"));
282         colorTableMenuItem.addActionListener(new ChangeMenuToPanelListener(ColorTablePanel.class, colorTableMenuItem.getText()));
283         convertMenu.add(colorTableMenuItem);
284 
285         JMenuItem colorPickerMenuItem = new JMenuItem(bundle.getString("picker.color.title"));
286         colorPickerMenuItem.addActionListener(new ChangeMenuToPanelListener(ColorPickerPanel.class, colorPickerMenuItem.getText()));
287         convertMenu.add(colorPickerMenuItem);
288 
289         JMenuItem baseConvertMenuItem = new JMenuItem(bundle.getString("convert.base.title"));
290         baseConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(BaseConvertPanel.class, baseConvertMenuItem.getText()));
291         convertMenu.add(baseConvertMenuItem);
292 
293         JMenuItem unicodeConvertMenuItem = new JMenuItem(bundle.getString("convert.unicode.title"));
294         unicodeConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(Zh2UnicodeConvertPanel.class, unicodeConvertMenuItem.getText()));
295         convertMenu.add(unicodeConvertMenuItem);
296 
297         JMenuItem encodingRecoveryMenuItem = new JMenuItem(bundle.getString("garbled.text.recovery.title"));
298         encodingRecoveryMenuItem.addActionListener(new ChangeMenuToPanelListener(GarbledTextRecoveryPanel.class, encodingRecoveryMenuItem.getText()));
299         convertMenu.add(encodingRecoveryMenuItem);
300 
301         JMenuItem asciiViewerMenuItem = new JMenuItem(bundle.getString("ascii.viewer.title"));
302         asciiViewerMenuItem.addActionListener(new ChangeMenuToPanelListener(AsciiGbViewerPanel.class, asciiViewerMenuItem.getText()));
303         convertMenu.add(asciiViewerMenuItem);
304 
305         JMenuItem relationShipConvertMenuItem = new JMenuItem(bundle.getString("convert.relationship.title"));
306         relationShipConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(RelationShipConvertPanel.class, relationShipConvertMenuItem.getText()));
307         convertMenu.add(relationShipConvertMenuItem);
308 
309         JMenuItem unsupervisedProtobufConvertMenuItem = new JMenuItem(bundle.getString("convert.protobuf.unsupervised.title"));
310         unsupervisedProtobufConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(UnsupervisedProtobufConvertPanel.class, unsupervisedProtobufConvertMenuItem.getText()));
311         convertMenu.add(unsupervisedProtobufConvertMenuItem);
312 
313         JMenuItem supervisedProtobufConvertMenuItem = new JMenuItem(bundle.getString("convert.protobuf.supervised.title"));
314         supervisedProtobufConvertMenuItem.addActionListener(new ChangeMenuToPanelListener(SupervisedProtobufConvertPanel.class, supervisedProtobufConvertMenuItem.getText()));
315         convertMenu.add(supervisedProtobufConvertMenuItem);
316     }
317 
318     private void createAndroidMenu() {
319         JMenu androidMenu = new JMenu(bundle.getString("android.title"));
320         menuBar.add(androidMenu);
321 
322         JMenuItem i18nAddMenuItem = new JMenuItem(bundle.getString("android.i18n.add.title"));
323         i18nAddMenuItem.addActionListener(new ChangeMenuToPanelListener(I18nAddPanel.class, i18nAddMenuItem.getText()));
324         androidMenu.add(i18nAddMenuItem);
325 
326         JMenuItem i18nFindLongestMenuItem = new JMenuItem(bundle.getString("android.i18n.longest.title"));
327         i18nFindLongestMenuItem.addActionListener(new ChangeMenuToPanelListener(I18nFindLongestPanel.class, i18nFindLongestMenuItem.getText()));
328         androidMenu.add(i18nFindLongestMenuItem);
329 
330         JMenuItem i18nRemoveMenuItem = new JMenuItem(bundle.getString("android.i18n.remove.title"));
331         i18nRemoveMenuItem.addActionListener(new ChangeMenuToPanelListener(I18nRemovePanel.class, i18nRemoveMenuItem.getText()));
332         androidMenu.add(i18nRemoveMenuItem);
333 
334         JMenuItem screenShotMenuItem = new JMenuItem(bundle.getString("android.screenshot.title"));
335         screenShotMenuItem.addActionListener(new ChangeMenuToPanelListener(ScreenShotPanel.class, screenShotMenuItem.getText()));
336         screenShotMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK));
337         androidMenu.add(screenShotMenuItem);
338 
339         JMenuItem monkeyMenuItem = new JMenuItem(bundle.getString("android.monkey.title"));
340         monkeyMenuItem.addActionListener(new ChangeMenuToPanelListener(MonkeyPanel.class, monkeyMenuItem.getText()));
341         androidMenu.add(monkeyMenuItem);
342 
343         JMenuItem dumpsysMenuItem = new JMenuItem(bundle.getString("android.dumpsys.title"));
344         dumpsysMenuItem.addActionListener(new ChangeMenuToPanelListener(DumpsysPanel.class, dumpsysMenuItem.getText()));
345         androidMenu.add(dumpsysMenuItem);
346     }
347 
348     private void createReverseMenu() {
349         JMenu reverseMenu = new JMenu(bundle.getString("reverse.title"));
350         reverseMenu.setMnemonic(KeyEvent.VK_R);
351         menuBar.add(reverseMenu);
352 
353         JMenuItem pluginVersionMenuItem = new JMenuItem(bundle.getString("reverse.plugin.version.title"));
354         pluginVersionMenuItem.addActionListener(new ChangeMenuToUrlListener(Constant.URL_PLUGIN_VERSION));
355         reverseMenu.add(pluginVersionMenuItem);
356 
357         JMenuItem apktoolMenuItem = new JMenuItem(bundle.getString("reverse.apktool.title"), KeyEvent.VK_D);
358         apktoolMenuItem.addActionListener(new ChangeMenuToPanelListener(ApktoolPanel.class, apktoolMenuItem.getText()));
359         reverseMenu.add(apktoolMenuItem);
360 
361         JMenuItem apkSignMenuItem = new JMenuItem(bundle.getString("reverse.apksigner.title"));
362         apkSignMenuItem.addActionListener(new ChangeMenuToPanelListener(ApkSignerPanel.class, apkSignMenuItem.getText()));
363         reverseMenu.add(apkSignMenuItem);
364 
365         JMenuItem jDMenuItem = new JMenuItem(bundle.getString("reverse.jd.gui.title"));
366         jDMenuItem.addActionListener(new ChangeMenToPluginJdListener());
367         reverseMenu.add(jDMenuItem);
368 
369         JMenuItem bytecodeViewerMenuItem = new JMenuItem(bundle.getString("reverse.bytecode.viewer.title"));
370         bytecodeViewerMenuItem.addActionListener(new ChangeMenuToPluginBytecodeViewerListener());
371         reverseMenu.add(bytecodeViewerMenuItem);
372 
373         JMenuItem luytenMenuItem = new JMenuItem(bundle.getString("reverse.luyten.title"));
374         luytenMenuItem.addActionListener(new ChangeMenuToPluginLuytenListener());
375         reverseMenu.add(luytenMenuItem);
376 
377         JMenuItem jdDuoMenuItem = new JMenuItem(bundle.getString("reverse.jd.duo.title"));
378         jdDuoMenuItem.addActionListener(new ChangeMenuToPluginJdDuoListener());
379         reverseMenu.add(jdDuoMenuItem);
380 
381         JMenuItem jdaMenuItem = new JMenuItem(bundle.getString("reverse.jda.title"));
382         jdaMenuItem.addActionListener(new ChangeMenuToPluginJdaListener());
383         reverseMenu.add(jdaMenuItem);
384 
385         JMenuItem jADXMenuItem = new JMenuItem(bundle.getString("reverse.jadx.title"));
386         jADXMenuItem.addActionListener(new ChangeMenuToPluginJadxListener());
387         reverseMenu.add(jADXMenuItem);
388 
389         JMenuItem aXMLPrinter = new JMenuItem(bundle.getString("reverse.axmlprinter.title"));
390         aXMLPrinter.addActionListener(new ChangeMenuToPanelListener(AxmlPrinterPanel.class, aXMLPrinter.getText()));
391         reverseMenu.add(aXMLPrinter);
392     }
393 
394     class ChangeMenuToPanelListener implements ChangeMenuListener {
395 
396         Class<? extends EasyPanel> easyPanelClass;
397 
398         EasyPanel panel = null;
399 
400         String title;
401 
402         public ChangeMenuToPanelListener(Class<? extends EasyPanel> easyPanelClass, String title) {
403             this.easyPanelClass = easyPanelClass;
404             this.title = title;
405             panel = createEasyPanel();
406         }
407 
408         @Override
409         public boolean isNeedPreChangeMenu() {
410             return panel.isNeedPreChangeMenu();
411         }
412 
413         @Override
414         public void onPreChangeMenu(IPreChangeMenuCallBack callBack) {
415             if (panel instanceof PluginPanel pluginPanel) {
416                 pluginPanel.preparePlugin(new ChangeMenuPreparePluginController(pluginPanel.getPluginFilename(), pluginPanel.isPluginNeedUnzip(), pluginPanel.isPluginNeedUnzipToSeparateDir(), callBack));
417             }
418         }
419 
420         @Override
421         public void onChangeMenu() {
422             UiStateKeeper.save(currentEasyPanel);
423             contentPane.removeAll();
424             contentPane.add(Box.createVerticalGlue());
425             panel.init();
426             panel.setBorder(BorderFactory.createTitledBorder(title));
427             contentPane.add(panel);
428             logger.info("Panel changed: " + panel.getClass().getSimpleName());
429             contentPane.add(Box.createVerticalGlue());
430             contentPane.revalidate();
431             contentPane.repaint();
432             refreshSizeAndLocation();
433             panel.afterPainted();
434             UiStateKeeper.restore(panel);
435             currentEasyPanel = panel;
436         }
437 
438         private EasyPanel createEasyPanel() {
439             if (easyPanelClass == null) {
440                 return new EasyPanel();
441             }
442             EasyPanel retEasyPanel = null;
443             try {
444                 retEasyPanel = easyPanelClass.getDeclaredConstructor().newInstance();
445             } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
446                      NoSuchMethodException e) {
447                 logger.info("createEasyPanel failed: {}", e.getMessage());
448             }
449             return Objects.requireNonNullElseGet(retEasyPanel, EasyPanel::new);
450         }
451     }
452 
453     @Override
454     protected void onWindowClosing(WindowEvent e) {
455         super.onWindowClosing(e);
456         UiStateKeeper.save(currentEasyPanel);
457     }
458 
459     @Override
460     protected void onWindowIconified(WindowEvent e) {
461         super.onWindowIconified(e);
462         UiStateKeeper.save(currentEasyPanel);
463     }
464 }