001 ///////////////////////////////////////////////// 002 // This file is part of Sears project. 003 // Subtitle Editor And Re-Synch 004 // A tool to easily modify and resynch movies subtitles. 005 ///////////////////////////////////////////////// 006 //This program is free software; 007 //you can redistribute it and/or modify it under the terms 008 //of the GNU General Public License 009 //as published by the Free Software Foundation; 010 //either version 2 of the License, or (at your option) any later version. 011 ///////////////////////////////////////////////// 012 //Sears project is available under sourceforge 013 // at adress: http://sourceforge.net/projects/sears/ 014 //Copyright (C) 2005 Booba Skaya 015 //Mail: booba.skaya@gmail.com 016 //////////////////////////////////////////////// 017 018 package sears.gui; 019 020 import java.awt.BorderLayout; 021 import java.awt.GridBagConstraints; 022 import java.awt.GridBagLayout; 023 import java.awt.event.ActionEvent; 024 import java.awt.event.ActionListener; 025 import java.awt.event.FocusEvent; 026 import java.awt.event.FocusListener; 027 028 import javax.swing.JLabel; 029 import javax.swing.JOptionPane; 030 import javax.swing.JPanel; 031 import javax.swing.JSlider; 032 import javax.swing.JTextField; 033 import javax.swing.event.ChangeEvent; 034 import javax.swing.event.ChangeListener; 035 036 import sears.tools.SearsResourceBundle; 037 import sears.tools.Trace; 038 039 /** 040 * Class DelayDialog. 041 * <br><b>Summary:</b><br> 042 * This class is a Dialog which permits to delay some subtitles. 043 */ 044 public class DelayDialog extends SearsJDialog { 045 046 private static final long serialVersionUID = -365612092452966123L; 047 048 private JPanel mainPanel = null; 049 050 private JPanel delayPanel = null; 051 052 private JLabel labelDelay = null; 053 054 private JTextField textDelay = null; 055 056 private JSlider jSliderDelay; 057 058 /** 059 * This is the default constructor 060 */ 061 public DelayDialog() { 062 super(SearsResourceBundle.getResource("delay_title")); 063 this.setContentPane(getMainPanel()); 064 configureSize(); 065 } 066 067 /** 068 * This method initializes jContentPane 069 * 070 * @return javax.swing.JPanel 071 */ 072 private JPanel getMainPanel() { 073 if (mainPanel == null) { 074 mainPanel = new JPanel(); 075 mainPanel.setLayout(new BorderLayout()); 076 mainPanel.add(getDelayPanel(), java.awt.BorderLayout.CENTER); 077 mainPanel.add(getJPanelButtons(), java.awt.BorderLayout.SOUTH); 078 } 079 return mainPanel; 080 } 081 082 /** 083 * This method initializes jPanel 084 * 085 * @return javax.swing.JPanel 086 */ 087 private JPanel getDelayPanel() { 088 if (delayPanel == null) { 089 labelDelay = new JLabel(); 090 labelDelay.setText(SearsResourceBundle.getResource("delay_label")); 091 delayPanel = new JPanel(); 092 delayPanel.setLayout(new GridBagLayout()); 093 GridBagConstraints gbc1 = new GridBagConstraints(); 094 gbc1.gridx = 0; 095 gbc1.gridy = 0; 096 delayPanel.add(labelDelay, gbc1); 097 GridBagConstraints gbc2 = new GridBagConstraints(); 098 gbc2.gridx = 1; 099 gbc2.gridy = 0; 100 gbc2.fill = GridBagConstraints.HORIZONTAL; 101 gbc2.weightx = 1; 102 delayPanel.add(getTextDelay(), gbc2); 103 GridBagConstraints gbc3 = new GridBagConstraints(); 104 gbc3.gridx = 0; 105 gbc3.gridy = 1; 106 gbc3.gridwidth = 2; 107 gbc3.fill = GridBagConstraints.HORIZONTAL; 108 gbc3.weightx = 1; 109 delayPanel.add(getJSliderDelay(), gbc3); 110 } 111 return delayPanel; 112 } 113 114 /** 115 * Method getJSpinnerDelay. 116 * <br><b>Summary:</b><br> 117 * This method creates the JSpinner to control the delay 118 * @return JSpinner. 119 */ 120 private JSlider getJSliderDelay() { 121 if(jSliderDelay == null){ 122 jSliderDelay = new JSlider(-100, 100); 123 jSliderDelay.setValue(10); 124 jSliderDelay.addChangeListener(new ChangeListener() { 125 public void stateChanged(ChangeEvent e) { 126 valueChanged(e.getSource()); 127 } 128 }); 129 } 130 return jSliderDelay; 131 } 132 133 /** 134 * Method valueChanged. 135 * <br><b>Summary:</b><br> 136 * This method is called when textField changed, or when JSpinner changed. 137 * @param source The one which change the first. 138 */ 139 protected void valueChanged(Object source) { 140 //If the slider triggered the change, update the textField (if necessary). 141 if (source.equals(jSliderDelay)) { 142 //by default we will not update the textField value. 143 boolean updateTextField = false; 144 //retrieve the slider delay value 145 double sliderDelayValue = ((double) jSliderDelay.getValue()) / 10; 146 updateTextField = true; 147 try { 148 // retrieve the TextField value. 149 double delay = getDoubleTextDelayValue(); 150 if (delay != sliderDelayValue) { 151 updateTextField = true; 152 } 153 } catch (NumberFormatException e) { 154 //TextField value is not valid : update ! 155 updateTextField = true; 156 } 157 //update textField if necessary 158 if (updateTextField) { 159 getTextDelay().setText("" + sliderDelayValue); 160 } 161 } else if (source.equals(textDelay)) { 162 //If the textDelay triggered the event, update the slider if necessary. 163 //Source is the TextDelay 164 try { 165 // retrieve the TextField value. 166 double delay = getDoubleTextDelayValue(); 167 double sliderDelayValue = ((double) jSliderDelay.getValue()) / 10; 168 if (delay != sliderDelayValue) { 169 // Udate slider. 170 //Beware if textField value is bigger than slider max 171 int newSliderValue = (int) (delay * 10); 172 if(Math.abs(newSliderValue) > jSliderDelay.getMaximum()){ 173 jSliderDelay.setMaximum(Math.abs(newSliderValue)); 174 jSliderDelay.setMinimum(-Math.abs(newSliderValue)); 175 } 176 jSliderDelay.setValue(newSliderValue); 177 } 178 } catch (NumberFormatException e) { 179 //TextField value is not valid : do not update slider! 180 } 181 } 182 } 183 184 185 /** 186 * Method getDoubleTextDelayValue. 187 * <br><b>Summary:</b><br> 188 * This method returns the double value of the delay in the textfield. 189 * @return double The double value of the delay in the textfield. 190 * @throws NumberFormatException 191 */ 192 public double getDoubleTextDelayValue() throws NumberFormatException{ 193 //the result of the method. 194 double result = 0; 195 String delayString = getTextDelay().getText(); 196 if (delayString != null && !delayString.equals("")) { 197 result = Double.parseDouble(delayString); 198 }else{ 199 result = 0; 200 } 201 //return the result; 202 return result; 203 } 204 /** 205 * Method okAction. 206 * <br><b>Summary:</b><br> 207 * This method is called when user validate the dialog. 208 */ 209 protected void okAction() { 210 //Just have to check parameters validity, if valids, dispose dialog,and set validation status to true. 211 String error = checkParameters(); 212 if (error != null && !error.equals("")) { 213 //Show error message. 214 JOptionPane.showMessageDialog(this, error, SearsResourceBundle.getResource("error_delayConfigurationError"), JOptionPane.ERROR_MESSAGE); 215 Trace.trace("Error in Delay parameters:" + error, Trace.WARNING_PRIORITY); 216 } else { 217 //else split configuration is valid, release dialog. 218 validationStatus = true; 219 dispose(); 220 } 221 } 222 223 /** 224 * Method checkParameters. 225 * <br><b>Summary:</b><br> 226 * This method checks the parameters. 227 * @return <b>String</b> "" if there is no error, or the error message. 228 */ 229 private String checkParameters() { 230 //Check file to open 231 String errorMessage = ""; 232 //check delay. 233 String delay = getTextDelay().getText(); 234 if (delay != null && !delay.equals("")) { 235 try { 236 Double.parseDouble(delay); 237 } catch (NumberFormatException e) { 238 //Delay value is not a number. 239 errorMessage += SearsResourceBundle.getResource("error_delayNotValid")+"\n"; 240 } 241 } else { 242 //Delay value is null. 243 errorMessage += SearsResourceBundle.getResource("error_delayNull")+"\n"; 244 } 245 return errorMessage; 246 } 247 248 /** 249 * This method initializes jTextField 250 * 251 * @return javax.swing.JTextField 252 */ 253 private JTextField getTextDelay() { 254 if (textDelay == null) { 255 textDelay = new JTextField(5); 256 textDelay.setToolTipText(SearsResourceBundle.getResource("delay_tip")); 257 textDelay.setText("1"); 258 //add an action listener to validate when user press 'enter' in textField. 259 textDelay.addActionListener(new ActionListener() { 260 public void actionPerformed(ActionEvent e) { 261 okAction(); 262 } 263 }); 264 //Add a focus listener, to update slider when textfield lost focus. 265 textDelay.addFocusListener(new FocusListener() { 266 public void focusLost(FocusEvent e) { 267 valueChanged(e.getSource()); 268 } 269 270 public void focusGained(FocusEvent e) { 271 //Nothing to do on focus gain 272 } 273 }); 274 } 275 return textDelay; 276 } 277 278 279 /** 280 * Method getDelay. 281 * <br><b>Summary:</b><br> 282 * Return the entered delay. 283 * @return <b>double</b> The entered delay. 284 */ 285 public double getDelay() { 286 return Double.parseDouble(getTextDelay().getText()); 287 } 288 289 /* (non-Javadoc) 290 * @see sears.gui.SearsJDialog#getDialogName() 291 */ 292 protected String getDialogName() { 293 return "delay"; 294 } 295 }