001package jmri.jmrit.beantable.oblock; 002 003import jmri.InstanceManager; 004import jmri.NamedBean; 005import jmri.jmrit.logix.OBlock; 006import jmri.jmrit.logix.OBlockManager; 007import jmri.jmrit.logix.Portal; 008import jmri.jmrit.logix.PortalManager; 009import jmri.swing.NamedBeanComboBox; 010import jmri.util.JmriJFrame; 011import jmri.util.swing.JComboBoxUtil; 012 013import javax.annotation.Nonnull; 014import javax.swing.*; 015import java.awt.*; 016import java.awt.event.ActionEvent; 017 018/** 019 * Defines a GUI for editing OBlocks - Portal objects in the _tabbed OBlock Table interface. 020 * Based on AudioSourceFrame. 021 * 022 * @author Matthew Harris copyright (c) 2009 023 * @author Egbert Broerse (C) 2020 024 */ 025public class PortalEditFrame extends JmriJFrame { 026 027 JPanel main = new JPanel(); 028 //private final JScrollPane scroll = new JScrollPane(main, ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); 029 030 PortalTableModel model; 031 PortalManager pm; 032 //private final Object lock = new Object(); 033 034 // UI components for Add/Edit Portal 035 private final JLabel portalLabel = new JLabel(Bundle.getMessage("PortalNameLabel"), JLabel.TRAILING); 036 private final JTextField portalUserName = new JTextField(15); 037 private final JLabel fromBlockLabel = new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("FromBlockName")), JLabel.TRAILING); 038 private final JLabel toBlockLabel = new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("OppBlockName")), JLabel.TRAILING); 039 private final NamedBeanComboBox<OBlock> fromBlockComboBox = new NamedBeanComboBox<>(InstanceManager.getDefault(OBlockManager.class), null, NamedBean.DisplayOptions.DISPLAYNAME); 040 private final NamedBeanComboBox<OBlock> toBlockComboBox = new NamedBeanComboBox<>(InstanceManager.getDefault(OBlockManager.class), null, NamedBean.DisplayOptions.DISPLAYNAME); 041 private final JLabel statusBar = new JLabel(Bundle.getMessage("AddPortalStatusEnter"), JLabel.LEADING); 042 043 private final PortalEditFrame frame = this; 044 private Portal _portal; 045 private boolean _newPortal = false; 046 047// @SuppressWarnings("OverridableMethodCallInConstructor") 048 public PortalEditFrame(@Nonnull String title, Portal portal, PortalTableModel model) { 049 super(title, true, true); 050 this.model = model; 051 pm = InstanceManager.getDefault(PortalManager.class); 052 layoutFrame(); 053 if (portal == null) { 054 resetFrame(); 055 setTitle(Bundle.getMessage("TitleAddPortal")); 056 _newPortal = true; 057 } else { 058 _portal = portal; 059 populateFrame(portal); 060 } 061 } 062 063 public void layoutFrame() { 064 frame.addHelpMenu("package.jmri.jmrit.beantable.OBlockTable", true); 065 frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS)); 066 frame.setSize(425, 225); 067 068 JPanel p = new JPanel(); 069 p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS)); 070 071 JPanel configGrid = new JPanel(); 072 GridLayout layout = new GridLayout(3, 2, 10, 0); // (int rows, int cols, int hgap, int vgap) 073 configGrid.setLayout(layout); 074 075 // row 1 076 configGrid.add(portalLabel); 077 JPanel p1 = new JPanel(); 078 p1.add(portalUserName, JPanel.CENTER_ALIGNMENT); 079 configGrid.add(p1); 080 // row 2 081 fromBlockComboBox.addActionListener(e -> { 082 if ((toBlockComboBox.getItemCount() > 0) && (fromBlockComboBox.getSelectedItem() != null) && 083 (toBlockComboBox.getSelectedItem() != null) && 084 (toBlockComboBox.getSelectedItem().equals(fromBlockComboBox.getSelectedItem()))) { 085 log.debug("resetting ToBlock"); 086 toBlockComboBox.setSelectedIndex(0); // clear the other one 087 } 088 }); 089 configGrid.add(fromBlockLabel); 090 configGrid.add(fromBlockComboBox); 091 fromBlockComboBox.setAllowNull(true); 092 JComboBoxUtil.setupComboBoxMaxRows(fromBlockComboBox); 093 // row 3 094 toBlockComboBox.addActionListener(e -> { 095 if ((toBlockComboBox.getItemCount() > 0) && (fromBlockComboBox.getSelectedItem() != null) && 096 (toBlockComboBox.getSelectedItem() != null) && 097 (toBlockComboBox.getSelectedItem().equals(fromBlockComboBox.getSelectedItem()))) { 098 log.debug("resetting FromBlock"); 099 fromBlockComboBox.setSelectedIndex(0); // clear the other one 100 } 101 }); 102 configGrid.add(toBlockLabel); 103 configGrid.add(toBlockComboBox); 104 toBlockComboBox.setAllowNull(true); 105 JComboBoxUtil.setupComboBoxMaxRows(toBlockComboBox); 106 107 p.add(configGrid); 108 p.add(Box.createVerticalGlue()); 109 110 p1 = new JPanel(); 111 statusBar.setFont(statusBar.getFont().deriveFont(0.9f * portalUserName.getFont().getSize())); // a bit smaller 112 statusBar.setForeground(Color.gray); 113 p1.add(statusBar); 114 p.add(p1); 115 116 // put buttons at the bottom 117 JPanel p2 = new JPanel(); 118 JButton cancel; 119 p2.add(cancel = new JButton(Bundle.getMessage("ButtonCancel"))); 120 cancel.addActionListener((ActionEvent e) -> frame.dispose()); 121 JButton ok; 122 p2.add(ok = new JButton(Bundle.getMessage("ButtonOK"))); 123 ok.addActionListener((ActionEvent e) -> { 124 applyPressed(e); 125 }); 126 p.add(p2, BorderLayout.SOUTH); 127 128 main.add(p); 129 frame.getContentPane().add(main); 130 frame.setEscapeKeyClosesWindow(true); 131 frame.getRootPane().setDefaultButton(ok); 132 } 133 134 /** 135 * Populate the Edit OBlock frame with default values. 136 */ 137 public void resetFrame() { 138 portalUserName.setText(null); 139 portalUserName.setBackground(Color.white); 140 if (fromBlockComboBox.getItemCount() > 0) { 141 fromBlockComboBox.setSelectedIndex(0); 142 toBlockComboBox.setSelectedIndex(0); // the combos use the same list so 1 check is sufficient 143 } 144 // reset statusBar text 145 if (fromBlockComboBox.getItemCount() < 2) { 146 status(Bundle.getMessage("NotEnoughBlocks"), true); 147 } else { 148 status(Bundle.getMessage("AddPortalStatusEnter"), false); 149 } 150 _newPortal = true; 151 } 152 153 /** 154 * Populate the Edit Portal frame with current values. 155 * 156 * @param p existing Portal to copy the attributes from 157 */ 158 public void populateFrame(Portal p) { 159 if (p == null) { 160 throw new IllegalArgumentException("Null OBlock object"); 161 } 162 portalUserName.setText(p.getName()); 163 if (p.getFromBlockName() != null) { 164 fromBlockComboBox.setSelectedItemByName(p.getFromBlockName()); 165 } 166 if (p.getToBlockName() != null) { 167 toBlockComboBox.setSelectedItemByName(p.getToBlockName()); 168 } 169 _newPortal = false; 170 } 171 172 private void applyPressed(ActionEvent e) { 173 String user = portalUserName.getText().trim(); 174 if (user.equals("")) { 175 // warn/help bar red 176 status(Bundle.getMessage("WarningSysNameEmpty"), true); 177 portalUserName.setBackground(Color.red); 178 return; 179 } 180 portalUserName.setBackground(Color.white); 181 status(Bundle.getMessage("AddPortalStatusEnter"), false); 182 if (fromBlockComboBox.getSelectedIndex() == -1 || toBlockComboBox.getSelectedIndex() == -1) { 183 status(Bundle.getMessage("PortalNeedsBlock", user), true); 184 return; 185 } 186 if (_newPortal) { 187 _portal = pm.createNewPortal(user); 188 if (_portal == null) { // pm found an existing portal by the same name 189 // warn/help bar red 190 status(Bundle.getMessage("WarningSysNameInUse"), true); 191 portalUserName.setBackground(Color.red); 192 return; 193 } 194 } else { 195 String msg = _portal.setName(user); // will check for duplicates 196 if (msg != null) { 197 status(msg, true); 198 return; 199 } 200 } 201 try { 202 OBlock block = fromBlockComboBox.getSelectedItem(); 203 if (block != null) { // could have been deleted in JMRI by now? 204 // SametoFromBlock is prevented between comboboxes 205 if (!_portal.setFromBlock(block, false)) { 206 String msg = Bundle.getMessage("BlockPathsConflict", fromBlockComboBox.getSelectedItemDisplayName(), _portal.getFromBlockName()); 207 int val = model.verifyWarning(msg); 208 if (val == 2) { 209 status(msg, true); 210 return; 211 } else { 212 status(Bundle.getMessage("AddPortalStatusEnter"), false); 213 } 214 } 215 _portal.setFromBlock(block, true); 216 } 217 block = toBlockComboBox.getSelectedItem(); 218 if (block != null) { 219 if (!_portal.setToBlock(block, false)) { 220 String msg = Bundle.getMessage("BlockPathsConflict", fromBlockComboBox.getSelectedItemDisplayName(), _portal.getFromBlockName()); 221 int val = model.verifyWarning(msg); 222 if (val == 2) { 223 status(msg, true); 224 return; 225 } else { 226 status(Bundle.getMessage("AddPortalStatusEnter"), false); 227 } 228 } 229 _portal.setToBlock(block, true); 230 } 231 } catch (IllegalArgumentException ex) { 232 jmri.util.swing.JmriJOptionPane.showMessageDialog(null, ex.getMessage(), 233 Bundle.getMessage("PortalCreateErrorTitle"), jmri.util.swing.JmriJOptionPane.ERROR_MESSAGE); 234 status(Bundle.getMessage("AddPortalFailed", user), true); 235 return; 236 } 237 // Notify changes 238 model.fireTableDataChanged(); 239 dispose(); 240 } 241 242 void status(String message, boolean warn){ 243 statusBar.setText(message); 244 statusBar.setForeground(warn ? Color.red : Color.gray); 245 } 246 247 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PortalEditFrame.class); 248 249}