1 /*
2  * Copyright (c) 2016 Helmut Neemann
3  * Use of this source code is governed by the GPL v3 license
4  * that can be found in the LICENSE file.
5  */
6 package de.neemann.gui;
7 
8 import de.neemann.digital.lang.Lang;
9 
10 import javax.swing.*;
11 import java.awt.*;
12 import java.awt.event.WindowAdapter;
13 import java.awt.event.WindowEvent;
14 
15 /**
16  * Frame needs to be set to DO_NOTHING_ON_CLOSE to work.
17  * Closing should by done by the {@link GUICloser#closeGUI()}.
18  */
19 public class ClosingWindowListener extends WindowAdapter {
20     private final static String SAVE_CHANGES_MESSAGE = Lang.get("win_saveChanges");
21     private final static String CONFIRM_EXIT_MESSAGE = Lang.get("win_confirmExit");
22     private final static String STATE_CHANGED_MESSAGE = Lang.get("win_stateChanged");
23     private final static String NO_MESSAGE = Lang.get("btn_discard");
24     private final static String YES_MESSAGE = Lang.get("btn_save");
25     private final static String CANCEL_MESSAGE = Lang.get("btn_editFurther");
26     private final Component parent;
27     private final GUICloser guiCloser;
28 
29     /**
30      * Create a new Instance
31      *
32      * @param parent      the parent component of the confirm dialog
33      * @param confirmSave the ConfirmSave interface
34      */
ClosingWindowListener(final JFrame parent, final ConfirmSave confirmSave)35     public ClosingWindowListener(final JFrame parent, final ConfirmSave confirmSave) {
36         this(parent, confirmSave, true);
37     }
38 
39     /**
40      * Create a new Instance
41      *
42      * @param parent      the parent component of the confirm dialog
43      * @param confirmSave the ConfirmSave interface
44      * @param doExit      if true the parent JFrame is disposed by this listener
45      */
ClosingWindowListener(final JFrame parent, final ConfirmSave confirmSave, final boolean doExit)46     private ClosingWindowListener(final JFrame parent, final ConfirmSave confirmSave, final boolean doExit) {
47         this((Component) parent, new GUICloser() {
48             @Override
49             public void closeGUI() {
50                 if (doExit) {
51                     parent.dispose();
52                 }
53             }
54 
55             @Override
56             public boolean isStateChanged() {
57                 return confirmSave.isStateChanged();
58             }
59 
60             @Override
61             public void saveChanges() {
62                 confirmSave.saveChanges();
63             }
64         });
65     }
66 
67     /**
68      * Used to check for save! No Window closing is performed!
69      *
70      * @param parent      the Parent frame
71      * @param confirmSave the confirmSafe interface
72      * @return true if to proceed
73      */
checkForSave(JFrame parent, ConfirmSave confirmSave)74     public static boolean checkForSave(JFrame parent, ConfirmSave confirmSave) {
75         if (confirmSave.isStateChanged()) {
76             int r = new ConfirmDialogBuilder(SAVE_CHANGES_MESSAGE)
77                     .setTitle(STATE_CHANGED_MESSAGE)
78                     .setNoOption(NO_MESSAGE)
79                     .setYesOption(YES_MESSAGE)
80                     .setCancleOption(CANCEL_MESSAGE)
81                     .show(parent);
82 
83             if (r == JOptionPane.YES_OPTION || r == JOptionPane.NO_OPTION) {
84                 if (r == JOptionPane.YES_OPTION) {
85                     confirmSave.saveChanges();
86                     return !confirmSave.isStateChanged();
87                 } else
88                     return true;
89             } else
90                 return false;
91         }
92         return true;
93     }
94 
95     /**
96      * Create a new Instance
97      *
98      * @param parent    the parent component of the confirm dialog
99      * @param guiCloser the guiCloser
100      */
ClosingWindowListener(Component parent, GUICloser guiCloser)101     private ClosingWindowListener(Component parent, GUICloser guiCloser) {
102         this.parent = parent;
103         this.guiCloser = guiCloser;
104     }
105 
106     @Override
windowClosing(WindowEvent e)107     public void windowClosing(WindowEvent e) {
108         if (guiCloser.isStateChanged()) {
109             int r = new ConfirmDialogBuilder(SAVE_CHANGES_MESSAGE)
110                     .setTitle(CONFIRM_EXIT_MESSAGE)
111                     .setNoOption(NO_MESSAGE)
112                     .setYesOption(YES_MESSAGE)
113                     .setCancleOption(CANCEL_MESSAGE)
114                     .show(parent);
115 
116             if (r == JOptionPane.YES_OPTION || r == JOptionPane.NO_OPTION) {
117                 if (r == JOptionPane.YES_OPTION) {
118                     guiCloser.saveChanges();
119                     if (!guiCloser.isStateChanged())
120                         guiCloser.closeGUI();
121                 } else
122                     guiCloser.closeGUI();
123             }
124         } else {
125             guiCloser.closeGUI();
126         }
127     }
128 
129     /**
130      * Interface to control the gui closing
131      */
132     public interface ConfirmSave {
133         /**
134          * @return true is state is changed and there is something to save
135          */
isStateChanged()136         boolean isStateChanged();
137 
138         /**
139          * save changes
140          */
saveChanges()141         void saveChanges();
142 
143     }
144 
145     /**
146      * Interface to control the gui closing
147      */
148     public interface GUICloser extends ConfirmSave {
149 
150         /**
151          * Close the GUI
152          */
closeGUI()153         void closeGUI();
154     }
155 
156 }
157