source: josm/trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java@ 11057

Last change on this file since 11057 was 10957, checked in by Don-vip, 8 years ago

see #13479 - make ConflictResolutionDialog inherit from ExtendedDialog

  • Property svn:eol-style set to native
File size: 23.8 KB
RevLine 
[3719]1// License: GPL. For details, see LICENSE file.
[1373]2package org.openstreetmap.josm.gui;
3
[2031]4import static org.openstreetmap.josm.tools.I18n.tr;
5
[1373]6import java.awt.Component;
7import java.awt.Dimension;
[10649]8import java.awt.Frame;
[3403]9import java.awt.GridBagConstraints;
[1373]10import java.awt.GridBagLayout;
[3403]11import java.awt.Insets;
[1811]12import java.awt.event.ActionEvent;
[7545]13import java.awt.event.KeyEvent;
[1427]14import java.util.ArrayList;
[3403]15import java.util.Arrays;
16import java.util.Collections;
[8390]17import java.util.HashSet;
[3403]18import java.util.List;
[8390]19import java.util.Set;
[1373]20
21import javax.swing.AbstractAction;
22import javax.swing.Action;
[3403]23import javax.swing.Icon;
[1373]24import javax.swing.JButton;
25import javax.swing.JDialog;
[3403]26import javax.swing.JLabel;
[1373]27import javax.swing.JOptionPane;
28import javax.swing.JPanel;
[1397]29import javax.swing.JScrollBar;
[1373]30import javax.swing.JScrollPane;
31import javax.swing.KeyStroke;
[3403]32import javax.swing.UIManager;
[1373]33
[7434]34import org.openstreetmap.josm.Main;
[2715]35import org.openstreetmap.josm.gui.help.HelpBrowser;
[2301]36import org.openstreetmap.josm.gui.help.HelpUtil;
[7401]37import org.openstreetmap.josm.gui.util.GuiHelper;
[6340]38import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
[7434]39import org.openstreetmap.josm.io.OnlineResource;
[1373]40import org.openstreetmap.josm.tools.GBC;
41import org.openstreetmap.josm.tools.ImageProvider;
[10791]42import org.openstreetmap.josm.tools.InputMapUtils;
[6221]43import org.openstreetmap.josm.tools.Utils;
[2138]44import org.openstreetmap.josm.tools.WindowGeometry;
[1373]45
[3403]46/**
47 * General configurable dialog window.
48 *
[5275]49 * If dialog is modal, you can use {@link #getValue()} to retrieve the
[3403]50 * button index. Note that the user can close the dialog
51 * by other means. This is usually equivalent to cancel action.
52 *
[5275]53 * For non-modal dialogs, {@link #buttonAction(int, ActionEvent)} can be overridden.
[3403]54 *
55 * There are various options, see below.
56 *
57 * Note: The button indices are counted from 1 and upwards.
[6070]58 * So for {@link #getValue()}, {@link #setDefaultButton(int)} and
[5275]59 * {@link #setCancelButton} the first button has index 1.
[6070]60 *
[4246]61 * Simple example:
[5275]62 * <pre>
[4246]63 * ExtendedDialog ed = new ExtendedDialog(
64 * Main.parent, tr("Dialog Title"),
65 * new String[] {tr("Ok"), tr("Cancel")});
66 * ed.setButtonIcons(new String[] {"ok", "cancel"}); // optional
67 * ed.setIcon(JOptionPane.WARNING_MESSAGE); // optional
68 * ed.setContent(tr("Really proceed? Interesting things may happen..."));
69 * ed.showDialog();
70 * if (ed.getValue() == 1) { // user clicked first button "Ok"
71 * // proceed...
72 * }
[5275]73 * </pre>
[3403]74 */
[1373]75public class ExtendedDialog extends JDialog {
[3351]76 private final boolean disposeOnClose;
[8840]77 private volatile int result;
[2031]78 public static final int DialogClosedOtherwise = 0;
[8840]79 private boolean toggleable;
[2138]80 private String rememberSizePref = "";
[8840]81 private transient WindowGeometry defaultWindowGeometry;
[2031]82 private String togglePref = "";
[2718]83 private int toggleValue = -1;
[6594]84 private ConditionalOptionPaneUtil.MessagePanel togglePanel;
[1427]85 private Component parent;
[2031]86 private Component content;
[1373]87 private final String[] bTexts;
[2285]88 private String[] bToolTipTexts;
[8308]89 private transient Icon[] bIcons;
[8399]90 private Set<Integer> cancelButtonIdx = Collections.emptySet();
[3403]91 private int defaultButtonIdx = 1;
[8840]92 protected JButton defaultButton;
[8308]93 private transient Icon icon;
[3403]94 private boolean modal;
[8840]95 private boolean focusOnDefaultButton;
[2285]96
97 /** true, if the dialog should include a help button */
98 private boolean showHelpButton;
99 /** the help topic */
100 private String helpTopic;
101
[2035]102 /**
103 * set to true if the content of the extended dialog should
[5266]104 * be placed in a {@link JScrollPane}
[2035]105 */
106 private boolean placeContentInScrollPane;
[1432]107
[1427]108 // For easy access when inherited
[8510]109 protected transient Insets contentInsets = new Insets(10, 5, 0, 5);
[8399]110 protected List<JButton> buttons = new ArrayList<>();
[1432]111
[1373]112 /**
[3675]113 * This method sets up the most basic options for the dialog. Add more
[2031]114 * advanced features with dedicated methods.
115 * Possible features:
116 * <ul>
117 * <li><code>setButtonIcons</code></li>
118 * <li><code>setContent</code></li>
119 * <li><code>toggleEnable</code></li>
120 * <li><code>toggleDisable</code></li>
121 * <li><code>setToggleCheckboxText</code></li>
[2138]122 * <li><code>setRememberWindowGeometry</code></li>
[2031]123 * </ul>
[2512]124 *
[2031]125 * When done, call <code>showDialog</code> to display it. You can receive
126 * the user's choice using <code>getValue</code>. Have a look at this function
127 * for possible return values.
[2512]128 *
[2031]129 * @param parent The parent element that will be used for position and maximum size
130 * @param title The text that will be shown in the window titlebar
131 * @param buttonTexts String Array of the text that will appear on the buttons. The first button is the default one.
132 */
[10680]133 public ExtendedDialog(Component parent, String title, String ... buttonTexts) {
[3351]134 this(parent, title, buttonTexts, true, true);
[2031]135 }
136
137 /**
138 * Same as above but lets you define if the dialog should be modal.
[6221]139 * @param parent The parent element that will be used for position and maximum size
140 * @param title The text that will be shown in the window titlebar
141 * @param buttonTexts String Array of the text that will appear on the buttons. The first button is the default one.
142 * @param modal Set it to {@code true} if you want the dialog to be modal
[2031]143 */
[6221]144 public ExtendedDialog(Component parent, String title, String[] buttonTexts, boolean modal) {
[3351]145 this(parent, title, buttonTexts, modal, true);
146 }
147
[10957]148 /**
149 * Same as above but lets you define if the dialog should be disposed on close.
150 * @param parent The parent element that will be used for position and maximum size
151 * @param title The text that will be shown in the window titlebar
152 * @param buttonTexts String Array of the text that will appear on the buttons. The first button is the default one.
153 * @param modal Set it to {@code true} if you want the dialog to be modal
154 * @param disposeOnClose whether to call {@link #dispose} when closing the dialog
155 */
[6221]156 public ExtendedDialog(Component parent, String title, String[] buttonTexts, boolean modal, boolean disposeOnClose) {
[10649]157 super(searchRealParent(parent), title, modal ? ModalityType.DOCUMENT_MODAL : ModalityType.MODELESS);
[2031]158 this.parent = parent;
[3403]159 this.modal = modal;
[6221]160 bTexts = Utils.copyArray(buttonTexts);
[3351]161 if (disposeOnClose) {
162 setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
163 }
164 this.disposeOnClose = disposeOnClose;
[2031]165 }
166
[10649]167 private static Frame searchRealParent(Component parent) {
168 if (parent == null) {
169 return null;
170 } else {
171 return GuiHelper.getFrameForComponent(parent);
172 }
173 }
174
[2031]175 /**
[3403]176 * Allows decorating the buttons with icons.
[6221]177 * @param buttonIcons The button icons
178 * @return {@code this}
[2031]179 */
[10680]180 public ExtendedDialog setButtonIcons(Icon ... buttonIcons) {
[6221]181 this.bIcons = Utils.copyArray(buttonIcons);
[2602]182 return this;
[1373]183 }
[1432]184
[2031]185 /**
[3403]186 * Convenience method to provide image names instead of images.
[6221]187 * @param buttonIcons The button icon names
188 * @return {@code this}
[3403]189 */
[10680]190 public ExtendedDialog setButtonIcons(String ... buttonIcons) {
[3403]191 bIcons = new Icon[buttonIcons.length];
[8510]192 for (int i = 0; i < buttonIcons.length; ++i) {
[3403]193 bIcons[i] = ImageProvider.get(buttonIcons[i]);
194 }
195 return this;
196 }
197
198 /**
[5275]199 * Allows decorating the buttons with tooltips. Expects a String array with
200 * translated tooltip texts.
[2512]201 *
[2285]202 * @param toolTipTexts the tool tip texts. Ignored, if null.
[6221]203 * @return {@code this}
[2285]204 */
[10680]205 public ExtendedDialog setToolTipTexts(String ... toolTipTexts) {
[6221]206 this.bToolTipTexts = Utils.copyArray(toolTipTexts);
[2602]207 return this;
[2285]208 }
209
210 /**
[2031]211 * Sets the content that will be displayed in the message dialog.
[2512]212 *
[2031]213 * Note that depending on your other settings more UI elements may appear.
214 * The content is played on top of the other elements though.
[2512]215 *
[2031]216 * @param content Any element that can be displayed in the message dialog
[6221]217 * @return {@code this}
[2031]218 */
[2602]219 public ExtendedDialog setContent(Component content) {
220 return setContent(content, true);
[2035]221 }
222
223 /**
224 * Sets the content that will be displayed in the message dialog.
[2512]225 *
[2035]226 * Note that depending on your other settings more UI elements may appear.
227 * The content is played on top of the other elements though.
[2512]228 *
[2035]229 * @param content Any element that can be displayed in the message dialog
[7545]230 * @param placeContentInScrollPane if true, places the content in a JScrollPane
[6221]231 * @return {@code this}
[2035]232 */
[2602]233 public ExtendedDialog setContent(Component content, boolean placeContentInScrollPane) {
[2031]234 this.content = content;
[2035]235 this.placeContentInScrollPane = placeContentInScrollPane;
[2602]236 return this;
[1397]237 }
[1432]238
[1427]239 /**
[2031]240 * Sets the message that will be displayed. The String will be automatically
241 * wrapped if it is too long.
[2512]242 *
[2031]243 * Note that depending on your other settings more UI elements may appear.
244 * The content is played on top of the other elements though.
[2512]245 *
[2031]246 * @param message The text that should be shown to the user
[6221]247 * @return {@code this}
[1427]248 */
[2602]249 public ExtendedDialog setContent(String message) {
250 return setContent(string2label(message), false);
[1427]251 }
[1432]252
[2031]253 /**
[3403]254 * Decorate the dialog with an icon that is shown on the left part of
[5275]255 * the window area. (Similar to how it is done in {@link JOptionPane})
[6221]256 * @param icon The icon to display
257 * @return {@code this}
[3403]258 */
259 public ExtendedDialog setIcon(Icon icon) {
260 this.icon = icon;
261 return this;
262 }
263
264 /**
[5275]265 * Convenience method to allow values that would be accepted by {@link JOptionPane} as messageType.
[6221]266 * @param messageType The {@link JOptionPane} messageType
267 * @return {@code this}
[3403]268 */
269 public ExtendedDialog setIcon(int messageType) {
270 switch (messageType) {
271 case JOptionPane.ERROR_MESSAGE:
272 return setIcon(UIManager.getIcon("OptionPane.errorIcon"));
273 case JOptionPane.INFORMATION_MESSAGE:
274 return setIcon(UIManager.getIcon("OptionPane.informationIcon"));
275 case JOptionPane.WARNING_MESSAGE:
276 return setIcon(UIManager.getIcon("OptionPane.warningIcon"));
277 case JOptionPane.QUESTION_MESSAGE:
278 return setIcon(UIManager.getIcon("OptionPane.questionIcon"));
279 case JOptionPane.PLAIN_MESSAGE:
280 return setIcon(null);
281 default:
282 throw new IllegalArgumentException("Unknown message type!");
283 }
284 }
285
286 /**
[2031]287 * Show the dialog to the user. Call this after you have set all options
[5275]288 * for the dialog. You can retrieve the result using {@link #getValue()}.
[6221]289 * @return {@code this}
[2031]290 */
[2602]291 public ExtendedDialog showDialog() {
[2031]292 // Check if the user has set the dialog to not be shown again
[6443]293 if (toggleCheckState()) {
[2718]294 result = toggleValue;
[2602]295 return this;
[2031]296 }
297
298 setupDialog();
[2627]299 if (defaultButton != null) {
300 getRootPane().setDefaultButton(defaultButton);
301 }
[7407]302 // Don't focus the "do not show this again" check box, but the default button.
303 if (toggleable || focusOnDefaultButton) {
304 requestFocusToDefaultButton();
305 }
[2031]306 setVisible(true);
307 toggleSaveState();
[2602]308 return this;
[2031]309 }
310
311 /**
[5275]312 * Retrieve the user choice after the dialog has been closed.
[6070]313 *
[5275]314 * @return <ul> <li>The selected button. The count starts with 1.</li>
315 * <li>A return value of {@link #DialogClosedOtherwise} means the dialog has been closed otherwise.</li>
316 * </ul>
[2031]317 */
318 public int getValue() {
319 return result;
320 }
321
[8840]322 private boolean setupDone;
[2711]323
[2662]324 /**
[5275]325 * This is called by {@link #showDialog()}.
[2662]326 * Only invoke from outside if you need to modify the contentPane
327 */
328 public void setupDialog() {
329 if (setupDone)
330 return;
331 setupDone = true;
332
[1397]333 setupEscListener();
[1432]334
[1373]335 JButton button;
336 JPanel buttonsPanel = new JPanel(new GridBagLayout());
[1432]337
[8510]338 for (int i = 0; i < bTexts.length; i++) {
[10957]339 button = new JButton(createButtonAction(i));
[2627]340 if (i == defaultButtonIdx-1) {
341 defaultButton = button;
342 }
[8510]343 if (bIcons != null && bIcons[i] != null) {
[3403]344 button.setIcon(bIcons[i]);
[1790]345 }
[2285]346 if (bToolTipTexts != null && i < bToolTipTexts.length && bToolTipTexts[i] != null) {
347 button.setToolTipText(bToolTipTexts[i]);
348 }
[1432]349
[8510]350 buttonsPanel.add(button, GBC.std().insets(2, 2, 2, 2));
[1427]351 buttons.add(button);
[1373]352 }
[2285]353 if (showHelpButton) {
[8510]354 buttonsPanel.add(new JButton(new HelpAction()), GBC.std().insets(2, 2, 2, 2));
355 HelpUtil.setHelpContext(getRootPane(), helpTopic);
[2285]356 }
[1432]357
358 JPanel cp = new JPanel(new GridBagLayout());
[2031]359
[3403]360 GridBagConstraints gc = new GridBagConstraints();
361 gc.gridx = 0;
362 int y = 0;
363 gc.gridy = y++;
364 gc.weightx = 0.0;
365 gc.weighty = 0.0;
366
367 if (icon != null) {
368 JLabel iconLbl = new JLabel(icon);
[8510]369 gc.insets = new Insets(10, 10, 10, 10);
[3403]370 gc.anchor = GridBagConstraints.NORTH;
[3404]371 gc.weighty = 1.0;
[3403]372 cp.add(iconLbl, gc);
373 gc.anchor = GridBagConstraints.CENTER;
374 gc.gridx = 1;
375 }
376
377 gc.fill = GridBagConstraints.BOTH;
378 gc.insets = contentInsets;
[3404]379 gc.weightx = 1.0;
380 gc.weighty = 1.0;
[3403]381 cp.add(content, gc);
382
383 gc.fill = GridBagConstraints.NONE;
384 gc.gridwidth = GridBagConstraints.REMAINDER;
[3404]385 gc.weightx = 0.0;
386 gc.weighty = 0.0;
[3403]387
388 if (toggleable) {
[6595]389 togglePanel = new ConditionalOptionPaneUtil.MessagePanel(null, ConditionalOptionPaneUtil.isInBulkOperation(togglePref));
[3403]390 gc.gridx = icon != null ? 1 : 0;
391 gc.gridy = y++;
392 gc.anchor = GridBagConstraints.LINE_START;
[8510]393 gc.insets = new Insets(5, contentInsets.left, 5, contentInsets.right);
[6594]394 cp.add(togglePanel, gc);
[2031]395 }
396
[10308]397 gc.gridy = y;
[3403]398 gc.anchor = GridBagConstraints.CENTER;
[8510]399 gc.insets = new Insets(5, 5, 5, 5);
[3403]400 cp.add(buttonsPanel, gc);
[2035]401 if (placeContentInScrollPane) {
402 JScrollPane pane = new JScrollPane(cp);
[9833]403 GuiHelper.setDefaultIncrement(pane);
[2035]404 pane.setBorder(null);
405 setContentPane(pane);
406 } else {
407 setContentPane(cp);
408 }
[1432]409 pack();
410
[1397]411 // Try to make it not larger than the parent window or at least not larger than 2/3 of the screen
[1373]412 Dimension d = getSize();
[1427]413 Dimension x = findMaxDialogSize();
[1432]414
[1397]415 boolean limitedInWidth = d.width > x.width;
416 boolean limitedInHeight = d.height > x.height;
[1373]417
[10378]418 if (x.width > 0 && d.width > x.width) {
419 d.width = x.width;
[1790]420 }
[8510]421 if (x.height > 0 && d.height > x.height) {
[1790]422 d.height = x.height;
423 }
[1432]424
[1397]425 // We have a vertical scrollbar and enough space to prevent a horizontal one
[8510]426 if (!limitedInWidth && limitedInHeight) {
[1397]427 d.width += new JScrollBar().getPreferredSize().width;
[1790]428 }
[1432]429
[1397]430 setSize(d);
431 setLocationRelativeTo(parent);
[1373]432 }
[1432]433
[10957]434 protected Action createButtonAction(final int i) {
435 return new AbstractAction(bTexts[i]) {
436 @Override
437 public void actionPerformed(ActionEvent evt) {
438 buttonAction(i, evt);
439 }
440 };
441 }
442
[1373]443 /**
[1432]444 * This gets performed whenever a button is clicked or activated
[5275]445 * @param buttonIndex the button index (first index is 0)
[1432]446 * @param evt the button event
447 */
[3355]448 protected void buttonAction(int buttonIndex, ActionEvent evt) {
449 result = buttonIndex+1;
[1432]450 setVisible(false);
451 }
452
453 /**
[1427]454 * Tries to find a good value of how large the dialog should be
[9866]455 * @return Dimension Size of the parent component if visible or 2/3 of screen size if not available or hidden
[1427]456 */
457 protected Dimension findMaxDialogSize() {
[9576]458 Dimension screenSize = GuiHelper.getScreenSize();
[2626]459 Dimension x = new Dimension(screenSize.width*2/3, screenSize.height*2/3);
[9866]460 if (parent != null && parent.isVisible()) {
[10035]461 x = GuiHelper.getFrameForComponent(parent).getSize();
[6310]462 }
[1427]463 return x;
464 }
[1432]465
[1427]466 /**
[1373]467 * Makes the dialog listen to ESC keypressed
468 */
469 private void setupEscListener() {
[1432]470 Action actionListener = new AbstractAction() {
[7545]471 @Override
472 public void actionPerformed(ActionEvent actionEvent) {
[1661]473 // 0 means that the dialog has been closed otherwise.
474 // We need to set it to zero again, in case the dialog has been re-used
475 // and the result differs from its default value
[2031]476 result = ExtendedDialog.DialogClosedOtherwise;
[8441]477 if (Main.isDebugEnabled()) {
478 Main.debug(getClass().getName()+" ESC action performed ("+actionEvent+") from "+new Exception().getStackTrace()[1]);
479 }
[1373]480 setVisible(false);
[1432]481 }
[1373]482 };
[1432]483
[10791]484 InputMapUtils.addEscapeAction(getRootPane(), actionListener);
[1373]485 }
[1856]486
[5646]487 protected final void rememberWindowGeometry(WindowGeometry geometry) {
488 if (geometry != null) {
489 geometry.remember(rememberSizePref);
490 }
491 }
[6070]492
[5646]493 protected final WindowGeometry initWindowGeometry() {
494 return new WindowGeometry(rememberSizePref, defaultWindowGeometry);
495 }
496
[2161]497 /**
498 * Override setVisible to be able to save the window geometry if required
499 */
[1856]500 @Override
501 public void setVisible(boolean visible) {
502 if (visible) {
[2025]503 repaint();
[1856]504 }
[2138]505
[8441]506 if (Main.isDebugEnabled()) {
507 Main.debug(getClass().getName()+".setVisible("+visible+") from "+new Exception().getStackTrace()[1]);
508 }
509
[2138]510 // Ensure all required variables are available
[8461]511 if (!rememberSizePref.isEmpty() && defaultWindowGeometry != null) {
[8510]512 if (visible) {
[5646]513 initWindowGeometry().applySafe(this);
[5638]514 } else if (isShowing()) { // should fix #6438, #6981, #8295
[5646]515 rememberWindowGeometry(new WindowGeometry(this));
[2138]516 }
517 }
518 super.setVisible(visible);
[3351]519
520 if (!visible && disposeOnClose) {
521 dispose();
522 }
[1856]523 }
[2031]524
525 /**
[5646]526 * Call this if you want the dialog to remember the geometry (size and position) set by the user.
[2138]527 * Set the pref to <code>null</code> or to an empty string to disable again.
528 * By default, it's disabled.
[2512]529 *
[2138]530 * Note: If you want to set the width of this dialog directly use the usual
531 * setSize, setPreferredSize, setMaxSize, setMinSize
[2512]532 *
[2138]533 * @param pref The preference to save the dimension to
534 * @param wg The default window geometry that should be used if no
535 * existing preference is found (only takes effect if
536 * <code>pref</code> is not null or empty
[6221]537 * @return {@code this}
[2138]538 */
[2602]539 public ExtendedDialog setRememberWindowGeometry(String pref, WindowGeometry wg) {
[2138]540 rememberSizePref = pref == null ? "" : pref;
541 defaultWindowGeometry = wg;
[2602]542 return this;
[2138]543 }
544
545 /**
[2031]546 * Calling this will offer the user a "Do not show again" checkbox for the
547 * dialog. Default is to not offer the choice; the dialog will be shown
[2718]548 * every time.
[3403]549 * Currently, this is not supported for non-modal dialogs.
[2031]550 * @param togglePref The preference to save the checkbox state to
[6221]551 * @return {@code this}
[2031]552 */
[2602]553 public ExtendedDialog toggleEnable(String togglePref) {
[3403]554 if (!modal) {
[7864]555 throw new IllegalStateException();
[3403]556 }
[2031]557 this.toggleable = true;
558 this.togglePref = togglePref;
[2602]559 return this;
[2031]560 }
561
562 /**
[2627]563 * Sets the button that will react to ENTER.
[7401]564 * @param defaultButtonIdx The button index (starts to 1)
[6221]565 * @return {@code this}
[2627]566 */
567 public ExtendedDialog setDefaultButton(int defaultButtonIdx) {
568 this.defaultButtonIdx = defaultButtonIdx;
569 return this;
570 }
571
572 /**
573 * Used in combination with toggle:
574 * If the user presses 'cancel' the toggle settings are ignored and not saved to the pref
[5909]575 * @param cancelButtonIdx index of the button that stands for cancel, accepts multiple values
[6221]576 * @return {@code this}
[2627]577 */
[3403]578 public ExtendedDialog setCancelButton(Integer... cancelButtonIdx) {
[8390]579 this.cancelButtonIdx = new HashSet<>(Arrays.<Integer>asList(cancelButtonIdx));
[2627]580 return this;
581 }
582
583 /**
[7407]584 * Makes default button request initial focus or not.
585 * @param focus {@code true} to make default button request initial focus
586 * @since 7407
[3403]587 */
[7407]588 public void setFocusOnDefaultButton(boolean focus) {
589 focusOnDefaultButton = focus;
590 }
591
592 private void requestFocusToDefaultButton() {
[7401]593 if (defaultButton != null) {
[10616]594 GuiHelper.runInEDT(defaultButton::requestFocusInWindow);
[3403]595 }
596 }
597
598 /**
[2031]599 * This function returns true if the dialog has been set to "do not show again"
600 * @return true if dialog should not be shown again
601 */
[6443]602 public final boolean toggleCheckState() {
[6087]603 toggleable = togglePref != null && !togglePref.isEmpty();
[6594]604 toggleValue = ConditionalOptionPaneUtil.getDialogReturnValue(togglePref);
605 return toggleable && toggleValue != -1;
[2031]606 }
607
608 /**
609 * This function checks the state of the "Do not show again" checkbox and
[5275]610 * writes the corresponding pref.
[2031]611 */
[8978]612 protected void toggleSaveState() {
[3403]613 if (!toggleable ||
[6594]614 togglePanel == null ||
[3403]615 cancelButtonIdx.contains(result) ||
616 result == ExtendedDialog.DialogClosedOtherwise)
[2031]617 return;
[6594]618 togglePanel.getNotShowAgain().store(togglePref, result);
[2031]619 }
620
621 /**
622 * Convenience function that converts a given string into a JMultilineLabel
[7545]623 * @param msg the message to display
624 * @return JMultilineLabel displaying {@code msg}
[2031]625 */
626 private static JMultilineLabel string2label(String msg) {
627 JMultilineLabel lbl = new JMultilineLabel(msg);
[2154]628 // Make it not wider than 1/2 of the screen
[9576]629 Dimension screenSize = GuiHelper.getScreenSize();
[2626]630 lbl.setMaxWidth(screenSize.width/2);
[7545]631 // Disable default Enter key binding to allow dialog's one (then enables to hit default button from here)
632 lbl.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), new Object());
[2031]633 return lbl;
634 }
[2285]635
636 /**
637 * Configures how this dialog support for context sensitive help.
638 * <ul>
639 * <li>if helpTopic is null, the dialog doesn't provide context sensitive help</li>
640 * <li>if helpTopic != null, the dialog redirect user to the help page for this helpTopic when
641 * the user clicks F1 in the dialog</li>
642 * <li>if showHelpButton is true, the dialog displays "Help" button (rightmost button in
643 * the button row)</li>
644 * </ul>
[2512]645 *
[2285]646 * @param helpTopic the help topic
647 * @param showHelpButton true, if the dialog displays a help button
[6221]648 * @return {@code this}
[2285]649 */
[2602]650 public ExtendedDialog configureContextsensitiveHelp(String helpTopic, boolean showHelpButton) {
[2285]651 this.helpTopic = helpTopic;
652 this.showHelpButton = showHelpButton;
[2602]653 return this;
[2285]654 }
655
656 class HelpAction extends AbstractAction {
[8441]657 /**
658 * Constructs a new {@code HelpAction}.
659 */
[8836]660 HelpAction() {
[2285]661 putValue(SHORT_DESCRIPTION, tr("Show help information"));
662 putValue(NAME, tr("Help"));
663 putValue(SMALL_ICON, ImageProvider.get("help"));
[7434]664 setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
[2285]665 }
666
[7434]667 @Override
668 public void actionPerformed(ActionEvent e) {
[2715]669 HelpBrowser.setUrlForHelpTopic(helpTopic);
[2285]670 }
671 }
[2512]672}
Note: See TracBrowser for help on using the repository browser.