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.io.File; 026 import java.io.IOException; 027 import java.util.ArrayList; 028 029 import javax.swing.BorderFactory; 030 import javax.swing.JButton; 031 import javax.swing.JCheckBox; 032 import javax.swing.JLabel; 033 import javax.swing.JOptionPane; 034 import javax.swing.JPanel; 035 import javax.swing.JSlider; 036 import javax.swing.JTextField; 037 import javax.swing.event.ChangeEvent; 038 import javax.swing.event.ChangeListener; 039 040 import sears.file.Subtitle; 041 import sears.file.SubtitleFile; 042 import sears.gui.resources.SearsResources; 043 import sears.tools.SearsResourceBundle; 044 import sears.tools.Trace; 045 046 /** 047 * Class JDialogSplit. 048 * <br><b>Summary:</b><br> 049 * This Class permit to enter Split parameters. 050 */ 051 public class JDialogSplit extends SearsJDialog implements ChangeListener { 052 private static final long serialVersionUID = -1582903664124772065L; 053 054 private JPanel jContentPane = null; 055 056 private JPanel jPanelCenter = null; 057 058 private JPanel jPanelOutputFiles = null; 059 060 private JLabel jLabelPart1 = null; 061 062 private JTextField jTextFieldPart1 = null; 063 064 private JButton jButtonPart1 = null; 065 066 private JLabel jLabelPart2 = null; 067 068 private JTextField jTextFieldPart2 = null; 069 070 private JButton jButtonPart2 = null; 071 072 private JPanel jPanelSubtitle = null; 073 074 private JLabel jLabelSubtitle = null; 075 076 private JSlider jSliderSubtitle = null; 077 078 private JPanel jPanelChecks = null; 079 080 private JCheckBox jCheckBoxDelay = null; 081 082 private JTextField jTextFieldDelay = null; 083 084 private JCheckBox jCheckBoxOpenSecond = null; 085 086 /**The entered destination files. This array is filled in the checkParameters method*/ 087 private File[] destinationFiles; 088 089 /**The subtitleList, that contains all the subtitles.*/ 090 private ArrayList subtitleList; 091 092 /**The first choosen subtitle and the last choosen one, when user validates the dialog.*/ 093 private int choosenSubtitle; 094 095 /**The opened subtitleFile.*/ 096 private SubtitleFile subtitleFile; 097 098 /** 099 * This is the default constructor 100 */ 101 public JDialogSplit(ArrayList _subtitleList, int _choosenSubtitle, SubtitleFile _subtitleFile) { 102 super(SearsResourceBundle.getResource("split_title")); 103 //Initialize attributes. 104 choosenSubtitle = _choosenSubtitle; 105 subtitleList = _subtitleList; 106 validationStatus = false; 107 subtitleFile = _subtitleFile; 108 initializeDestinationFiles(); 109 setContentPane(getJContentPane()); 110 configureSize(); 111 } 112 113 /** 114 * Method initializeDestinationFiles. 115 * <br><b>Summary:</b><br> 116 * Call to method to initialize the destination files array. 117 */ 118 private void initializeDestinationFiles() { 119 //construct array. 120 destinationFiles = new File[2]; 121 //Construct filename 1 (which will contains the first range) 122 String fileName = subtitleFile.getFile().getName(); 123 //remove extension 124 fileName = fileName.substring(0, fileName.lastIndexOf(".")); 125 destinationFiles[0] = new File(subtitleFile.getFile().getParent() + File.separator + fileName + "_1.srt"); 126 //construct filename 2 127 destinationFiles[1] = new File(subtitleFile.getFile().getParent() + File.separator + fileName + "_2.srt"); 128 } 129 130 /** 131 * This method initializes jContentPane 132 * 133 * @return javax.swing.JPanel 134 */ 135 private JPanel getJContentPane() { 136 if (jContentPane == null) { 137 jContentPane = new JPanel(); 138 jContentPane.setLayout(new BorderLayout()); 139 jContentPane.add(getJPanelButtons(), java.awt.BorderLayout.SOUTH); 140 jContentPane.add(getJPanelCenter(), java.awt.BorderLayout.CENTER); 141 } 142 return jContentPane; 143 } 144 145 /** 146 * Method okAction. 147 * <br><b>Summary:</b><br> 148 * This method is called when user validate the dialog. 149 */ 150 protected void okAction() { 151 //Just have to check parameters validity, if valids, dispose dialog,and set validation status to true. 152 String error = checkParameters(); 153 if (error != null && !error.equals("")) { 154 //Show error message. 155 JOptionPane.showMessageDialog(this, error, SearsResourceBundle.getResource("error_splitConfigurationError"), 156 JOptionPane.ERROR_MESSAGE); 157 Trace.trace("Error in Split parameters:" + error, Trace.WARNING_PRIORITY); 158 } else { 159 //else split configuration is valid, release dialog. 160 validationStatus = true; 161 dispose(); 162 } 163 } 164 165 /** 166 * Method checkParameters. 167 * <br><b>Summary:</b><br> 168 * This method permits to check the split parameters validity. 169 * It sets the final parameters that will be returned by the public methods. 170 * @return <b>String</b> "" if there is no error in parameters, error message otherwise. 171 */ 172 private String checkParameters() { 173 //The error message that will be returned. 174 String errorMessage = ""; 175 //Check first destination file. 176 errorMessage += checkFile(getJTextFieldPart1().getText(), 0); 177 //check second file. 178 errorMessage += checkFile(getJTextFieldPart2().getText(), 1); 179 //check choosen subtitle. 180 //nothing to check... slider is obsviously between min and max :/ 181 choosenSubtitle = getJSliderSubtitle().getValue(); 182 //check delay. 183 if (getJCheckBoxDelay().isSelected()) { 184 String delay = getJTextFieldDelay().getText(); 185 if (delay != null && !delay.equals("")) { 186 try { 187 Double.parseDouble(delay); 188 } catch (NumberFormatException e) { 189 //Delay value is not a number. 190 errorMessage += SearsResourceBundle.getResource("error_delayNotValid") + "\n"; 191 } 192 } else { 193 //Delay value is null. 194 errorMessage += SearsResourceBundle.getResource("error_delayNull") + "\n"; 195 } 196 } 197 return errorMessage; 198 } 199 200 /** 201 * Method checkFile. 202 * <br><b>Summary:</b><br> 203 * This method check a destination fileName validity. 204 * @param fileName The fileNAme to check. 205 * @param destinationIndex The destination index, 0 for first part, and 1 for the second part. 206 * @return String The new error message. 207 */ 208 private String checkFile(String fileName, int destinationIndex) { 209 String errorMessage = ""; 210 if (fileName != null && !fileName.equals("")) { 211 File file = new File(fileName); 212 try { 213 if ((file.exists() && file.canWrite()) || file.createNewFile()) { 214 //set destination file 215 destinationFiles[destinationIndex] = file; 216 } else { 217 //cannot write to file! 218 errorMessage += SearsResourceBundle.getResource("error_cannotWrite") + fileName + ".\n"; 219 } 220 } catch (IOException e) { 221 //cannot write to file! 222 errorMessage += SearsResourceBundle.getResource("error_cannotWrite") + fileName + ".\n"; 223 } 224 } else { 225 //cannot write to file! 226 errorMessage += SearsResourceBundle.getResource("error_destinationNotDefined1") + " " + (destinationIndex + 1) + " " 227 + SearsResourceBundle.getResource("error_destinationNotDefined2") + "\n"; 228 } 229 return errorMessage; 230 } 231 232 /** 233 * This method initializes jPanel 234 * 235 * @return javax.swing.JPanel 236 */ 237 private JPanel getJPanelCenter() { 238 if (jPanelCenter == null) { 239 GridBagConstraints gridBagConstraints12 = new GridBagConstraints(); 240 gridBagConstraints12.gridx = 0; 241 gridBagConstraints12.gridy = 4; 242 gridBagConstraints12.anchor = java.awt.GridBagConstraints.WEST; 243 gridBagConstraints12.fill = java.awt.GridBagConstraints.HORIZONTAL; 244 GridBagConstraints gridBagConstraints11 = new GridBagConstraints(); 245 gridBagConstraints11.fill = java.awt.GridBagConstraints.HORIZONTAL; 246 gridBagConstraints11.gridx = 0; 247 gridBagConstraints11.gridy = 2; 248 gridBagConstraints11.gridheight = 2; 249 GridBagConstraints gridBagConstraints = new GridBagConstraints(); 250 gridBagConstraints.gridx = 0; 251 gridBagConstraints.gridheight = 2; 252 gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL; 253 gridBagConstraints.gridy = 0; 254 jPanelCenter = new JPanel(); 255 jPanelCenter.setLayout(new GridBagLayout()); 256 jPanelCenter.add(getJPanelOutputFiles(), gridBagConstraints); 257 jPanelCenter.add(getJPanelSubtitle(), gridBagConstraints11); 258 jPanelCenter.add(getJPanelChecks(), gridBagConstraints12); 259 } 260 return jPanelCenter; 261 } 262 263 /** 264 * This method initializes jPanel 265 * 266 * @return javax.swing.JPanel 267 */ 268 private JPanel getJPanelOutputFiles() { 269 if (jPanelOutputFiles == null) { 270 GridBagConstraints gridBagConstraints4 = new GridBagConstraints(); 271 gridBagConstraints4.fill = java.awt.GridBagConstraints.HORIZONTAL; 272 gridBagConstraints4.weightx = 1.0; 273 gridBagConstraints4.gridx = 1; 274 gridBagConstraints4.gridy = 1; 275 GridBagConstraints gridBagConstraints5 = new GridBagConstraints(); 276 gridBagConstraints5.gridx = 2; 277 gridBagConstraints5.insets = new java.awt.Insets(1, 0, 7, 0); 278 gridBagConstraints5.ipadx = 0; 279 gridBagConstraints5.gridy = 1; 280 GridBagConstraints gridBagConstraints3 = new GridBagConstraints(); 281 gridBagConstraints3.gridx = 0; 282 gridBagConstraints3.gridy = 1; 283 jLabelPart2 = new JLabel(); 284 jLabelPart2.setText(SearsResourceBundle.getResource("split_part") + "2"); 285 jLabelPart1 = new JLabel(); 286 jLabelPart1.setText(SearsResourceBundle.getResource("split_part") + "1"); 287 GridBagConstraints gridBagConstraints2 = new GridBagConstraints(); 288 gridBagConstraints2.gridx = 2; 289 gridBagConstraints2.gridy = 0; 290 GridBagConstraints gridBagConstraints1 = new GridBagConstraints(); 291 gridBagConstraints1.gridx = 1; 292 gridBagConstraints1.gridy = 0; 293 gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL; 294 gridBagConstraints1.weightx = 1.0; 295 jPanelOutputFiles = new JPanel(); 296 jPanelOutputFiles.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), SearsResourceBundle 297 .getResource("split_outputFiles"))); 298 jPanelOutputFiles.setSize(400, 200); 299 jPanelOutputFiles.setLayout(new GridBagLayout()); 300 jPanelOutputFiles.add(jLabelPart1, new GridBagConstraints()); 301 jPanelOutputFiles.add(getJTextFieldPart1(), gridBagConstraints1); 302 jPanelOutputFiles.add(getJButtonPart1(), gridBagConstraints2); 303 jPanelOutputFiles.add(jLabelPart2, gridBagConstraints3); 304 jPanelOutputFiles.add(getJTextFieldPart2(), gridBagConstraints4); 305 jPanelOutputFiles.add(getJButtonPart2(), gridBagConstraints5); 306 } 307 return jPanelOutputFiles; 308 } 309 310 /** 311 * This method initializes jTextField 312 * 313 * @return javax.swing.JTextField 314 */ 315 private JTextField getJTextFieldPart1() { 316 if (jTextFieldPart1 == null) { 317 jTextFieldPart1 = new JTextField(18); 318 jTextFieldPart1.setText(destinationFiles[0].getAbsolutePath()); 319 } 320 return jTextFieldPart1; 321 } 322 323 /** 324 * This method initializes jButton 325 * 326 * @return javax.swing.JButton 327 */ 328 private JButton getJButtonPart1() { 329 if (jButtonPart1 == null) { 330 jButtonPart1 = new JButton(SearsResources.getIcon("BrowseIcon")); 331 jButtonPart1.addActionListener(new ActionListener() { 332 public void actionPerformed(ActionEvent e) { 333 browseDestinationFile(0); 334 } 335 }); 336 } 337 return jButtonPart1; 338 } 339 340 /** 341 * Method browseDestinationFile. 342 * <br><b>Summary:</b><br> 343 * Use thid method to choose destination files. 344 * @param i An <b>int</b> equals to 0 to choose first part, or 1 to choose second part. 345 */ 346 protected void browseDestinationFile(int i) { 347 File choosenFile = MainWindow.instance.showSRTBrowser(); 348 if (choosenFile != null) { 349 if (i == 0) { 350 getJTextFieldPart1().setText(choosenFile.getAbsolutePath()); 351 } else { 352 getJTextFieldPart2().setText(choosenFile.getAbsolutePath()); 353 } 354 } 355 } 356 357 /** 358 * This method initializes jTextField 359 * 360 * @return javax.swing.JTextField 361 */ 362 private JTextField getJTextFieldPart2() { 363 if (jTextFieldPart2 == null) { 364 jTextFieldPart2 = new JTextField(18); 365 jTextFieldPart2.setText(destinationFiles[1].getAbsolutePath()); 366 } 367 return jTextFieldPart2; 368 } 369 370 /** 371 * This method initializes jButton 372 * 373 * @return javax.swing.JButton 374 */ 375 private JButton getJButtonPart2() { 376 if (jButtonPart2 == null) { 377 jButtonPart2 = new JButton(SearsResources.getIcon("BrowseIcon")); 378 jButtonPart2.addActionListener(new ActionListener() { 379 public void actionPerformed(ActionEvent e) { 380 browseDestinationFile(1); 381 } 382 }); 383 } 384 return jButtonPart2; 385 } 386 387 /** 388 * This method initializes jPanel 389 * 390 * @return javax.swing.JPanel 391 */ 392 private JPanel getJPanelSubtitle() { 393 if (jPanelSubtitle == null) { 394 jPanelSubtitle = new JPanel(); 395 jPanelSubtitle.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), SearsResourceBundle 396 .getResource("split_cutOnST"))); 397 jPanelSubtitle.setLayout(new GridLayout(2, 1)); 398 jPanelSubtitle.add(getJLabelSubtitle(), null); 399 jPanelSubtitle.add(getJSliderSubtitle(), null); 400 } 401 return jPanelSubtitle; 402 } 403 404 /** 405 * This method initialize the JLabelSubtitle. 406 * 407 * @return javax.swing.JLabel 408 */ 409 private JLabel getJLabelSubtitle() { 410 if (jLabelSubtitle == null) { 411 jLabelSubtitle = new JLabel(); 412 setSubtitleLabel(choosenSubtitle); 413 } 414 return jLabelSubtitle; 415 } 416 417 /** 418 * This method initializes jSlider 419 * 420 * @return javax.swing.JSlider 421 */ 422 private JSlider getJSliderSubtitle() { 423 if (jSliderSubtitle == null) { 424 jSliderSubtitle = new JSlider(0, subtitleList.size() - 1, choosenSubtitle); 425 jSliderSubtitle.addChangeListener(this); 426 } 427 return jSliderSubtitle; 428 } 429 430 /** 431 * This method initializes jPanel 432 * 433 * @return javax.swing.JPanel 434 */ 435 private JPanel getJPanelChecks() { 436 if (jPanelChecks == null) { 437 GridBagConstraints gridBagConstraints8 = new GridBagConstraints(); 438 gridBagConstraints8.gridx = 0; 439 gridBagConstraints8.anchor = java.awt.GridBagConstraints.WEST; 440 gridBagConstraints8.gridwidth = 2; 441 gridBagConstraints8.gridy = 1; 442 GridBagConstraints gridBagConstraints7 = new GridBagConstraints(); 443 gridBagConstraints7.fill = java.awt.GridBagConstraints.NONE; 444 gridBagConstraints7.weightx = 1.0; 445 GridBagConstraints gridBagConstraints6 = new GridBagConstraints(); 446 gridBagConstraints6.anchor = java.awt.GridBagConstraints.WEST; 447 jPanelChecks = new JPanel(); 448 jPanelChecks.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), SearsResourceBundle 449 .getResource("split_options"))); 450 jPanelChecks.setLayout(new GridBagLayout()); 451 jPanelChecks.add(getJCheckBoxDelay(), gridBagConstraints6); 452 jPanelChecks.add(getJTextFieldDelay(), gridBagConstraints7); 453 jPanelChecks.add(getJCheckBoxOpenSecond(), gridBagConstraints8); 454 } 455 return jPanelChecks; 456 } 457 458 /** 459 * This method initializes jCheckBox 460 * 461 * @return javax.swing.JCheckBox 462 */ 463 private JCheckBox getJCheckBoxDelay() { 464 if (jCheckBoxDelay == null) { 465 jCheckBoxDelay = new JCheckBox(SearsResourceBundle.getResource("split_delay2ndPart")); 466 } 467 return jCheckBoxDelay; 468 } 469 470 /** 471 * This method initializes jTextField 472 * 473 * @return javax.swing.JTextField 474 */ 475 private JTextField getJTextFieldDelay() { 476 if (jTextFieldDelay == null) { 477 jTextFieldDelay = new JTextField("1", 4); 478 jTextFieldDelay.setToolTipText(SearsResourceBundle.getResource("delay_tip")); 479 } 480 return jTextFieldDelay; 481 } 482 483 /** 484 * This method initializes jCheckBox 485 * 486 * @return javax.swing.JCheckBox 487 */ 488 private JCheckBox getJCheckBoxOpenSecond() { 489 if (jCheckBoxOpenSecond == null) { 490 jCheckBoxOpenSecond = new JCheckBox(SearsResourceBundle.getResource("split_open2ndPart")); 491 } 492 return jCheckBoxOpenSecond; 493 } 494 495 /** 496 * Method getDestinationsFiles. 497 * <br><b>Summary:</b><br> 498 * This method returns the entered destinations files. 499 * @return <b>Files[]</b> The entered destination files. or null if user didn't validate. 500 */ 501 public File[] getDestinationsFiles() { 502 //The result of the method. 503 return destinationFiles; 504 } 505 506 /* (non-Javadoc) 507 * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) 508 */ 509 public void stateChanged(ChangeEvent e) { 510 //When slider change of value, change the content of the jLabelSubtitle. 511 if (e.getSource() == jSliderSubtitle) { 512 setSubtitleLabel(jSliderSubtitle.getValue()); 513 } 514 } 515 516 /** 517 * Method setSubtitleLabel. 518 * <br><b>Summary:</b><br> 519 * Call this method to fill the subtitle label with the content of the subtitle at the given index. 520 * @param index The <b>int</b> index to find the subtitle. 521 */ 522 private void setSubtitleLabel(int index) { 523 //Get the subtitle at the given index. 524 Subtitle subtitle = (Subtitle) subtitleList.get(index); 525 //construct message to show in label. 526 //Put ST number, and append the message. 527 String message = "[" + subtitle.getNumber() + "]" + subtitle.getSubtitle(); 528 //Cut long ST, not to perturb GUI. 529 int maxLength = 35; 530 if (message.length() > maxLength) { 531 message = message.substring(0, maxLength - 1) + "..."; 532 } 533 //set the label to the content of the subtitle. 534 getJLabelSubtitle().setText(message); 535 } 536 537 /** 538 * Method getDelay. 539 * <br><b>Summary:</b><br> 540 * This method return the delay entered for the second part. 541 * @return double The delay entered for the second part, or 1 if not delay is necessary (1s will be the delay by default). 542 */ 543 public double getSecondPartDelay() { 544 //the result of the method. 545 double result = -1; 546 if (getJCheckBoxDelay().isSelected()) { 547 try { 548 //get the delay from the textField. 549 result = Double.parseDouble(getJTextFieldDelay().getText()); 550 } catch (NumberFormatException e) { 551 Trace.trace("Bad number entered in Delay ! Delay is ignored.", Trace.ERROR_PRIORITY); 552 //set a delay of 1 553 result = 1; 554 } 555 } 556 //return the result 557 return result; 558 } 559 560 /** 561 * Method needToOpenSecondPart. 562 * <br><b>Summary:</b><br> 563 * Return true if the open second part checkBox is selected. 564 * @return boolean True if the open second part checkBox is selected. False otherwise. 565 */ 566 public boolean needToOpenSecondPart() { 567 //return true if checkBox is selectd. 568 return getJCheckBoxOpenSecond().isSelected(); 569 } 570 571 /** 572 * Method getChoosenSubtitle. 573 * <br><b>Summary:</b><br> 574 * This method return the choosen subtitle index for spliting. 575 * @return <b>int</b> The choosen subtitle index for spliting. 576 */ 577 public int getChoosenSubtitle() { 578 return choosenSubtitle; 579 } 580 581 /* (non-Javadoc) 582 * @see sears.gui.SearsJDialog#getDialogName() 583 */ 584 protected String getDialogName() { 585 return "split"; 586 } 587 }