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 availbale 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.GridLayout; 024 import java.awt.event.ActionEvent; 025 import java.awt.event.ActionListener; 026 import java.util.ArrayList; 027 028 import javax.swing.BorderFactory; 029 import javax.swing.JButton; 030 import javax.swing.JLabel; 031 import javax.swing.JPanel; 032 import javax.swing.JSlider; 033 import javax.swing.JTextField; 034 import javax.swing.event.ChangeEvent; 035 import javax.swing.event.ChangeListener; 036 037 import sears.file.Subtitle; 038 import sears.file.SubtitleFile; 039 import sears.tools.SearsResourceBundle; 040 041 /** 042 * Class ResynchroDialog. 043 * <br><b>Summary:</b><br> 044 * The GUI to do a resynchro 045 */ 046 public class ResynchroDialog extends SearsJDialog { 047 private static final long serialVersionUID = 7702754672054592460L; 048 049 private JPanel jContentPane = null; 050 051 private JPanel mainPanel = null; 052 053 private JLabel[] jLabelSource = null; 054 055 private JTextField[] jTextSource = null; 056 057 private JLabel[] jLabelDestination = null; 058 059 private JTextField[] jTextDestination = null; 060 061 private JSlider[] jSliders = null; 062 063 private JLabel[] jLabelSubtitles = null; 064 065 /**The sources, if precised at Dialog construction*/ 066 private int[] sources; 067 068 /**The subtitleList, that contains all the subtitles.*/ 069 private ArrayList<Subtitle> subtitleList; 070 071 /** 072 * Constructor ResynchroDialog. 073 * <br><b>Summary:</b><br> 074 * The constructor of the class ResynchroDialog 075 * Construct a new Resynchro dialog, using the given sources. 076 * @param subtitleList The subtitles. 077 * @param sources The index of the selected subtitles for the resynchro. 078 */ 079 public ResynchroDialog(ArrayList<Subtitle> subtitleList, int[] sources) { 080 super(SearsResourceBundle.getResource("resynch_title")); 081 this.sources = sources; 082 this.subtitleList = subtitleList; 083 //construct the source/Destination arrays using sources size. 084 jLabelSource = new JLabel[sources.length]; 085 jLabelDestination = new JLabel[sources.length]; 086 jTextSource = new JTextField[sources.length]; 087 jTextDestination = new JTextField[sources.length]; 088 jSliders = new JSlider[sources.length]; 089 jLabelSubtitles = new JLabel[sources.length]; 090 initialize(); 091 configureSize(); 092 } 093 094 /** 095 * Constructor ResynchroDialog. 096 * <br><b>Summary:</b><br> 097 * The constructor of the class ResynchroDialog 098 * @param subtitleList The subtitles. 099 */ 100 public ResynchroDialog(ArrayList<Subtitle> subtitleList) { 101 this(subtitleList, new int[]{0, 0}); 102 } 103 104 /** 105 * This method initializes this 106 */ 107 protected void initialize() { 108 this.setContentPane(getJContentPane()); 109 setLocationRelativeTo(getParent()); 110 validationStatus=false; 111 } 112 113 /** 114 * This method initializes jContentPane 115 * 116 * @return javax.swing.JPanel 117 */ 118 private JPanel getJContentPane() { 119 if (jContentPane == null) { 120 jContentPane = new JPanel(); 121 jContentPane.setLayout(new BorderLayout()); 122 jContentPane.add(getMainPanel(), java.awt.BorderLayout.CENTER); 123 jContentPane.add(getJPanelButtons(), java.awt.BorderLayout.SOUTH); 124 } 125 return jContentPane; 126 } 127 128 /** 129 * This method initializes jPanel 130 * 131 * @return javax.swing.JPanel 132 */ 133 private JPanel getMainPanel() { 134 if (mainPanel == null) { 135 mainPanel = new JPanel(); 136 mainPanel.setLayout(new GridLayout(sources.length, 1)); 137 mainPanel.setBorder(super.createEmptyBorder()); 138 for(int i = 0; i < sources.length; i++){ 139 mainPanel.add(getJPanelSubtitle(i)); 140 } 141 } 142 return mainPanel; 143 } 144 145 /** 146 * Method getJPanelSubtitle. 147 * <br><b>Summary:</b><br> 148 * This method returns the JPanel that is used to define the subtitle of the given index. 149 * @param index The index of the resynchro subtitle. 150 * @return (<b>JPanel</b>) the JPanel that is used to define the subtitle of the given index. 151 */ 152 private JPanel getJPanelSubtitle(int index) { 153 //The result of the method. 154 JPanel result = new JPanel(); 155 result.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "["+index+"]")); 156 result.setLayout(new GridBagLayout()); 157 final int myIndex = index; 158 //Now construct the panel content. 159 jTextSource[index] = new JTextField("00:00:00,000"); 160 jLabelSource[index] = new JLabel(SearsResourceBundle.getResource("resynch_source")+" "+index+":"); 161 jTextDestination[index] = new JTextField("00:00:00,000"); 162 //change the destination value if subttitle is anchored. 163 Subtitle subtitle = subtitleList.get(sources[index]); 164 if(subtitle.isAnchored()){ 165 jTextDestination[index].setText(SubtitleFile.timeToString(subtitle.getAnchor())); 166 } 167 jLabelDestination[index] = new JLabel(SearsResourceBundle.getResource("resynch_destination")+" "+index+":"); 168 //Construct the JSlider, current value is the selected source index. 169 jLabelSubtitles[index] = new JLabel(((Subtitle) subtitleList.get(sources[index])).getSubtitle()); 170 jSliders[index] = new JSlider(0, subtitleList.size()-1); 171 jSliders[index].addChangeListener(new ChangeListener() { 172 public void stateChanged(ChangeEvent e) { 173 sliderValueChanged(myIndex); 174 } 175 }); 176 jSliders[index].setValue(sources[index]); 177 //Construct a button that will permit to copy source to destination. 178 JButton jButtonCopy = new JButton("=>"); 179 jButtonCopy.setToolTipText(SearsResourceBundle.getResource("resynch_copy")); 180 jButtonCopy.addActionListener(new ActionListener() { 181 public void actionPerformed(ActionEvent e) { 182 copyAction(myIndex); 183 } 184 }); 185 186 //Add the component in the panel using GridBagLayout. 187 GridBagConstraints gbc1 = new GridBagConstraints(); 188 gbc1.gridx = 0; 189 gbc1.gridy = 0; 190 gbc1.ipadx = 4; 191 result.add(jLabelSource[index], gbc1); 192 GridBagConstraints gbc2 = new GridBagConstraints(); 193 gbc2.gridx = 1; 194 gbc2.gridy = 0; 195 gbc2.fill = GridBagConstraints.HORIZONTAL; 196 result.add(jTextSource[index], gbc2); 197 GridBagConstraints gbc3 = new GridBagConstraints(); 198 gbc3.gridx = 2; 199 gbc3.gridy = 0; 200 gbc3.weightx = 1.0; 201 gbc3.anchor = GridBagConstraints.CENTER; 202 result.add(jButtonCopy, gbc3); 203 GridBagConstraints gbc4 = new GridBagConstraints(); 204 gbc4.gridx = 3; 205 gbc4.gridy = 0; 206 gbc4.ipadx = 4; 207 result.add(jLabelDestination[index], gbc4); 208 GridBagConstraints gbc5 = new GridBagConstraints(); 209 gbc5.gridx = 4; 210 gbc5.gridy = 0; 211 gbc5.fill = GridBagConstraints.HORIZONTAL; 212 result.add(jTextDestination[index], gbc5); 213 //Line 2 214 GridBagConstraints gbc6 = new GridBagConstraints(); 215 gbc6.gridx = 0; 216 gbc6.gridy = 1; 217 gbc6.weightx = 1.0; 218 gbc6.fill = GridBagConstraints.HORIZONTAL; 219 gbc6.gridwidth = 5; 220 result.add(jLabelSubtitles[index], gbc6); 221 //line3 222 GridBagConstraints gbc7 = new GridBagConstraints(); 223 gbc7.gridx = 0; 224 gbc7.gridy = 2; 225 gbc7.weightx = 1.0; 226 gbc7.fill = GridBagConstraints.HORIZONTAL; 227 gbc7.gridwidth = 5; 228 result.add(jSliders[index], gbc7); 229 //return the result. 230 return result; 231 } 232 233 234 /** 235 * Method copyAction. 236 * <br><b>Summary:</b><br> 237 * This method permits to copy the value of a source to the corresponding destination. 238 * @param index The index of the source/destination. 239 */ 240 protected void copyAction(int index) { 241 //retrieve the source value. 242 String sourceValue = jTextSource[index].getText(); 243 //set it in the corresponding destination 244 jTextDestination[index].setText(sourceValue); 245 } 246 247 /** 248 * Method sliderValueChanged. 249 * <br><b>Summary:</b><br> 250 * This method is called by the slider to indicate that their position changed. 251 * @param index The index of the slider that change 252 */ 253 protected void sliderValueChanged(int index) { 254 //A slider has moved. 255 //get the new slider's value. 256 int subtitleIndex = jSliders[index].getValue(); 257 //Changed the text of the JLabelSubtitle. 258 //Get the subtitle at the given index. 259 Subtitle subtitle = (Subtitle) subtitleList.get(subtitleIndex); 260 //construct message to show in label. 261 //Put ST number, and append the message. 262 String message = "[" + subtitle.getNumber() + "]" + " " + subtitle.getSubtitle(); 263 //Cut long ST, not to perturb GUI. 264 int maxLength = 35; 265 if (message.length() > maxLength) { 266 message = message.substring(0, maxLength - 1) + "..."; 267 } 268 //set the label to the content of the subtitle. 269 jLabelSubtitles[index].setText(message); 270 //And set the source textField. 271 jTextSource[index].setText(SubtitleFile.timeToString(subtitle.getStartDate())); 272 } 273 274 /* (non-Javadoc) 275 * @see sears.gui.SearsJDialog#hasBeenValidated() 276 */ 277 public boolean hasBeenValidated() { 278 return validationStatus; 279 } 280 281 /** 282 * Method getResult. 283 * <br><b>Summary:</b><br> 284 * This method returns the resynchro dialog result. 285 * @return <b>int[]</b> An array of int:[source1, destination1, source2, destination2 .... etc] 286 */ 287 public int[] getResult() { 288 289 int[] result = new int[sources.length * 2]; 290 for (int i = 0; i < sources.length; i++) { 291 result[2*i] = SubtitleFile.stringToTime(jTextSource[i].getText()); 292 result[2*i+1] = SubtitleFile.stringToTime(jTextDestination[i].getText()); 293 } 294 return result; 295 } 296 297 /* (non-Javadoc) 298 * @see sears.gui.SearsJDialog#getDialogName() 299 */ 300 protected String getDialogName() { 301 return "resynchro"; 302 } 303 }