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