001package jmri.jmrit.logixng.actions; 002 003import java.beans.PropertyChangeEvent; 004import java.beans.PropertyChangeListener; 005import java.util.*; 006 007import jmri.*; 008import jmri.Block; 009import jmri.Sensor; 010import jmri.jmrit.display.layoutEditor.LayoutBlock; 011import jmri.jmrit.display.layoutEditor.LayoutBlockManager; 012import jmri.jmrit.logixng.*; 013import jmri.jmrit.logixng.util.*; 014import jmri.jmrit.logixng.util.parser.*; 015import jmri.util.ThreadingUtil; 016 017/** 018 * This action triggers a block. 019 * 020 * @author Daniel Bergqvist Copyright 2021 021 * @author Dave Sand Copyright 2021 022 */ 023public class ActionBlock extends AbstractDigitalAction 024 implements PropertyChangeListener { 025 026 private final LogixNG_SelectNamedBean<Block> _selectNamedBean = 027 new LogixNG_SelectNamedBean<>( 028 this, Block.class, InstanceManager.getDefault(BlockManager.class), this); 029 030 private final LogixNG_SelectEnum<DirectOperation> _selectEnum = 031 new LogixNG_SelectEnum<>(this, DirectOperation.values(), DirectOperation.SetOccupied, this); 032 033 private final LogixNG_SelectString _selectBlockValue = 034 new LogixNG_SelectString(this, this); 035 036 037 public ActionBlock(String sys, String user) 038 throws BadUserNameException, BadSystemNameException { 039 super(sys, user); 040 } 041 042 @Override 043 public Base getDeepCopy(Map<String, String> systemNames, Map<String, String> userNames) throws ParserException { 044 DigitalActionManager manager = InstanceManager.getDefault(DigitalActionManager.class); 045 String sysName = systemNames.get(getSystemName()); 046 String userName = userNames.get(getSystemName()); 047 if (sysName == null) sysName = manager.getAutoSystemName(); 048 ActionBlock copy = new ActionBlock(sysName, userName); 049 copy.setComment(getComment()); 050 _selectNamedBean.copy(copy._selectNamedBean); 051 _selectEnum.copy(copy._selectEnum); 052 _selectBlockValue.copy(copy._selectBlockValue); 053 return manager.registerAction(copy); 054 } 055 056 public LogixNG_SelectNamedBean<Block> getSelectNamedBean() { 057 return _selectNamedBean; 058 } 059 060 public LogixNG_SelectEnum<DirectOperation> getSelectEnum() { 061 return _selectEnum; 062 } 063 064 public LogixNG_SelectString getSelectBlockValue() { 065 return _selectBlockValue; 066 } 067 068 /** {@inheritDoc} */ 069 @Override 070 public Category getCategory() { 071 return Category.ITEM; 072 } 073 074 /** {@inheritDoc} */ 075 @Override 076 public void execute() throws JmriException { 077 ConditionalNG conditionalNG = getConditionalNG(); 078 079 Block block = _selectNamedBean.evaluateNamedBean(conditionalNG); 080 081 if (block == null) { 082 return; 083 } 084 085 DirectOperation oper = _selectEnum.evaluateEnum(getConditionalNG()); 086 087 // Variables used in lambda must be effectively final 088 DirectOperation theOper = oper; 089 090 ThreadingUtil.runOnLayoutWithJmriException(() -> { 091 Sensor sensor; 092 LayoutBlock lblk; 093 094 switch (theOper) { 095 case SetOccupied: 096 sensor = block.getSensor(); 097 if (sensor != null) { 098 try { 099 sensor.setKnownState(Sensor.ACTIVE); 100 } catch (JmriException ex) { 101 log.debug("Exception setting sensor active"); 102 } 103 } else { 104 throw new JmriException(Bundle.getMessage("ActionBlock_ErrorSensor", block.getDisplayName())); 105 } 106 break; 107 case SetNotOccupied: 108 sensor = block.getSensor(); 109 if (sensor != null) { 110 try { 111 sensor.setKnownState(Sensor.INACTIVE); 112 } catch (JmriException ex) { 113 log.debug("Exception setting sensor inactive"); 114 } 115 } else { 116 throw new JmriException(Bundle.getMessage("ActionBlock_ErrorSensor", block.getDisplayName())); 117 } 118 break; 119 case SetAltColorOn: 120 lblk = InstanceManager.getDefault(LayoutBlockManager.class).getLayoutBlock(block); 121 if (lblk != null) { 122 lblk.setUseExtraColor(true); 123 } else { 124 throw new JmriException(Bundle.getMessage("ActionBlock_ErrorLayoutBlock", block.getDisplayName())); 125 } 126 break; 127 case SetAltColorOff: 128 lblk = InstanceManager.getDefault(LayoutBlockManager.class).getLayoutBlock(block); 129 if (lblk != null) { 130 lblk.setUseExtraColor(false); 131 } else { 132 throw new JmriException(Bundle.getMessage("ActionBlock_ErrorLayoutBlock", block.getDisplayName())); 133 } 134 break; 135 case SetNullValue: 136 block.setValue(null); 137 break; 138 case SetValue: 139 block.setValue(_selectBlockValue.evaluateValue(conditionalNG)); 140 break; 141 default: 142 throw new IllegalArgumentException("invalid oper state: " + theOper.name()); 143 } 144 }); 145 } 146 147 @Override 148 public FemaleSocket getChild(int index) throws IllegalArgumentException, UnsupportedOperationException { 149 throw new UnsupportedOperationException("Not supported."); 150 } 151 152 @Override 153 public int getChildCount() { 154 return 0; 155 } 156 157 @Override 158 public String getShortDescription(Locale locale) { 159 return Bundle.getMessage(locale, "ActionBlock_Short"); 160 } 161 162 @Override 163 public String getLongDescription(Locale locale) { 164 String namedBean = _selectNamedBean.getDescription(locale); 165 String state = _selectEnum.getDescription(locale); 166 167 if (_selectEnum.isDirectAddressing()) { 168 if (_selectEnum.getEnum() == DirectOperation.SetValue) { 169 String bundleKey = "ActionBlock_Long_Value"; 170 return Bundle.getMessage(locale, bundleKey, namedBean, _selectBlockValue.getDescription(locale)); 171 } 172 } 173 174 return Bundle.getMessage(locale, "ActionBlock_Long", namedBean, state); 175 } 176 177 /** {@inheritDoc} */ 178 @Override 179 public void setup() { 180 // Do nothing 181 } 182 183 /** {@inheritDoc} */ 184 @Override 185 public void registerListenersForThisClass() { 186 _selectNamedBean.registerListeners(); 187 _selectEnum.registerListeners(); 188 _selectBlockValue.registerListeners(); 189 } 190 191 /** {@inheritDoc} */ 192 @Override 193 public void unregisterListenersForThisClass() { 194 _selectNamedBean.unregisterListeners(); 195 _selectEnum.unregisterListeners(); 196 _selectBlockValue.unregisterListeners(); 197 } 198 199 /** {@inheritDoc} */ 200 @Override 201 public void disposeMe() { 202 } 203 204 public enum DirectOperation { 205 SetOccupied(Bundle.getMessage("ActionBlock_SetOccupied")), 206 SetNotOccupied(Bundle.getMessage("ActionBlock_SetNotOccupied")), 207 SetAltColorOn(Bundle.getMessage("ActionBlock_SetAltColorOn")), 208 SetAltColorOff(Bundle.getMessage("ActionBlock_SetAltColorOff")), 209 SetNullValue(Bundle.getMessage("ActionBlock_SetNullValue")), 210 SetValue(Bundle.getMessage("ActionBlock_SetValue")); 211 212 private final String _text; 213 214 private DirectOperation(String text) { 215 this._text = text; 216 } 217 218 @Override 219 public String toString() { 220 return _text; 221 } 222 223 } 224 225 /** {@inheritDoc} */ 226 @Override 227 public void getUsageDetail(int level, NamedBean bean, List<NamedBeanUsageReport> report, NamedBean cdl) { 228 _selectNamedBean.getUsageDetail(level, bean, report, cdl, this, LogixNG_SelectNamedBean.Type.Action); 229 } 230 231 /** {@inheritDoc} */ 232 @Override 233 public void propertyChange(PropertyChangeEvent evt) { 234 getConditionalNG().execute(); 235 } 236 237 private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ActionBlock.class); 238 239}