001package jmri.jmrit.display; 002 003import jmri.jmrit.logixng.LogixNG; 004 005import javax.swing.*; 006import javax.swing.event.ListSelectionEvent; 007import javax.swing.event.ListSelectionListener; 008import java.awt.*; 009import java.awt.event.ActionEvent; 010import java.awt.event.ActionListener; 011import java.awt.event.ItemEvent; 012import java.awt.event.ItemListener; 013import java.util.ArrayList; 014import java.util.List; 015 016public class LogixNGDeleteDialog extends JDialog { 017 018 private JLabel label; 019 private JList<CheckableItem> itemList; 020 private DefaultListModel<CheckableItem> listModel; 021 private JCheckBox selectAllCheckBox; 022 private JCheckBox disableCheckBox; 023 private JButton okButton; 024 private List<CheckableItem> selectedItems; 025 private boolean isSelectAllChecked = false; // Track the state of the "Select All" checkbox 026 027 public LogixNGDeleteDialog(Frame owner, String panelName, List<LogixNG> items) { 028 super(owner, Bundle.getMessage("LogixNGDeleteDialog_Title"), true); // true for modal dialog 029 initComponents(panelName, items); 030 layoutComponents(); 031 addEventHandlers(); 032 selectedItems = new ArrayList<>(); 033 } 034 035 private void initComponents(String panelName, List<LogixNG> items) { 036 label = new JLabel(Bundle.getMessage("LogixNGDeleteDialog_PanelText", panelName)); 037 listModel = new DefaultListModel<>(); 038 for (LogixNG item : items) { 039 listModel.addElement(new CheckableItem(item)); 040 } 041 itemList = new JList<>(listModel); 042 itemList.setCellRenderer(new CheckboxListCellRenderer()); 043 itemList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); 044 045 selectAllCheckBox = new JCheckBox(Bundle.getMessage("LogixNGDeleteDialog_SelectCheckBox")); 046 disableCheckBox = new JCheckBox(Bundle.getMessage("LogixNGDeleteDialog_DisableCheckBox")); 047 048 okButton = new JButton(Bundle.getMessage("ButtonOK")); 049 getRootPane().setDefaultButton(okButton); 050 } 051 052 private void layoutComponents() { 053 JPanel contentPanel = new JPanel(); 054 contentPanel.setLayout(new BorderLayout()); 055 056 // Header panel for the "Select All" checkbox 057 JPanel headerPanel = new JPanel(new BorderLayout()); 058 headerPanel.add(label, BorderLayout.NORTH); 059 headerPanel.add(itemList, BorderLayout.CENTER); 060 headerPanel.add(selectAllCheckBox, BorderLayout.SOUTH); 061 contentPanel.add(headerPanel, BorderLayout.NORTH); 062 063 //scroll pane for the list 064 JScrollPane scrollPane = new JScrollPane(itemList); 065 contentPanel.add(scrollPane, BorderLayout.CENTER); 066 067 // Button panel for OK and Cancel buttons 068 JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); 069 buttonPanel.add(okButton); 070 071 JPanel southPanel = new JPanel(new BorderLayout()); 072 southPanel.add(disableCheckBox, BorderLayout.NORTH); 073 southPanel.add(buttonPanel, BorderLayout.SOUTH); 074 contentPanel.add(southPanel, BorderLayout.SOUTH); 075 076 setContentPane(contentPanel); 077 pack(); 078 setLocationRelativeTo(getOwner()); // Center relative to owner 079 } 080 081 private void addEventHandlers() { 082 selectAllCheckBox.addItemListener(new ItemListener() { 083 @Override 084 public void itemStateChanged(ItemEvent e) { 085 isSelectAllChecked = e.getStateChange() == ItemEvent.SELECTED; // update the flag 086 for (int i = 0; i < listModel.getSize(); i++) { 087 listModel.getElementAt(i).setSelected(isSelectAllChecked); 088 } 089 itemList.repaint(); // Refresh the list to show changes 090 } 091 }); 092 093 itemList.addListSelectionListener(new ListSelectionListener() { 094 @Override 095 public void valueChanged(ListSelectionEvent e) { 096 if (!e.getValueIsAdjusting()) { // Only handle the final event 097 int selectedIndex = itemList.getSelectedIndex(); 098 if (selectedIndex != -1) { 099 CheckableItem selectedItem = listModel.getElementAt(selectedIndex); 100 selectedItem.setSelected(!selectedItem.isSelected()); // Toggle 101 listModel.setElementAt(selectedItem, selectedIndex); // Update the model 102 itemList.repaint(); // Ensure the checkbox is updated 103 104 // Update "Select All" checkbox 105 updateSelectAllCheckbox(); 106 } 107 } 108 } 109 }); 110 111 okButton.addActionListener(new ActionListener() { 112 @Override 113 public void actionPerformed(ActionEvent e) { 114 selectedItems.clear(); // Clear previous selection 115 for (int i = 0; i < listModel.getSize(); i++) { 116 CheckableItem item = listModel.getElementAt(i); 117 if (item.isSelected()) { 118 selectedItems.add(item); 119 } 120 } 121 setVisible(false); // Close the dialog 122 } 123 }); 124 } 125 /** 126 * Updates the "Select All" checkbox based on the current state of the items in the list. 127 */ 128 private void updateSelectAllCheckbox() { 129 boolean allSelected = true; 130 for (int i = 0; i < listModel.getSize(); i++) { 131 if (!listModel.getElementAt(i).isSelected()) { 132 allSelected = false; 133 break; 134 } 135 } 136 selectAllCheckBox.setSelected(allSelected); 137 isSelectAllChecked = allSelected; 138 } 139 140 public List<LogixNG> getSelectedItems() { 141 ArrayList<LogixNG> selections = new ArrayList<>(); 142 for (CheckableItem item : selectedItems) { 143 selections.add(item.getLogixNG()); 144 } 145 return selections; 146 } 147 148 public boolean isDisableLogixNG() { 149 return disableCheckBox.isSelected(); 150 } 151 152 // Inner class for items in the list 153 public static class CheckableItem { 154 private LogixNG logixNG; 155 private boolean isSelected; 156 157 public CheckableItem(LogixNG logixNG) { 158 this.logixNG = logixNG; 159 this.isSelected = false; 160 } 161 162 public LogixNG getLogixNG() { 163 return logixNG; 164 } 165 166 public boolean isSelected() { 167 return isSelected; 168 } 169 170 public void setSelected(boolean selected) { 171 isSelected = selected; 172 } 173 174 @Override 175 public String toString() { 176 return logixNG.getDisplayName(); 177 } 178 } 179 180 // Inner class for custom cell renderer 181 private static class CheckboxListCellRenderer extends JPanel implements ListCellRenderer<CheckableItem> { 182 private JCheckBox checkBox; 183 184 public CheckboxListCellRenderer() { 185 setLayout(new BorderLayout()); 186 checkBox = new JCheckBox(); 187 checkBox.setMargin(new Insets(0, 0, 0, 0)); 188 add(checkBox, BorderLayout.CENTER); 189 setOpaque(true); 190 } 191 192 @Override 193 public Component getListCellRendererComponent(JList<? extends CheckableItem> list, CheckableItem value, int index, boolean isSelected, boolean cellHasFocus) { 194 checkBox.setText(value.getLogixNG().getDisplayName()); 195 checkBox.setSelected(value.isSelected()); 196 checkBox.setEnabled(list.isEnabled()); 197 checkBox.setFont(list.getFont()); 198 199 if (isSelected) { 200 setBackground(list.getSelectionBackground()); 201 setForeground(list.getSelectionForeground()); 202 } else { 203 setBackground(list.getBackground()); 204 setForeground(list.getForeground()); 205 } 206 207 return this; 208 } 209 } 210} 211