001package jmri.jmrit.vsdecoder.swing; 002 003import java.awt.BorderLayout; 004import java.awt.GridBagConstraints; 005import java.awt.GridBagLayout; 006import java.awt.Insets; 007import java.awt.event.ActionEvent; 008import java.awt.event.ActionListener; 009import java.awt.event.KeyEvent; 010import java.beans.PropertyChangeEvent; 011import java.beans.PropertyChangeListener; 012import java.util.ArrayList; 013import java.util.HashMap; 014import java.util.Map; 015import javax.swing.BorderFactory; 016import javax.swing.Box; 017import javax.swing.BoxLayout; 018import javax.swing.JButton; 019import javax.swing.JComponent; 020import javax.swing.JLabel; 021import javax.swing.JPanel; 022import javax.swing.SwingConstants; 023import javax.swing.border.Border; 024import jmri.jmrit.vsdecoder.EngineSoundEvent; 025import jmri.jmrit.vsdecoder.SoundEvent; 026import jmri.jmrit.vsdecoder.VSDConfig; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030/** 031 * New GUI pane for a Virtual Sound Decoder (VSDecoder). 032 * 033 * <hr> 034 * This file is part of JMRI. 035 * <p> 036 * JMRI is free software; you can redistribute it and/or modify it under 037 * the terms of version 2 of the GNU General Public License as published 038 * by the Free Software Foundation. See the "COPYING" file for a copy 039 * of this license. 040 * <p> 041 * JMRI is distributed in the hope that it will be useful, but WITHOUT 042 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 043 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 044 * for more details. 045 * 046 * @author Mark Underwood Copyright (C) 2011 047 */ 048public class VSDControl extends JPanel { 049 050 public static final String OPTION_CHANGE = "OptionChange"; // NOI18N 051 public static final String DELETE = "DeleteDecoder"; // NOI18N 052 053 // Map of Mnemonic KeyEvent values to GUI Components 054 private static final Map<String, Integer> Mnemonics = new HashMap<>(); 055 056 static { 057 // GUI buttons 058 Mnemonics.put("OptionButton", KeyEvent.VK_O); 059 Mnemonics.put("DeleteButton", KeyEvent.VK_D); 060 } 061 062 String address; 063 064 Border tb; 065 JLabel addressLabel; 066 JButton optionButton; 067 JButton deleteButton; 068 069 JPanel soundsPanel; 070 JPanel configPanel; 071 072 private VSDConfig config; 073 074 /** 075 * Constructor 076 */ 077 public VSDControl() { 078 super(); 079 initComponents(""); 080 } 081 082 /** 083 * Constructor 084 * 085 * @param title (String) : Window title 086 */ 087 public VSDControl(String title) { 088 super(); 089 address = title; 090 config = new VSDConfig(); 091 initComponents(title); 092 } 093 094 public VSDControl(VSDConfig c) { 095 super(); 096 config = c; 097 address = config.getLocoAddress().toString(); 098 initComponents(address); 099 } 100 101 static public JPanel generateBlank() { 102 VSDControl temp = new VSDControl(""); 103 JLabel jl = new JLabel(Bundle.getMessage("BlankVSDControlLabel")); 104 jl.setMinimumSize(temp.getPreferredSize()); 105 jl.setPreferredSize(temp.getPreferredSize()); 106 jl.setHorizontalAlignment(SwingConstants.CENTER); 107 JPanel jp = new JPanel(); 108 jp.setLayout(new BorderLayout()); 109 jp.add(jl, BorderLayout.CENTER); 110 jl.setMinimumSize(temp.getPreferredSize()); 111 jp.setPreferredSize(temp.getPreferredSize()); 112 jp.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), 113 BorderFactory.createLoweredBevelBorder())); 114 return jp; 115 } 116 117 private GridBagConstraints setConstraints(int x, int y) { 118 return setConstraints(x, y, GridBagConstraints.HORIZONTAL, new Insets(2, 2, 2, 2), GridBagConstraints.LINE_START); 119 } 120 121 /* 122 private GridBagConstraints setConstraints(int x, int y, int fill) { 123 return setConstraints(x, y, fill, new Insets(2,2,2,2), GridBagConstraints.LINE_START); 124 } 125 */ 126 127 private GridBagConstraints setConstraints(int x, int y, int fill, Insets ins, int anchor) { 128 GridBagConstraints gbc1 = new GridBagConstraints(); 129 gbc1.insets = ins; 130 gbc1.gridx = x; 131 gbc1.gridy = y; 132 gbc1.weightx = 100.0; 133 gbc1.weighty = 100.0; 134 gbc1.gridwidth = 1; 135 gbc1.anchor = anchor; 136 gbc1.fill = fill; 137 138 return gbc1; 139 } 140 141 /** 142 * Initialize the GUI components. 143 * @param title future title, not yet coded.. 144 */ 145 protected void initComponents(String title) { 146 // Create the border. 147 // Could make this a titled border with the loco address as the title... 148 //tb = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED); 149 tb = BorderFactory.createCompoundBorder(BorderFactory.createRaisedBevelBorder(), 150 BorderFactory.createLoweredBevelBorder()); 151 152 this.setBorder(tb); 153 154 this.setLayout(new GridBagLayout()); 155 156 // Create the buttons and slider 157 soundsPanel = new JPanel(); 158 soundsPanel.setLayout(new GridBagLayout()); 159 addressLabel = new JLabel(address); 160 161 configPanel = new JPanel(); 162 configPanel.setLayout(new BoxLayout(configPanel, BoxLayout.PAGE_AXIS)); 163 optionButton = new JButton(Bundle.getMessage("OptionsButtonLabel")); 164 deleteButton = new JButton(Bundle.getMessage("ButtonDelete")); 165 configPanel.add(Box.createHorizontalGlue()); 166 configPanel.add(optionButton); 167 optionButton.setToolTipText(Bundle.getMessage("MgrOptionButtonToolTip")); 168 optionButton.setMnemonic(Mnemonics.get("OptionButton")); 169 configPanel.add(Box.createHorizontalGlue()); 170 configPanel.add(deleteButton); 171 deleteButton.setToolTipText(Bundle.getMessage("MgrDeleteButtonToolTip")); 172 deleteButton.setMnemonic(Mnemonics.get("DeleteButton")); 173 174 JPanel alPanel = new JPanel(); 175 alPanel.setLayout(new BoxLayout(alPanel, BoxLayout.PAGE_AXIS)); 176 alPanel.add(addressLabel); 177 alPanel.add(new JLabel(config.getProfileName())); 178 179 // Add them to the panel 180 this.add(alPanel, new GridBagConstraints(0, 0, 1, 2, 100.0, 100.0, 181 GridBagConstraints.LINE_START, 182 GridBagConstraints.NONE, 183 new Insets(2, 2, 2, 2), 184 0, 0)); 185 this.add(soundsPanel, setConstraints(2, 0)); 186 this.add(configPanel, setConstraints(3, 0)); 187 188 optionButton.addActionListener(new ActionListener() { 189 @Override 190 public void actionPerformed(ActionEvent e) { 191 optionButtonPressed(e); 192 } 193 }); 194 deleteButton.addActionListener(new ActionListener() { 195 @Override 196 public void actionPerformed(ActionEvent e) { 197 deleteButtonPressed(e); 198 } 199 }); 200 201 this.setVisible(true); 202 } 203 204 /** 205 * Add buttons for the selected Profile's defined sounds 206 * @param elist list of sounds to make buttons from. 207 */ 208 public void addSoundButtons(ArrayList<SoundEvent> elist) { 209 soundsPanel.removeAll(); 210 for (SoundEvent e : elist) { 211 if (e.getButton() != null) { 212 log.debug("adding button {}", e.getButton()); 213 JComponent jc = e.getButton(); 214 GridBagConstraints gbc = new GridBagConstraints(); 215 // Force the EngineSoundEvent to the second row. 216 if (e instanceof EngineSoundEvent) { 217 gbc.gridy = 1; 218 gbc.gridwidth = elist.size() - 1; 219 gbc.fill = GridBagConstraints.NONE; 220 gbc.anchor = GridBagConstraints.LINE_START; 221 soundsPanel.add(jc, gbc); 222 } else { 223 gbc.gridy = 0; 224 soundsPanel.add(jc, gbc); 225 } 226 } 227 } 228 } 229 230 /** 231 * Handle "Option" button presses. 232 * @param e unused. 233 */ 234 protected void optionButtonPressed(ActionEvent e) { 235 log.debug("({}) Option Button Pressed", address); 236 VSDOptionsDialog d = new VSDOptionsDialog(this, Bundle.getMessage("OptionsDialogTitlePrefix") + " " + this.address); 237 d.addPropertyChangeListener(new PropertyChangeListener() { 238 @Override 239 public void propertyChange(PropertyChangeEvent event) { 240 log.debug("property change name: {}, old: {}, new: {}", event.getPropertyName(), event.getOldValue(), event.getNewValue()); 241 optionsDialogPropertyChange(event); 242 } 243 }); 244 } 245 246 /** 247 * Handle "Delete" button presses. 248 * @param e unused. 249 */ 250 protected void deleteButtonPressed(ActionEvent e) { 251 log.debug("({}) Delete Button Pressed", address); 252 firePropertyChange(DELETE, address, null); 253 } 254 255 /** 256 * Callback for the Option Dialog. 257 * @param event the event to get new value from. 258 */ 259 protected void optionsDialogPropertyChange(PropertyChangeEvent event) { 260 log.debug("internal options dialog handler"); 261 firePropertyChange(OPTION_CHANGE, null, event.getNewValue()); 262 } 263 264 private static final Logger log = LoggerFactory.getLogger(VSDControl.class); 265 266}