001package jmri.implementation.swing; 002 003import java.awt.Component; 004 005import jmri.implementation.AbstractShutDownTask; 006import jmri.util.swing.JmriJOptionPane; 007 008/** 009 * Provides a base for using Swing to ask if shutdown should conditionally 010 * continue. 011 * <p> 012 * Sequence: 013 * <ol> 014 * <li>checkPromptNeeded determines if ready to shutdown. If so, return ready. 015 * <li>Issue a prompt, asking if the user wants to continue or do something else 016 * <li>Recheck until something decided. 017 * </ol> 018 * 019 * <p> 020 * If no "action" name is provided, only the continue and cancel options are 021 * shown. 022 * 023 * @author Bob Jacobsen Copyright (C) 2008 024 */ 025public class SwingShutDownTask extends AbstractShutDownTask { 026 027 /** 028 * Constructor specifies the warning message and action to take 029 * 030 * @param name the name of the task (used in logs) 031 * @param warning the prompt to display 032 * @param action the action button to display 033 * @param component the parent component of the dialog 034 */ 035 public SwingShutDownTask(String name, String warning, String action, Component component) { 036 super(name); 037 this.component = component; 038 this.warning = warning; 039 this.action = action; 040 } 041 042 String warning; 043 String action; 044 Component component; 045 private boolean didPrompt = false; 046 047 /** 048 * {@inheritDoc} 049 * 050 * This implementation displays a dialog allowing a user continue stopping 051 * the app, abort stopping the app, or take a custom action. Closing the 052 * dialog without choosing any button is treated as aborting stopping the 053 * app. 054 * 055 * @see #didPrompt() 056 * @see #doPrompt() 057 */ 058 @Override 059 public final Boolean call() { 060 if (!checkPromptNeeded()) { 061 // issue prompt 062 Object[] possibleValues; 063 if (action != null) { 064 possibleValues = new Object[]{Bundle.getMessage("ButtonContinue"), 065 Bundle.getMessage("ButtonAbort"), 066 action}; 067 } else { 068 possibleValues = new Object[]{Bundle.getMessage("ButtonContinue"), 069 Bundle.getMessage("ButtonAbort")}; 070 } 071 072 int selectedValue = JmriJOptionPane.showOptionDialog(component, 073 warning, 074 Bundle.getMessage("ShutDownWarningTitle"), 075 JmriJOptionPane.DEFAULT_OPTION, 076 JmriJOptionPane.WARNING_MESSAGE, null, 077 possibleValues, possibleValues[possibleValues.length - 1]); 078 switch (selectedValue) { 079 case 1: 080 case -1: 081 // abort quit 082 return false; 083 case 0: 084 // quit anyway 085 return true; 086 case 2: 087 // take action and try again 088 didPrompt = true; 089 return doPrompt(); 090 default: 091 // unexpected value, log but continue 092 log.error("unexpected selection: {}", selectedValue); 093 return true; 094 } 095 } 096 return true; 097 } 098 099 /** 100 * {@inheritDoc} 101 * 102 * This implementation calls {@link #didPrompt()} if the user took the 103 * prompt action. 104 */ 105 @Override 106 public void run() { 107 if (didPrompt) { 108 didPrompt(); 109 } 110 } 111 112 /** 113 * Provide a subclass-specific check as to whether it's OK to shutdown. If 114 * not, issue a prompt before continuing. Default implementation never 115 * passes, causing message to be emitted. 116 * 117 * @return true if ready to shutdown, and no prompt needed. false to present 118 * dialog before shutdown proceeds 119 */ 120 protected boolean checkPromptNeeded() { 121 return false; 122 } 123 124 /** 125 * Handle the request to address a potential blocker to stopping. This 126 * method is called in {@link #run()} and must not interact with the user. 127 * <p> 128 * This is a dummy implementation, intended to be overloaded. 129 */ 130 protected void didPrompt() { 131 // do nothing 132 } 133 134 /** 135 * Handle the request to address a potential blocker to stopping. This 136 * method is called in {@link #call()} and can interact with the user. 137 * <p> 138 * This is a dummy implementation, intended to be overloaded. 139 * 140 * @return true if ready to shutdown, false to end shutdown 141 */ 142 protected boolean doPrompt() { 143 return true; 144 } 145 146 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(SwingShutDownTask.class); 147 148}