001package jmri.jmrit.logixng.swing; 002 003import java.util.*; 004 005import javax.annotation.CheckForNull; 006import javax.annotation.Nonnull; 007import javax.swing.JComponent; 008import javax.swing.JDialog; 009import javax.swing.JLabel; 010import javax.swing.JPanel; 011 012import jmri.NamedBean; 013import jmri.NamedBean.BadUserNameException; 014import jmri.NamedBean.BadSystemNameException; 015import jmri.jmrit.logixng.Base; 016import jmri.jmrit.logixng.BaseManager; 017import jmri.jmrit.logixng.MaleSocket; 018 019/** 020 * The parent interface for configuring classes with Swing. 021 * 022 * @author Daniel Bergqvist Copyright 2018 023 */ 024public interface SwingConfiguratorInterface extends Comparable<SwingConfiguratorInterface> { 025 026 /** 027 * Set the dialog of this SWI. 028 * 029 * @param dialog the dialog 030 */ 031 public void setJDialog(JDialog dialog); 032 033 /** 034 * Set the dialog of this SWI. 035 * 036 * @return the dialog 037 */ 038 public JDialog getJDialog(); 039 040 /** 041 * Get the menu text for execute/evaluate. 042 * @return the menu text 043 */ 044 public String getExecuteEvaluateMenuText(); 045 046 /** 047 * Execute or evaluate an item that this object configures. 048 * @param object the object to execute or evaluate 049 */ 050 public void executeEvaluate(@Nonnull Base object); 051 052 /** 053 * Get the manager that handles the beans for the new object. 054 * This is used for validation of the system name for the bean that this 055 * class creates. 056 * 057 * @return the manager 058 */ 059 public BaseManager<? extends NamedBean> getManager(); 060 061 /** 062 * Get a configuration panel when a new object is to be created and we don't 063 * have it yet. 064 * This method initializes the panel with an empty configuration. 065 * 066 * @param buttonPanel panel with the buttons 067 * @return a panel that configures this object 068 * @throws IllegalArgumentException if this class does not support the class 069 * with the name given in parameter 'className' 070 */ 071 public JPanel getConfigPanel(JPanel buttonPanel) throws IllegalArgumentException; 072 073 /** 074 * Get a configuration panel for an object. 075 * This method initializes the panel with the configuration of the object. 076 * 077 * @param object the object for which to return a configuration panel 078 * @param buttonPanel panel with the buttons 079 * @return a panel that configures this object 080 */ 081 public JPanel getConfigPanel(@Nonnull Base object, JPanel buttonPanel) throws IllegalArgumentException; 082 083 /** 084 * Validate the form. 085 * <P> 086 * The parameter errorMessage is used to give the error message in case of 087 * an error. If there are errors, the error messages is added to the list 088 * errorMessage. 089 * 090 * @param errorMessages the error messages in case of an error 091 * @return true if data in the form is valid, false otherwise 092 */ 093 public boolean validate(@Nonnull List<String> errorMessages); 094 095 /** 096 * Get an example of a system name 097 * @return the system name 098 */ 099 public String getExampleSystemName(); 100 101 /** 102 * Create a new system name. 103 * @return a new system name 104 */ 105 public String getAutoSystemName(); 106 107 /** 108 * Create a new object with the data entered.This method must also register the object in its manager. 109 * 110 * @param systemName system name 111 * @param userName user name 112 * @return a male socket for the new object 113 */ 114 @Nonnull 115 public MaleSocket createNewObject(@Nonnull String systemName, @CheckForNull String userName) 116 throws BadUserNameException, BadSystemNameException; 117 118 /** 119 * Updates the object with the data in the form. 120 * 121 * @param object the object to update 122 */ 123 public void updateObject(@Nonnull Base object); 124 125 /** 126 * Returns the name of the class that this class configures. 127 * 128 * @return the name of the class this class configures. 129 */ 130 @Override 131 public String toString(); 132 133 /** 134 * Set default values for this dialog. 135 * This method is used by tests to be able to run validation without 136 * knowing which data that needs to be entered for the validation to pass. 137 */ 138 public default void setDefaultValues() { 139 // Do nothing 140 } 141 142 /** 143 * Is the SWI ready to be closed? 144 * @return true if the SWI is ready to be closed, false otherwise. 145 */ 146 public default boolean canClose() { 147 return true; 148 } 149 150 /** 151 * Dispose the panel and remove all the listeners that this class may have 152 * registered. 153 */ 154 public void dispose(); 155 156 157 /** 158 * Parses the message and creates a list of components there the given 159 * components are separated by JLabel components from the message. 160 * @param message the message to be parsed 161 * @param components the components 162 * @return the components separated with JLabel components 163 */ 164 public static List<JComponent> parseMessage(String message, JComponent[] components) { 165 List<JComponent> componentsToReturn = new ArrayList<>(); 166 StringBuilder sb = new StringBuilder(); 167 boolean parseNumber = false; 168 169 for (int index=0; index < message.length(); index++) { 170 int character = message.codePointAt(index); 171 172 if (parseNumber) { 173 if (character == '}') { 174 int number = Integer.parseInt(sb.toString()); 175 componentsToReturn.add(components[number]); 176 sb = new StringBuilder(); 177 parseNumber = false; 178 } else if ((character >= '0') && (character <= '9')) { 179 sb.appendCodePoint(character); 180 } else { 181 throw new IllegalArgumentException( 182 "left curly bracket must be followed by a digit but is followed by " 183 + Arrays.toString(Character.toChars(character))); 184 } 185 } else { 186 if (character == '{') { 187 parseNumber = true; 188 componentsToReturn.add(new JLabel(sb.toString())); 189 sb = new StringBuilder(); 190 } else { 191 sb.appendCodePoint(character); 192 } 193 } 194 } 195 196 if (sb.length() > 0) componentsToReturn.add(new JLabel(sb.toString())); 197 198 return componentsToReturn; 199 } 200 201 /** {@inheritDoc} */ 202 @Override 203 public default int compareTo(SwingConfiguratorInterface swi) { 204 return toString().compareTo(swi.toString()); 205 } 206 207}