source: josm/trunk/src/org/openstreetmap/josm/gui/dialogs/ConflictResolutionDialog.java@ 5998

Last change on this file since 5998 was 5998, checked in by Don-vip, 11 years ago

fix #8775 - IllegalComponentStateException when remembering position of dialogs not displayed on screen

  • Property svn:eol-style set to native
File size: 7.9 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.dialogs;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.BorderLayout;
8import java.awt.Component;
9import java.awt.Dimension;
10import java.awt.FlowLayout;
11import java.awt.event.ActionEvent;
12import java.beans.PropertyChangeEvent;
13import java.beans.PropertyChangeListener;
14
15import javax.swing.AbstractAction;
16import javax.swing.Action;
17import javax.swing.BorderFactory;
18import javax.swing.JButton;
19import javax.swing.JDialog;
20import javax.swing.JOptionPane;
21import javax.swing.JPanel;
22import javax.swing.WindowConstants;
23
24import org.openstreetmap.josm.Main;
25import org.openstreetmap.josm.command.Command;
26import org.openstreetmap.josm.data.osm.OsmPrimitive;
27import org.openstreetmap.josm.gui.DefaultNameFormatter;
28import org.openstreetmap.josm.gui.conflict.pair.ConflictResolver;
29import org.openstreetmap.josm.gui.help.HelpBrowser;
30import org.openstreetmap.josm.gui.help.HelpUtil;
31import org.openstreetmap.josm.tools.ImageProvider;
32import org.openstreetmap.josm.tools.WindowGeometry;
33
34/**
35 * This is an extended dialog for resolving conflict between {@link OsmPrimitive}s.
36 *
37 */
38public class ConflictResolutionDialog extends JDialog implements PropertyChangeListener {
39 /** the conflict resolver component */
40 private ConflictResolver resolver;
41
42 private ApplyResolutionAction applyResolutionAction;
43
44 @Override
45 public void removeNotify() {
46 super.removeNotify();
47 unregisterListeners();
48 }
49
50 @Override
51 public void setVisible(boolean isVisible) {
52 String geom = getClass().getName() + ".geometry";
53 if (isVisible){
54 toFront();
55 new WindowGeometry(geom, WindowGeometry.centerInWindow(Main.parent,
56 new Dimension(600, 400))).applySafe(this);
57 } else {
58 if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
59 new WindowGeometry(this).remember(geom);
60 }
61 unregisterListeners();
62 }
63 super.setVisible(isVisible);
64 }
65
66 private void closeDialog() {
67 setVisible(false);
68 dispose();
69 }
70
71 /**
72 * builds the sub panel with the control buttons
73 *
74 * @return the panel
75 */
76 protected JPanel buildButtonRow() {
77 JPanel pnl = new JPanel();
78 pnl.setLayout(new FlowLayout(FlowLayout.CENTER));
79
80 applyResolutionAction = new ApplyResolutionAction();
81 JButton btn = new JButton(applyResolutionAction);
82 btn.setName("button.apply");
83 pnl.add(btn);
84
85 btn = new JButton(new CancelAction());
86 btn.setName("button.cancel");
87 pnl.add(btn);
88
89 btn = new JButton(new HelpAction());
90 btn.setName("button.help");
91 pnl.add(btn);
92
93 pnl.setBorder(BorderFactory.createLoweredBevelBorder());
94 return pnl;
95 }
96
97 private void registerListeners() {
98 resolver.addPropertyChangeListener(applyResolutionAction);
99 }
100
101 private void unregisterListeners() {
102 resolver.removePropertyChangeListener(applyResolutionAction);
103 resolver.unregisterListeners();
104 }
105
106 /**
107 * builds the GUI
108 */
109 protected void build() {
110 setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
111 updateTitle();
112 getContentPane().setLayout(new BorderLayout());
113
114 resolver = new ConflictResolver();
115 resolver.setName("panel.conflictresolver");
116 getContentPane().add(resolver, BorderLayout.CENTER);
117 getContentPane().add(buildButtonRow(), BorderLayout.SOUTH);
118
119 resolver.addPropertyChangeListener(this);
120 HelpUtil.setHelpContext(this.getRootPane(), ht("Dialog/Conflict"));
121
122 registerListeners();
123 }
124
125 public ConflictResolutionDialog(Component parent) {
126 super(JOptionPane.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
127 build();
128 }
129
130 public ConflictResolver getConflictResolver() {
131 return resolver;
132 }
133
134 /**
135 * Action for canceling conflict resolution
136 */
137 class CancelAction extends AbstractAction {
138 public CancelAction() {
139 putValue(Action.SHORT_DESCRIPTION, tr("Cancel conflict resolution and close the dialog"));
140 putValue(Action.NAME, tr("Cancel"));
141 putValue(Action.SMALL_ICON, ImageProvider.get("", "cancel"));
142 setEnabled(true);
143 }
144
145 public void actionPerformed(ActionEvent arg0) {
146 closeDialog();
147 }
148 }
149
150 /**
151 * Action for canceling conflict resolution
152 */
153 static class HelpAction extends AbstractAction {
154 public HelpAction() {
155 putValue(Action.SHORT_DESCRIPTION, tr("Show help information"));
156 putValue(Action.NAME, tr("Help"));
157 putValue(Action.SMALL_ICON, ImageProvider.get("help"));
158 setEnabled(true);
159 }
160
161 public void actionPerformed(ActionEvent arg0) {
162 HelpBrowser.setUrlForHelpTopic(ht("/Dialog/Conflict"));
163 }
164 }
165
166 /**
167 * Action for applying resolved differences in a conflict
168 *
169 */
170 class ApplyResolutionAction extends AbstractAction implements PropertyChangeListener {
171 public ApplyResolutionAction() {
172 putValue(Action.SHORT_DESCRIPTION, tr("Apply resolved conflicts and close the dialog"));
173 putValue(Action.NAME, tr("Apply Resolution"));
174 putValue(Action.SMALL_ICON, ImageProvider.get("dialogs", "conflict"));
175 updateEnabledState();
176 }
177
178 protected void updateEnabledState() {
179 setEnabled(resolver.isResolvedCompletely());
180 }
181
182 public void actionPerformed(ActionEvent arg0) {
183 if (! resolver.isResolvedCompletely()) {
184 Object[] options = {
185 tr("Close anyway"),
186 tr("Continue resolving")};
187 int ret = JOptionPane.showOptionDialog(Main.parent,
188 tr("<html>You did not finish to merge the differences in this conflict.<br>"
189 + "Conflict resolutions will not be applied unless all differences<br>"
190 + "are resolved.<br>"
191 + "Click <strong>{0}</strong> to close anyway.<strong> Already<br>"
192 + "resolved differences will not be applied.</strong><br>"
193 + "Click <strong>{1}</strong> to return to resolving conflicts.</html>"
194 , options[0].toString(), options[1].toString()
195 ),
196 tr("Conflict not resolved completely"),
197 JOptionPane.YES_NO_OPTION,
198 JOptionPane.WARNING_MESSAGE,
199 null,
200 options,
201 options[1]
202 );
203 switch(ret) {
204 case JOptionPane.YES_OPTION:
205 closeDialog();
206 break;
207 default:
208 return;
209 }
210 }
211 Command cmd = resolver.buildResolveCommand();
212 Main.main.undoRedo.add(cmd);
213 closeDialog();
214 }
215
216 public void propertyChange(PropertyChangeEvent evt) {
217 if (evt.getPropertyName().equals(ConflictResolver.RESOLVED_COMPLETELY_PROP)) {
218 updateEnabledState();
219 }
220 }
221 }
222
223 protected void updateTitle() {
224 updateTitle(null);
225 }
226
227 protected void updateTitle(OsmPrimitive my) {
228 if (my == null) {
229 setTitle(tr("Resolve conflicts"));
230 } else {
231 setTitle(tr("Resolve conflicts for ''{0}''", my.getDisplayName(DefaultNameFormatter.getInstance())));
232 }
233 }
234
235 public void propertyChange(PropertyChangeEvent evt) {
236 if (evt.getPropertyName().equals(ConflictResolver.MY_PRIMITIVE_PROP)) {
237 updateTitle((OsmPrimitive)evt.getNewValue());
238 }
239 }
240}
Note: See TracBrowser for help on using the repository browser.