001package jmri.jmrit.conditional; 002 003import java.awt.event.ActionEvent; 004import java.util.List; 005 006import javax.annotation.Nonnull; 007 008import javax.swing.Box; 009import javax.swing.BoxLayout; 010import javax.swing.JComponent; 011import javax.swing.JLabel; 012import javax.swing.JPanel; 013import javax.swing.JTextField; 014 015import jmri.*; 016import jmri.util.JmriJFrame; 017 018/** 019 * Basis for ConditionalEditFrame and ConditionalCopyFrame. 020 * Holds the common features. 021 * 022 * @author Pete Cressman Copyright (C) 2020 023 */ 024public class ConditionalFrame extends JmriJFrame { 025 protected ConditionalList _parent; 026 boolean _dataChanged = false; 027 028 // ------------ Current Conditional Information ------------ 029 List<ConditionalVariable> _variableList; 030 List<ConditionalAction> _actionList; 031 032 Conditional.AntecedentOperator _logicType = Conditional.AntecedentOperator.ALL_AND; 033 String _antecedent; 034 boolean _trigger; 035 boolean _referenceByMemory; 036 037 // ------------------ Common window parts -------------- 038 private JTextField _conditionalUserName; 039 040 static final int STRUT = 10; 041 042 // ------------------------------------------------------------------ 043 044 ConditionalFrame(String title, @Nonnull Conditional conditional, ConditionalList parent) { 045 super(title, false, false); 046 _parent = parent; 047 _variableList = conditional.getCopyOfStateVariables(); 048 _actionList = conditional.getCopyOfActions(); 049 _logicType = conditional.getLogicType(); 050 _antecedent = conditional.getAntecedentExpression(); 051 } 052 053 JPanel makeTopPanel(@Nonnull Conditional conditional) { 054 JPanel panel = new JPanel(); 055 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 056 JPanel panel1 = new JPanel(); 057 panel1.add(new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("ColumnSystemName")))); 058 JTextField systemName = new JTextField(30); 059 systemName.setText(conditional.getSystemName()); 060 systemName.setEditable(false); 061 panel1.add(systemName); 062 panel.add(panel1); 063 JPanel panel2 = new JPanel(); 064 panel2.add(new JLabel(Bundle.getMessage("MakeLabel", Bundle.getMessage("ColumnUserName")))); 065 _conditionalUserName = new JTextField(30); 066 panel2.add(_conditionalUserName); 067 _conditionalUserName.setText(conditional.getUserName()); 068 _conditionalUserName.setToolTipText(Bundle.getMessage("ConditionalUserNameHint")); 069 panel.add(panel2); 070 return panel; 071 } 072 073 /** 074 * Create Variable and Action editing pane center part. (Utility) 075 * 076 * @param comp Field or comboBox to include on sub pane 077 * @param label property key for label 078 * @param hint property key for tooltip for this sub pane 079 * @return JPanel containing interface 080 */ 081 JPanel makeEditPanel(@Nonnull JComponent comp, @Nonnull String label, @javax.annotation.CheckForNull String hint) { 082 JPanel panel = new JPanel(); 083 panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); 084 JPanel p = new JPanel(); 085 p.add(new JLabel(Bundle.getMessage(label))); 086 panel.add(p); 087 if (hint != null) { 088 panel.setToolTipText(Bundle.getMessage(hint)); 089 } 090 comp.setMaximumSize(comp.getPreferredSize()); // override for text fields 091 panel.add(comp); 092 panel.add(Box.createVerticalGlue()); 093 return panel; 094 } 095 096 /** 097 * Respond to the Update Conditional Button in the Edit Conditional window. 098 * 099 * @param e The event heard 100 * @return true if updated 101 */ 102 boolean updateConditionalPressed(ActionEvent e) { 103 log.debug("updateConditionalPressed"); 104 String pref = InstanceManager.getDefault(jmri.LogixManager.class).getSystemPrefix(); 105 // The IX:RTXINITIALIZER keyword has a type of NONE 106 // Safely remove elements from the list (or use array.remove) if more than 1 107 _variableList.removeIf( cvar -> 108 (cvar.getType() == Conditional.Type.NONE && !cvar.getName().equals(pref + "X:RTXINITIALIZER"))); 109 // and actions 110 _actionList.removeIf(cact -> cact.getType() == Conditional.Action.NONE); 111 if (_parent.updateConditional(_conditionalUserName.getText(), _logicType, _trigger, _antecedent)) { 112 if (_dataChanged) { 113 _parent._showReminder = true; 114 } 115 return true; 116 } 117 return false; 118 } 119 120 /** 121 * Respond to the Cancel button in the Edit Conditional frame. 122 * <p> 123 * Does the cleanup from deleteConditionalPressed, updateConditionalPressed 124 * and _editConditionalFrame window closer. 125 */ 126 void cancelConditionalPressed() { 127 log.debug("cancelConditionalPressed"); 128 _dataChanged = false; 129 _parent.closeConditionalFrame(); 130 } 131 132 boolean checkReferenceByMemory(@Nonnull String name) { 133 _referenceByMemory = false; 134 if (name.length() > 0 && name.charAt(0) == '@') { 135 String memName = name.substring(1); 136 if (!_parent.confirmIndirectMemory(memName)) { 137 return false; 138 } 139 memName = _parent.validateMemoryReference(memName); 140 if (memName == null) { 141 return false; 142 } 143 _referenceByMemory = true; 144 } 145 return true; 146 } 147 148 /** 149 * Check that a state variable is not also used as an action 150 * @param name of the state variable 151 * @param itemType item type of the state variable 152 * @return true if action is not an action of if the user OK's 153 * its use as such. 154 */ 155 boolean checkIsAction(@Nonnull String name, Conditional.ItemType itemType) { 156 String actionName = null; 157 for (ConditionalAction action : _actionList) { 158 Conditional.ItemType actionType = action.getType().getItemType(); 159 if (itemType == actionType) { 160 if (name.equals(action.getDeviceName())) { 161 actionName = action.getDeviceName(); 162 } else { 163 NamedBean bean = action.getBean(); 164 if (bean != null && 165 (name.equals(bean.getSystemName()) || 166 name.equals(bean.getUserName()))) { 167 actionName = action.getDeviceName(); 168 } 169 } 170 } 171 if (actionName != null) { 172 return _parent.confirmActionAsVariable(actionName, name); 173 } 174 } 175 return true; 176 } 177 178 /** 179 * Check that an action is not also used as a state variable 180 * @param name of the action 181 * @param itemType item type of the action 182 * @return true if action is not a state variable of if the user OK's 183 * its use as such. 184 */ 185 boolean checkIsVariable(@Nonnull String name, Conditional.ItemType itemType) { 186 String varName = null; 187 for (ConditionalVariable condVar : _variableList) { 188 Conditional.ItemType varType = condVar.getType().getItemType(); 189 if (itemType == varType) { 190 if (name.equals(condVar.getName())) { 191 varName = condVar.getName(); 192 } else { 193 NamedBean bean = condVar.getBean(); 194 if (bean != null && 195 (name.equals(bean.getSystemName()) || 196 name.equals(bean.getUserName()))) { 197 varName = condVar.getName(); 198 } 199 } 200 } 201 if (varName != null) { 202 return _parent.confirmActionAsVariable(name, varName); 203 } 204 } 205 return true; 206 } 207 208 private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ConditionalFrame.class); 209 210}