001package jmri.jmrit.beantable.oblock; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005import javax.annotation.Nonnull; 006import javax.swing.*; 007import javax.swing.table.AbstractTableModel; 008import jmri.InstanceManager; 009import jmri.jmrit.logix.*; 010import jmri.util.gui.GuiLafPreferencesManager; 011import jmri.util.swing.JmriJOptionPane; 012 013/** 014 * GUI to define OBlock Portals. 015* <p> 016* Can be used with two interfaces: 017* <ul> 018* <li>original "desktop" InternalFrames (parent class TableFrames, an extended JmriJFrame) 019* <li>JMRI standard Tabbed tables (parent class JPanel) 020* </ul> 021* The _tabbed field decides, it is set in prefs (restart required). 022 * <hr> 023 * This file is part of JMRI. 024 * <p> 025 * JMRI is free software; you can redistribute it and/or modify it under the 026 * terms of version 2 of the GNU General Public License as published by the Free 027 * Software Foundation. See the "COPYING" file for a copy of this license. 028 * <p> 029 * JMRI is distributed in the hope that it will be useful, but WITHOUT ANY 030 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 031 * A PARTICULAR PURPOSE. See the GNU General Public License for more details. 032 * 033 * @author Pete Cressman (C) 2010 034 * @author Egbert Broerse (C) 2020 035 */ 036public class PortalTableModel extends AbstractTableModel implements PropertyChangeListener, jmri.Disposable { 037 038 public static final int FROM_BLOCK_COLUMN = 0; 039 public final int NAME_COLUMN = 1; // not static to fetch from _tabbed OBlockTablePanel 040 public static final int TO_BLOCK_COLUMN = 2; 041 public static final int DELETE_COL = 3; 042 public static final int EDIT_COL = 4; 043 public static final int NUMCOLS = 4; 044 // reports + 1 for EDIT column if _tabbed 045 046 private final PortalManager _manager; 047 private final String[] tempRow = new String[NUMCOLS]; 048 private final boolean _tabbed; // set from prefs (restart required) 049 private final TableFrames _parent; 050 051 public PortalTableModel(@Nonnull TableFrames parent) { 052 super(); 053 _parent = parent; 054 _tabbed = InstanceManager.getDefault(GuiLafPreferencesManager.class).isOblockEditTabbed(); 055 _manager = InstanceManager.getDefault(PortalManager.class); 056 if (!_tabbed) { 057 // specific stuff for _desktop 058 initTempRow(); 059 } 060 } 061 062 public void initListeners() { 063 _manager.addPropertyChangeListener(this); 064 } 065 066 private void initTempRow() { 067 for (int i = 0; i < NUMCOLS; i++) { 068 tempRow[i] = null; 069 } 070 tempRow[DELETE_COL] = Bundle.getMessage("ButtonClear"); 071 } 072 073 @Override 074 public int getColumnCount() { 075 return NUMCOLS + (_tabbed ? 1 : 0); // add Edit column on _tabbed 076 } 077 078 @Override 079 public int getRowCount() { 080 return _manager.getPortalCount() + (_tabbed ? 0 : 1); // + 1 row in _desktop to create entry row 081 } 082 083 @Override 084 public String getColumnName(int col) { 085 switch (col) { 086 case FROM_BLOCK_COLUMN: 087 return Bundle.getMessage("FromBlockName"); 088 case NAME_COLUMN: 089 return Bundle.getMessage("PortalName"); 090 case TO_BLOCK_COLUMN: 091 return Bundle.getMessage("OppBlockName"); 092 case EDIT_COL: 093 return " "; 094 default: 095 // fall through 096 break; 097 } 098 return ""; 099 } 100 101 @Override 102 public Object getValueAt(int row, int col) { 103 log.debug("getValueAt row= {} col= {}", row, col); 104 if (row == _manager.getPortalCount()) { // this must be tempRow 105 return tempRow[col]; 106 } 107 Portal portal = _manager.getPortal(row); 108 if (portal == null) { 109 if (col == DELETE_COL) { 110 return Bundle.getMessage("ButtonClear"); 111 } 112 return tempRow[col]; 113 } else { 114 switch (col) { 115 case FROM_BLOCK_COLUMN: 116 return portal.getFromBlockName(); 117 case NAME_COLUMN: 118 return portal.getName(); 119 case TO_BLOCK_COLUMN: 120 return portal.getToBlockName(); 121 case DELETE_COL: 122 return Bundle.getMessage("ButtonDelete"); 123 case EDIT_COL: 124 return Bundle.getMessage("ButtonEdit"); 125 default: 126 // fall through 127 break; 128 } 129 } 130 return null; 131 } 132 133 @Override 134 public void setValueAt(Object value, int row, int col) { 135// log.debug("setValueAt value= {}, row= {} col= {}", row, col); 136 String msg = null; 137 if (row == _manager.getPortalCount()) { // set tempRow, only used on _desktop 138 if (col == DELETE_COL) { 139 initTempRow(); 140 fireTableRowsUpdated(row, row); 141 return; 142 } else { 143 String str = (String) value; 144 if (str == null || str.trim().length() == 0) { 145 tempRow[col] = null; 146 return; 147 } else { 148 tempRow[col] = str.trim(); 149 } 150 } 151 OBlockManager oBlockMgr = InstanceManager.getDefault(OBlockManager.class); 152 OBlock fromBlock = null; 153 OBlock toBlock = null; 154 if (tempRow[FROM_BLOCK_COLUMN] != null) { 155 fromBlock = oBlockMgr.getOBlock(tempRow[FROM_BLOCK_COLUMN]); 156 if (fromBlock == null) { 157 msg = Bundle.getMessage("NoSuchBlock", tempRow[FROM_BLOCK_COLUMN]); 158 } 159 } 160 if (msg == null && tempRow[TO_BLOCK_COLUMN] != null) { 161 toBlock = oBlockMgr.getOBlock(tempRow[TO_BLOCK_COLUMN]); 162 if (toBlock == null) { 163 msg = Bundle.getMessage("NoSuchBlock", tempRow[TO_BLOCK_COLUMN]); 164 } 165 } 166 if (msg == null && tempRow[NAME_COLUMN] != null) { 167 if (fromBlock != null && toBlock != null ) { 168 if (fromBlock.equals(toBlock)) { 169 msg = Bundle.getMessage("SametoFromBlock", fromBlock.getDisplayName()); 170 } else { 171 Portal portal = _manager.createNewPortal(tempRow[NAME_COLUMN]); 172 if (portal != null) { 173 portal.setToBlock(toBlock, false); 174 portal.setFromBlock(fromBlock, false); 175 initTempRow(); 176 fireTableDataChanged(); 177 } else { 178 msg = Bundle.getMessage("DuplPortalName", value); 179 } 180 } 181 } else if ((fromBlock == null) ^ (toBlock == null)) { 182 msg = Bundle.getMessage("PortalNeedsBlock", tempRow[NAME_COLUMN]); 183 } 184 } 185 if (msg != null) { 186 JmriJOptionPane.showMessageDialog(null, msg, 187 Bundle.getMessage("WarningTitle"), JmriJOptionPane.WARNING_MESSAGE); 188 } 189 return; 190 } 191 192 Portal portal = _manager.getPortal(row); 193 if (portal == null) { 194 log.error("Portal null, getValueAt row= {}, col= {}, portalListSize= {}", 195 row, col, _manager.getPortalCount()); 196 return; 197 } 198 199 switch (col) { // existing Portals in table 200 case FROM_BLOCK_COLUMN: 201 OBlock block = InstanceManager.getDefault(OBlockManager.class).getOBlock((String) value); 202 if (block == null) { 203 msg = Bundle.getMessage("NoSuchBlock", value); 204 break; 205 } 206 if (block.equals(portal.getToBlock())) { 207 msg = Bundle.getMessage("SametoFromBlock", block.getDisplayName()); 208 break; 209 } 210 if (!portal.setFromBlock(block, false)) { 211 int val = _parent.verifyWarning( 212 Bundle.getMessage("BlockPathsConflict", value, portal.getFromBlockName())); 213 if (val == 2) { 214 break; 215 } 216 } 217 portal.setFromBlock(block, true); 218 fireTableRowsUpdated(row, row); 219 break; 220 case NAME_COLUMN: 221 msg = portal.setName((String)value); 222 if (msg == null ) { 223 fireTableRowsUpdated(row, row); 224 } 225 break; 226 case TO_BLOCK_COLUMN: 227 block = InstanceManager.getDefault(jmri.jmrit.logix.OBlockManager.class).getOBlock((String) value); 228 if (block == null) { 229 msg = Bundle.getMessage("NoSuchBlock", value); 230 break; 231 } 232 if (block.equals(portal.getFromBlock())) { 233 msg = Bundle.getMessage("SametoFromBlock", block.getDisplayName()); 234 break; 235 } 236 if (!portal.setToBlock(block, false)) { 237 int val = _parent.verifyWarning(Bundle.getMessage("BlockPathsConflict", value, portal.getToBlockName())); 238 if (val == 2) { 239 break; 240 } 241 } 242 portal.setToBlock(block, true); 243 fireTableRowsUpdated(row, row); 244 break; 245 case DELETE_COL: 246 if (deletePortal(portal)) { 247 fireTableDataChanged(); 248 } 249 break; 250 case EDIT_COL: 251 editPortal(portal); 252 break; 253 default: 254 log.warn("Unhandled column: {}", col); 255 break; 256 } 257 if (msg != null) { 258 JmriJOptionPane.showMessageDialog(null, msg, 259 Bundle.getMessage("WarningTitle"), JmriJOptionPane.WARNING_MESSAGE); 260 } 261 } 262 263 private boolean deletePortal(Portal portal) { 264 int val = _parent.verifyWarning(Bundle.getMessage("DeletePortalConfirm", portal.getName())); 265 if (val != 2) { 266 return portal.dispose(); 267 } 268 return false; 269 } 270 271 private void editPortal(Portal portal) { 272 if (_tabbed) { 273 // open PortalEditFrame 274 PortalEditFrame portalFrame = new PortalEditFrame( 275 Bundle.getMessage("TitleEditPortal", portal.getName()), portal, this); 276 portalFrame.setVisible(true); 277 } 278 } 279 280 @Override 281 public boolean isCellEditable(int row, int col) { 282 return true; 283 } 284 285 @Override 286 public Class<?> getColumnClass(int col) { 287 switch (col) { 288 case DELETE_COL: 289 case EDIT_COL: 290 return JButton.class; 291 default: 292 return String.class; 293 } 294 } 295 296 public int getPreferredWidth(int col) { 297 switch (col) { 298 case FROM_BLOCK_COLUMN: 299 case NAME_COLUMN: 300 case TO_BLOCK_COLUMN: 301 return new JTextField(15).getPreferredSize().width; 302 case DELETE_COL: 303 case EDIT_COL: 304 return new JButton("DELETE").getPreferredSize().width; 305 default: 306 // fall through 307 break; 308 } 309 return 5; 310 } 311 312 // for Print 313 protected String getBeanType() { 314 return "Portal"; 315 } 316 317 @Override 318 public void propertyChange(PropertyChangeEvent e) { 319 String property = e.getPropertyName(); 320 if (log.isDebugEnabled()) { 321 log.debug("PropertyChangeEvent property = {} source= {}", property, e.getSource().getClass().getName()); 322 } 323 switch (property) { 324 case "pathCount": 325 case "numPortals": 326 initTempRow(); 327 fireTableDataChanged(); 328 break; 329 case "NameChange": 330 int row = _manager.getIndexOf((Portal) e.getNewValue()); 331 fireTableRowsUpdated(row, row); 332 break; 333 case "signals": 334 _parent.getSignalTableModel().propertyChange(e); 335 break; 336 default: 337 } 338 } 339 340 protected int verifyWarning(String message) { 341 return (_parent.verifyWarning(message)); 342 } 343 344 @Override 345 public void dispose() { 346 _manager.removePropertyChangeListener(this); 347 } 348 349 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PortalTableModel.class); 350 351}