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.Dimension; 021 import java.awt.GridLayout; 022 import java.awt.Point; 023 import java.awt.Toolkit; 024 import java.awt.Window; 025 import java.awt.datatransfer.DataFlavor; 026 import java.awt.datatransfer.Transferable; 027 import java.awt.datatransfer.UnsupportedFlavorException; 028 import java.awt.event.ActionEvent; 029 import java.awt.event.ActionListener; 030 import java.awt.event.MouseEvent; 031 import java.awt.event.MouseListener; 032 import java.awt.event.WindowEvent; 033 import java.awt.event.WindowListener; 034 import java.io.File; 035 import java.io.IOException; 036 import java.util.ArrayList; 037 import java.util.Date; 038 import java.util.HashMap; 039 import java.util.List; 040 import java.util.Locale; 041 import java.util.StringTokenizer; 042 043 import javax.swing.ImageIcon; 044 import javax.swing.JButton; 045 import javax.swing.JComponent; 046 import javax.swing.JFileChooser; 047 import javax.swing.JFrame; 048 import javax.swing.JMenu; 049 import javax.swing.JMenuBar; 050 import javax.swing.JMenuItem; 051 import javax.swing.JOptionPane; 052 import javax.swing.JPanel; 053 import javax.swing.JPopupMenu; 054 import javax.swing.JScrollPane; 055 import javax.swing.JSlider; 056 import javax.swing.JTable; 057 import javax.swing.JToolBar; 058 import javax.swing.SwingUtilities; 059 import javax.swing.TransferHandler; 060 import javax.swing.UIManager; 061 import javax.swing.UnsupportedLookAndFeelException; 062 import javax.swing.event.ChangeEvent; 063 import javax.swing.event.ChangeListener; 064 import javax.swing.filechooser.FileFilter; 065 import javax.swing.table.TableColumn; 066 067 import sears.Version; 068 import sears.file.SrtFile; 069 import sears.file.Subtitle; 070 import sears.file.SubtitleFile; 071 import sears.gui.resources.SearsResources; 072 import sears.tools.SearsAction; 073 import sears.tools.SearsProperties; 074 import sears.tools.SearsResourceBundle; 075 import sears.tools.Trace; 076 import sears.tools.Updater; 077 import sears.tools.Utils; 078 import sears.tools.player.DefaultPlayer; 079 import sears.tools.player.PlayerException; 080 import sears.tools.player.PlayerInterface; 081 import sears.tools.player.VLCPlayer; 082 083 /** 084 * Class MainWindow. 085 * <br><b>Summary:</b><br> 086 * This is the main Interface of the sears project. 087 * It contains a JTable to displays the subtitles, and menus to interact and launch actions. 088 */ 089 public class MainWindow extends JFrame implements MouseListener, WindowListener { 090 private static final long serialVersionUID = -6575979899788187615L; 091 092 /** The instance of the mainWindow */ 093 public static MainWindow instance; 094 095 /**The menuBar*/ 096 private JMenuBar jMenuBar; 097 098 /**The subtitle file that is currently opened by Sears*/ 099 private SubtitleFile subtitleFile; 100 101 /**The main panel.*/ 102 private JPanel mainPanel; 103 104 /**The JTable that contains the subtitles.*/ 105 private JTable table; 106 107 /**The JTableModel that is used by the JTable.*/ 108 private SubtitleTableModel tableModel; 109 110 /**The list of subtitles actually in the subtitle file opened*/ 111 private ArrayList<Subtitle> subtitleList; 112 113 /**The application icon*/ 114 private ImageIcon searsIcon; 115 116 /**The Actions hashMap where key is (String) actionId and Value is corresponding SearsAction.*/ 117 private HashMap<String, SearsAction> actions; 118 119 /**The JToolBar*/ 120 private JToolBar jToolBar; 121 122 /**The JPopupMenu*/ 123 private JPopupMenu jPopupMenu; 124 125 /**The Player*/ 126 protected PlayerInterface player = null; 127 128 /**The JPanelVideoControler that controls the video.*/ 129 private JPanelVideoControler jPanelVideoControler; 130 131 /**The full path to the player executable.*/ 132 private static String playerVideoFile = null; 133 134 /** (<b>ArrayList<File></b>) recentFiles: The recentFiles */ 135 private ArrayList<File> recentFiles = null; 136 137 /** (<b>JMenu</b>) recentFileMenu: The recentFileMenu */ 138 private JMenu recentFileMenu; 139 140 /** (<b>int</b>) RECENT_FILE_NUMBER: The max number of recent files to be displayed.*/ 141 private static final int RECENT_FILE_NUMBER = 10; 142 143 /**The Actions Keys*/ 144 /**Open action key, to open a subtitle file*/ 145 protected static String ACTION_KEY_OPEN = "open"; 146 147 /**Save action key, to save current file.*/ 148 protected static String ACTION_KEY_SAVE = "save"; 149 150 /**SaveAs action key, to save current file.*/ 151 protected static String ACTION_KEY_SAVE_AS = "saveAs"; 152 153 /**Quit action key, to save current file.*/ 154 protected static String ACTION_KEY_QUIT = "quit"; 155 156 /**Delay action key, to delay ST.*/ 157 protected static String ACTION_KEY_DELAY = "delay"; 158 159 /**Resynch action key, to resynch ST.*/ 160 protected static String ACTION_KEY_RESYNCH = "resynch"; 161 162 /**Split action key, to split ST.*/ 163 protected static String ACTION_KEY_SPLIT = "split"; 164 165 /**Append action key, to append ST.*/ 166 protected static String ACTION_KEY_APPEND = "append"; 167 168 /**Accent action key, to Accent repair.*/ 169 protected static String ACTION_KEY_ACCENT_REPAIR = "accentRepair"; 170 171 /**Chain action key, to chain repair.*/ 172 protected static String ACTION_KEY_CHAIN_REPAIR = "chainRepair"; 173 174 /**HTML action key, to html repair.*/ 175 protected static String ACTION_KEY_HTML_REPAIR = "htmlRepair"; 176 177 /**Order action key, to order repair.*/ 178 protected static String ACTION_KEY_ORDER_REPAIR = "orderRepair"; 179 180 /**Time action key, to time repair.*/ 181 protected static String ACTION_KEY_TIME_REPAIR = "timeRepair"; 182 183 /**NormalizeDuration action key, to time repair.*/ 184 protected static String ACTION_KEY_NORMALIZE_DURATION = "normalizeDuration"; 185 186 /**Select video action key.*/ 187 protected static String ACTION_KEY_SELECT_VIDEO = "selectVideo"; 188 189 /**Options action key.*/ 190 protected static String ACTION_KEY_OPTIONS = "options"; 191 192 /**Play action key.*/ 193 protected static String ACTION_KEY_PLAY = "play"; 194 195 /**Stop action key.*/ 196 protected static String ACTION_KEY_STOP = "stop"; 197 198 /**Pause action key.*/ 199 protected static String ACTION_KEY_PAUSE = "pause"; 200 201 /**Previous action key.*/ 202 protected static String ACTION_KEY_PREVIOUS = "previous"; 203 204 /**Next action key.*/ 205 protected static String ACTION_KEY_NEXT = "next"; 206 207 /**TrackTrigger action key.*/ 208 protected static String ACTION_KEY_TRACKER_TRIGGER = "trackTrigger"; 209 210 /**gotoSub action key.*/ 211 protected static String ACTION_KEY_GOTO_SUB = "gotoSub"; 212 213 /**magicResynchro action key.*/ 214 protected static String ACTION_KEY_MAGIC_RESYNCHRO = "magicResynchro"; 215 216 /**remoaveAllAnchors action key.*/ 217 protected static String ACTION_KEY_REMOVE_ALL_ANCHORS = "removeAllAnchors"; 218 219 /**about action key.*/ 220 protected static String ACTION_KEY_ABOUT = "about"; 221 222 /** (<b>String[]</b>) FILE_OPEN_DEPENDANT_ACTIONS: The Actions that depend on a file open status*/ 223 private static final String[] FILE_OPEN_DEPENDANT_ACTIONS = new String[] { 224 ACTION_KEY_ACCENT_REPAIR 225 , ACTION_KEY_APPEND 226 , ACTION_KEY_CHAIN_REPAIR 227 , ACTION_KEY_DELAY 228 , ACTION_KEY_HTML_REPAIR 229 , ACTION_KEY_MAGIC_RESYNCHRO 230 , ACTION_KEY_NORMALIZE_DURATION 231 , ACTION_KEY_ORDER_REPAIR 232 , ACTION_KEY_RESYNCH, ACTION_KEY_SAVE 233 , ACTION_KEY_SAVE_AS 234 , ACTION_KEY_SPLIT 235 , ACTION_KEY_TIME_REPAIR }; 236 237 /** (<b>String[]</b>) FILE_CHANGED_DEPENDANT_ACTIONS: The actions that depend on a file change status*/ 238 private static final String[] FILE_CHANGED_DEPENDANT_ACTIONS = new String[]{ 239 ACTION_KEY_SAVE}; 240 241 /** 242 * 243 * Constructor MainWindow. 244 * <br><b>Summary:</b><br> 245 * Constructor of the class. 246 * construct the GUI. 247 */ 248 public MainWindow() { 249 super(); 250 instance = this; 251 //restore recent files 252 recentFiles = new ArrayList<File>(); 253 String recentFileProperty = SearsProperties.getProperty(SearsProperties.RECENT_FILES); 254 StringTokenizer stk = new StringTokenizer(recentFileProperty, ";"); 255 while(stk.hasMoreTokens()){ 256 String recentFile = stk.nextToken(); 257 recentFiles.add(new File(recentFile)); 258 } 259 //try to get the locale from properties 260 String lang = SearsProperties.getProperty(SearsProperties.LANGUAGE, "en"); 261 String count = SearsProperties.getProperty(SearsProperties.COUNTRY, "US"); 262 Locale locale = new Locale(lang, count); 263 new SearsResourceBundle(); 264 setSelectedLocale(locale); 265 //set the look and feel on the current OS. 266 try { 267 String selectedLookAndFeel = SearsProperties.getProperty(SearsProperties.LOOK_AND_FEEL, UIManager 268 .getSystemLookAndFeelClassName()); 269 UIManager.setLookAndFeel(selectedLookAndFeel); 270 //SwingUtilities.updateComponentTreeUI(instance); 271 SearsProperties.setProperty(SearsProperties.LOOK_AND_FEEL, selectedLookAndFeel); 272 //MainWindow.instance.repaint(); 273 } catch (ClassNotFoundException e1) { 274 // TODO Auto-generated catch block 275 e1.printStackTrace(); 276 } catch (InstantiationException e1) { 277 // TODO Auto-generated catch block 278 e1.printStackTrace(); 279 } catch (IllegalAccessException e1) { 280 // TODO Auto-generated catch block 281 e1.printStackTrace(); 282 } catch (UnsupportedLookAndFeelException e1) { 283 // TODO Auto-generated catch block 284 e1.printStackTrace(); 285 } 286 //Set the size. 287 int width = Integer.parseInt(SearsProperties.getProperty("MainWindow" + SearsProperties.SUFFIX_WIDTH, "600")); 288 int heigth = Integer.parseInt(SearsProperties.getProperty("MainWindow" + SearsProperties.SUFFIX_HEIGTH, "400")); 289 setSize(width, heigth); 290 searsIcon = SearsResources.getIcon("SearsGUIIcon"); 291 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); 292 //Set the frame's icon 293 setIconImage(searsIcon.getImage()); 294 updateWindowsName(); 295 centerFrame(instance); 296 addWindowListener(this); 297 //Construct the actions. 298 constructActions(); 299 mainPanel = new JPanel(); 300 mainPanel.setLayout(new GridLayout(1, 1)); 301 getContentPane().setLayout(new BorderLayout()); 302 getContentPane().add(mainPanel, BorderLayout.CENTER); 303 constructJMenuBar(); 304 setJMenuBar(jMenuBar); 305 constructJToolBar(); 306 getContentPane().add(jToolBar, BorderLayout.NORTH); 307 getContentPane().add(getJPanelVideoControler(), BorderLayout.SOUTH); 308 subtitleList = new ArrayList<Subtitle>(); 309 tableModel = new SubtitleTableModel(subtitleList); 310 table = new JTable(tableModel); 311 table.setRowSelectionAllowed(true); 312 table.addMouseListener(this); 313 // Add the Transfer handler, which will handle the files Drag and drops. 314 SubtitleFileTransfertHandler searsTransferHandler = new SubtitleFileTransfertHandler(); 315 getRootPane().setTransferHandler(searsTransferHandler); 316 table.setTransferHandler(searsTransferHandler); 317 //create table renderer. 318 //setting the table column sizes and renderer. 319 TableColumn column = null; 320 for (int i = 0; i < SubtitleTableModel.COLUMN_NUMBER; i++) { 321 column = table.getColumnModel().getColumn(i); 322 column.setCellRenderer(new SubtitleTableCellRenderer(subtitleList)); 323 column.setHeaderRenderer(new SubtitleAnchorHeaderTableCellRenderer( 324 table.getTableHeader().getDefaultRenderer())); 325 switch (i) { 326 case SubtitleTableModel.ANCHOR_COLUMN: { 327 column.setPreferredWidth(18); 328 column.setMaxWidth(18); 329 break; 330 } 331 case SubtitleTableModel.ID_COLUMN: { 332 column.setPreferredWidth(40); 333 column.setMaxWidth(60); 334 break; 335 } 336 case SubtitleTableModel.START_DATE_COLUMN: { 337 column.setPreferredWidth(100); 338 column.setMaxWidth(100); 339 break; 340 } 341 case SubtitleTableModel.END_DATE_COLUMN: { 342 column.setPreferredWidth(100); 343 column.setMaxWidth(100); 344 break; 345 } 346 } 347 } 348 mainPanel.add(new JScrollPane(table)); 349 350 // 351 // Create the thread of video time handler 352 PlayerTimeHandler playerTimeHandler = new PlayerTimeHandler(); 353 Thread playerTimeHandlerThread = new Thread(playerTimeHandler, "playerTimeHandler"); 354 playerTimeHandlerThread.start(); 355 jPanelVideoControler.setJSliderSearchListener(playerTimeHandler); 356 357 lookForUpdate(); 358 } 359 360 /** 361 * Method getJPanelVideoControler. 362 * <br><b>Summary:</b><br> 363 * Return the JPanel that control the video. 364 * @return The JPanel video controler. 365 */ 366 private JPanel getJPanelVideoControler() { 367 if (jPanelVideoControler == null) { 368 jPanelVideoControler = new JPanelVideoControler(); 369 } 370 return jPanelVideoControler; 371 } 372 373 /** 374 * Method lookForUpdate. 375 * <br><b>Summary:</b><br> 376 * This method look for an update, if the SearsProperties.UPDATE_ADDRESS is not equals to "". 377 * and will display a message to the user if a new Sears version is available. 378 */ 379 private void lookForUpdate() { 380 //If an address update has been set, then update. 381 String updateAddress = SearsProperties.getProperty(SearsProperties.UPDATE_ADDRESS, "firstLaunch"); 382 if (!updateAddress.equals("")) { 383 //If it is the first launch 384 if (updateAddress.equals("firstLaunch")) { 385 setUpdateAddress(Updater.DEFAULT_UPDATE_ADDRESS); 386 updateAddress = Updater.DEFAULT_UPDATE_ADDRESS; 387 } 388 //look for update. 389 new Updater(this, updateAddress, Double.parseDouble(Version.VERSION)); 390 } 391 } 392 393 /** 394 * Method setUpdateAddress. 395 * <br><b>Summary:</b><br> 396 * This method set the new update address. 397 * @param address The new update address to set. 398 */ 399 private void setUpdateAddress(String address) { 400 SearsProperties.setProperty(SearsProperties.UPDATE_ADDRESS, address); 401 } 402 403 /** 404 * Method constructActions. 405 * <br><b>Summary:</b><br> 406 * This method construct the actions. 407 */ 408 private void constructActions() { 409 actions = new HashMap<String, SearsAction>(); 410 //construct Open action 411 actions.put(ACTION_KEY_OPEN, new OpenAction()); 412 //construct Save action 413 actions.put(ACTION_KEY_SAVE, new SaveAction()); 414 //construct SaveAs action 415 actions.put(ACTION_KEY_SAVE_AS, new SaveAsAction()); 416 //construct quit action 417 actions.put(ACTION_KEY_QUIT, new QuitAction()); 418 //construct Delay action 419 actions.put(ACTION_KEY_DELAY, new DelayAction()); 420 //construct Resynch action 421 actions.put(ACTION_KEY_RESYNCH, new ResynchAction()); 422 //construct Split action 423 actions.put(ACTION_KEY_SPLIT, new SplitAction()); 424 //construct Append action 425 actions.put(ACTION_KEY_APPEND, new AppendAction()); 426 //construct AccentRepairAction 427 actions.put(ACTION_KEY_ACCENT_REPAIR, new AccentRepairAction()); 428 //construct ChainRepairAction 429 actions.put(ACTION_KEY_CHAIN_REPAIR, new ChainRepairAction()); 430 //construct HtmlRepairAction 431 actions.put(ACTION_KEY_HTML_REPAIR, new HtmlRepairAction()); 432 //construct OrderRepairAction 433 actions.put(ACTION_KEY_ORDER_REPAIR, new OrderRepairAction()); 434 //construct TimeRepairAction 435 actions.put(ACTION_KEY_TIME_REPAIR, new TimeRepairAction()); 436 //construct NormalizeDurationAction 437 actions.put(ACTION_KEY_NORMALIZE_DURATION, new NormalizeDurationAction()); 438 //construct SelectVideoAction 439 actions.put(ACTION_KEY_SELECT_VIDEO, new SelectVideoAction()); 440 //construct optionsAction 441 actions.put(ACTION_KEY_OPTIONS, new OptionsAction()); 442 //construct playAction 443 actions.put(ACTION_KEY_PLAY, new PlayAction()); 444 //construct stopAction 445 actions.put(ACTION_KEY_STOP, new StopAction()); 446 //construct pauseAction 447 actions.put(ACTION_KEY_PAUSE, new PauseAction()); 448 //construct previousAction 449 actions.put(ACTION_KEY_PREVIOUS, new PreviousAction()); 450 //construct nextAction 451 actions.put(ACTION_KEY_NEXT, new NextAction()); 452 //construct trackerTriggerAction 453 actions.put(ACTION_KEY_TRACKER_TRIGGER, new TrackerTriggerAction()); 454 //construct gotoSubAction 455 actions.put(ACTION_KEY_GOTO_SUB, new GotoSubAction()); 456 //construct magicResynchroAction 457 actions.put(ACTION_KEY_MAGIC_RESYNCHRO, new MagicResynchroAction()); 458 //Construct removeAllAnchorsAction 459 actions.put(ACTION_KEY_REMOVE_ALL_ANCHORS, new RemoveAllAnchorsAction()); 460 //Construct aboutAction 461 actions.put(ACTION_KEY_ABOUT, new AboutAction()); 462 //update the actions status 463 updateActionStatus(); 464 } 465 466 /** 467 * Method constructJMenuBar. 468 * <br><b>Summary:</b><br> 469 * This method construct the JMenuBar 470 */ 471 private void constructJMenuBar() { 472 jMenuBar = new JMenuBar(); 473 ///////////// 474 //FILE MENU 475 ///////////// 476 JMenu jMenuFile = new JMenu(SearsResourceBundle.getResource("menuBar_file")); 477 jMenuBar.add(jMenuFile); 478 //OPEN ITEM 479 jMenuFile.add(new JMenuItem(getAction(ACTION_KEY_OPEN))); 480 //OPEN RECENT FILE 481 recentFileMenu = new JMenu(SearsResourceBundle.getResource("RecentFileName")); 482 recentFileMenu.setToolTipText(SearsResourceBundle.getResource("RecentFileTip")); 483 recentFileMenu.setIcon(SearsResources.getIcon("RecentFileIcon")); 484 jMenuFile.add(recentFileMenu); 485 updateRecentFileMenu(); 486 //SAVE ITEM 487 jMenuFile.add(new JMenuItem(getAction(ACTION_KEY_SAVE))); 488 //SAVE AS ITEM 489 jMenuFile.add(new JMenuItem(getAction(ACTION_KEY_SAVE_AS))); 490 //QUIT ITEM 491 //if platform isn't a Mac platform: 492 if(System.getProperty("mrj.version") == null){ 493 jMenuFile.add(new JMenuItem(getAction(ACTION_KEY_QUIT))); 494 } 495 ////////////////// 496 //ACTION MENU 497 ///////////////// 498 JMenu jMenuAction = new JMenu(SearsResourceBundle.getResource("menuBar_action")); 499 jMenuBar.add(jMenuAction); 500 //DELAY ITEM 501 jMenuAction.add(new JMenuItem(getAction(ACTION_KEY_DELAY))); 502 //RESYNCHRO ITEM 503 jMenuAction.add(new JMenuItem(getAction(ACTION_KEY_RESYNCH))); 504 //MAGIC RESYNCHRO ITEM 505 jMenuAction.add(new JMenuItem(getAction(ACTION_KEY_MAGIC_RESYNCHRO))); 506 //REMOVE ALL ANCHORS ITEM 507 jMenuAction.add(new JMenuItem(getAction(ACTION_KEY_REMOVE_ALL_ANCHORS))); 508 //Add a separator 509 jMenuAction.addSeparator(); 510 //SPLIT FILE ITEM 511 jMenuAction.add(new JMenuItem(getAction(ACTION_KEY_SPLIT))); 512 //SPLIT FILE ITEM 513 jMenuAction.add(new JMenuItem(getAction(ACTION_KEY_APPEND))); 514 ////////////////// 515 //REPAIR MENU 516 ///////////////// 517 JMenu jMenuRepair = new JMenu(SearsResourceBundle.getResource("menuBar_repair")); 518 jMenuBar.add(jMenuRepair); 519 //CHAIN REPAIR 520 jMenuRepair.add(new JMenuItem(getAction(ACTION_KEY_CHAIN_REPAIR))); 521 //Add a separator 522 jMenuRepair.addSeparator(); 523 //ACCENT REPAIR 524 jMenuRepair.add(new JMenuItem(getAction(ACTION_KEY_ACCENT_REPAIR))); 525 //HTML REPAIR 526 jMenuRepair.add(new JMenuItem(getAction(ACTION_KEY_HTML_REPAIR))); 527 //Add a separator 528 jMenuRepair.addSeparator(); 529 //ORDER REPAIR 530 jMenuRepair.add(new JMenuItem(getAction(ACTION_KEY_ORDER_REPAIR))); 531 //TIME REPAIR 532 jMenuRepair.add(new JMenuItem(getAction(ACTION_KEY_TIME_REPAIR))); 533 //TIME REPAIR 534 jMenuRepair.add(new JMenuItem(getAction(ACTION_KEY_NORMALIZE_DURATION))); 535 ////////////////// 536 //PLAYER MENU 537 ///////////////// 538 JMenu jMenuPlayer = new JMenu(SearsResourceBundle.getResource("menuBar_player")); 539 jMenuBar.add(jMenuPlayer); 540 //SELECT VIDEO 541 jMenuPlayer.add(new JMenuItem(getAction(ACTION_KEY_SELECT_VIDEO))); 542 //LAUNCH PLAYER 543 jMenuPlayer.add(new JMenuItem(getAction(ACTION_KEY_PLAY))); 544 //PAUSE PLAYER 545 jMenuPlayer.add(new JMenuItem(getAction(ACTION_KEY_PAUSE))); 546 //STOP PLAYER 547 jMenuPlayer.add(new JMenuItem(getAction(ACTION_KEY_STOP))); 548 //PREVIOUS PLAYER 549 jMenuPlayer.add(new JMenuItem(getAction(ACTION_KEY_PREVIOUS))); 550 //NEXT PLAYER 551 jMenuPlayer.add(new JMenuItem(getAction(ACTION_KEY_NEXT))); 552 ////////////////// 553 //OPTIONS MENU 554 ///////////////// 555 JMenu jMenuOptions = new JMenu(SearsResourceBundle.getResource("menuBar_options")); 556 jMenuBar.add(jMenuOptions); 557 //OPTIONS 558 jMenuOptions.add(new JMenuItem(getAction(ACTION_KEY_OPTIONS))); 559 ////////////////// 560 //HELP MENU 561 ///////////////// 562 JMenu helpMenu = new JMenu(SearsResourceBundle.getResource("menuBar_help")); 563 jMenuBar.add(helpMenu); 564 JMenuItem helpItem = new JMenuItem(SearsResourceBundle.getResource("menuBar_help")); 565 helpItem.setIcon(SearsResources.getIcon("HelpIcon")); 566 helpItem.addActionListener(new ActionListener() { 567 public void actionPerformed(ActionEvent arg0) { 568 //default title and icon 569 JOptionPane 570 .showMessageDialog( 571 instance, 572 "You can find help on Sears\n by going to sears sourceforge page:\nhttp://sears.sourceforge.net/", 573 "Sears Help", JOptionPane.INFORMATION_MESSAGE, searsIcon); 574 } 575 }); 576 helpMenu.add(helpItem); 577 helpMenu.add(new JMenuItem(getAction(ACTION_KEY_ABOUT))); 578 } 579 580 /** 581 * Method constructJMenuBar. 582 * <br><b>Summary:</b><br> 583 * This method construct the JMenuBar 584 */ 585 private void constructJToolBar() { 586 jToolBar = new JToolBar(); 587 ///////////// 588 //FILE TOOLS 589 ///////////// 590 //OPEN ITEM 591 JButton button = new JButton(getAction(ACTION_KEY_OPEN)); 592 button.setText(null); 593 jToolBar.add(button); 594 //SAVE ITEM 595 button = new JButton(getAction(ACTION_KEY_SAVE)); 596 button.setText(null); 597 jToolBar.add(button); 598 //add separator 599 jToolBar.addSeparator(); 600 ////////////////// 601 //ACTION MENU 602 ///////////////// 603 //DELAY ITEM 604 button = new JButton(getAction(ACTION_KEY_DELAY)); 605 button.setText(null); 606 jToolBar.add(button); 607 //MAGIC RESYNCHRO ITEM 608 button = new JButton(getAction(ACTION_KEY_MAGIC_RESYNCHRO)); 609 button.setText(null); 610 jToolBar.add(button); 611 //REMOVE ALL ANCHORS ITEM 612 button = new JButton(getAction(ACTION_KEY_REMOVE_ALL_ANCHORS)); 613 button.setText(null); 614 jToolBar.add(button); 615 //SPLIT ITEM 616 button = new JButton(getAction(ACTION_KEY_SPLIT)); 617 button.setText(null); 618 jToolBar.add(button); 619 //APPEND ITEM 620 button = new JButton(getAction(ACTION_KEY_APPEND)); 621 button.setText(null); 622 jToolBar.add(button); 623 //add separator 624 jToolBar.addSeparator(); 625 ////////////////// 626 //REPAIR MENU 627 ///////////////// 628 //CHAIN REPAIR ITEM 629 button = new JButton(getAction(ACTION_KEY_CHAIN_REPAIR)); 630 button.setText(null); 631 jToolBar.add(button); 632 633 //ACCENT REPAIR ITEM 634 button = new JButton(getAction(ACTION_KEY_ACCENT_REPAIR)); 635 button.setText(null); 636 jToolBar.add(button); 637 //HTML REPAIR ITEM 638 button = new JButton(getAction(ACTION_KEY_HTML_REPAIR)); 639 button.setText(null); 640 jToolBar.add(button); 641 jToolBar.addSeparator(); 642 ////////////////// 643 //TOOLS MENU 644 ///////////////// 645 //OPTIONS BUTTON 646 button = new JButton(getAction(ACTION_KEY_OPTIONS)); 647 button.setText(null); 648 jToolBar.add(button); 649 } 650 651 /** 652 * Method getAction. 653 * <br><b>Summary:</b><br> 654 * Return the SearsActions that correspond to the given key. 655 * @param key The <b>String</b> Action key to search for. 656 * @return SearsAction The <b>SearsAction</b> that correspond to the key, or null if not found. 657 */ 658 protected SearsAction getAction(String key) { 659 //Search and return the action in the actions map. 660 return (SearsAction) actions.get(key); 661 } 662 663 /** 664 * Method delayAction. 665 * <br><b>Summary:</b><br> 666 * Use this method to set a delay on subtitles. 667 * It will show a dialog to enter a delay to the selected subtitles. 668 */ 669 protected void delayAction() { 670 //Must have opened a subtitle file to apply a delay. 671 if (subtitleFile != null) { 672 //get the selected rows to delay. 673 int[] indexToDelay = table.getSelectedRows(); 674 //ask the user for delay to apply 675 DelayDialog dd = new DelayDialog(); 676 dd.setVisible(true); 677 //if user choose a delay. 678 if (dd.hasBeenValidated()) { 679 double delay = dd.getDelay(); 680 //delay the subtitle with the given delay. 681 //multiply by 1000, because delay is indicated in second, with possible milliseconds. 682 subtitleFile.delay(indexToDelay, (int) (delay * 1000)); 683 //indicate table that data have changed 684 tableModel.fireTableDataChanged(); 685 } 686 updateWindowsName(); 687 updateActionStatus(); 688 } else { 689 //Must have opened a subtitle file to apply a delay. 690 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeDelay"), Trace.WARNING_PRIORITY); 691 } 692 } 693 694 /** 695 * Method resynchroAction. 696 * <br><b>Summary:</b><br> 697 * Use this method to resynchro subtitles. 698 * If user has selected the Two source point, the dialog shown will be pre-filled with good values. 699 */ 700 protected void resynchroAction() { 701 //Must have opened a subtitle file to apply a resynchro. 702 if (subtitleFile != null) { 703 //check wether user choose two source subtitles. 704 int[] selectedIndex = table.getSelectedRows(); 705 ResynchroDialog rd; 706 //If user choose sources, use them in shown dialog. 707 if (selectedIndex.length > 1) { 708 //Keep only 2 subtitles. interpolation of level n will come after :) 709 int[] selectedIndex2 = new int[2]; 710 selectedIndex2[0] = selectedIndex[0]; 711 selectedIndex2[1] = selectedIndex[1]; 712 //TODO: create n-level interpolation in SubtitleFile! 713 //construct the dialog. 714 rd = new ResynchroDialog(subtitleList, selectedIndex2); 715 } else { 716 //If no subtitles has been selected, construct empty resynchro dialog. 717 rd = new ResynchroDialog(subtitleList); 718 } 719 //show the constructed dialog. 720 rd.setVisible(true); 721 //check user's response. 722 if (rd.hasBeenValidated()) { 723 //if user has validated the dialog, get the result. 724 int[] result = rd.getResult(); 725 //and resynchro the subtitles. 726 subtitleFile.resynchro(result); 727 //indicate the table that data have changed. 728 tableModel.fireTableDataChanged(); 729 } 730 updateWindowsName(); 731 updateActionStatus(); 732 } else { 733 //Must have opened a subtitle file to apply a resynchro. 734 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeResynch"), Trace.WARNING_PRIORITY); 735 } 736 } 737 738 /** 739 * Method magicResynchroAction. 740 * <br><b>Summary:</b><br> 741 * Apply a magic resynchro 742 */ 743 protected void magicResynchroAction(){ 744 if (subtitleFile != null) { 745 subtitleFile.magicResynchro(); 746 //After magic resynchro, remove all anchors. 747 removeAllAnchorsAction(); 748 updateWindowsName(); 749 updateActionStatus(); 750 } else { 751 //Must have opened a subtitle file to apply a resynchro. 752 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeResynch"), Trace.WARNING_PRIORITY); 753 } 754 } 755 756 /** 757 * Method saveAsAction. 758 * <br><b>Summary:</b><br> 759 * Method called when want to save the subtitle file. 760 * open a JFolderChooser to chooser where to save the file. 761 */ 762 protected void saveAsAction() { 763 Trace.trace("SaveAsAction", Trace.ALGO_PRIORITY); 764 JFileChooser fc = null; 765 //If have already opened a subtitle file, choose content directory. 766 if (subtitleFile != null) { 767 fc = new JFileChooser(subtitleFile.getContentDirectory()); 768 fc.setSelectedFile(subtitleFile.getFile()); 769 } else { 770 fc = new JFileChooser(); 771 } 772 fc.setApproveButtonText(SearsResourceBundle.getResource("button_saveAs")); 773 int returnVal = fc.showOpenDialog(instance); 774 fc.setFileFilter(new FileFilter() { 775 public String getDescription() { 776 return SearsResourceBundle.getResource("various_subtitleFileDescription"); 777 } 778 779 public boolean accept(File f) { 780 return f.isDirectory() || Utils.getExtension(f).equals("srt"); 781 } 782 }); 783 if (returnVal == 0) { 784 //if user has choosed a file, save in it. 785 File file = fc.getSelectedFile(); 786 Trace.trace(SearsResourceBundle.getResource("various_saveAs") + " " + file.getName() + "."); 787 subtitleFile.writeToFile(file); 788 openFile(file); 789 } else { 790 //User caceled the save action. 791 Trace.trace(SearsResourceBundle.getResource("various_openCommandCanceled")); 792 } 793 updateWindowsName(); 794 updateActionStatus(); 795 } 796 797 /** 798 * Method saveAction. 799 * <br><b>Summary:</b><br> 800 * Method called when want to save the subtitle file. 801 */ 802 protected void saveAction() { 803 Trace.trace("SaveAction", Trace.ALGO_PRIORITY); 804 if (subtitleFile != null) { 805 subtitleFile.writeToFile(subtitleFile.getFile()); 806 updateWindowsName(); 807 updateActionStatus(); 808 } 809 } 810 811 /** 812 * Method quitAction. 813 * <br><b>Summary:</b><br> 814 * Use this method to quit Sears. 815 */ 816 protected void quitAction() { 817 //check current file before quit. 818 if (checkUnsavedFileBeforeAction()) { 819 Trace.trace(SearsResourceBundle.getResource("various_quittingSears"), Trace.ALGO_PRIORITY); 820 if (player != null) { 821 player.quit(); 822 } 823 saveMainWindowProperties(); 824 SearsProperties.saveProperties(); 825 System.exit(0); 826 } 827 } 828 829 /** 830 * Method saveMainWindowProperties. 831 * <br><b>Summary:</b><br> 832 * This method saves the MainWindow properties of Sears. 833 */ 834 private void saveMainWindowProperties() { 835 //save windows properties. 836 SearsProperties.setProperty("MainWindow" + SearsProperties.SUFFIX_WIDTH, "" + this.getWidth()); 837 SearsProperties.setProperty("MainWindow" + SearsProperties.SUFFIX_HEIGTH, "" + this.getHeight()); 838 //save the folder property. 839 if (subtitleFile != null) { 840 SearsProperties.setProperty(SearsProperties.LAST_FOLDER, "" + subtitleFile.getContentDirectory()); 841 } 842 //Save the locale. 843 SearsProperties.setProperty(SearsProperties.LANGUAGE, getLocale().getLanguage().toString()); 844 SearsProperties.setProperty(SearsProperties.COUNTRY, getLocale().getCountry().toString()); 845 //Save the recent files list. 846 String recentFilesProperty = ""; 847 for(File file: recentFiles){ 848 recentFilesProperty+=file.getAbsolutePath()+";"; 849 } 850 SearsProperties.setProperty(SearsProperties.RECENT_FILES, recentFilesProperty); 851 852 } 853 854 /** 855 * Method openAction. 856 * <br><b>Summary:</b><br> 857 * Use this method to open a subtitle file. 858 * Displays a dialog to choose the file to open. 859 */ 860 protected void openAction() { 861 Trace.trace("OpenAction", Trace.ALGO_PRIORITY); 862 File file = showSRTBrowser(); 863 if (file != null) { 864 //If user has choose a file to open, open it. 865 Trace.trace(SearsResourceBundle.getResource("various_opening") + " " + file.getName() + "."); 866 // Close the video file 867 if (subtitleFile != null) { 868 playerVideoFile = null; 869 } 870 openFile(file); 871 // Check if the player is running 872 if(player != null) { 873 stopAction(); 874 playAction(); 875 } 876 } else { 877 //if user canceled opening action, do nothing. 878 Trace.trace(SearsResourceBundle.getResource("various_openCommandCanceled")); 879 } 880 } 881 882 /** 883 * Method showBrowser. 884 * <br><b>Summary:</b><br> 885 * This method shows a browser, to permits subtitle file selection. 886 * Open the browser at the current subtitle file location, if any. 887 * @param filter The file filter 888 * @return <b>File</b> 889 */ 890 public File showBrowser(FileFilter filter) { 891 //The result of the method. 892 File result = null; 893 if(subtitleFile != null){ 894 result = showBrowser(filter, subtitleFile.getFile()); 895 }else{ 896 result = showBrowser(filter, null); 897 } 898 //return the result. 899 return result; 900 } 901 902 /** 903 * Method showBrowser. 904 * <br><b>Summary:</b><br> 905 * This method shows a browser, to permits subtitle file selection. 906 * Open the browser at the given file location. 907 * @param filter The file filter. 908 * @param sourceFile Open the browser in the file's parent path. 909 * @return <b>File</b> 910 */ 911 public File showBrowser(FileFilter filter, File sourceFile) { 912 //The result of the method 913 File result = null; 914 //create the file chooser. 915 JFileChooser fc = null; 916 if (sourceFile != null) { 917 fc = new JFileChooser(sourceFile.getParent()); 918 } else { 919 fc = new JFileChooser(SearsProperties.getProperty(SearsProperties.LAST_FOLDER, "")); 920 } 921 //Set a filter on extension file. 922 if (filter != null){ 923 fc.setFileFilter(filter); 924 } 925 //show the browser 926 if (fc.showOpenDialog(instance) == JFileChooser.APPROVE_OPTION) { 927 //set result if user approved selection. 928 result = fc.getSelectedFile(); 929 } 930 return result; 931 } 932 933 /** 934 * Method showSRTBrowser. 935 * <br><b>Summary:</b><br> 936 * This method shows a browser, to permits subtitle file selection. 937 * @return <b>File</b> 938 */ 939 public File showSRTBrowser() { 940 return showBrowser(new FileFilter() { 941 public String getDescription() { 942 return SearsResourceBundle.getResource("various_subtitleFileDescription"); 943 } 944 945 public boolean accept(File f) { 946 return f.isDirectory() || Utils.getExtension(f).equals("srt"); 947 } 948 }); 949 } 950 951 /** 952 * Method showVideoBrowser. 953 * <br><b>Summary:</b><br> 954 * This method shows a browser, to permits video selection. 955 * @return <b>File</b> 956 */ 957 public File showVideoBrowser() { 958 return showBrowser(new FileFilter() { 959 public String getDescription() { 960 return SearsResourceBundle.getResource("various_videoFileDescription"); 961 } 962 963 public boolean accept(File f) { 964 return f.isDirectory() || Utils.getExtension(f).equals("avi") || Utils.getExtension(f).equals("mkv") 965 || Utils.getExtension(f).equals("divx") || Utils.getExtension(f).equals("mov") 966 || Utils.getExtension(f).equals("ogm") || Utils.getExtension(f).equals("wmv") 967 || Utils.getExtension(f).equals("mpg") || Utils.getExtension(f).equals("mpeg"); 968 } 969 }); 970 } 971 972 /** 973 * Method openFile. <br> 974 * <b>Summary:</b><br> 975 * This method open a subtitle file, and put it in the table. 976 * 977 * @param file 978 * The subtitle file to open 979 */ 980 public void openFile(File file) { 981 //check current file before open. 982 if (checkUnsavedFileBeforeAction()) { 983 //Empty the subtitle list. 984 subtitleList.clear(); 985 //create the new subtitleFile. 986 subtitleFile = new SrtFile(file, subtitleList); 987 //indicate table that datas have changed. 988 tableModel.fireTableDataChanged(); 989 updateWindowsName(); 990 addToRecentFileList(file); 991 updateActionStatus(); 992 } 993 } 994 995 /** 996 * Method addToRecentFileList. 997 * <br><b>Summary:</b><br> 998 * This method permits to add a new file to recent file list. 999 * @param file The file that has been opened. 1000 */ 1001 private void addToRecentFileList(File file) { 1002 //remove if previously added. 1003 recentFiles.remove(file); 1004 //save the newly opened file under recent file list. 1005 recentFiles.add(file); 1006 //Remove oldest one, if list is too long. 1007 if(recentFiles.size() > RECENT_FILE_NUMBER){ 1008 recentFiles.remove(0); 1009 } 1010 //Update the recentFile menu. 1011 updateRecentFileMenu(); 1012 } 1013 1014 /** 1015 * Method updateRecentFileMenu. 1016 * <br><b>Summary:</b><br> 1017 * Permit to update the recent file menu. 1018 */ 1019 private void updateRecentFileMenu() { 1020 //Remove all previous menu items. 1021 recentFileMenu.removeAll(); 1022 //And parse all the recent file adding a menuItem for each file. 1023 //parse in reverse order, to put older opened files at the end. 1024 for(int i= recentFiles.size()-1; i >= 0 ;i --){ 1025 final File finalFile = recentFiles.get(i); 1026 JMenuItem jMenuItem = new JMenuItem(finalFile.getName()); 1027 jMenuItem.addActionListener(new ActionListener() { 1028 public void actionPerformed(ActionEvent e) { 1029 openFile(finalFile); 1030 } 1031 }); 1032 recentFileMenu.add(jMenuItem); 1033 } 1034 } 1035 1036 /** 1037 * Method centerFrame. 1038 * <br><b>Summary:</b><br> 1039 * center frame on screen. 1040 * @param window The window to center. 1041 */ 1042 public static void centerFrame(Window window) { 1043 Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); 1044 int w = window.getSize().width; 1045 int h = window.getSize().height; 1046 int x = (dim.width - w) / 2; 1047 int y = (dim.height - h) / 2; 1048 window.setLocation(x, y); 1049 } 1050 1051 /** 1052 * Class DelayAction. 1053 * <br><b>Summary:</b><br> 1054 * The delay action. 1055 */ 1056 class DelayAction extends SearsAction { 1057 private static final long serialVersionUID = -1004418974524773725L; 1058 1059 public DelayAction() { 1060 super("Delay"); 1061 } 1062 1063 /* (non-Javadoc) 1064 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1065 */ 1066 public void actionPerformed(ActionEvent e) { 1067 delayAction(); 1068 } 1069 } 1070 1071 /** 1072 * Class OpenAction. 1073 * <br><b>Summary:</b><br> 1074 * This is the open action, call when user wants to open a file. 1075 */ 1076 class OpenAction extends SearsAction { 1077 private static final long serialVersionUID = -6340643915376767725L; 1078 1079 public OpenAction() { 1080 super("Open"); 1081 } 1082 1083 /* (non-Javadoc) 1084 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1085 */ 1086 public void actionPerformed(ActionEvent e) { 1087 openAction(); 1088 } 1089 } 1090 1091 /** 1092 * Class SaveAction. 1093 * <br><b>Summary:</b><br> 1094 * The Save Action 1095 */ 1096 class SaveAction extends SearsAction { 1097 private static final long serialVersionUID = 4144500453750320579L; 1098 1099 public SaveAction() { 1100 super("Save"); 1101 } 1102 1103 /* (non-Javadoc) 1104 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1105 */ 1106 public void actionPerformed(ActionEvent e) { 1107 saveAction(); 1108 } 1109 } 1110 1111 /** 1112 * Class SaveAsAction. 1113 * <br><b>Summary:</b><br> 1114 * The SaveAs Action 1115 */ 1116 class SaveAsAction extends SearsAction { 1117 private static final long serialVersionUID = 8310536551059661660L; 1118 1119 public SaveAsAction() { 1120 super("SaveAs"); 1121 } 1122 1123 /* (non-Javadoc) 1124 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1125 */ 1126 public void actionPerformed(ActionEvent e) { 1127 saveAsAction(); 1128 } 1129 } 1130 1131 /** 1132 * Class ResynchAction. 1133 * <br><b>Summary:</b><br> 1134 * The Resynch Action 1135 */ 1136 class ResynchAction extends SearsAction { 1137 private static final long serialVersionUID = -3381309933952740831L; 1138 1139 public ResynchAction() { 1140 super("Resynch"); 1141 } 1142 1143 /* (non-Javadoc) 1144 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1145 */ 1146 public void actionPerformed(ActionEvent e) { 1147 resynchroAction(); 1148 } 1149 } 1150 1151 /** 1152 * Class SplitAction. 1153 * <br><b>Summary:</b><br> 1154 * The Split Action 1155 */ 1156 class SplitAction extends SearsAction { 1157 private static final long serialVersionUID = 4890494133812108855L; 1158 1159 public SplitAction() { 1160 super("Split"); 1161 } 1162 1163 /* (non-Javadoc) 1164 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1165 */ 1166 public void actionPerformed(ActionEvent e) { 1167 splitAction(); 1168 } 1169 } 1170 1171 /** 1172 * Class AppendAction. 1173 * <br><b>Summary:</b><br> 1174 * The Append Action 1175 */ 1176 class AppendAction extends SearsAction { 1177 private static final long serialVersionUID = 307293671858946138L; 1178 1179 public AppendAction() { 1180 super("Append"); 1181 } 1182 1183 /* (non-Javadoc) 1184 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1185 */ 1186 public void actionPerformed(ActionEvent e) { 1187 appendAction(); 1188 } 1189 } 1190 1191 /** 1192 * Class QuitAction. 1193 * <br><b>Summary:</b><br> 1194 * The Quit Action 1195 */ 1196 class QuitAction extends SearsAction { 1197 private static final long serialVersionUID = -7251685640412615636L; 1198 1199 public QuitAction() { 1200 super("Quit"); 1201 } 1202 1203 /* (non-Javadoc) 1204 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1205 */ 1206 public void actionPerformed(ActionEvent e) { 1207 quitAction(); 1208 } 1209 } 1210 1211 /** 1212 * Class OrderRepairAction. 1213 * <br><b>Summary:</b><br> 1214 * The OrderRepair Action 1215 */ 1216 class OrderRepairAction extends SearsAction { 1217 private static final long serialVersionUID = 8302695242689945983L; 1218 1219 public OrderRepairAction() { 1220 super("OrderRepair"); 1221 } 1222 1223 /* (non-Javadoc) 1224 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1225 */ 1226 public void actionPerformed(ActionEvent e) { 1227 orderRepairAction(); 1228 } 1229 } 1230 1231 /** 1232 * Class PlayAction. 1233 * <br><b>Summary:</b><br> 1234 * The Play Action 1235 */ 1236 class PlayAction extends SearsAction { 1237 private static final long serialVersionUID = -8943325412755437272L; 1238 1239 public PlayAction() { 1240 super("Play"); 1241 } 1242 1243 /* (non-Javadoc) 1244 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1245 */ 1246 public void actionPerformed(ActionEvent e) { 1247 playAction(); 1248 } 1249 } 1250 1251 /** 1252 * Class StopAction. 1253 * <br><b>Summary:</b><br> 1254 * The Stop Action 1255 */ 1256 class StopAction extends SearsAction { 1257 private static final long serialVersionUID = -5754273483777981782L; 1258 1259 public StopAction() { 1260 super("Stop"); 1261 } 1262 1263 /* (non-Javadoc) 1264 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1265 */ 1266 public void actionPerformed(ActionEvent e) { 1267 stopAction(); 1268 } 1269 } 1270 1271 /** 1272 * Class PauseAction. 1273 * <br><b>Summary:</b><br> 1274 * The Pause Action 1275 */ 1276 class PauseAction extends SearsAction { 1277 private static final long serialVersionUID = -4954880612379971754L; 1278 1279 public PauseAction() { 1280 super("Pause"); 1281 } 1282 1283 /* (non-Javadoc) 1284 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1285 */ 1286 public void actionPerformed(ActionEvent e) { 1287 pauseAction(); 1288 } 1289 } 1290 1291 /** 1292 * Class PreviousAction. 1293 * <br><b>Summary:</b><br> 1294 * The Previous Action 1295 */ 1296 class PreviousAction extends SearsAction { 1297 private static final long serialVersionUID = 7512470475148460128L; 1298 1299 public PreviousAction() { 1300 super("Previous"); 1301 } 1302 1303 /* (non-Javadoc) 1304 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1305 */ 1306 public void actionPerformed(ActionEvent e) { 1307 previousAction(); 1308 } 1309 } 1310 1311 /** 1312 * Class NextAction. 1313 * <br><b>Summary:</b><br> 1314 * The Next Action 1315 */ 1316 class NextAction extends SearsAction { 1317 private static final long serialVersionUID = -4498355509337819003L; 1318 1319 public NextAction() { 1320 super("Next"); 1321 } 1322 1323 /* (non-Javadoc) 1324 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1325 */ 1326 public void actionPerformed(ActionEvent e) { 1327 nextAction(); 1328 } 1329 } 1330 1331 /** 1332 * Class TrackerTriggerAction. 1333 * <br><b>Summary:</b><br> 1334 * The TrackerTrigger Action 1335 */ 1336 class TrackerTriggerAction extends SearsAction { 1337 private static final long serialVersionUID = 5091927415403379314L; 1338 1339 public TrackerTriggerAction() { 1340 super("TrackerTrigger"); 1341 } 1342 1343 /* (non-Javadoc) 1344 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1345 */ 1346 public void actionPerformed(ActionEvent e) { 1347 trackerTriggerAction(); 1348 } 1349 } 1350 1351 /** 1352 * Method orderRepairAction. 1353 * <br><b>Summary:</b><br> 1354 * This method is called when user wants to repair the order of the subtitle file. 1355 * It will check chronology, order ST's with their start time, and finally fix ST's numbers. 1356 */ 1357 public void orderRepairAction() { 1358 //Must have opened a subtitle file to repair. 1359 if (subtitleFile != null) { 1360 //Apply order repair 1361 subtitleFile.orderRepair(); 1362 //indicate table that data have changed 1363 tableModel.fireTableDataChanged(); 1364 updateWindowsName(); 1365 updateActionStatus(); 1366 } else { 1367 //Must have opened a subtitle file to apply a delay. 1368 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeRepair"), Trace.WARNING_PRIORITY); 1369 } 1370 } 1371 1372 /** 1373 * Method pauseAction. 1374 * <br><b>Summary:</b><br> 1375 * This method when user wants to pause the video 1376 */ 1377 public void pauseAction() { 1378 try { 1379 if(player != null) { 1380 //Pause the video player 1381 player.pause(); 1382 } 1383 } catch (PlayerException e) { 1384 //display an error message. 1385 Trace.trace(e.getMessage(), Trace.ERROR_PRIORITY); 1386 } 1387 } 1388 1389 /** 1390 * Method trackerTriggerAction. 1391 * <br><b>Summary:</b><br> 1392 * This method is called when user wants to change the tracker mode. 1393 */ 1394 public void trackerTriggerAction() { 1395 // TODO change the tracker mode. 1396 Trace.trace("TriggerAction"); 1397 } 1398 1399 /** 1400 * Method nextAction. 1401 * <br><b>Summary:</b><br> 1402 * This method is called when user wants to move forward in the video. 1403 */ 1404 public void nextAction() { 1405 try { 1406 if(player != null) { 1407 int currentOffset = player.getPosition(); 1408 if(currentOffset != -1) { 1409 //Go forward using the time step. 1410 int timeStep = jPanelVideoControler.getTimeStep(); 1411 player.setPosition(currentOffset + timeStep); 1412 } 1413 } 1414 } catch (PlayerException e) { 1415 //display an error message. 1416 Trace.trace(e.getMessage(), Trace.ERROR_PRIORITY); 1417 } 1418 } 1419 1420 /** 1421 * Method previousAction. 1422 * <br><b>Summary:</b><br> 1423 * This method is called when user wants to go backward in the video. 1424 */ 1425 public void previousAction() { 1426 try { 1427 if(player != null) { 1428 int currentOffset = player.getPosition(); 1429 if(currentOffset != -1) { 1430 //Go forward using the time step. 1431 int timeStep = jPanelVideoControler.getTimeStep(); 1432 player.setPosition(currentOffset - timeStep); 1433 } 1434 } 1435 } catch (PlayerException e) { 1436 //display an error message. 1437 Trace.trace(e.getMessage(), Trace.ERROR_PRIORITY); 1438 } 1439 } 1440 1441 /** 1442 * Method stopAction. 1443 * <br><b>Summary:</b><br> 1444 * This method is called when user wants to stop the video. 1445 */ 1446 public void stopAction() { 1447 if(player != null) { 1448 try { 1449 player.stop(); 1450 } catch (PlayerException e) { 1451 //display an error message. 1452 Trace.trace(e.getMessage(), Trace.ERROR_PRIORITY); 1453 } 1454 } 1455 } 1456 1457 /** 1458 * Method playAction. 1459 * <br><b>Summary:</b><br> 1460 * This method is called when user wants to play the video. 1461 */ 1462 public void playAction() { 1463 String playerFile = SearsProperties.getProperty(SearsProperties.PLAYER_FULL_PATH); 1464 if (playerFile != "") { 1465 // Save the subtitle in tempory file 1466 SubtitleFile subFile = subtitleFile; 1467 if (subFile == null) { 1468 // Create a fake subtitle file if no file exists 1469 subFile = new SrtFile(); 1470 subFile.addFakeSub(); 1471 } 1472 subFile.writeToTemporaryFile(); 1473 String subtitleFileName = subFile.getTemporaryFile().getAbsolutePath(); 1474 1475 // Launch VLC player 1476 try { 1477 if (player == null) { 1478 player = constructPlayer(); 1479 } 1480 // Select the video file 1481 if (playerVideoFile == null) { 1482 selectVideoAction(); 1483 } else { 1484 //Verify that user has chosen a file. 1485 if(playerVideoFile != null) { 1486 //Launch the video player 1487 player.play(playerVideoFile, subtitleFileName); 1488 } 1489 } 1490 } catch (PlayerException e) { 1491 //display an error message. 1492 Trace.trace(e.getMessage(), Trace.ERROR_PRIORITY); 1493 } 1494 } else { 1495 JOptionPane.showOptionDialog(instance, 1496 SearsResourceBundle.getResource("error_playerNotDefined"), 1497 SearsResourceBundle.getResource("error_message"), 1498 JOptionPane.CLOSED_OPTION, 1499 JOptionPane.ERROR_MESSAGE, null, null, null); 1500 } 1501 } 1502 1503 /** 1504 * Class AccentRepairAction. 1505 * <br><b>Summary:</b><br> 1506 * The AccentRepair Action 1507 */ 1508 class AccentRepairAction extends SearsAction { 1509 private static final long serialVersionUID = 1881880058709461107L; 1510 1511 public AccentRepairAction() { 1512 super("AccentRepair"); 1513 } 1514 1515 /* (non-Javadoc) 1516 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1517 */ 1518 public void actionPerformed(ActionEvent e) { 1519 accentRepairAction(); 1520 } 1521 } 1522 1523 /** 1524 * Method accentRepairAction. 1525 * <br><b>Summary:</b><br> 1526 * This method is called when user wants to remove 1527 * the accents and special characters from the selected subtitle file. 1528 * 1529 */ 1530 public void accentRepairAction() { 1531 //Must have opened a subtitle file to repair accents. 1532 if (subtitleFile != null) { 1533 //get the selected rows. 1534 int[] selectedIndex = table.getSelectedRows(); 1535 //Remove accent from them. 1536 subtitleFile.accentRepair(selectedIndex); 1537 //indicate table that data have changed 1538 tableModel.fireTableDataChanged(); 1539 updateWindowsName(); 1540 updateActionStatus(); 1541 } else { 1542 //Must have opened a subtitle file to apply a delay. 1543 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeAccentRepair"), Trace.WARNING_PRIORITY); 1544 } 1545 } 1546 1547 /** 1548 * Class HtmlRepairAction. 1549 * <br><b>Summary:</b><br> 1550 * The HtmlRepair Action 1551 */ 1552 class HtmlRepairAction extends SearsAction { 1553 private static final long serialVersionUID = 2595376205493266568L; 1554 1555 public HtmlRepairAction() { 1556 super("HtmlRepair"); 1557 } 1558 1559 /* (non-Javadoc) 1560 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1561 */ 1562 public void actionPerformed(ActionEvent e) { 1563 htmlRepairAction(); 1564 } 1565 } 1566 1567 /** 1568 * Method htmlRepairAction. 1569 * <br><b>Summary:</b><br> 1570 * This method is called when user wants to remove 1571 * the htmls. 1572 */ 1573 public void htmlRepairAction() { 1574 //Must have opened a subtitle file to repair. 1575 if (subtitleFile != null) { 1576 //get the selected rows. 1577 int[] selectedIndex = table.getSelectedRows(); 1578 //Remove html tags from them. 1579 subtitleFile.htmlRepair(selectedIndex); 1580 //indicate table that data have changed 1581 tableModel.fireTableDataChanged(); 1582 updateWindowsName(); 1583 updateActionStatus(); 1584 } else { 1585 //Must have opened a subtitle file to apply a delay. 1586 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeHTMLRepair"), Trace.WARNING_PRIORITY); 1587 } 1588 } 1589 1590 /** 1591 * Class SelectVideoAction. 1592 * <br><b>Summary:</b><br> 1593 * The SelectVideo Action 1594 */ 1595 class SelectVideoAction extends SearsAction { 1596 private static final long serialVersionUID = 3081640943800843335L; 1597 1598 public SelectVideoAction() { 1599 super("SelectVideo"); 1600 } 1601 1602 /* (non-Javadoc) 1603 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1604 */ 1605 public void actionPerformed(ActionEvent e) { 1606 selectVideoAction(); 1607 } 1608 } 1609 1610 /** 1611 * Method selectVideoAction. 1612 * <br><b>Summary:</b><br> 1613 * This method is called when user wants to select the video file. 1614 */ 1615 public void selectVideoAction() { 1616 File file = showVideoBrowser(); 1617 if (file != null) { 1618 playerVideoFile = file.getAbsolutePath(); 1619 SearsProperties.setProperty(SearsProperties.LAST_FOLDER, file.getParent()); 1620 stopAction(); 1621 playAction(); 1622 } 1623 } 1624 1625 /** 1626 * Method constructPlayer. 1627 * <br><b>Summary:</b><br> 1628 * This method construct a new player, in function of the one selected in the properties. 1629 * @return 1630 */ 1631 private PlayerInterface constructPlayer() throws PlayerException { 1632 //The result of the method. 1633 PlayerInterface result = null; 1634 //First is to get the selected player. 1635 try { 1636 int selectedPlayer = Integer.parseInt(SearsProperties.getProperty(SearsProperties.PLAYER_SELECTED)); 1637 //Construct the player that correspond to the new selected one. 1638 switch (selectedPlayer) { 1639 case SearsProperties.KEY_VLC: 1640 result = new VLCPlayer(); 1641 break; 1642 case SearsProperties.KEY_OTHER: 1643 result = new DefaultPlayer(); 1644 break; 1645 } 1646 } catch (NumberFormatException e) { 1647 //There is an error in the player selected. 1648 throw new PlayerException("Selected player type is invalid:" 1649 + SearsProperties.getProperty(SearsProperties.PLAYER_SELECTED)); 1650 } 1651 //return the result. 1652 return result; 1653 } 1654 1655 /** 1656 * Class ChainRepairAction. <br> 1657 * <b>Summary:</b><br> 1658 * The ChainRepair Action 1659 */ 1660 class ChainRepairAction extends SearsAction { 1661 private static final long serialVersionUID = 1973498050830247049L; 1662 1663 public ChainRepairAction() { 1664 super("ChainRepair"); 1665 } 1666 1667 /* (non-Javadoc) 1668 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1669 */ 1670 public void actionPerformed(ActionEvent e) { 1671 chainRepairAction(); 1672 } 1673 } 1674 1675 /** 1676 * Method chainRepairAction. 1677 * <br><b>Summary:</b><br> 1678 * This method is called when user wants to chain repair. 1679 * It will apply several repair action. 1680 */ 1681 public void chainRepairAction() { 1682 //Must have opened a subtitle file to repair. 1683 if (subtitleFile != null) { 1684 //Show the chain repair dialog 1685 JDialogChainRepair cr = new JDialogChainRepair(); 1686 cr.setVisible(true); 1687 //Get the result. 1688 boolean[] result = cr.getResult(); 1689 //Apply repair action in function of the result. 1690 //The accent repair 1691 if (result[0]) { 1692 subtitleFile.accentRepair(null); 1693 } 1694 //The HTML repair 1695 if (result[1]) { 1696 subtitleFile.htmlRepair(null); 1697 } 1698 //The orderRepair 1699 if (result[2]) { 1700 subtitleFile.orderRepair(); 1701 } 1702 //The Time Repair 1703 if (result[3]) { 1704 subtitleFile.timeRepair(); 1705 } 1706 //indicate table that data have changed 1707 tableModel.fireTableDataChanged(); 1708 updateWindowsName(); 1709 updateActionStatus(); 1710 } else { 1711 //Must have opened a subtitle file to apply a chain repair. 1712 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeChainRepair"), Trace.WARNING_PRIORITY); 1713 } 1714 } 1715 1716 /** 1717 * Class TimeRepairAction. 1718 * <br><b>Summary:</b><br> 1719 * The TimeRepair Action 1720 */ 1721 class TimeRepairAction extends SearsAction { 1722 private static final long serialVersionUID = 1635491769577703287L; 1723 1724 public TimeRepairAction() { 1725 super("TimeRepair"); 1726 } 1727 1728 /* (non-Javadoc) 1729 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1730 */ 1731 public void actionPerformed(ActionEvent e) { 1732 timeRepairAction(); 1733 } 1734 } 1735 1736 /** 1737 * Class NormalizeDurationAction. 1738 * <br><b>Summary:</b><br> 1739 * The NormalizeDuration Action 1740 */ 1741 class NormalizeDurationAction extends SearsAction { 1742 1743 /** (<b>long</b>) serialVersionUID: The serialVersionUID */ 1744 private static final long serialVersionUID = -7636895212998797145L; 1745 1746 public NormalizeDurationAction() { 1747 super("NormalizeDuration"); 1748 } 1749 1750 /* (non-Javadoc) 1751 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1752 */ 1753 public void actionPerformed(ActionEvent e) { 1754 NormalizeDurationAction(); 1755 } 1756 } 1757 1758 1759 /** 1760 * Method NormalizeDurationAction. 1761 * <br><b>Summary:</b><br> 1762 * This permit to normalize the ST duration. 1763 */ 1764 private void NormalizeDurationAction() { 1765 //Must have opened a subtitle file to apply a delay. 1766 if (subtitleFile != null) { 1767 //get the selected rows to delay. 1768 int[] indexToNormalize = table.getSelectedRows(); 1769 //ask the user for delay to apply 1770 JDialogNormalizeAction jd = new JDialogNormalizeAction(); 1771 jd.setVisible(true); 1772 //if user choose a delay. 1773 if (jd.hasBeenValidated()) { 1774 double[] times = jd.getTimes(); 1775 //delay the subtitle with the given delay. 1776 //multiply by 1000, because time is indicated in second, with possible milliseconds. 1777 subtitleFile.normalizeDuration(indexToNormalize, (int) (times[0] * 1000), (int) (times[1] * 1000)); 1778 //indicate table that data have changed 1779 tableModel.fireTableDataChanged(); 1780 } 1781 updateWindowsName(); 1782 updateActionStatus(); 1783 } else { 1784 //Must have opened a subtitle file to apply a delay. 1785 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeNormalize"), Trace.WARNING_PRIORITY); 1786 } 1787 } 1788 1789 /** 1790 * Class OptionsAction. 1791 * <br><b>Summary:</b><br> 1792 * The Options Action 1793 */ 1794 class OptionsAction extends SearsAction { 1795 1796 1797 /** (<b>long</b>) serialVersionUID: The serialVersionUID */ 1798 private static final long serialVersionUID = -4333319058198937067L; 1799 1800 public OptionsAction() { 1801 super("Options"); 1802 } 1803 1804 /* (non-Javadoc) 1805 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1806 */ 1807 public void actionPerformed(ActionEvent e) { 1808 optionsAction(); 1809 } 1810 } 1811 1812 /** 1813 * Method optionsAction. 1814 * <br><b>Summary:</b><br> 1815 * This method is called when user wants to change sears options. 1816 * It will display the options dialog, and set the sears properties. 1817 */ 1818 private void optionsAction() { 1819 //Show ans options dialog. 1820 JDialogOptions jDialogOptions = new JDialogOptions(); 1821 jDialogOptions.setVisible(true); 1822 //If options has been validated, set the new options. 1823 if (jDialogOptions.hasBeenValidated()) { 1824 //A boolean to know if a message has to be displayed. 1825 boolean displayRebootMessage = false; 1826 //set the selected locale, if changed. 1827 Locale selectedLocale = jDialogOptions.getSelectedLocale(); 1828 if (!SearsProperties.getProperty(SearsProperties.LANGUAGE, "").equals( 1829 selectedLocale.getLanguage().toString()) 1830 || !SearsProperties.getProperty(SearsProperties.COUNTRY, "").equals( 1831 selectedLocale.getCountry().toString())) { 1832 setSelectedLocale(selectedLocale); 1833 //To see changes, you have to reboot. 1834 displayRebootMessage = true; 1835 } 1836 //set the look and feel if changed. 1837 String selectedLookAndFeel = jDialogOptions.getSelectedLookAndFeel(); 1838 if (!selectedLookAndFeel.equals(SearsProperties.getProperty(SearsProperties.LOOK_AND_FEEL, ""))) { 1839 setLookAndFeel(selectedLookAndFeel); 1840 //To see changes, you have to reboot. 1841 displayRebootMessage = true; 1842 } 1843 //set the player if changed. 1844 String selectedPlayerPath = jDialogOptions.getConfiguredPlayerPath(); 1845 int selectedPlayer = jDialogOptions.getSelectedPlayer(); 1846 if (!selectedPlayerPath.equals(SearsProperties.getProperty(SearsProperties.PLAYER_FULL_PATH, "")) 1847 || !("" + selectedPlayer).equals(SearsProperties.getProperty(SearsProperties.PLAYER_SELECTED, ""))) { 1848 setPlayer(selectedPlayerPath, selectedPlayer); 1849 } 1850 //Set the DOS line separator options, if changed. 1851 String selectedDOSLineSeparator = jDialogOptions.getSelectedDOSLineSeparator(); 1852 if (!selectedDOSLineSeparator.equals(SearsProperties.getProperty(SearsProperties.DOS_LINE_SEPARATOR, ""))) { 1853 SearsProperties.setProperty(SearsProperties.DOS_LINE_SEPARATOR, selectedDOSLineSeparator); 1854 } 1855 //Set the check for update option, if changed. 1856 boolean selectedCheckForUpdates = jDialogOptions.getSelectedCheckForUpdates(); 1857 if (selectedCheckForUpdates 1858 && SearsProperties.getProperty(SearsProperties.UPDATE_ADDRESS, "firstLaunch").equals("")) { 1859 //If user checks, and no address has been set in properties. 1860 //then set the default one. 1861 SearsProperties.setProperty(SearsProperties.UPDATE_ADDRESS, Updater.DEFAULT_UPDATE_ADDRESS); 1862 } else if (!selectedCheckForUpdates) { 1863 //Else if user does not want to check for updates, set to "". 1864 SearsProperties.setProperty(SearsProperties.UPDATE_ADDRESS, ""); 1865 } 1866 //Set the VLC restart options, if changed. 1867 String selectedVlcRestart = jDialogOptions.getSelectedVlcRestart(); 1868 if (!selectedVlcRestart.equals(SearsProperties.getProperty(SearsProperties.VLC_RESTART, 1869 VLCPlayer.DEFAULT_VLC_RESTART))) { 1870 SearsProperties.setProperty(SearsProperties.VLC_RESTART, selectedVlcRestart); 1871 } 1872 //Set the icon set option, if changed. 1873 String selectedIconSet = jDialogOptions.getSelectedIconSet(); 1874 if (selectedIconSet != null && !selectedIconSet.equals(SearsProperties.getProperty(SearsProperties.ICON_SET))) { 1875 SearsProperties.setProperty(SearsProperties.ICON_SET, selectedIconSet); 1876 displayRebootMessage = true; 1877 } 1878 //Now display warning message about reboot. 1879 if (displayRebootMessage) { 1880 JOptionPane.showConfirmDialog(instance, SearsResourceBundle.getResource("warning_rebootToSeeChanges"), 1881 SearsResourceBundle.getResource("warning_rebootToSeeChangesTitle"), JOptionPane.DEFAULT_OPTION, 1882 JOptionPane.WARNING_MESSAGE); 1883 } 1884 } 1885 } 1886 1887 /** 1888 * Class AboutAction. 1889 * <br><b>Summary:</b><br> 1890 * The About Action 1891 */ 1892 class AboutAction extends SearsAction { 1893 /** (<b>long</b>) serialVersionUID: The serialVersionUID */ 1894 private static final long serialVersionUID = 2988713944030176952L; 1895 1896 public AboutAction() { 1897 super("About"); 1898 } 1899 1900 /* (non-Javadoc) 1901 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1902 */ 1903 public void actionPerformed(ActionEvent e) { 1904 aboutAction(); 1905 } 1906 } 1907 1908 /** 1909 * Method dialogAction. 1910 * <br><b>Summary:</b><br> 1911 * This method is called when user wants to see the about dialog window. 1912 * It will display the about dialog.. 1913 */ 1914 private void aboutAction() { 1915 // we create a new JDialogAbout and set it visible: 1916 JDialogAbout jDialogAbout = new JDialogAbout("about"); 1917 jDialogAbout.configureSize(); 1918 jDialogAbout.setVisible(true); 1919 } 1920 1921 /** 1922 * Class GotoSubAction. 1923 * <br><b>Summary:</b><br> 1924 * The GotoSub Action 1925 */ 1926 class GotoSubAction extends SearsAction { 1927 private static final long serialVersionUID = 4897317673745710990L; 1928 1929 public GotoSubAction() { 1930 super("GotoSub"); 1931 } 1932 1933 /* (non-Javadoc) 1934 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1935 */ 1936 public void actionPerformed(ActionEvent e) { 1937 gotoSubAction(); 1938 } 1939 } 1940 1941 /** 1942 * Class MagicResynchroAction. 1943 * <br><b>Summary:</b><br> 1944 * The MagicResynchro 1945 */ 1946 class MagicResynchroAction extends SearsAction { 1947 1948 /** (<b>long</b>) serialVersionUID: The serialVersionUID */ 1949 private static final long serialVersionUID = 7188578370344829732L; 1950 1951 public MagicResynchroAction() { 1952 super("MagicResynchro"); 1953 } 1954 1955 /* (non-Javadoc) 1956 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1957 */ 1958 public void actionPerformed(ActionEvent e) { 1959 magicResynchroAction(); 1960 } 1961 } 1962 1963 /** 1964 * Class RemoveAllAnchorsAction. 1965 * <br><b>Summary:</b><br> 1966 * The RemoveAllAnchorsAction 1967 */ 1968 class RemoveAllAnchorsAction extends SearsAction { 1969 1970 /** (<b>long</b>) serialVersionUID: The serialVersionUID */ 1971 private static final long serialVersionUID = 2484034561626602996L; 1972 1973 public RemoveAllAnchorsAction() { 1974 super("RemoveAllAnchors"); 1975 } 1976 1977 /* (non-Javadoc) 1978 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) 1979 */ 1980 public void actionPerformed(ActionEvent e) { 1981 removeAllAnchorsAction(); 1982 } 1983 } 1984 1985 /** 1986 * Method removeAllAnchorsAction. 1987 * <br><b>Summary:</b><br> 1988 * Call this method to remove all the anchors from subtitles. 1989 */ 1990 private void removeAllAnchorsAction() { 1991 if(subtitleList != null){ 1992 //Parse all the subtitles, and remove anchor from them. 1993 for(Subtitle subtitle : subtitleList){ 1994 subtitle.unanchor(); 1995 } 1996 updateActionStatus(); 1997 //update table. 1998 tableModel.fireTableDataChanged(); 1999 } 2000 } 2001 2002 2003 2004 /** 2005 * Method gotoSubAction. 2006 * <br><b>Summary:</b><br> 2007 * This method permits to set the video position to the selected subtitle. 2008 */ 2009 public void gotoSubAction() { 2010 //First is to get the selected subtitle. 2011 int selectedRow = table.getSelectedRow(); 2012 //If selected and player is not null, go to this subtitle. 2013 if(player != null && selectedRow != -1){ 2014 Subtitle selectedSubtitle = (Subtitle) subtitleList.get(selectedRow); 2015 if(selectedSubtitle != null){ 2016 try { 2017 //Divide by 1000, because start date is in milliseconds. 2018 player.setPosition(selectedSubtitle.getStartDate()/1000); 2019 } catch (PlayerException e) { 2020 Trace.trace(e.getMessage(), Trace.ERROR_PRIORITY); 2021 } 2022 } 2023 } 2024 } 2025 2026 2027 2028 2029 /** 2030 * Method setPlayer. 2031 * <br><b>Summary:</b><br> 2032 * Set the player. 2033 * @param selectedPlayerPath The player full path to set. 2034 * @param selectedPlayer The player to set. 2035 */ 2036 private void setPlayer(String selectedPlayerPath, int selectedPlayer) { 2037 SearsProperties.setProperty(SearsProperties.PLAYER_FULL_PATH, selectedPlayerPath); 2038 SearsProperties.setProperty(SearsProperties.PLAYER_SELECTED, "" + selectedPlayer); 2039 if (player != null) { 2040 //quit previous player if exist. 2041 player.quit(); 2042 //disable the player 2043 player = null; 2044 } 2045 //construct the new player 2046 try { 2047 player = constructPlayer(); 2048 } catch (PlayerException e) { 2049 e.printStackTrace(); 2050 } 2051 } 2052 2053 2054 /** 2055 * Method setSelectedLocale. 2056 * <br><b>Summary:</b><br> 2057 * Use this to set the locale. 2058 * @param selectedLocale The locale to set. 2059 */ 2060 private void setSelectedLocale(Locale selectedLocale) { 2061 SearsResourceBundle.setLocale(selectedLocale); 2062 SearsProperties.setProperty(SearsProperties.LANGUAGE, selectedLocale.getLanguage()); 2063 SearsProperties.setProperty(SearsProperties.COUNTRY, selectedLocale.getCountry()); 2064 setLocale(selectedLocale); 2065 } 2066 2067 /** 2068 * Method setLookAndFeel. 2069 * <br><b>Summary:</b><br> 2070 * Use this method to sets the look and feel. 2071 * @param selectedLookAndFeel The look and feel to set. 2072 */ 2073 private void setLookAndFeel(String selectedLookAndFeel) { 2074 SearsProperties.setProperty(SearsProperties.LOOK_AND_FEEL, selectedLookAndFeel); 2075 } 2076 2077 /** 2078 * Method timeRepairAction. 2079 * <br><b>Summary:</b><br> 2080 * This method is called when user wants to time repair. 2081 * It will correct the time superposition problem. 2082 * When subtitle ends after next ST start time. 2083 */ 2084 public void timeRepairAction() { 2085 //Must have opened a subtitle file to repair. 2086 if (subtitleFile != null) { 2087 //Apply Time repair 2088 subtitleFile.timeRepair(); 2089 //indicate table that data have changed 2090 tableModel.fireTableDataChanged(); 2091 updateWindowsName(); 2092 updateActionStatus(); 2093 } else { 2094 //Must have opened a subtitle file to apply a delay. 2095 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeTimeRepair"), Trace.WARNING_PRIORITY); 2096 } 2097 } 2098 2099 /** 2100 * Method splitAction. 2101 * <br><b>Summary:</b><br> 2102 * This method is called when user wants to split STs file in two files. 2103 * Must have selected the ST to split from. 2104 */ 2105 public void splitAction() { 2106 //Must have opened a subtitle. 2107 if (subtitleFile != null) { 2108 int selectedIndex = table.getSelectedRow(); 2109 if (selectedIndex == -1) { 2110 selectedIndex = 0; 2111 } 2112 //show Split dialog. 2113 JDialogSplit splitDialog = new JDialogSplit(subtitleList, selectedIndex, subtitleFile); 2114 splitDialog.setLocationRelativeTo(this); 2115 splitDialog.setVisible(true); 2116 if (splitDialog.hasBeenValidated()) { 2117 //Get the destination files. 2118 File[] destinationFiles = splitDialog.getDestinationsFiles(); 2119 //The the second part delay 2120 double secondPartDelay = splitDialog.getSecondPartDelay(); 2121 //Look for open second part option. 2122 boolean openSecondPart = splitDialog.needToOpenSecondPart(); 2123 //Get the choosen subtitle for split. 2124 int subtitleIndex = splitDialog.getChoosenSubtitle(); 2125 //Apply spliting to subtitleFile. 2126 //multiply by 1000, because delay is indicated in second, with possible milliseconds. 2127 SubtitleFile[] parts = subtitleFile.split(destinationFiles, subtitleIndex, 2128 (int) (secondPartDelay * 1000)); 2129 //At the end save the two files. 2130 Trace.trace("Saving splitted files", Trace.ALGO_PRIORITY); 2131 parts[0].writeToFile(parts[0].getFile()); 2132 parts[1].writeToFile(parts[1].getFile()); 2133 //If need to open second part, open it ! 2134 if (openSecondPart) { 2135 openFile(parts[1].getFile()); 2136 } 2137 } 2138 updateWindowsName(); 2139 updateActionStatus(); 2140 } else { 2141 //Must have opened a subtitle file to apply a split. 2142 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeSplit"), Trace.WARNING_PRIORITY); 2143 } 2144 } 2145 2146 /** 2147 * Method appendAction. 2148 * <br><b>Summary:</b><br> 2149 * This method is called when user wants to make an append Action. 2150 */ 2151 public void appendAction() { 2152 //Must have opened a subtitle. 2153 if (subtitleFile != null) { 2154 //show Append dialog. 2155 JDialogAppend appendDialog = new JDialogAppend(); 2156 appendDialog.setVisible(true); 2157 if (appendDialog.hasBeenValidated()) { 2158 File fileToAppend = appendDialog.getFileToAppend(); 2159 double delay = appendDialog.getDelay(); 2160 if (fileToAppend != null) { 2161 SrtFile srtFileToAppend = new SrtFile(fileToAppend, new ArrayList<Subtitle>()); 2162 //Append file to current one. 2163 //multiply by 1000, because delay is indicated in second, with possible milliseconds. 2164 subtitleFile.append(srtFileToAppend, (int) (delay * 1000)); 2165 } 2166 //indicate table that data have changed 2167 tableModel.fireTableDataChanged(); 2168 } 2169 updateWindowsName(); 2170 updateActionStatus(); 2171 } else { 2172 //Must have opened a subtitle file to apply an append. 2173 Trace.trace(SearsResourceBundle.getResource("warning_mustOpenBeforeAppend"), Trace.WARNING_PRIORITY); 2174 } 2175 } 2176 2177 /** 2178 * Method <b>watchForUnsavedFile</b> 2179 * <br><b>Summary:</b><br> 2180 * This method check that current file (if open) does not have unsaved modifications. 2181 * If it has, ask for user to "save", "don't save" or "cancel". 2182 * If user click on save, current file will be saved, method returns true. 2183 * If user click on save, current file is not saved, method returns true. 2184 * if user click on cancel, file is not saved, method returns false. 2185 * Parameters: 2186 * @return <b>boolean</b> True if user wants to continue (click on "save" or "don't save") 2187 * , or if file has no modifications. false if user clicked on "cancel" 2188 * 2189 */ 2190 private boolean checkUnsavedFileBeforeAction() { 2191 //The result of the method 2192 boolean result = true; 2193 //If there already is an unsaved open file, warn the user before opening. 2194 if (subtitleFile != null && subtitleFile.isFileChanged()) { 2195 result = false; 2196 //File is not saved, ask for saving. 2197 String message = SearsResourceBundle.getResource("warning_fileNotSaved"); 2198 //Custom button text 2199 Object[] options = { SearsResourceBundle.getResource("button_save"), 2200 SearsResourceBundle.getResource("button_dontSave"), 2201 SearsResourceBundle.getResource("button_cancel") }; 2202 int userChoice = JOptionPane.showOptionDialog(instance, message, SearsResourceBundle 2203 .getResource("warning_fileNotSaved"), JOptionPane.YES_NO_CANCEL_OPTION, 2204 JOptionPane.QUESTION_MESSAGE, null, options, options[2]); 2205 //If user choose to save file, save it, and return true. 2206 if (userChoice == 0) { 2207 saveAction(); 2208 result = true; 2209 } else if (userChoice == 1) { 2210 //if user choosed don't save, just return true 2211 result = true; 2212 }//else return false. 2213 } 2214 //return the result 2215 return result; 2216 } 2217 2218 /** 2219 * Method updateWindowsName. 2220 * <br><b>Summary:</b><br> 2221 * Update the main windows name. 2222 */ 2223 private void updateWindowsName() { 2224 String title = SearsResources.getString("SearsGUITitle")+Version.VERSION; 2225 if (subtitleFile != null) { 2226 title += " - " + subtitleFile.getFile().getName(); 2227 if (subtitleFile.isFileChanged()) { 2228 title += "*"; 2229 } 2230 } 2231 setTitle(title); 2232 } 2233 2234 /* (non-Javadoc) 2235 * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) 2236 */ 2237 public void mouseClicked(MouseEvent e) { 2238 maybeShowPopup(e); 2239 mayBeAnchor(e); 2240 } 2241 2242 /** 2243 * Method mayBeAnchor. 2244 * <br><b>Summary:</b><br> 2245 * This method is called whn a click is detected. 2246 * It permits to check an anchor event. 2247 * @param e The mouseEvent that called for this mayBeAnchor. 2248 */ 2249 private void mayBeAnchor(MouseEvent e) { 2250 if (e.getButton() == MouseEvent.BUTTON1 && e.getComponent() == table) { 2251 //click must be on 4rth column. 2252 Point clickPoint = new Point(e.getX(), e.getY()); 2253 if(table.columnAtPoint(clickPoint) == SubtitleTableModel.ANCHOR_COLUMN){ 2254 //retrieve the clicked row. 2255 int row = table.rowAtPoint(clickPoint); 2256 anchorSubtitle(row); 2257 } 2258 } 2259 2260 } 2261 2262 /** 2263 * Method anchorSubtitle. 2264 * <br><b>Summary:</b><br> 2265 * This method permits to anchor/un-anchor the given index subtitle. 2266 * @param subtitleIndex The subtitle index to anchor. 2267 */ 2268 private void anchorSubtitle(int row) { 2269 //Retrieve current playing time. 2270 if (player != null) { 2271 try { 2272 // Retrieve the given subtitle. 2273 Subtitle subtitle = subtitleList.get(row); 2274 if (subtitle.isAnchored()) { 2275 subtitle.unanchor(); 2276 } else { 2277 int currentPosition = player.getPosition(); 2278 subtitle.anchor(currentPosition); 2279 } 2280 //Indicate to table, that data changed. 2281 tableModel.fireTableDataChanged(); 2282 //Update actions 2283 updateActionStatus(); 2284 } catch (PlayerException e) { 2285 e.printStackTrace(); 2286 } 2287 } 2288 } 2289 2290 /* (non-Javadoc) 2291 * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent) 2292 */ 2293 public void mouseEntered(MouseEvent e) { 2294 } 2295 2296 /* (non-Javadoc) 2297 * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent) 2298 */ 2299 public void mouseExited(MouseEvent e) { 2300 } 2301 2302 /* (non-Javadoc) 2303 * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) 2304 */ 2305 public void mousePressed(MouseEvent e) { 2306 maybeShowPopup(e); 2307 } 2308 2309 /** 2310 * Method maybeShowPopup. 2311 * <br><b>Summary:</b><br> 2312 * Show the popup menu if necessary 2313 * @param e The mouse event. 2314 */ 2315 private void maybeShowPopup(MouseEvent e) { 2316 //Check wether it is a right button, or a system pop-up trigger. 2317 if (e.getButton() == MouseEvent.BUTTON3 || e.isPopupTrigger()) { 2318 getJPopUpMenu().show(e.getComponent(), e.getX(), e.getY()); 2319 } 2320 } 2321 2322 /** 2323 * Method getJPopUpMenu. 2324 * <br><b>Summary:</b><br> 2325 * Construct/return the JPopUpMenu. 2326 * @return <b>JPopupMenu</b> The Sears JPopupMenu. 2327 */ 2328 private JPopupMenu getJPopUpMenu() { 2329 if (jPopupMenu == null) { 2330 jPopupMenu = new JPopupMenu("Sears"); 2331 ////////////////// 2332 //ACTION MENU 2333 ///////////////// 2334 //Add a separator. 2335 jPopupMenu.addSeparator(); 2336 //DELAY ITEM 2337 jPopupMenu.add(getAction(ACTION_KEY_DELAY)); 2338 //RESYNCHRO ITEM 2339 jPopupMenu.add(getAction(ACTION_KEY_RESYNCH)); 2340 //Add a separator. 2341 jPopupMenu.addSeparator(); 2342 //SPLIT ITEM 2343 jPopupMenu.add(getAction(ACTION_KEY_SPLIT)); 2344 //APPEND ITEM 2345 jPopupMenu.add(getAction(ACTION_KEY_APPEND)); 2346 //Add a separator. 2347 jPopupMenu.addSeparator(); 2348 //GOTO SUB 2349 jPopupMenu.add(getAction(ACTION_KEY_GOTO_SUB)); 2350 } 2351 return jPopupMenu; 2352 } 2353 2354 /** 2355 * Method <b>fileChanged</b> 2356 * <br><b>Summary:</b><br> 2357 * Set the fileChanged status flag to true. 2358 */ 2359 public void fileChanged() { 2360 if (subtitleFile != null) { 2361 subtitleFile.fileChanged(); 2362 } 2363 updateWindowsName(); 2364 } 2365 2366 /* (non-Javadoc) 2367 * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) 2368 */ 2369 public void mouseReleased(MouseEvent e) { 2370 // TODO Auto-generated method stub 2371 } 2372 2373 /* (non-Javadoc) 2374 * @see java.awt.event.WindowListener#windowActivated(java.awt.event.WindowEvent) 2375 */ 2376 public void windowActivated(WindowEvent e) { 2377 // TODO Auto-generated method stub 2378 } 2379 2380 /* (non-Javadoc) 2381 * @see java.awt.event.WindowListener#windowClosed(java.awt.event.WindowEvent) 2382 */ 2383 public void windowClosed(WindowEvent e) { 2384 quitAction(); 2385 } 2386 2387 /* (non-Javadoc) 2388 * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) 2389 */ 2390 public void windowClosing(WindowEvent e) { 2391 quitAction(); 2392 } 2393 2394 /* (non-Javadoc) 2395 * @see java.awt.event.WindowListener#windowDeactivated(java.awt.event.WindowEvent) 2396 */ 2397 public void windowDeactivated(WindowEvent e) { 2398 // TODO Auto-generated method stub 2399 } 2400 2401 /* (non-Javadoc) 2402 * @see java.awt.event.WindowListener#windowDeiconified(java.awt.event.WindowEvent) 2403 */ 2404 public void windowDeiconified(WindowEvent e) { 2405 // TODO Auto-generated method stub 2406 } 2407 2408 /* (non-Javadoc) 2409 * @see java.awt.event.WindowListener#windowIconified(java.awt.event.WindowEvent) 2410 */ 2411 public void windowIconified(WindowEvent e) { 2412 // TODO Auto-generated method stub 2413 } 2414 2415 /* (non-Javadoc) 2416 * @see java.awt.event.WindowListener#windowOpened(java.awt.event.WindowEvent) 2417 */ 2418 public void windowOpened(WindowEvent e) { 2419 // TODO Auto-generated method stub 2420 } 2421 2422 2423 /** 2424 * Method updateActionStatus. 2425 * <br><b>Summary:</b><br> 2426 * This method permits to update the action enabling status 2427 */ 2428 private void updateActionStatus(){ 2429 //File dependant Actions. 2430 boolean enableFileDependant = false; 2431 if(subtitleFile != null){ 2432 enableFileDependant = true; 2433 } 2434 for (int i = 0; i < FILE_OPEN_DEPENDANT_ACTIONS.length; i++) { 2435 actions.get(FILE_OPEN_DEPENDANT_ACTIONS[i]).setEnabled(enableFileDependant); 2436 } 2437 //File changed dependant. 2438 boolean enableFileChangedDependant = false; 2439 if(subtitleFile != null && subtitleFile.isFileChanged()){ 2440 enableFileChangedDependant = true; 2441 } 2442 for (int i = 0; i < FILE_CHANGED_DEPENDANT_ACTIONS.length; i++) { 2443 actions.get(FILE_CHANGED_DEPENDANT_ACTIONS[i]).setEnabled(enableFileChangedDependant); 2444 } 2445 //Then update actions, that depends on anchors number. 2446 int anchorsNumber = getAnchorsNumber(); 2447 if(anchorsNumber == 0){ 2448 actions.get(ACTION_KEY_MAGIC_RESYNCHRO).setEnabled(false); 2449 actions.get(ACTION_KEY_REMOVE_ALL_ANCHORS).setEnabled(false); 2450 }else if (anchorsNumber < 2){ 2451 //need at least 2 anchors to apply a magic resynchro 2452 actions.get(ACTION_KEY_MAGIC_RESYNCHRO).setEnabled(false); 2453 actions.get(ACTION_KEY_REMOVE_ALL_ANCHORS).setEnabled(true); 2454 }else { 2455 actions.get(ACTION_KEY_MAGIC_RESYNCHRO).setEnabled(true); 2456 actions.get(ACTION_KEY_REMOVE_ALL_ANCHORS).setEnabled(true); 2457 } 2458 } 2459 2460 /** 2461 * Method getAnchorsNumber. 2462 * <br><b>Summary:</b><br> 2463 * This method returns the number of defined anchors. 2464 * @return (<b>int</b>) The number of defined anchors. 2465 */ 2466 private int getAnchorsNumber() { 2467 //the result of the method. 2468 int result = 0; 2469 if(subtitleList != null){ 2470 for(Subtitle subtitle : subtitleList){ 2471 if(subtitle.isAnchored()){ 2472 result ++; 2473 } 2474 } 2475 } 2476 //return the result. 2477 return result; 2478 } 2479 2480 /** 2481 * Class SubtitleFileTransfertHandler. 2482 * Summary: 2483 * This TransferHanlder check for subtitle file drag and drop. 2484 * It permits to open Subtitle file that are draged from OS's location, such as 2485 * Navigator. 2486 */ 2487 protected class SubtitleFileTransfertHandler extends TransferHandler { 2488 private static final long serialVersionUID = 5833961095020955565L; 2489 2490 public SubtitleFileTransfertHandler() { 2491 super(); 2492 } 2493 2494 /* (non-Javadoc) 2495 * @see javax.swing.TransferHandler#canImport(javax.swing.JComponent, java.awt.datatransfer.DataFlavor[]) 2496 */ 2497 public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) { 2498 //Check import available. 2499 //The result of the method. 2500 boolean result = false; 2501 //Parse the array. 2502 for (int i = 0; i < transferFlavors.length; i++) { 2503 //retrieve current element. 2504 DataFlavor dataFlavor = transferFlavors[i]; 2505 //We could only import FileList flavor. 2506 //Which are files to be opened by Sears. 2507 if (dataFlavor.isFlavorJavaFileListType()) { 2508 result = true; 2509 } 2510 } 2511 //return the result. 2512 return result; 2513 } 2514 2515 /* (non-Javadoc) 2516 * @see javax.swing.TransferHandler#importData(javax.swing.JComponent, java.awt.datatransfer.Transferable) 2517 */ 2518 public boolean importData(JComponent comp, Transferable t) { 2519 //the result of the method. 2520 boolean result = false; 2521 try { 2522 Object list = t.getTransferData(DataFlavor.javaFileListFlavor); 2523 if (list instanceof List && ((List) list).size() > 0) { 2524 //Get the first file of the list, and open it. 2525 File fileToOpen = (File) ((List) list).get(0); 2526 instance.openFile(fileToOpen); 2527 result = true; 2528 } 2529 } catch (UnsupportedFlavorException exception) { 2530 // TODO Auto-generated catch block 2531 exception.printStackTrace(); 2532 } catch (IOException exception) { 2533 // TODO Auto-generated catch block 2534 exception.printStackTrace(); 2535 } 2536 //return the result 2537 return result; 2538 } 2539 } 2540 2541 /** 2542 * Class PlayerTimeHandler. 2543 * Summary: 2544 * This PlayerTimeHandler check for video length and position. 2545 */ 2546 private class PlayerTimeHandler implements Runnable, ChangeListener { 2547 private boolean jSliderIsMoving = false; 2548 private boolean jSliderIsUpdating = false; 2549 private long updateDate = 0; 2550 private int currentPosition = 0; 2551 private int oldPosition = 0; 2552 private int subtitleFocusIndex = -1; 2553 2554 /* (non-Javadoc) 2555 * @see java.lang.Runnable#run() 2556 */ 2557 public void run() { 2558 int previousOffset = -1; 2559 int previousLength = -1; 2560 while (true) { 2561 try { 2562 Thread.sleep(200); 2563 if(player != null) { 2564 // get the position and length of video 2565 int currentOffset = player.getPosition(); 2566 if(currentOffset == -1) 2567 currentOffset = 0; 2568 int videoLength = player.getLength(); 2569 if(videoLength == -1) 2570 videoLength = 0; 2571 // update only if it is not the same position and length 2572 if(videoLength != previousLength) { 2573 previousLength = videoLength; 2574 // 2575 // Update the JSlider bar 2576 jSliderIsUpdating = true; 2577 jPanelVideoControler.setJSliderSearchLength(videoLength); 2578 jSliderIsUpdating = false; 2579 } 2580 if(currentOffset != previousOffset) { 2581 previousOffset = currentOffset; 2582 // 2583 // Update the video position label and slider bar. 2584 if(jSliderIsMoving == false) { 2585 jSliderIsUpdating = true; 2586 jPanelVideoControler.setJSliderSearchPosition(currentOffset); 2587 jSliderIsUpdating = false; 2588 } 2589 // 2590 // Update the current subtitle focus 2591 if((subtitleFile != null) && (jPanelVideoControler.jCheckBoxTrackModeIsSelected())) { 2592 Subtitle activeSubtitle = subtitleFile.getSubtitleAtDate((currentOffset+1)*1000); 2593 final int row = activeSubtitle.getNumber() - 1; 2594 if(subtitleFocusIndex != row) { 2595 subtitleFocusIndex = row; 2596 SwingUtilities.invokeLater(new Runnable(){ 2597 public void run() { 2598 table.changeSelection(row, 0, false, false); 2599 table.changeSelection(row+4, 0, true, true); 2600 } 2601 }); 2602 } 2603 } 2604 } 2605 // Update video according to the JSlider 2606 if(jSliderIsMoving == true) { 2607 Date date = new Date(); 2608 if(((date.getTime() - updateDate) > 1000) && (oldPosition != currentPosition)) { 2609 // set the new reference date 2610 updateDate = date.getTime(); 2611 oldPosition = currentPosition; 2612 // Set the new position 2613 try { 2614 player.setPosition(oldPosition); 2615 } catch (Exception e) { 2616 Trace.trace("PlayerTimeHandler failed cannot set video position:"+e.getMessage()); 2617 } 2618 } 2619 } 2620 } 2621 } catch (Exception e) { 2622 Trace.trace("PlayerTimeHandler failed:"+e.getMessage()); 2623 } 2624 } 2625 } 2626 2627 /* (non-Javadoc) 2628 * @see javax.swing.event.ChangeListener#stateChanged(javax.swing.event.ChangeEvent) 2629 */ 2630 public void stateChanged(ChangeEvent changeEvent) { 2631 JSlider source = (JSlider)changeEvent.getSource(); 2632 // get the current slider position 2633 currentPosition = (int)source.getValue(); 2634 jSliderIsMoving = true; 2635 // slider stops moving 2636 if (!source.getValueIsAdjusting()) { 2637 jSliderIsMoving = false; 2638 if((jSliderIsUpdating == false) && (oldPosition != currentPosition)) { 2639 // Set the new position 2640 try { 2641 player.setPosition(currentPosition); 2642 } catch (Exception e) { 2643 Trace.trace("PlayerTimeHandler failed cannot set video position:"+e.getMessage()); 2644 } 2645 } 2646 } 2647 // update the video time 2648 jPanelVideoControler.setJLabelTime(Utils.formatTime(currentPosition)); 2649 } 2650 } 2651 }