001package jmri.jmrix.loconet.alm; 002 003import java.awt.FlowLayout; 004import java.awt.Dimension; 005import java.awt.event.KeyEvent; 006 007import javax.swing.JComponent; 008import javax.swing.JPanel; 009import javax.swing.JTabbedPane; 010import javax.swing.ButtonGroup; 011import javax.swing.event.ChangeEvent; 012import javax.swing.BoxLayout; 013 014import jmri.jmrix.loconet.swing.LnPanel; 015import jmri.jmrix.loconet.LnConstants; 016import jmri.jmrix.loconet.LocoNetSystemConnectionMemo; 017import jmri.jmrix.loconet.LocoNetMessage; 018import jmri.jmrix.loconet.ds64.SimpleTurnoutStateEntry; 019 020import org.slf4j.Logger; 021import org.slf4j.LoggerFactory; 022 023/** 024 * Contains all the route of a device. 025 * 026 * @author B. Milhaupt (C) 2024 027 */ 028public class LnSimple7thGenDeviceRoutes extends LnPanel { 029 private JComponent[] routePanel; 030 private LnSimple7thGenRoute[] route; // has route info plus swing stuff! 031 private final int deviceNumber; 032 private final int serNum; 033 private int baseAddr; 034 private int howManyRoutes; 035 private final String[] entryName; 036 037 private int opsw1to7; 038 039 private JTabbedPane routesTabbedPane; 040 041 public LnSimple7thGenDeviceRoutes(int deviceType, int serNum) { 042 this.deviceNumber = deviceType; 043 this.serNum = serNum; 044 howManyRoutes = 8; 045 if (this.deviceNumber == LnConstants.RE_IPL_DIGITRAX_HOST_DS78V) { 046 this.howManyRoutes = 16; 047 } 048 route = new LnSimple7thGenRoute[howManyRoutes]; 049 for (int i = 0; 050 i < howManyRoutes; ++ i) { 051 route[i] = new LnSimple7thGenRoute(); 052 } 053 this.entryName = new String[]{"Top", "2", "3", "4", "5", "6", "7", "8"}; 054 } 055 056 /** 057 * {@inheritDoc} 058 */ 059 @Override 060 public void initComponents(LocoNetSystemConnectionMemo memo) { 061 super.initComponents(memo); 062 } 063 064 /** 065 * {@inheritDoc} 066 */ 067 @Override 068 public void initComponents() { 069 super.initComponents(); 070 071 routesTabbedPane = new JTabbedPane(); 072 routePanel = new JComponent[howManyRoutes]; 073 route = new LnSimple7thGenRoute[howManyRoutes]; 074 for (int i = 0; i < howManyRoutes; ++i) { 075 route[i] = new LnSimple7thGenRoute(); 076 routePanel[i] = makeTextPanel(i, 8); 077 routesTabbedPane.addTab("Route "+Integer.toString(i+1), null, 078 routePanel[i] , ""); 079 routesTabbedPane.setMnemonicAt(i, KeyEvent.VK_1 +i); 080 } 081 routePanel[howManyRoutes-1].setPreferredSize(new Dimension(460, 50)); 082 083 add(routesTabbedPane); 084 085 //The following line enables to use scrolling tabs. 086 routesTabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); 087 088 routesTabbedPane.addChangeListener((ChangeEvent e) -> { 089 if (e.getSource() instanceof JTabbedPane) { 090 JTabbedPane pane = (JTabbedPane) e.getSource(); 091 int routeNum = pane.getSelectedIndex() + 1; 092 // get the route guiEntry 093 memo.getLnTrafficController().sendLocoNetMessage(new LocoNetMessage(new int[] { 094 LnConstants.OPC_IMM_PACKET_2, 0x10, 0x02, 0x02, 095 (routeNum - 1) * 2, 0, 0, 0, 096 0, 0, 0, 0, 097 0, 0, 0, 0})); 098 } 099 }); 100 routesTabbedPane.repaint(); 101 102 // Select device X s/n N for route accesss. 103 memo.getLnTrafficController().sendLocoNetMessage(new LocoNetMessage(new int[] { 104 LnConstants.OPC_IMM_PACKET_2, 0x10, 0x02, 0x0e, 105 0, 0, 0, 0, 106 0, deviceNumber, this.opsw1to7, serNum & 0x7f, 107 (serNum >> 7) & 0x7F, (this.baseAddr-1) & 0x7f, 108 ((this.baseAddr-1) >> 7) & 0x7f, 109 0})); 110 } 111 112 protected JComponent makeTextPanel(int i, int numEntries) { 113 JPanel panel = new JPanel(false); 114 panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); 115 JPanel jp; 116 for (int j = 0; j < 8; ++j) { 117 jp = new JPanel(); 118 jp.setLayout(new FlowLayout()); 119 SimpleTurnoutStateEntry stse = route[i].getRouteEntry(j).guiEntry; 120 jp.add(stse.createEntryPanel(entryName[j])); 121 122 jp.add(stse.getAddressField()); 123 jp.add(stse.closedRadioButton); 124 jp.add(stse.thrownRadioButton); 125 jp.add(stse.unusedRadioButton); 126 ButtonGroup bg = new ButtonGroup(); 127 bg.add(stse.closedRadioButton); 128 bg.add(stse.thrownRadioButton); 129 bg.add(stse.unusedRadioButton); 130 131 stse.unusedRadioButton.setSelected(true); 132 panel.add(jp); 133 } 134 135 return panel; 136 } 137 138 /** 139 * Get the device turnoutNumber (IPL device turnoutNumber) from the device name. 140 * @param name Device name 141 * @return device turnoutNumber 142 */ 143 public static int getDeviceType(String name) { 144 String s = name.toUpperCase(); 145 switch (s) { 146 case "DS74": 147 return LnConstants.RE_IPL_DIGITRAX_HOST_DS74; 148 case "DS78V": 149 return LnConstants.RE_IPL_DIGITRAX_HOST_DS78V; 150 case "PM74": 151 return LnConstants.RE_IPL_DIGITRAX_HOST_PM74; 152 case "SE74": 153 return LnConstants.RE_IPL_DIGITRAX_HOST_SE74; 154 default: 155 return -1; 156 } 157 } 158 159 /** 160 * Get the device name from the device (IPL) nuber. 161 * @param typeNum device type number 162 * @return String containing the device name 163 */ 164 public static String getDeviceName(int typeNum) { 165 switch (typeNum) { 166 case LnConstants.RE_IPL_DIGITRAX_HOST_DS74: 167 return "DS74"; 168 case LnConstants.RE_IPL_DIGITRAX_HOST_DS78V: 169 return "DS78V"; 170 case LnConstants.RE_IPL_DIGITRAX_HOST_PM74: 171 return "PM74"; 172 case LnConstants.RE_IPL_DIGITRAX_HOST_SE74: 173 return "SE74"; 174 default: 175 return null; 176 } 177 } 178 /** 179 * Getter. 180 * @return device type turnoutNumber 181 */ 182 public int getDeviceType() { 183 return deviceNumber; 184 } 185 186 /** 187 * Getter. 188 * @return device serial turnoutNumber 189 */ 190 public int getSerNum() { 191 return serNum; 192 } 193 194/** 195 * Get the routes. 196 * @return cloned LnSimple7thGenRoute[], if any. 197 */ 198 public LnSimple7thGenRoute[] getRoutes() { 199 return route.clone(); 200 } 201 202 /** 203 * get a specific route. 204 * 205 * @param routeNumber route number 206 * @return LnSimple7thGenRoute 207 */ 208 public LnSimple7thGenRoute getRoutes(int routeNumber) { 209 return route[routeNumber]; 210 } 211 212 /** 213 * Set the routes. 214 * 215 * @param newRoutes an array of routes 216 */ 217 public void setRoutes(LnSimple7thGenRoute[] newRoutes) { 218 route = newRoutes.clone(); 219 } 220 221 /** 222 * Set one route entry. 223 * 224 * @param routeNum route number 225 * @param entryNum entry number 226 * @param turn Turnout number 227 * @param posn Position 228 */ 229 public void setOneEntry(int routeNum, int entryNum, int turn, 230 RouteSwitchPositionEnum posn) { 231 LnSimpleRouteEntry entry = new LnSimpleRouteEntry(); 232 entry.setNumber(turn); 233 entry.setPosition(posn); 234 route[routeNum].setRouteEntry(entryNum, entry); 235 } 236 237 /** 238 * Set four entries for a route 239 * @param routeNum Route number 240 * @param entrySet Entry set 241 * @param entrya Entry a of the set 242 * @param entryb Entry b of the set 243 * @param entryc Entry c of the set 244 * @param entryd Entry d of the set 245 * @return a route 246 */ 247 public LnSimple7thGenRoute setFourEntries(int routeNum, int entrySet, 248 int entrya, int entryb, int entryc, int entryd) { 249 int entry = (entrySet == 1) ? 4 : 0; 250 251 int entryaTurn = (entrya == 0x3fff) ? 0 : (entrya & 0x7ff); 252 RouteSwitchPositionEnum entrya_posn = RouteSwitchPositionEnum.UNUSED ; 253 if (entrya != 0x3fff) { 254 entrya_posn = (((entrya & 0x3800) == 0x1800) ? 255 RouteSwitchPositionEnum.CLOSED : RouteSwitchPositionEnum.THROWN); 256 } 257 setOneEntry(routeNum, entry, entryaTurn, entrya_posn); 258 259 int entrybTurn = (entryb == 0x3fff) ? 0 : (entryb & 0x7ff); 260 RouteSwitchPositionEnum entryb_posn =RouteSwitchPositionEnum.UNUSED ; 261 if (entryb != 0x3fff) { 262 entryb_posn = (((entryb & 0x3800) == 0x1800) ? 263 RouteSwitchPositionEnum.CLOSED : RouteSwitchPositionEnum.THROWN); 264 } 265 setOneEntry(routeNum, entry+1, entrybTurn, entryb_posn); 266 267 int entrycTurn = (entryc == 0x3fff) ? 0 : (entryc & 0x7ff); 268 RouteSwitchPositionEnum entryc_posn =RouteSwitchPositionEnum.UNUSED ; 269 if (entryc != 0x3fff) { 270 entryc_posn = (((entryc & 0x3800) == 0x1800) ? 271 RouteSwitchPositionEnum.CLOSED : RouteSwitchPositionEnum.THROWN); 272 } 273 setOneEntry(routeNum, entry+2, entrycTurn, entryc_posn); 274 275 int entrydTurn = (entryd == 0x3fff) ? 0 : (entryd & 0x7ff); 276 RouteSwitchPositionEnum entryd_posn =RouteSwitchPositionEnum.UNUSED ; 277 if (entryd != 0x3fff) { 278 entryd_posn = (((entryd & 0x3800) == 0x1800) ? 279 RouteSwitchPositionEnum.CLOSED : RouteSwitchPositionEnum.THROWN); 280 } 281 setOneEntry(routeNum, entry+3, entrydTurn, entryd_posn); 282 283 log.debug("setFourEntries: done: route {} entry {} thru {}, {}, {}, {}, {}", 284 routeNum, entry, entry + 3, 285 getOneEntryString(routeNum, entry), getOneEntryString(routeNum, entry+1), 286 getOneEntryString(routeNum, entry+2), getOneEntryString(routeNum, entry+3)); 287 288 return getRoute(routeNum); 289 } 290 291 /** 292 * get a route entry as a string. 293 * @param routeNum Route number 294 * @param entryNum Entry number 295 * @return String like "Unused" or "1c" or "2044t" 296 */ 297 public String getOneEntryString(int routeNum, int entryNum) { 298 RouteSwitchPositionEnum r = route[routeNum].getRouteEntry(entryNum).getPosition(); 299 if (r.equals(RouteSwitchPositionEnum.UNUSED)) { 300 return "Unused"; 301 } 302 return Integer.toString(route[routeNum].getRouteEntry(entryNum).getNumber()) + r.toString(); 303 } 304 305 /** 306 * Get a route. 307 * @param routeNum Route number 308 * @return LnSimple7thGenRoute, or null if route not defined 309 */ 310 public LnSimple7thGenRoute getRoute(int routeNum) { 311 if ((routeNum >=0) && (routeNum < route.length)) { 312 return route[routeNum]; 313 } else { 314 log.warn("getRoutes({}): not configured.", routeNum); 315 return null; 316 } 317 } 318 319 /** 320 * Getter. 321 * @return Base Addr 322 */ 323 public int getBaseAddr() { 324 return baseAddr; 325 } 326 327 /** 328 * Setter. 329 * @param baseAddr the base address 330 */ 331 public void setBaseAddr(int baseAddr) { 332 this.baseAddr = baseAddr; 333 } 334 335 private final static Logger log = LoggerFactory.getLogger(LnSimple7thGenDeviceRoutes.class); 336}