001package jmri.jmrit.logixng.tools.swing; 002 003import java.awt.Component; 004import java.awt.Toolkit; 005import java.awt.event.ActionEvent; 006import java.awt.event.KeyEvent; 007import java.beans.PropertyVetoException; 008import java.text.MessageFormat; 009import java.util.ArrayList; 010import java.util.List; 011 012import javax.swing.*; 013 014import jmri.Manager; 015import jmri.NamedBean; 016import jmri.Reference; 017import jmri.util.swing.JmriJOptionPane; 018 019/** 020 * Helper class for deleting a bean 021 * 022 * @author Daniel Bergqvist (C) 2022 023 * 024 * @param <E> the type of NamedBean supported by this model 025 */ 026public class DeleteBean<E extends NamedBean> { 027 028 private final Manager<E> _manager; 029 030 public DeleteBean(Manager<E> manager) { 031 _manager = manager; 032 } 033 034 public void delete( 035 final E x, 036 boolean hasChildren, 037 DeleteTask<E> deleteTask, 038 GetListenersRef<E> getListenersRef, 039 String className) { 040 delete(x, hasChildren, deleteTask, getListenersRef, className, false); 041 } 042 043 public boolean delete( 044 final E x, 045 boolean hasChildren, 046 DeleteTask<E> deleteTask, 047 GetListenersRef<E> getListenersRef, 048 String className, 049 boolean modal) { 050 051 final Reference<Boolean> reference = new Reference<>(false); 052 final jmri.UserPreferencesManager p; 053 p = jmri.InstanceManager.getNullableDefault(jmri.UserPreferencesManager.class); 054 055 StringBuilder message = new StringBuilder(); 056 try { 057 _manager.deleteBean(x, "CanDelete"); // NOI18N 058 } catch (PropertyVetoException e) { 059 if (e.getPropertyChangeEvent().getPropertyName().equals("DoNotDelete")) { // NOI18N 060 log.warn("{} : Do Not Delete", e.getMessage()); 061 message.append(Bundle.getMessage("VetoDeleteBean", x.getBeanType(), x.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME), e.getMessage())); 062 JmriJOptionPane.showMessageDialog(null, message.toString(), 063 Bundle.getMessage("QuestionTitle"), 064 JmriJOptionPane.ERROR_MESSAGE); 065 return false; 066 } 067 message.append(e.getMessage()); 068 } 069 List<String> listenerRefs = new ArrayList<>(); 070 getListenersRef.getListenerRefsIncludingChildren(x, listenerRefs); 071 int listenerRefsCount = listenerRefs.size(); 072 log.debug("Delete with {}", listenerRefsCount); 073 if (p != null && p.getMultipleChoiceOption(className, "deleteLogixNG") == 0x02 && message.toString().isEmpty()) { 074 deleteTask.deleteBean(x); 075 } else { 076 final JDialog dialog = new JDialog((JFrame)null, modal); 077 dialog.setTitle(Bundle.getMessage("QuestionTitle")); 078 dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 079 JPanel container = new JPanel(); 080 container.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 081 container.setLayout(new BoxLayout(container, BoxLayout.Y_AXIS)); 082 083 if (listenerRefsCount > 0) { // warn of listeners attached before delete 084 String prompt = hasChildren 085 ? "DeleteWithChildrenPrompt" : "DeletePrompt"; 086 JLabel question = new JLabel(Bundle.getMessage(prompt, x.getDisplayName(NamedBean.DisplayOptions.USERNAME_SYSTEMNAME))); 087 question.setAlignmentX(Component.CENTER_ALIGNMENT); 088 container.add(question); 089 090 ArrayList<String> listeners = new ArrayList<>(); 091 for (String listenerRef : listenerRefs) { 092 if (!listeners.contains(listenerRef)) { 093 listeners.add(listenerRef); 094 } 095 } 096 097 message.append("<br>"); 098 message.append(Bundle.getMessage("ReminderInUse", listenerRefsCount)); 099 message.append("<ul>"); 100 for (String listener : listeners) { 101 message.append("<li>"); 102 message.append(listener); 103 message.append("</li>"); 104 } 105 message.append("</ul>"); 106 107 JEditorPane pane = new JEditorPane(); 108 pane.setContentType("text/html"); 109 pane.setText("<html>" + message.toString() + "</html>"); 110 pane.setEditable(false); 111 JScrollPane jScrollPane = new JScrollPane(pane); 112 container.add(jScrollPane); 113 } else { 114 String prompt = hasChildren 115 ? "DeleteWithChildrenPrompt" : "DeletePrompt"; 116 String msg = MessageFormat.format( 117 Bundle.getMessage(prompt), x.getSystemName()); 118 JLabel question = new JLabel(msg); 119 question.setAlignmentX(Component.CENTER_ALIGNMENT); 120 container.add(question); 121 } 122 123 final JCheckBox remember = new JCheckBox(Bundle.getMessage("MessageRememberSetting")); 124 remember.setFont(remember.getFont().deriveFont(10f)); 125 remember.setAlignmentX(Component.CENTER_ALIGNMENT); 126 127 JButton yesButton = new JButton(Bundle.getMessage("ButtonYes")); 128 JButton noButton = new JButton(Bundle.getMessage("ButtonNo")); 129 JPanel button = new JPanel(); 130 button.setAlignmentX(Component.CENTER_ALIGNMENT); 131 button.add(yesButton); 132 button.add(noButton); 133 container.add(button); 134 135 noButton.addActionListener((ActionEvent e) -> { 136 //there is no point in remembering this the user will never be 137 //able to delete a bean! 138 reference.set(false); 139 dialog.dispose(); 140 }); 141 142 yesButton.addActionListener((ActionEvent e) -> { 143 if (remember.isSelected() && p != null) { 144 p.setMultipleChoiceOption(className, "deleteLogixNG", 0x02); // NOI18N 145 } 146 deleteTask.deleteBean(x); 147 reference.set(true); 148 dialog.dispose(); 149 }); 150 container.add(remember); 151 container.setAlignmentX(Component.CENTER_ALIGNMENT); 152 container.setAlignmentY(Component.CENTER_ALIGNMENT); 153 dialog.getContentPane().add(container); 154 dialog.pack(); 155 156 dialog.getRootPane().setDefaultButton(noButton); 157 noButton.requestFocusInWindow(); // set default keyboard focus, after pack() before setVisible(true) 158 dialog.getRootPane().registerKeyboardAction(e -> { // escape to exit 159 dialog.setVisible(false); 160 dialog.dispose(); }, 161 KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW); 162 163 dialog.setLocation((Toolkit.getDefaultToolkit().getScreenSize().width) / 2 - dialog.getWidth() / 2, 164 (Toolkit.getDefaultToolkit().getScreenSize().height) / 2 - dialog.getHeight() / 2); 165 dialog.setModal(true); 166 dialog.setVisible(true); 167 } 168 Boolean result = reference.get(); 169 return result != null && result; 170 } 171 172 173 public interface DeleteTask<T> { 174 void deleteBean(T bean); 175 } 176 177 178 public interface GetListenersRef<T> { 179 void getListenerRefsIncludingChildren(T bean, List<String> list); 180 } 181 182 183 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(DeleteBean.class); 184}