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