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