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 package sears.gui; 018 019 import java.awt.BorderLayout; 020 import java.awt.GridBagConstraints; 021 import java.awt.GridBagLayout; 022 import java.awt.GridLayout; 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 /** 041 * Class JDialogNormalizeAction. 042 * This dialog permits to define the parameters of a normalizeDuration action. 043 * i.e the min duration and the max duration of the ST. 044 */ 045 public class JDialogNormalizeAction extends SearsJDialog { 046 047 /** (<b>long</b>) serialVersionUID: The serialVersionUID */ 048 private static final long serialVersionUID = -6105540923502362579L; 049 private JPanel jContentPane; 050 private JPanel jPanelCenter; 051 052 protected static final int MIN = 0; 053 054 protected static final int MAX = 1; 055 056 private static final int NB_TIMES = 2; 057 058 private static final String[] MIN_MAX_SUFFIXES = new String[]{"min", "max"}; 059 private static final String[] DEFAULT_MIN_MAX = new String[]{"0.5", "5"}; 060 061 private JPanel[] jPanelTime = null; 062 private JLabel[] jLabelTime = null; 063 private JTextField[] jTextFieldTime = null; 064 private JSlider[] jSliderTime = null; 065 066 /** 067 * This is the default constructor 068 */ 069 public JDialogNormalizeAction() { 070 super(SearsResourceBundle.getResource("normalizeDuration_title")); 071 jPanelTime = new JPanel[NB_TIMES]; 072 jTextFieldTime = new JTextField[NB_TIMES]; 073 jSliderTime = new JSlider[NB_TIMES]; 074 jLabelTime = new JLabel[NB_TIMES]; 075 setContentPane(getJContentPane()); 076 configureSize(); 077 } 078 079 /** 080 * Method getJContentPane. 081 * <br><b>Summary:</b><br> 082 * return the contentPane 083 * @return (<b>JPanel</b>) A JPanel. 084 */ 085 private JPanel getJContentPane() { 086 if (jContentPane == null) { 087 jContentPane = new JPanel(); 088 jContentPane.setBorder(super.createEmptyBorder()); 089 jContentPane.setLayout(new BorderLayout()); 090 jContentPane.add(getJPanelCenter(), java.awt.BorderLayout.CENTER); 091 jContentPane.add(getJPanelButtons(), java.awt.BorderLayout.SOUTH); 092 } 093 return jContentPane; 094 } 095 096 /** 097 * This method initializes jPanel 098 * 099 * @return javax.swing.JPanel 100 */ 101 private JPanel getJPanelCenter() { 102 if (jPanelCenter == null) { 103 jPanelCenter = new JPanel(); 104 jPanelCenter.setLayout(new GridLayout(NB_TIMES,1)); 105 jPanelCenter.add(getJPanelTime(MIN)); 106 jPanelCenter.add(getJPanelTime(MAX)); 107 } 108 return jPanelCenter; 109 } 110 111 /** 112 * Method getTimePanel. 113 * <br><b>Summary:</b><br> 114 * Return a penl to define a time, that use a slider, and a textField. 115 * @param minMax MIN or MAX. 116 * @return (<b>JPanel</b>) A JPanel. 117 */ 118 private JPanel getJPanelTime(int minMax) { 119 if (jPanelTime[minMax] == null) { 120 jLabelTime[minMax] = new JLabel(); 121 jLabelTime[minMax].setText(SearsResourceBundle.getResource("normalizeDuration_"+MIN_MAX_SUFFIXES[minMax]+"_label")); 122 jPanelTime[minMax] = new JPanel(); 123 jPanelTime[minMax].setLayout(new GridBagLayout()); 124 GridBagConstraints gbc1 = new GridBagConstraints(); 125 gbc1.gridx = 0; 126 gbc1.gridy = 0; 127 jPanelTime[minMax].add(jLabelTime[minMax], gbc1); 128 GridBagConstraints gbc2 = new GridBagConstraints(); 129 gbc2.gridx = 1; 130 gbc2.gridy = 0; 131 gbc2.fill = GridBagConstraints.HORIZONTAL; 132 gbc2.weightx = 1; 133 jPanelTime[minMax].add(getJTextFieldTime(minMax), gbc2); 134 GridBagConstraints gbc3 = new GridBagConstraints(); 135 gbc3.gridx = 0; 136 gbc3.gridy = 1; 137 gbc3.gridwidth = 2; 138 gbc3.fill = GridBagConstraints.HORIZONTAL; 139 gbc3.weightx = 1; 140 jPanelTime[minMax].add(getJSliderTime(minMax), gbc3); 141 } 142 return jPanelTime[minMax]; 143 } 144 145 146 /** 147 * Method getJSliderTime. 148 * <br><b>Summary:</b><br> 149 * return the slider that correspond to the given min or max. 150 * @param minMax MIN or MAX. 151 * @return (<b>JSlider</b>) A JSlider. 152 */ 153 private JSlider getJSliderTime(int minMax) { 154 if(jSliderTime[minMax] == null){ 155 jSliderTime[minMax] = new JSlider(0, 100); 156 jSliderTime[minMax].setValue((int) Double.parseDouble(DEFAULT_MIN_MAX[minMax])*10); 157 final int minMaxFinal = minMax; 158 jSliderTime[minMax].addChangeListener(new ChangeListener() { 159 public void stateChanged(ChangeEvent e) { 160 valueChanged(e.getSource(), minMaxFinal); 161 } 162 }); 163 } 164 return jSliderTime[minMax]; 165 } 166 167 /** 168 * Method valueChanged. 169 * <br><b>Summary:</b><br> 170 * this method is called when a slider changed or value. 171 * @param source The slider that generates the event. 172 * @param minMax To know if it is min or max that changed. 173 */ 174 private void valueChanged(Object source, int minMax) { 175 //If the slider triggered the change, update the textField (if necessary). 176 if (source instanceof JSlider) { 177 //by default we will not update the textField value. 178 boolean updateTextField = false; 179 //retrieve the slider delay value 180 double sliderDelayValue = ((double) jSliderTime[minMax].getValue()) / 10; 181 updateTextField = true; 182 try { 183 // retrieve the TextField value. 184 double delay = getDoubleTextDelayValue(minMax); 185 if (delay != sliderDelayValue) { 186 updateTextField = true; 187 } 188 } catch (NumberFormatException e) { 189 //TextField value is not valid : update ! 190 updateTextField = true; 191 } 192 //update textField if necessary 193 if (updateTextField) { 194 jTextFieldTime[minMax].setText("" + sliderDelayValue); 195 } 196 } else if (source instanceof JTextField) { 197 //If the textDelay triggered the event, update the slider if necessary. 198 //Source is the TextDelay 199 try { 200 // retrieve the TextField value. 201 double delay = getDoubleTextDelayValue(minMax); 202 double sliderDelayValue = ((double) jSliderTime[minMax].getValue()) / 10; 203 if (delay != sliderDelayValue) { 204 // Udate slider. 205 //Beware if textField value is bigger than slider max 206 int newSliderValue = (int) (delay * 10); 207 if(Math.abs(newSliderValue) > jSliderTime[minMax].getMaximum()){ 208 jSliderTime[minMax].setMaximum(Math.abs(newSliderValue)); 209 } 210 jSliderTime[minMax].setValue(newSliderValue); 211 } 212 } catch (NumberFormatException e) { 213 //TextField value is not valid : do not update slider! 214 } 215 } 216 217 } 218 219 /** 220 * Method getDoubleTextDelayValue. 221 * <br><b>Summary:</b><br> 222 * This method returns the double value of the delay in the textfield for given minMax 223 * @param minMax To select the MIN or the MAX 224 * @return double The double value of the delay in the textfield. 225 * @throws NumberFormatException 226 */ 227 public double getDoubleTextDelayValue(int minMax) throws NumberFormatException{ 228 //the result of the method. 229 double result = 0; 230 String delayString = jTextFieldTime[minMax].getText(); 231 if (delayString != null && !delayString.equals("")) { 232 result = Double.parseDouble(delayString); 233 }else{ 234 result = 0; 235 } 236 //return the result; 237 return result; 238 } 239 240 241 /** 242 * Method getJTextFieldTime. 243 * <br><b>Summary:</b><br> 244 * return the textField that correspond to the given min or max. 245 * @param minMax MIN or MAX 246 * @return (<b>JTextField</b>) A JTextField. 247 */ 248 private JTextField getJTextFieldTime(int minMax) { 249 if (jTextFieldTime[minMax] == null) { 250 jTextFieldTime[minMax] = new JTextField(5); 251 jTextFieldTime[minMax].setToolTipText(SearsResourceBundle.getResource("delay_tip")); 252 jTextFieldTime[minMax].setText(DEFAULT_MIN_MAX[minMax]); 253 //add an action listener to validate when user press 'enter' in textField. 254 jTextFieldTime[minMax].addActionListener(new ActionListener() { 255 public void actionPerformed(ActionEvent e) { 256 okAction(); 257 } 258 }); 259 //Add a focus listener, to update slider when textfield lost focus. 260 final int minMaxFinal = minMax; 261 jTextFieldTime[minMax].addFocusListener(new FocusListener() { 262 public void focusLost(FocusEvent e) { 263 valueChanged(e.getSource(), minMaxFinal); 264 } 265 266 public void focusGained(FocusEvent e) { 267 //Nothing to do on focus gain 268 } 269 }); 270 } 271 return jTextFieldTime[minMax]; 272 } 273 274 /** 275 * Method okAction. 276 * <br><b>Summary:</b><br> 277 * This method is called when user validate the dialog. 278 */ 279 protected void okAction() { 280 //Just have to check parameters validity, if valids, dispose dialog,and set validation status to true. 281 String error = checkParameters(); 282 if (error != null && !error.equals("")) { 283 //Show error message. 284 JOptionPane.showMessageDialog(this, error, SearsResourceBundle.getResource("error_delayConfigurationError"), JOptionPane.ERROR_MESSAGE); 285 Trace.trace("Error in Delay parameters:" + error, Trace.WARNING_PRIORITY); 286 } else { 287 //else split configuration is valid, release dialog. 288 validationStatus = true; 289 dispose(); 290 } 291 } 292 293 /** 294 * Method checkParameters. 295 * <br><b>Summary:</b><br> 296 * This method checks the parameters. 297 * @return <b>String</b> "" if there is no error, or the error message. 298 */ 299 private String checkParameters() { 300 //Check file to open 301 String errorMessage = ""; 302 //check time for min and max. 303 for(int i= 0; i < NB_TIMES;i++ ){ 304 String delay = jTextFieldTime[i].getText(); 305 if (delay != null && !delay.equals("")) { 306 try { 307 Double.parseDouble(delay); 308 } catch (NumberFormatException e) { 309 //Delay value is not a number. 310 errorMessage += "["+MIN_MAX_SUFFIXES[i]+"]"+SearsResourceBundle.getResource("error_delayNotValid")+"\n"; 311 } 312 } else { 313 //Delay value is null. 314 errorMessage += "["+MIN_MAX_SUFFIXES[i]+"]"+SearsResourceBundle.getResource("error_delayNull")+"\n"; 315 } 316 } 317 return errorMessage; 318 } 319 320 /** 321 * Method getTimes. 322 * <br><b>Summary:</b><br> 323 * return the times configured by the user. 324 * chack that user validates the dialog. 325 * @return (<b>double[]</b>) The result of the normalize dialog, double[]=[MIN, MAX]. 326 */ 327 public double[] getTimes(){ 328 //The result of the method. 329 double[] result = new double[NB_TIMES]; 330 for(int i= 0; i<NB_TIMES;i++){ 331 result[i] = Double.parseDouble(jTextFieldTime[i].getText()); 332 } 333 //return the result. 334 return result; 335 } 336 337 /* (non-Javadoc) 338 * @see sears.gui.SearsJDialog#getDialogName() 339 */ 340 protected String getDialogName() { 341 return "normalizeDuration"; 342 } 343 344 }