[zhyi~subversion:30] Separated the logic for processing SRT to a single class.

  • From: zhyi@kenai.com
  • To: commits@zhyi.kenai.com
  • Subject: [zhyi~subversion:30] Separated the logic for processing SRT to a single class.
  • Date: Sun, 18 Oct 2009 05:18:22 +0000

Project:    zhyi
Repository: subversion
Revision:   30
Author:     zhyi
Date:       2009-10-18 05:18:16 UTC
Link:       

Log Message:
------------
Separated the logic for processing SRT to a single class.


Revisions:
----------
30


Modified Paths:
---------------
SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/Bundle_zh_CN.properties
SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SettingsDialog.form
SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtEditorFrame.form
SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/Bundle.properties
SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtEditorFrame.java
SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SettingsDialog.java


Added Paths:
------------
SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtToolkit.java


Diffs:
------
Index: SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SettingsDialog.java
===================================================================
--- SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SettingsDialog.java      
  (revision 29)
+++ SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SettingsDialog.java      
  (revision 30)
@@ -98,6 +98,8 @@
 
         fontLabel.setText(bundle.getString("Font")); // NOI18N
 
+        fontComboBox.setToolTipText(bundle.getString("FontToolTip")); // 
NOI18N
+
         GroupLayout layout = new GroupLayout(getContentPane());
         getContentPane().setLayout(layout);
         layout.setHorizontalGroup(
@@ -117,7 +119,7 @@
                         .addComponent(fontLabel)
                         .addPreferredGap(ComponentPlacement.RELATED)
                         .addComponent(fontComboBox, 0, 180, Short.MAX_VALUE))
-                    .addComponent(jSeparator1, GroupLayout.DEFAULT_SIZE, 
235, Short.MAX_VALUE)
+                    .addComponent(jSeparator1, GroupLayout.DEFAULT_SIZE, 
238, Short.MAX_VALUE)
                     .addGroup(Alignment.TRAILING, 
layout.createSequentialGroup()
                         .addComponent(okButton)
                         .addPreferredGap(ComponentPlacement.RELATED)
Index: SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SettingsDialog.form
===================================================================
--- SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SettingsDialog.form      
  (revision 29)
+++ SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SettingsDialog.form      
  (revision 30)
@@ -43,7 +43,7 @@
                       <EmptySpace max="-2" attributes="0"/>
                       <Component id="fontComboBox" pref="180" max="32767" 
attributes="0"/>
                   </Group>
-                  <Component id="jSeparator1" alignment="0" pref="235" 
max="32767" attributes="0"/>
+                  <Component id="jSeparator1" alignment="0" pref="238" 
max="32767" attributes="0"/>
                   <Group type="102" alignment="1" attributes="0">
                       <Component id="okButton" linkSize="2" min="-2" 
max="-2" attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
@@ -150,6 +150,11 @@
       </Properties>
     </Component>
     <Component class="javax.swing.JComboBox" name="fontComboBox">
+      <Properties>
+        <Property name="toolTipText" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+          <ResourceString 
bundle="com/zhyi/srtsubtitleeditor/Bundle.properties" key="FontToolTip" 
replaceFormat="bundle.getString(&quot;{key}&quot;)"/>
+        </Property>
+      </Properties>
       <AuxValues>
         <AuxValue name="JavaCodeGenerator_CreateCodeCustom" 
type="java.lang.String" value="fontComboBox = new JComboBox(&#xd;&#xa;        
GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(locale));"/>
       </AuxValues>
Index: SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/Bundle.properties
===================================================================
--- SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/Bundle.properties  
(revision 29)
+++ SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/Bundle.properties  
(revision 30)
@@ -45,7 +45,7 @@
 SrtFile=SRT Subtitle File
 Ready=Ready
 Cancel=Cancel
-BadTime=Bad format at line {0} in the SRT file:\nThe format of the start or 
end time may not match "hh:MM:ss,mmm".
+BadTime=Bad format at line {0} in the SRT file:\nThe format of the start or 
end time doesn't match "hh:MM:ss,mmm".
 FileTooLarge=Seems the chosen file isn't SRT for the size is too large 
(>1MB).\nDo you still want to load it?
 Warning=Warning
 Error=Error
@@ -58,8 +58,13 @@
 Charset=Charset:
 Language=Language:
 CharsetToolTip=<html><b>Select the charset for loading and saving SRT 
files</b><br>A wrong charset might result in messy code.</html>
-LanguangeToolTip=<html><b>Select the UI languange</b><br>You have to restart 
the application to take effect.</html>
+LanguangeToolTip=<html><b>Select the UI language</b><br>You have to restart 
the application to take effect.</html>
 OK=OK
 #\u9ED8\u8BA4\u8BED\u8A00\uFF08\u82F1\u8BED\uFF09
 DefaultLanguage=Default Language (English)
 Font=Font:
+FontToolTip=<html><b>Select the UI font</b><br>You have to restart the 
application to take effect.</html>
+ContinuousEdit=Continuous Edit
+ContinuousEditToolTip=If selected, once a subtitle is updated, the next 
subtitle will automatically be loaded to editor.
+Loading=Loading...
+Saving=Saving...
Index: 
SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/Bundle_zh_CN.properties
===================================================================
--- SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/Bundle_zh_CN.properties  
  (revision 29)
+++ SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/Bundle_zh_CN.properties  
  (revision 30)
@@ -45,7 +45,7 @@
 SrtFile=SRT \u5B57\u5E55\u6587\u4EF6
 Ready=\u5C31\u7EEA
 Cancel=\u53D6\u6D88
-BadTime=SRT \u6587\u4EF6\u4E2D\u7684\u7B2C {0} 
\u884C\u683C\u5F0F\u9519\u8BEF\uFF1A\n\u5F00\u59CB\u6216\u7ED3\u675F\u65F6\u95F4\u7684\u683C\u5F0F\u53EF\u80FD\u4E0D\u7B26\u5408\u201Chh:MM:ss,mm\u201D\u3002
+BadTime=SRT \u6587\u4EF6\u4E2D\u7684\u7B2C {0} 
\u884C\u683C\u5F0F\u9519\u8BEF\uFF1A\n\u5F00\u59CB\u6216\u7ED3\u675F\u65F6\u95F4\u7684\u683C\u5F0F\u4E0D\u7B26\u5408\u201Chh:MM:ss,mm\u201D\u3002
 FileTooLarge=\u6240\u9009\u7684\u6587\u4EF6\u4F3C\u4E4E\u4E0D\u662F 
SRT\uFF0C\u56E0\u4E3A\u5B83\u592A\u5927\u4E86\uFF08>1MB\uFF09\u3002\n\u4F60\u4ECD\u7136\u60F3\u8F7D\u5165\u5B83\u5417\uFF1F
 Warning=\u8B66\u544A
 Error=\u9519\u8BEF
@@ -63,3 +63,8 @@
 #\u9ED8\u8BA4\u8BED\u8A00\uFF08\u82F1\u8BED\uFF09
 DefaultLanguage=\u9ED8\u8BA4\u8BED\u8A00\uFF08\u82F1\u6587\uFF09
 Font=\u5B57\u4F53\uFF1A
+FontToolTip=<html><b>\u9009\u62E9\u754C\u9762\u5B57\u4F53</b><br>\u5FC5\u987B\u91CD\u542F\u5E94\u7528\u7A0B\u5E8F\u624D\u80FD\u751F\u6548\u3002</html>
+ContinuousEdit=\u8FDE\u7EED\u7F16\u8F91
+ContinuousEditToolTip=\u5982\u679C\u9009\u4E2D\uFF0C\u5219\u5728\u66F4\u65B0\u4E00\u6761\u5B57\u5E55\u540E\uFF0C\u81EA\u52A8\u5C06\u4E0B\u4E00\u6761\u5B57\u5E55\u8F7D\u5165\u5230\u7F16\u8F91\u533A\u3002
+Loading=\u6B63\u5728\u8F7D\u5165\u2026\u2026
+Saving=\u6B63\u5728\u4FDD\u5B58\u2026\u2026
Index: SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtEditorFrame.java
===================================================================
--- SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtEditorFrame.java      
  (revision 29)
+++ SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtEditorFrame.java      
  (revision 30)
@@ -18,7 +18,7 @@
  */
 package com.zhyi.srtsubtitleeditor;
 
-import com.zhyi.zylib.SwingToolkit;
+import com.zhyi.zylib.toolkit.SwingToolkit;
 import java.awt.Color;
 import java.awt.Component;
 import java.awt.EventQueue;
@@ -26,17 +26,15 @@
 import java.awt.event.ActionListener;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowListener;
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.util.ResourceBundle;
-import java.util.regex.Pattern;
+import java.util.Vector;
 import javax.swing.BorderFactory;
 import javax.swing.GroupLayout;
 import javax.swing.GroupLayout.Alignment;
 import javax.swing.JButton;
+import javax.swing.JCheckBox;
 import javax.swing.JComboBox;
 import javax.swing.JFileChooser;
 import javax.swing.JFrame;
@@ -58,6 +56,7 @@
 import javax.swing.WindowConstants;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import javax.swing.table.DefaultTableModel;
+import javax.swing.table.TableColumnModel;
 import javax.swing.table.TableModel;
 
 /**
@@ -67,25 +66,20 @@
 public class SrtEditorFrame extends JFrame implements ActionListener, 
WindowListener {
 
     private final int maxLength = 1024 * 1024;
-    private final Pattern timePattern = Pattern.compile(
-            "^\\d{2}(:[0-5]\\d){2},\\d{3}$");
     private final TableModel emptyModel = new DefaultTableModel();
 
     private SettingsDialog settingsDialog;
+    private ResourceBundle bundle = Context.getBundle();
 
     // Used to trace the bad format of an SRT file.
     private int lineNumber;
     private int subtitleIndex;
     private DefaultTableModel tableModel;
-    private ResourceBundle bundle;
-    private String[] columnNames;
 
     public SrtEditorFrame() {
         settingsDialog = new SettingsDialog(this, true);
-        initEnvironment();
         initComponents();
-        fixComboBoxUIForWindows();
-        enableComponents(false);
+        enableEditingComponents(false);
     }
 
     /**
@@ -112,6 +106,7 @@
         contentScrollPane = new JScrollPane();
         contentTextArea = new JTextArea();
         updateSubtitleButton = new JButton();
+        continuousEditCheckBox = new JCheckBox();
         addBeforeButton = new JButton();
         addAfterButton = new JButton();
         moveUpButton = new JButton();
@@ -171,6 +166,9 @@
 
         updateSubtitleButton.setText(bundle.getString("UpdateSubtitle")); // 
NOI18N
 
+        continuousEditCheckBox.setSelected(true);
+        continuousEditCheckBox.setText(bundle.getString("ContinuousEdit")); 
// NOI18N
+
         GroupLayout editSubtitlePanelLayout = new 
GroupLayout(editSubtitlePanel);
         editSubtitlePanel.setLayout(editSubtitlePanelLayout);
         editSubtitlePanelLayout.setHorizontalGroup(
@@ -181,16 +179,19 @@
                     .addGroup(editSubtitlePanelLayout.createSequentialGroup()
                         .addComponent(beginTimeLabel)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(beginTimeTextField, 
GroupLayout.DEFAULT_SIZE, 142, Short.MAX_VALUE)
+                        .addComponent(beginTimeTextField, 
GroupLayout.DEFAULT_SIZE, 144, Short.MAX_VALUE)
                         .addGap(18, 18, 18)
                         .addComponent(endTimeLabel)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(endTimeTextField, 
GroupLayout.DEFAULT_SIZE, 143, Short.MAX_VALUE))
+                        .addComponent(endTimeTextField, 
GroupLayout.DEFAULT_SIZE, 145, Short.MAX_VALUE))
                     .addGroup(editSubtitlePanelLayout.createSequentialGroup()
                         .addComponent(contentLabel)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(contentScrollPane, 
GroupLayout.DEFAULT_SIZE, 361, Short.MAX_VALUE))
-                    .addComponent(updateSubtitleButton, Alignment.TRAILING))
+                        .addComponent(contentScrollPane, 
GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE))
+                    .addGroup(Alignment.TRAILING, 
editSubtitlePanelLayout.createSequentialGroup()
+                        .addComponent(continuousEditCheckBox)
+                        .addPreferredGap(ComponentPlacement.RELATED, 113, 
Short.MAX_VALUE)
+                        .addComponent(updateSubtitleButton)))
                 .addContainerGap())
         );
         editSubtitlePanelLayout.setVerticalGroup(
@@ -205,9 +206,11 @@
                 .addPreferredGap(ComponentPlacement.RELATED)
                 
.addGroup(editSubtitlePanelLayout.createParallelGroup(Alignment.LEADING)
                     .addComponent(contentLabel)
-                    .addComponent(contentScrollPane, 
GroupLayout.DEFAULT_SIZE, 72, Short.MAX_VALUE))
+                    .addComponent(contentScrollPane, 
GroupLayout.DEFAULT_SIZE, 75, Short.MAX_VALUE))
                 .addPreferredGap(ComponentPlacement.RELATED)
-                .addComponent(updateSubtitleButton)
+                
.addGroup(editSubtitlePanelLayout.createParallelGroup(Alignment.BASELINE)
+                    .addComponent(updateSubtitleButton)
+                    .addComponent(continuousEditCheckBox))
                 .addContainerGap())
         );
 
@@ -253,7 +256,7 @@
                     .addGroup(ajustTimePanelLayout.createSequentialGroup()
                         .addComponent(amountLabel)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(amountTextField, 
GroupLayout.DEFAULT_SIZE, 52, Short.MAX_VALUE)
+                        .addComponent(amountTextField, 
GroupLayout.DEFAULT_SIZE, 53, Short.MAX_VALUE)
                         .addPreferredGap(ComponentPlacement.RELATED)
                         .addComponent(msLabel))
                     .addGroup(ajustTimePanelLayout.createSequentialGroup()
@@ -321,25 +324,25 @@
             .addGroup(layout.createSequentialGroup()
                 .addContainerGap()
                 .addGroup(layout.createParallelGroup(Alignment.LEADING)
-                    .addComponent(srtScrollPane, GroupLayout.DEFAULT_SIZE, 
620, Short.MAX_VALUE)
+                    .addComponent(srtScrollPane, GroupLayout.DEFAULT_SIZE, 
644, Short.MAX_VALUE)
                     .addGroup(Alignment.TRAILING, 
layout.createSequentialGroup()
                         .addComponent(loadButton)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(pathTextField, 
GroupLayout.DEFAULT_SIZE, 363, Short.MAX_VALUE)
+                        .addComponent(pathTextField, 
GroupLayout.DEFAULT_SIZE, 365, Short.MAX_VALUE)
                         .addPreferredGap(ComponentPlacement.RELATED)
                         .addComponent(saveButton)
                         .addPreferredGap(ComponentPlacement.RELATED)
                         .addComponent(saveAsButton))
                     .addGroup(layout.createSequentialGroup()
-                        .addComponent(addBeforeButton, 
GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE)
+                        .addComponent(addBeforeButton, 
GroupLayout.DEFAULT_SIZE, 126, Short.MAX_VALUE)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(addAfterButton, 
GroupLayout.DEFAULT_SIZE, 120, Short.MAX_VALUE)
+                        .addComponent(addAfterButton, 
GroupLayout.DEFAULT_SIZE, 124, Short.MAX_VALUE)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(moveUpButton, 
GroupLayout.DEFAULT_SIZE, 119, Short.MAX_VALUE)
+                        .addComponent(moveUpButton, 
GroupLayout.DEFAULT_SIZE, 123, Short.MAX_VALUE)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(moveDownButton, 
GroupLayout.DEFAULT_SIZE, 120, Short.MAX_VALUE)
+                        .addComponent(moveDownButton, 
GroupLayout.DEFAULT_SIZE, 124, Short.MAX_VALUE)
                         .addPreferredGap(ComponentPlacement.RELATED)
-                        .addComponent(deleteButton, 
GroupLayout.DEFAULT_SIZE, 115, Short.MAX_VALUE))
+                        .addComponent(deleteButton, 
GroupLayout.DEFAULT_SIZE, 123, Short.MAX_VALUE))
                     .addGroup(Alignment.TRAILING, 
layout.createSequentialGroup()
                         .addComponent(editSubtitlePanel, 
GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                         .addPreferredGap(ComponentPlacement.RELATED)
@@ -352,7 +355,7 @@
                         .addComponent(progressBar, 
GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, 
GroupLayout.PREFERRED_SIZE)
                         .addPreferredGap(ComponentPlacement.RELATED)
                         .addComponent(toolBar, GroupLayout.PREFERRED_SIZE, 
GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
-                    .addComponent(separator1, GroupLayout.DEFAULT_SIZE, 620, 
Short.MAX_VALUE))
+                    .addComponent(separator1, GroupLayout.DEFAULT_SIZE, 644, 
Short.MAX_VALUE))
                 .addContainerGap())
         );
 
@@ -435,25 +438,6 @@
     public void windowOpened(java.awt.event.WindowEvent evt) {
     }// </editor-fold>//GEN-END:initComponents
 
-    private void initEnvironment() {
-        bundle = Context.getBundle();
-        columnNames = new String[] {
-            bundle.getString("IndexTableHeader"),
-            bundle.getString("BeginTimeTableHeader"),
-            bundle.getString("EndTimeTableHeader"),
-            bundle.getString("ContentTableHeader")
-        };
-    }
-
-    // Removes the unnecessary border of JComboBox for Windows Vista and 
above.
-    private void fixComboBoxUIForWindows() {
-        String osName = System.getProperty("os.name");
-        double osVersion = 
Double.parseDouble(System.getProperty("os.version"));
-        if (osName.startsWith("Windows") && osVersion >= 6.0) {
-            directionComboBox.setBorder(null);
-        }
-    }
-
     private void aboutButtonActionPerformed(ActionEvent evt) 
{//GEN-FIRST:event_aboutButtonActionPerformed
         JOptionPane.showMessageDialog(this, bundle.getString("AboutContent"),
                 bundle.getString("AboutTitle"), 
JOptionPane.INFORMATION_MESSAGE);
@@ -472,34 +456,8 @@
                     return;
                 }
             }
-
             pathTextField.setText(srt.getPath());
-            enableComponents(false);
-            srtTable.setModel(emptyModel);
-            new SwingWorker<Void, Void>() {
-
-                @Override
-                protected Void doInBackground() throws Exception {
-                    // TO DO: Should show up exception if an error 
occurred...
-                    loadSrt();
-                    return null;
-                }
-
-                @Override
-                protected void done() {
-                    try {
-                        srtTable.setModel(tableModel);
-                        
srtTable.getTableHeader().setReorderingAllowed(false);
-                        
srtTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-//                        srtTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
-                    } catch (Exception ex) {
-                        showException(ex);
-                    } finally {
-                        enableComponents(true);
-                    }
-                }
-
-            }.execute();
+            loadSrt();
         }
     }//GEN-LAST:event_loadButtonActionPerformed
 
@@ -517,7 +475,7 @@
         }
     }//GEN-LAST:event_formWindowClosing
 
-    private void enableComponents(boolean enabled) {
+    private void enableEditingComponents(boolean enabled) {
         saveButton.setEnabled(enabled);
         saveAsButton.setEnabled(enabled);
         srtTable.setEnabled(enabled);
@@ -538,104 +496,68 @@
         cancelTaskButton.setEnabled(enabled);
     }
 
-    private void loadSrt() throws SubtitleFormatException, IOException {
-        tableModel = new DefaultTableModel(columnNames, 0) {
+    private void showException(Exception ex) {
+        JOptionPane.showMessageDialog(this, ex.getMessage(),
+                bundle.getString("Error"), JOptionPane.ERROR_MESSAGE);
+    }
 
+    private void loadSrt() {
+        loadButton.setEnabled(false);
+        enableEditingComponents(false);
+        srtTable.setModel(emptyModel);
+        progressBar.setIndeterminate(true);
+        progressBar.setString(bundle.getString("Loading"));
+        new SwingWorker<Vector<Vector<Object>>, Void>() {
+
             @Override
-            public boolean isCellEditable(int row, int column) {
-                return false;
+            protected Vector<Vector<Object>> doInBackground() throws 
Exception {
+                return SrtToolkit.parseSrt(new 
File(pathTextField.getText()));
             }
 
-        };
-        BufferedReader in = new BufferedReader(new InputStreamReader(
-                new FileInputStream(pathTextField.getText()), 
Context.getCharset()));
-        lineNumber = 0;
-        subtitleIndex = 1;
-        while (readOneSubtitle(in)) {
-        }
-    }
+            @Override
+            protected void done() {
+                try {
+                    Vector<String> columnNames = new Vector<String>();
+                    columnNames.add(bundle.getString("IndexTableHeader"));
+                    
columnNames.add(bundle.getString("BeginTimeTableHeader"));
+                    columnNames.add(bundle.getString("EndTimeTableHeader"));
+                    columnNames.add(bundle.getString("ContentTableHeader"));
+                    srtTable.setModel(new DefaultTableModel(get(), 
columnNames) {
 
-    /**
-     * Read one subtitle from the reader and insert the parsed data to
-     * {@code tableModel}.
-     * @param in The reader to read the subtitles from.
-     * @return {@code true} if one subtitle is read, otherwise {@code false}.
-     * @throws SubtitleFormatException If the format is wrong.
-     * @throws IOException If an I/O error occured.
-     */
-    private boolean readOneSubtitle(BufferedReader in)
-            throws SubtitleFormatException, IOException {
-        // If there're more subtitles, the line should be the index.
-        String index = readNonEmptyLine(in);
-        if (index == null) {
-            return false;
-        }
+                        @Override
+                        public boolean isCellEditable(int row, int column) {
+                            return false;
+                        }
 
-        // Start to read a subtitle.
-        // We can bypass the index, for it's easy and safe to regenerate 
them.
-        // Read begin and end times.
-        String[] times = readStartAndEndTimes(in);
-        if (times == null) {
-            return false;
-        }
-
-        tableModel.addRow(new Object[] {
-            subtitleIndex++, times[0], times[1], readContent(in)
-        });
-        return true;
-    }
-
-    private String readNonEmptyLine(BufferedReader in) throws IOException {
-        String line = null;
-        // Skip empty lines.
-        do {
-            line = readLine(in);
-            if (line == null) {
-                return null;
+                    });
+                    srtTable.getTableHeader().setReorderingAllowed(false);
+                    
srtTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+                    srtTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
+                    TableColumnModel columnModel = srtTable.getColumnModel();
+                    columnModel.getColumn(0).setPreferredWidth(50);
+                    columnModel.getColumn(1).setPreferredWidth(100);
+                    columnModel.getColumn(2).setPreferredWidth(100);
+                    columnModel.getColumn(3).setPreferredWidth(500);
+                } catch (Exception ex) {
+                    Throwable cause = ex.getCause();
+                    if (cause != null && (cause instanceof IOException
+                            || cause instanceof SubtitleFormatException)) {
+                        showException((Exception) cause);
+                    } else {
+                        showException(ex);
+                    }
+                    return;
+                } finally {
+                    loadButton.setEnabled(true);
+                    progressBar.setIndeterminate(false);
+                    progressBar.setString(bundle.getString("Ready"));
+                }
+                enableEditingComponents(true);
             }
-        } while (line.isEmpty());
-        return line;
-    }
 
-    private String[] readStartAndEndTimes(BufferedReader in)
-            throws SubtitleFormatException, IOException {
-        String time = readLine(in);
-        if (time == null) {
-            return null;
-        }
-        String[] times = time.split(" --> ");
-        if (times.length != 2
-                || !timePattern.matcher(times[0]).matches()
-                || !timePattern.matcher(times[1]).matches()) {
-            throw new SubtitleFormatException(bundle.getString("BadTime"));
-        }
-        return times;
+        }.execute();
     }
 
-    private String readContent(BufferedReader in) throws IOException {
-        String content = "";
-        String line = readLine(in);
-        while (line != null) {
-            if (line.isEmpty()) {
-                break;
-            }
-            content = content + line + "\n";
-            line = readLine(in);
-        }
-        return content;
-    }
-
-    private String readLine(BufferedReader in) throws IOException {
-        String line = in.readLine();
-        lineNumber++;
-        return line;
-    }
-
-    private void showException(Exception ex) {
-        JOptionPane.showMessageDialog(this, ex.getMessage(),
-                bundle.getString("Error"), JOptionPane.ERROR_MESSAGE);
-    }
-
     public static void main(String args[]) {
         try {
             
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
@@ -674,6 +596,7 @@
     private JLabel contentLabel;
     private JScrollPane contentScrollPane;
     private JTextArea contentTextArea;
+    private JCheckBox continuousEditCheckBox;
     private JButton deleteButton;
     private JComboBox directionComboBox;
     private JLabel directionLabel;
Index: SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtEditorFrame.form
===================================================================
--- SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtEditorFrame.form      
  (revision 29)
+++ SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtEditorFrame.form      
  (revision 30)
@@ -44,26 +44,26 @@
           <Group type="102" attributes="0">
               <EmptySpace max="-2" attributes="0"/>
               <Group type="103" groupAlignment="0" attributes="0">
-                  <Component id="srtScrollPane" alignment="0" pref="620" 
max="32767" attributes="0"/>
+                  <Component id="srtScrollPane" alignment="0" pref="644" 
max="32767" attributes="0"/>
                   <Group type="102" alignment="1" attributes="0">
                       <Component id="loadButton" min="-2" max="-2" 
attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
-                      <Component id="pathTextField" pref="363" max="32767" 
attributes="0"/>
+                      <Component id="pathTextField" pref="365" max="32767" 
attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
                       <Component id="saveButton" linkSize="7" min="-2" 
max="-2" attributes="0"/>
                       <EmptySpace max="-2" attributes="0"/>
                       <Component id="saveAsButton" linkSize="7" min="-2" 
max="-2" attributes="0"/>
                   </Group>
                   <Group type="102" alignment="0" attributes="0">
-                      <Component id="addBeforeButton" pref="122" max="32767" 
attributes="0"/>
+                      <Component id="addBeforeButton" pref="126" max="32767" 
attributes="0"/>
                       <EmptySpace min="-2" max="-2" attributes="0"/>
-                      <Component id="addAfterButton" pref="120" max="32767" 
attributes="0"/>
+                      <Component id="addAfterButton" pref="124" max="32767" 
attributes="0"/>
                       <EmptySpace min="-2" max="-2" attributes="0"/>
-                      <Component id="moveUpButton" pref="119" max="32767" 
attributes="0"/>
+                      <Component id="moveUpButton" pref="123" max="32767" 
attributes="0"/>
                       <EmptySpace min="-2" max="-2" attributes="0"/>
-                      <Component id="moveDownButton" pref="120" max="32767" 
attributes="0"/>
+                      <Component id="moveDownButton" pref="124" max="32767" 
attributes="0"/>
                       <EmptySpace min="-2" max="-2" attributes="0"/>
-                      <Component id="deleteButton" pref="115" max="32767" 
attributes="0"/>
+                      <Component id="deleteButton" pref="123" max="32767" 
attributes="0"/>
                   </Group>
                   <Group type="102" alignment="1" attributes="0">
                       <Component id="editSubtitlePanel" max="32767" 
attributes="0"/>
@@ -79,7 +79,7 @@
                       <EmptySpace max="-2" attributes="0"/>
                       <Component id="toolBar" min="-2" max="-2" 
attributes="0"/>
                   </Group>
-                  <Component id="separator1" alignment="0" pref="620" 
max="32767" attributes="0"/>
+                  <Component id="separator1" alignment="0" pref="644" 
max="32767" attributes="0"/>
               </Group>
               <EmptySpace max="-2" attributes="0"/>
           </Group>
@@ -182,18 +182,22 @@
                       <Group type="102" alignment="0" attributes="0">
                           <Component id="beginTimeLabel" min="-2" max="-2" 
attributes="0"/>
                           <EmptySpace max="-2" attributes="0"/>
-                          <Component id="beginTimeTextField" pref="142" 
max="32767" attributes="0"/>
+                          <Component id="beginTimeTextField" pref="144" 
max="32767" attributes="0"/>
                           <EmptySpace type="separate" min="-2" max="-2" 
attributes="0"/>
                           <Component id="endTimeLabel" min="-2" max="-2" 
attributes="0"/>
                           <EmptySpace min="-2" max="-2" attributes="0"/>
-                          <Component id="endTimeTextField" pref="143" 
max="32767" attributes="0"/>
+                          <Component id="endTimeTextField" pref="145" 
max="32767" attributes="0"/>
                       </Group>
                       <Group type="102" alignment="0" attributes="0">
                           <Component id="contentLabel" min="-2" max="-2" 
attributes="0"/>
                           <EmptySpace max="-2" attributes="0"/>
-                          <Component id="contentScrollPane" pref="361" 
max="32767" attributes="0"/>
+                          <Component id="contentScrollPane" pref="377" 
max="32767" attributes="0"/>
                       </Group>
-                      <Component id="updateSubtitleButton" alignment="1" 
min="-2" max="-2" attributes="0"/>
+                      <Group type="102" alignment="1" attributes="0">
+                          <Component id="continuousEditCheckBox" min="-2" 
max="-2" attributes="0"/>
+                          <EmptySpace pref="113" max="32767" attributes="0"/>
+                          <Component id="updateSubtitleButton" min="-2" 
max="-2" attributes="0"/>
+                      </Group>
                   </Group>
                   <EmptySpace max="-2" attributes="0"/>
               </Group>
@@ -212,10 +216,13 @@
                   <EmptySpace max="-2" attributes="0"/>
                   <Group type="103" groupAlignment="0" attributes="0">
                       <Component id="contentLabel" min="-2" max="-2" 
attributes="1"/>
-                      <Component id="contentScrollPane" pref="72" 
max="32767" attributes="1"/>
+                      <Component id="contentScrollPane" pref="75" 
max="32767" attributes="1"/>
                   </Group>
                   <EmptySpace max="-2" attributes="0"/>
-                  <Component id="updateSubtitleButton" min="-2" max="-2" 
attributes="0"/>
+                  <Group type="103" groupAlignment="3" attributes="0">
+                      <Component id="updateSubtitleButton" alignment="3" 
min="-2" max="-2" attributes="0"/>
+                      <Component id="continuousEditCheckBox" alignment="3" 
min="-2" max="-2" attributes="0"/>
+                  </Group>
                   <EmptySpace max="-2" attributes="0"/>
               </Group>
           </Group>
@@ -269,6 +276,14 @@
             </Property>
           </Properties>
         </Component>
+        <Component class="javax.swing.JCheckBox" 
name="continuousEditCheckBox">
+          <Properties>
+            <Property name="selected" type="boolean" value="true"/>
+            <Property name="text" type="java.lang.String" 
editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+              <ResourceString 
bundle="com/zhyi/srtsubtitleeditor/Bundle.properties" key="ContinuousEdit" 
replaceFormat="bundle.getString(&quot;{key}&quot;)"/>
+            </Property>
+          </Properties>
+        </Component>
       </SubComponents>
     </Container>
     <Component class="javax.swing.JButton" name="addBeforeButton">
@@ -336,7 +351,7 @@
                       <Group type="102" alignment="0" attributes="0">
                           <Component id="amountLabel" linkSize="3" min="-2" 
max="-2" attributes="0"/>
                           <EmptySpace max="-2" attributes="0"/>
-                          <Component id="amountTextField" pref="52" 
max="32767" attributes="0"/>
+                          <Component id="amountTextField" pref="53" 
max="32767" attributes="0"/>
                           <EmptySpace max="-2" attributes="0"/>
                           <Component id="msLabel" min="-2" max="-2" 
attributes="0"/>
                       </Group>
Index: SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtToolkit.java
===================================================================
--- SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtToolkit.java    
(revision 0)
+++ SrtSubtitleEditor/src/com/zhyi/srtsubtitleeditor/SrtToolkit.java    
(revision 30)
@@ -0,0 +1,162 @@
+/*
+ * SrtToolkit.java
+ *
+ * Copyright (C) 2009 Zhao Yi
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+package com.zhyi.srtsubtitleeditor;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.text.MessageFormat;
+import java.util.Vector;
+import java.util.regex.Pattern;
+
+/**
+ * This class contains methods for processing SRT files.
+ * @author Zhao Yi
+ */
+public class SrtToolkit {
+
+    private static final Pattern TIME_PATTERN = Pattern.compile(
+            "^\\d{2}(:[0-5]\\d){2},\\d{3}$");
+    private static int lineNumber = 0;
+    private static int subtitleIndex = 1;
+
+    /**
+     * Parses a SRT file to a vector of vectors which can be used directly 
for
+     * constructing a {@code DefaultTableModel} object. Each sub-vector
+     * represents a subtitle (index, begin time, end time and content).
+     * @param srtFile The SR file.
+     * @return A vector of vector containing all subtitles.
+     * @throws SubtitleFormatException If the begin or end time of a subtitle
+     * is bad formatted.
+     * @throws IOException If any I/O error occureed.
+     */
+    public static Vector<Vector<Object>> parseSrt(File srtFile)
+            throws SubtitleFormatException, IOException {
+        lineNumber = 0;
+        subtitleIndex = 0;
+        BufferedReader in = new BufferedReader(new InputStreamReader(
+                new FileInputStream(srtFile), Context.getCharset()));
+        Vector<Vector<Object>> subtitles = new Vector<Vector<Object>>();
+        Vector<Object> subtitle = readOneSubtitle(in);
+        while (subtitle != null) {
+            subtitles.add(subtitle);
+            subtitle = readOneSubtitle(in);
+        }
+        in.close();
+        return subtitles;
+    }
+
+    /**
+     * Saves subtitles to an SRT file.
+     * @param subtitles A vector of vector containing all subtitles which can
+     * be got from the SRT table's model.
+     * @param srtFile The SRT file.
+     * @throws IOException If any I/O error occureed.
+     */
+    public static void saveSrt(Vector<Vector<Object>> subtitles, File 
srtFile)
+            throws IOException {
+        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
+                new FileOutputStream(srtFile), Context.getCharset()));
+        for (Vector<Object> subtitle : subtitles) {
+            for (Object datum : subtitle) {
+                out.write((String) datum);
+                out.newLine();
+            }
+            out.newLine();
+        }
+        out.close();
+    }
+
+    private static Vector<Object> readOneSubtitle(BufferedReader in)
+            throws SubtitleFormatException, IOException {
+        // If there're more subtitles, the line should be the index. However,
+        // the index is ignored, for it will be added automatically later.
+        String index = readNonEmptyLine(in);
+        if (index == null) {
+            return null;
+        }
+
+        // Read begin and end times.
+        String[] times = readBeginAndEndTimes(in);
+        if (times == null) {
+            return null;
+        }
+
+        Vector<Object> subtitle = new Vector<Object>();
+        subtitle.add(subtitleIndex++);
+        subtitle.add(times[0]);
+        subtitle.add(times[1]);
+        subtitle.add(readContent(in));
+        return subtitle;
+    }
+
+    private static String readNonEmptyLine(BufferedReader in) throws 
IOException {
+        String line = null;
+        // Skip empty lines.
+        do {
+            line = readLine(in);
+            if (line == null) {
+                // The end of file.
+                return null;
+            }
+        } while (line.isEmpty());
+        return line;
+    }
+
+    private static String[] readBeginAndEndTimes(BufferedReader in)
+            throws SubtitleFormatException, IOException {
+        String time = readLine(in);
+        if (time == null) {
+            return null;
+        }
+        String[] times = time.split(" --> ");
+        if (times.length != 2
+                || !TIME_PATTERN.matcher(times[0]).matches()
+                || !TIME_PATTERN.matcher(times[1]).matches()) {
+            throw new SubtitleFormatException(MessageFormat.format(
+                    Context.getBundle().getString("BadTime"), lineNumber));
+        }
+        return times;
+    }
+
+    private static String readContent(BufferedReader in) throws IOException {
+        String content = "";
+        String line = readLine(in);
+        while (line != null) {
+            if (line.isEmpty()) {
+                break;
+            }
+            content = content + line + "\n";
+            line = readLine(in);
+        }
+        return content;
+    }
+
+    private static String readLine(BufferedReader in) throws IOException {
+        String line = in.readLine();
+        lineNumber++;
+        return line;
+    }
+
+}





[zhyi~subversion:30] Separated the logic for processing SRT to a single class.

zhyi 10/18/2009
  • Mysql
  • Glassfish
  • Jruby
  • Rails
  • Nblogo
Terms of Use; Privacy Policy;
© 2010, Oracle Corporation and/or its affiliates
(revision 20120518.3c65429)
 
 
Close
loading
Please Confirm
Close