001package jmri.jmrit.beantable.usermessagepreferences; 002 003import java.awt.BorderLayout; 004import java.awt.Dimension; 005import java.beans.PropertyChangeEvent; 006import java.util.ArrayList; 007import java.util.HashMap; 008import java.util.Map.Entry; 009import javax.swing.BorderFactory; 010import javax.swing.BoxLayout; 011import javax.swing.JCheckBox; 012import javax.swing.JComboBox; 013import javax.swing.JComponent; 014import javax.swing.JLabel; 015import javax.swing.JPanel; 016import javax.swing.JScrollPane; 017import javax.swing.JTabbedPane; 018import jmri.UserPreferencesManager; 019import jmri.jmrit.beantable.AudioTableAction; 020import jmri.jmrit.beantable.BlockTableAction; 021import jmri.jmrit.beantable.LRouteTableAction; 022import jmri.jmrit.beantable.LightTableAction; 023import jmri.jmrit.beantable.LogixTableAction; 024import jmri.jmrit.beantable.MemoryTableAction; 025import jmri.jmrit.beantable.ReporterTableAction; 026import jmri.jmrit.beantable.RouteTableAction; 027import jmri.jmrit.beantable.SensorTableAction; 028import jmri.jmrit.beantable.SignalGroupTableAction; 029import jmri.jmrit.beantable.SignalHeadTableAction; 030import jmri.jmrit.beantable.SignalMastTableAction; 031import jmri.jmrit.beantable.TransitTableAction; 032import jmri.jmrit.beantable.TurnoutTableAction; 033import jmri.swing.PreferencesPanel; 034import jmri.util.swing.JmriPanel; 035import org.openide.util.lookup.ServiceProvider; 036 037/** 038 * Pane to show User Message Preferences. 039 * 040 * @author Kevin Dickerson Copyright (C) 2009 041 */ 042@ServiceProvider(service = PreferencesPanel.class) 043public class UserMessagePreferencesPane extends JmriPanel implements PreferencesPanel { 044 045 UserPreferencesManager p; 046 047 public UserMessagePreferencesPane() { 048 super(); 049 p = jmri.InstanceManager.getDefault(UserPreferencesManager.class); 050 p.addPropertyChangeListener((PropertyChangeEvent e) -> { 051 if (e.getPropertyName().equals(UserPreferencesManager.PREFERENCES_UPDATED)) { 052 refreshOptions(); 053 } 054 }); 055 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 056 057 setMinimumMessagePref(); 058 add(tab); 059 } 060 061 private synchronized void setMinimumMessagePref() { 062 //This ensures that as a minimum that the following items are at least initialised and appear in the preference panel 063 p.setClassDescription(AudioTableAction.class.getName()); 064 p.setClassDescription(BlockTableAction.class.getName()); 065 066 p.setClassDescription(LightTableAction.class.getName()); 067 p.setClassDescription(LogixTableAction.class.getName()); 068 p.setClassDescription(LRouteTableAction.class.getName()); 069 p.setClassDescription(MemoryTableAction.class.getName()); 070 071 p.setClassDescription(ReporterTableAction.class.getName()); 072 p.setClassDescription(RouteTableAction.class.getName()); 073 074 p.setClassDescription(SensorTableAction.class.getName()); 075 p.setClassDescription(SignalGroupTableAction.class.getName()); 076 p.setClassDescription(SignalHeadTableAction.class.getName()); 077 p.setClassDescription(SignalMastTableAction.class.getName()); 078 079 p.setClassDescription(TransitTableAction.class.getName()); 080 p.setClassDescription(TurnoutTableAction.class.getName()); 081 082 newMessageTab(); 083 } 084 085 JTabbedPane tab = new JTabbedPane(); 086 087 private HashMap<JComboBox<Object>, ListItems> _comboBoxes = new HashMap<>(); 088 private HashMap<JCheckBox, ListItems> _checkBoxes = new HashMap<>(); 089 090 private synchronized void newMessageTab() { 091 remove(tab); 092 tab = new JTabbedPane(); 093 094 //might need to redo this so that it doesn't recreate everything all the time. 095 _comboBoxes = new HashMap<>(); 096 _checkBoxes = new HashMap<>(); 097 098 ArrayList<String> preferenceClassList = p.getPreferencesClasses(); 099 for (String strClass : preferenceClassList) { 100 JPanel classholder = new JPanel(); 101 classholder.setLayout(new BorderLayout()); 102 103 HashMap<Integer, String> options; 104 boolean add = false; 105 boolean addtoindependant = false; 106 if (p.getPreferencesSize(strClass) > 1) { 107 addtoindependant = true; 108 } 109 JPanel classPanel = new JPanel(); 110 classPanel.setLayout(new BoxLayout(classPanel, BoxLayout.Y_AXIS)); 111 classPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 112 for (int j = 0; j < p.getMultipleChoiceSize(strClass); j++) { 113 String itemName = p.getChoiceName(strClass, j); 114 options = p.getChoiceOptions(strClass, itemName); 115 if (options != null) { 116 JComboBox<Object> optionBox = new JComboBox<>(); 117 ListItems li = new ListItems(strClass, itemName); 118 _comboBoxes.put(optionBox, li); 119 li.isIncluded(addtoindependant); 120 optionBox.removeAllItems(); 121 for (Object value : options.values()) { 122 optionBox.addItem(value); 123 } 124 int current = p.getMultipleChoiceOption(strClass, itemName); 125 126 if (options.containsKey(current)) { 127 optionBox.setSelectedItem(options.get(current)); 128 } 129 if (addtoindependant) { 130 JPanel optionPanel = new JPanel(); 131 JLabel _comboLabel = new JLabel(p.getChoiceDescription(strClass, itemName), JLabel.LEFT); 132 _comboLabel.setAlignmentX(0.5f); 133 optionPanel.add(_comboLabel); 134 optionPanel.add(optionBox); 135 add = true; 136 classPanel.add(optionPanel); 137 } 138 } 139 } 140 ArrayList<String> singleList = p.getPreferenceList(strClass); 141 if (!singleList.isEmpty()) { 142 for (int i = 0; i < singleList.size(); i++) { 143 String itemName = p.getPreferenceItemName(strClass, i); 144 String description = p.getPreferenceItemDescription(strClass, itemName); 145 if ((description != null) && (!description.isEmpty())) { 146 JCheckBox check = new JCheckBox(description); 147 check.setSelected(p.getPreferenceState(strClass, itemName)); 148 ListItems li = new ListItems(strClass, itemName); 149 _checkBoxes.put(check, li); 150 li.isIncluded(addtoindependant); 151 152 if (addtoindependant) { 153 classPanel.add(check); 154 add = true; 155 } 156 } 157 } 158 } 159 if (add) { 160 classholder.add(classPanel, BorderLayout.NORTH); 161 if (p.getPreferencesSize(strClass) > 1) { 162 JScrollPane scrollPane = new JScrollPane(classholder); 163 scrollPane.setPreferredSize(new Dimension(300, 300)); 164 scrollPane.setBorder(BorderFactory.createEmptyBorder()); 165 tab.add(scrollPane, p.getClassDescription(strClass)); 166 } 167 } 168 } 169 HashMap<String, ArrayList<ListItems>> countOfItems = new HashMap<>(); 170 HashMap<String, ArrayList<JCheckBox>> countOfItemsCheck = new HashMap<>(); 171 HashMap<String, ArrayList<JComboBox<Object>>> countOfItemsCombo = new HashMap<>(); 172 173 for (Entry<JComboBox<Object>, ListItems> entry : _comboBoxes.entrySet()) { 174 if (!entry.getValue().isIncluded()) { 175 String strItem = entry.getValue().getItem(); 176 if (!countOfItems.containsKey(strItem)) { 177 countOfItems.put(strItem, new ArrayList<>()); 178 countOfItemsCombo.put(strItem, new ArrayList<>()); 179 } 180 ArrayList<ListItems> a = countOfItems.get(strItem); 181 a.add(entry.getValue()); 182 183 ArrayList<JComboBox<Object>> acb = countOfItemsCombo.get(strItem); 184 acb.add(entry.getKey()); 185 } 186 } 187 188 for (Entry<JCheckBox, ListItems> entry : _checkBoxes.entrySet()) { 189 if (!entry.getValue().isIncluded()) { 190 String strItem = entry.getValue().getItem(); 191 if (!countOfItems.containsKey(strItem)) { 192 countOfItems.put(strItem, new ArrayList<>()); 193 countOfItemsCheck.put(strItem, new ArrayList<>()); 194 } 195 ArrayList<ListItems> a = countOfItems.get(strItem); 196 a.add(entry.getValue()); 197 198 ArrayList<JCheckBox> acb = countOfItemsCheck.get(strItem); 199 acb.add(entry.getKey()); 200 } 201 } 202 203 JPanel miscPanel = new JPanel(); 204 miscPanel.setLayout(new BoxLayout(miscPanel, BoxLayout.Y_AXIS)); 205 206 JPanel mischolder = new JPanel(); 207 mischolder.setLayout(new BorderLayout()); 208 mischolder.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); 209 for (Entry<String, ArrayList<ListItems>> entry : countOfItems.entrySet()) { 210 ArrayList<ListItems> a = entry.getValue(); 211 ArrayList<JCheckBox> chb = countOfItemsCheck.get(entry.getKey()); 212 ArrayList<JComboBox<Object>> cob = countOfItemsCombo.get(entry.getKey()); 213 if (a.size() > 1) { 214 JPanel tableDeleteTabPanel = new JPanel(); 215 tableDeleteTabPanel.setLayout(new BoxLayout(tableDeleteTabPanel, BoxLayout.Y_AXIS)); 216 JLabel tableDeleteInfoLabel = new JLabel(p.getChoiceDescription(a.get(0).getClassName(), a.get(0).getItem()), JLabel.CENTER); 217 tableDeleteInfoLabel.setAlignmentX(0.5f); 218 tableDeleteTabPanel.add(tableDeleteInfoLabel); 219 JPanel inside = new JPanel(); 220 if (cob != null) { 221 JPanel insideCombo = new JPanel(); 222 int gridsize = (int) (Math.ceil((cob.size() / 2.0))); 223 insideCombo.setLayout(new jmri.util.javaworld.GridLayout2(gridsize, 2 * 2, 10, 2)); 224 for (JComboBox<Object> combo : cob) { 225 JLabel _comboLabel = new JLabel(p.getClassDescription(_comboBoxes.get(combo).getClassName()), JLabel.RIGHT); 226 _comboBoxes.get(combo).isIncluded(true); 227 insideCombo.add(_comboLabel); 228 insideCombo.add(combo); 229 } 230 inside.add(insideCombo); 231 } 232 if (chb != null) { 233 JPanel insideCheck = new JPanel(); 234 insideCheck.setLayout(new jmri.util.javaworld.GridLayout2(chb.size(), 1)); 235 for (JCheckBox check : chb) { 236 JLabel _checkLabel = new JLabel(p.getClassDescription(_checkBoxes.get(check).getClassName()), JLabel.RIGHT); 237 _checkBoxes.get(check).isIncluded(true); 238 insideCheck.add(_checkLabel); 239 insideCheck.add(check); 240 } 241 inside.add(insideCheck); 242 } 243 tableDeleteTabPanel.add(inside); 244 JScrollPane scrollPane = new JScrollPane(tableDeleteTabPanel); 245 scrollPane.setPreferredSize(new Dimension(300, 300)); 246 tab.add(scrollPane, entry.getKey()); 247 } else { 248 JPanel itemPanel = new JPanel(); 249 JPanel subItem = new JPanel(); 250 subItem.setLayout(new BoxLayout(subItem, BoxLayout.Y_AXIS)); 251 subItem.add(new JLabel(p.getClassDescription(a.get(0).getClassName()), JLabel.CENTER)); 252 253 if (countOfItemsCheck.containsKey(entry.getKey())) { 254 subItem.add(countOfItemsCheck.get(entry.getKey()).get(0)); 255 itemPanel.add(subItem); 256 miscPanel.add(itemPanel); 257 } 258 } 259 } 260 261 add(tab); 262 mischolder.add(miscPanel, BorderLayout.NORTH); 263 JScrollPane miscScrollPane = new JScrollPane(mischolder); 264 miscScrollPane.setPreferredSize(new Dimension(300, 300)); 265 266 tab.add(miscScrollPane, "Misc items"); 267 revalidate(); 268 } 269 270 @Override 271 public String getPreferencesItem() { 272 return "MESSAGES"; // NOI18N 273 } 274 275 @Override 276 public String getPreferencesItemText() { 277 return Bundle.getMessage("MenuMessages"); // NOI18N 278 } 279 280 @Override 281 public String getTabbedPreferencesTitle() { 282 return null; 283 } 284 285 @Override 286 public String getLabelKey() { 287 return null; 288 } 289 290 @Override 291 public JComponent getPreferencesComponent() { 292 return this; 293 } 294 295 @Override 296 public boolean isPersistant() { 297 return false; 298 } 299 300 @Override 301 public String getPreferencesTooltip() { 302 return null; 303 } 304 305 @Override 306 public void savePreferences() { 307 this.updateManager(); 308 } 309 310 @Override 311 public synchronized boolean isDirty() { 312 for (Entry<JComboBox<Object>, ListItems> entry : _comboBoxes.entrySet()) { 313 String strClass = entry.getValue().getClassName(); 314 String strItem = entry.getValue().getItem(); 315 if (!p.getChoiceOptions(strClass, strItem).get(p.getMultipleChoiceOption(strClass, strItem)).equals(entry.getKey().getSelectedItem())) { 316 return true; 317 } 318 } 319 for (Entry<JCheckBox, ListItems> entry : _checkBoxes.entrySet()) { 320 String strClass = entry.getValue().getClassName(); 321 String strItem = entry.getValue().getItem(); 322 if (p.getPreferenceState(strClass, strItem) != entry.getKey().isSelected()) { 323 return true; 324 } 325 } 326 return false; 327 } 328 329 @Override 330 public boolean isRestartRequired() { 331 return false; 332 } 333 334 @Override 335 public boolean isPreferencesValid() { 336 return true; // no validity checking performed 337 } 338 339 static class ListItems { 340 341 String strClass; 342 String item; 343 boolean included = false; 344 345 ListItems(String strClass, String item) { 346 this.strClass = strClass; 347 this.item = item; 348 } 349 350 String getClassName() { 351 return strClass; 352 } 353 354 String getItem() { 355 return item; 356 } 357 358 boolean isIncluded() { 359 return included; 360 } 361 362 void isIncluded(boolean boo) { 363 included = boo; 364 } 365 } 366 367 boolean updating = false; 368 369 public synchronized void updateManager() { 370 updating = true; 371 p.setLoading(); 372 373 for (Entry<JComboBox<Object>, ListItems> entry : _comboBoxes.entrySet()) { 374 String strClass = entry.getValue().getClassName(); 375 String strItem = entry.getValue().getItem(); 376 String strSelection = (String) entry.getKey().getSelectedItem(); 377 p.setMultipleChoiceOption(strClass, strItem, strSelection); 378 } 379 380 for (Entry<JCheckBox, ListItems> entry : _checkBoxes.entrySet()) { 381 String strClass = entry.getValue().getClassName(); 382 String strItem = entry.getValue().getItem(); 383 p.setPreferenceState(strClass, strItem, entry.getKey().isSelected()); 384 } 385 386 updating = false; 387 p.finishLoading(); 388 refreshOptions(); 389 } 390 391 private void refreshOptions() { 392 if (updating) { 393 return; 394 } 395 newMessageTab(); 396 } 397 398}