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