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