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 { 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 static public final int DELETE_COL = 3; 042 static public final int EDIT_COL = 4; 043 public static final int NUMCOLS = 4; 044 // reports + 1 for EDIT column if _tabbed 045 046 PortalManager _manager; 047 private final String[] tempRow = new String[NUMCOLS]; 048 private final boolean _tabbed; // set from prefs (restart required) 049 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 _manager.addPropertyChangeListener(this); 057 if (!_tabbed) { 058 // specific stuff for _desktop 059 initTempRow(); 060 } 061 } 062 063 void initTempRow() { 064 for (int i = 0; i < NUMCOLS; i++) { 065 tempRow[i] = null; 066 } 067 tempRow[DELETE_COL] = Bundle.getMessage("ButtonClear"); 068 } 069 070 @Override 071 public int getColumnCount() { 072 return NUMCOLS + (_tabbed ? 1 : 0); // add Edit column on _tabbed 073 } 074 075 @Override 076 public int getRowCount() { 077 return _manager.getPortalCount() + (_tabbed ? 0 : 1); // + 1 row in _desktop to create entry row 078 } 079 080 @Override 081 public String getColumnName(int col) { 082 switch (col) { 083 case FROM_BLOCK_COLUMN: 084 return Bundle.getMessage("FromBlockName"); 085 case NAME_COLUMN: 086 return Bundle.getMessage("PortalName"); 087 case TO_BLOCK_COLUMN: 088 return Bundle.getMessage("OppBlockName"); 089 case EDIT_COL: 090 return " "; 091 default: 092 // fall through 093 break; 094 } 095 return ""; 096 } 097 098 @Override 099 public Object getValueAt(int row, int col) { 100 log.debug("getValueAt row= {} col= {}", row, col); 101 if (row == _manager.getPortalCount()) { // this must be tempRow 102 return tempRow[col]; 103 } 104 Portal portal = _manager.getPortal(row); 105 if (portal == null) { 106 if (col == DELETE_COL) { 107 return Bundle.getMessage("ButtonClear"); 108 } 109 return tempRow[col]; 110 } else { 111 switch (col) { 112 case FROM_BLOCK_COLUMN: 113 return portal.getFromBlockName(); 114 case NAME_COLUMN: 115 return portal.getName(); 116 case TO_BLOCK_COLUMN: 117 return portal.getToBlockName(); 118 case DELETE_COL: 119 return Bundle.getMessage("ButtonDelete"); 120 case EDIT_COL: 121 return Bundle.getMessage("ButtonEdit"); 122 default: 123 // fall through 124 break; 125 } 126 } 127 return null; 128 } 129 130 @Override 131 public void setValueAt(Object value, int row, int col) { 132// log.debug("setValueAt value= {}, row= {} col= {}", row, col); 133 String msg = null; 134 if (row == _manager.getPortalCount()) { // set tempRow, only used on _desktop 135 if (col == DELETE_COL) { 136 initTempRow(); 137 fireTableRowsUpdated(row, row); 138 return; 139 } else { 140 String str = (String) value; 141 if (str == null || str.trim().length() == 0) { 142 tempRow[col] = null; 143 return; 144 } else { 145 tempRow[col] = str.trim(); 146 } 147 } 148 OBlockManager OBlockMgr = InstanceManager.getDefault(jmri.jmrit.logix.OBlockManager.class); 149 OBlock fromBlock = null; 150 OBlock toBlock = null; 151 if (tempRow[FROM_BLOCK_COLUMN] != null) { 152 fromBlock = OBlockMgr.getOBlock(tempRow[FROM_BLOCK_COLUMN]); 153 if (fromBlock == null) { 154 msg = Bundle.getMessage("NoSuchBlock", tempRow[FROM_BLOCK_COLUMN]); 155 } 156 } 157 if (msg == null && tempRow[TO_BLOCK_COLUMN] != null) { 158 toBlock = OBlockMgr.getOBlock(tempRow[TO_BLOCK_COLUMN]); 159 if (toBlock == null) { 160 msg = Bundle.getMessage("NoSuchBlock", tempRow[TO_BLOCK_COLUMN]); 161 } 162 } 163 if (msg == null && tempRow[NAME_COLUMN] != null) { 164 if (fromBlock != null && toBlock != null ) { 165 if (fromBlock.equals(toBlock)) { 166 msg = Bundle.getMessage("SametoFromBlock", fromBlock.getDisplayName()); 167 } else { 168 Portal portal = _manager.createNewPortal(tempRow[NAME_COLUMN]); 169 if (portal != null) { 170 portal.setToBlock(toBlock, false); 171 portal.setFromBlock(fromBlock, false); 172 initTempRow(); 173 fireTableDataChanged(); 174 } else { 175 msg = Bundle.getMessage("DuplPortalName", value); 176 } 177 } 178 } else if ((fromBlock == null) ^ (toBlock == null)) { 179 msg = Bundle.getMessage("PortalNeedsBlock", tempRow[NAME_COLUMN]); 180 } 181 } 182 if (msg != null) { 183 JmriJOptionPane.showMessageDialog(null, msg, 184 Bundle.getMessage("WarningTitle"), JmriJOptionPane.WARNING_MESSAGE); 185 } 186 return; 187 } 188 189 Portal portal = _manager.getPortal(row); 190 if (portal == null) { 191 log.error("Portal null, getValueAt row= {}, col= {}, portalListSize= {}", row, col, _manager.getPortalCount()); 192 return; 193 } 194 195 switch (col) { // existing Portals in table 196 case FROM_BLOCK_COLUMN: 197 OBlock block = InstanceManager.getDefault(jmri.jmrit.logix.OBlockManager.class).getOBlock((String) value); 198 if (block == null) { 199 msg = Bundle.getMessage("NoSuchBlock", value); 200 break; 201 } 202 if (block.equals(portal.getToBlock())) { 203 msg = Bundle.getMessage("SametoFromBlock", block.getDisplayName()); 204 break; 205 } 206 if (!portal.setFromBlock(block, false)) { 207 int val = _parent.verifyWarning(Bundle.getMessage("BlockPathsConflict", value, portal.getFromBlockName())); 208 if (val == 2) { 209 break; 210 } 211 } 212 portal.setFromBlock(block, true); 213 fireTableRowsUpdated(row, row); 214 break; 215 case NAME_COLUMN: 216 msg = portal.setName((String)value); 217 if (msg == null ) { 218 fireTableRowsUpdated(row, row); 219 } 220 break; 221 case TO_BLOCK_COLUMN: 222 block = InstanceManager.getDefault(jmri.jmrit.logix.OBlockManager.class).getOBlock((String) value); 223 if (block == null) { 224 msg = Bundle.getMessage("NoSuchBlock", value); 225 break; 226 } 227 if (block.equals(portal.getFromBlock())) { 228 msg = Bundle.getMessage("SametoFromBlock", block.getDisplayName()); 229 break; 230 } 231 if (!portal.setToBlock(block, false)) { 232 int val = _parent.verifyWarning(Bundle.getMessage("BlockPathsConflict", value, portal.getToBlockName())); 233 if (val == 2) { 234 break; 235 } 236 } 237 portal.setToBlock(block, true); 238 fireTableRowsUpdated(row, row); 239 break; 240 case DELETE_COL: 241 if (deletePortal(portal)) { 242 fireTableDataChanged(); 243 } 244 break; 245 case EDIT_COL: 246 editPortal(portal); 247 break; 248 default: 249 log.warn("Unhandled column: {}", col); 250 break; 251 } 252 if (msg != null) { 253 JmriJOptionPane.showMessageDialog(null, msg, 254 Bundle.getMessage("WarningTitle"), JmriJOptionPane.WARNING_MESSAGE); 255 } 256 } 257 258 private boolean deletePortal(Portal portal) { 259 int val = _parent.verifyWarning(Bundle.getMessage("DeletePortalConfirm", portal.getName())); 260 if (val != 2) { 261 return portal.dispose(); 262 } 263 return false; 264 } 265 266 private void editPortal(Portal portal) { 267 if (_tabbed) { 268 // open PortalEditFrame 269 PortalEditFrame portalFrame = new PortalEditFrame(Bundle.getMessage("TitleEditPortal", portal.getName()), portal, this); 270 portalFrame.setVisible(true); 271 } 272 } 273 274 @Override 275 public boolean isCellEditable(int row, int col) { 276 return true; 277 } 278 279 @Override 280 public Class<?> getColumnClass(int col) { 281 switch (col) { 282 case DELETE_COL: 283 case EDIT_COL: 284 return JButton.class; 285 default: 286 return String.class; 287 } 288 } 289 290 public int getPreferredWidth(int col) { 291 switch (col) { 292 case FROM_BLOCK_COLUMN: 293 case NAME_COLUMN: 294 case TO_BLOCK_COLUMN: 295 return new JTextField(15).getPreferredSize().width; 296 case DELETE_COL: 297 case EDIT_COL: 298 return new JButton("DELETE").getPreferredSize().width; 299 default: 300 // fall through 301 break; 302 } 303 return 5; 304 } 305 306 // for Print 307 protected String getBeanType() { 308 return "Portal"; 309 } 310 311 @Override 312 public void propertyChange(PropertyChangeEvent e) { 313 String property = e.getPropertyName(); 314 if (log.isDebugEnabled()) { 315 log.debug("PropertyChangeEvent property = {} source= {}", property, e.getSource().getClass().getName()); 316 } 317 switch (property) { 318 case "pathCount": 319 case "numPortals": 320 initTempRow(); 321 fireTableDataChanged(); 322 break; 323 case "NameChange": 324 int row = _manager.getIndexOf((Portal) e.getNewValue()); 325 fireTableRowsUpdated(row, row); 326 break; 327 case "signals": 328 _parent.getSignalTableModel().propertyChange(e); 329 break; 330 default: 331 } 332 } 333 334 protected int verifyWarning(String message) { 335 return (_parent.verifyWarning(message)); 336 } 337 338 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PortalTableModel.class); 339 340}