2006-02-18 22:55:58 +01:00
// Copyright (c) 2006, Rodrigo Braz Monteiro
2006-01-16 22:02:54 +01:00
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
////////////
// Includes
2006-03-01 04:17:31 +01:00
# include <algorithm>
# include <wx/clipbrd.h>
# include <wx/tokenzr.h>
# include <wx/filename.h>
2006-01-16 22:02:54 +01:00
# include "subs_grid.h"
# include "ass_file.h"
# include "ass_dialogue.h"
# include "ass_style.h"
# include "video_display.h"
# include "vfr.h"
# include "subs_edit_box.h"
# include "options.h"
# include "frame_main.h"
# include "hotkeys.h"
2006-03-01 04:17:31 +01:00
# include "utils.h"
2006-01-16 22:02:54 +01:00
///////////////
// Event table
2006-02-18 22:55:58 +01:00
BEGIN_EVENT_TABLE ( SubtitlesGrid , BaseGrid )
2006-01-16 22:02:54 +01:00
EVT_KEY_DOWN ( SubtitlesGrid : : OnKeyDown )
EVT_MENU ( MENU_SWAP , SubtitlesGrid : : OnSwap )
EVT_MENU ( MENU_DUPLICATE , SubtitlesGrid : : OnDuplicate )
EVT_MENU ( MENU_DUPLICATE_NEXT_FRAME , SubtitlesGrid : : OnDuplicateNextFrame )
EVT_MENU ( MENU_JOIN_CONCAT , SubtitlesGrid : : OnJoinConcat )
EVT_MENU ( MENU_JOIN_REPLACE , SubtitlesGrid : : OnJoinReplace )
EVT_MENU ( MENU_ADJOIN , SubtitlesGrid : : OnAdjoin )
EVT_MENU ( MENU_ADJOIN2 , SubtitlesGrid : : OnAdjoin2 )
EVT_MENU ( MENU_INSERT_BEFORE , SubtitlesGrid : : OnInsertBefore )
EVT_MENU ( MENU_INSERT_AFTER , SubtitlesGrid : : OnInsertAfter )
EVT_MENU ( MENU_INSERT_BEFORE_VIDEO , SubtitlesGrid : : OnInsertBeforeVideo )
EVT_MENU ( MENU_INSERT_AFTER_VIDEO , SubtitlesGrid : : OnInsertAfterVideo )
EVT_MENU ( MENU_COPY , SubtitlesGrid : : OnCopyLines )
EVT_MENU ( MENU_PASTE , SubtitlesGrid : : OnPasteLines )
EVT_MENU ( MENU_CUT , SubtitlesGrid : : OnCutLines )
EVT_MENU ( MENU_DELETE , SubtitlesGrid : : OnDeleteLines )
EVT_MENU ( MENU_SET_START_TO_VIDEO , SubtitlesGrid : : OnSetStartToVideo )
EVT_MENU ( MENU_SET_END_TO_VIDEO , SubtitlesGrid : : OnSetEndToVideo )
EVT_MENU ( MENU_SET_VIDEO_TO_START , SubtitlesGrid : : OnSetVideoToStart )
EVT_MENU ( MENU_SET_VIDEO_TO_END , SubtitlesGrid : : OnSetVideoToEnd )
EVT_MENU ( MENU_JOIN_AS_KARAOKE , SubtitlesGrid : : OnJoinAsKaraoke )
EVT_MENU ( MENU_1_12_2_RECOMBINE , SubtitlesGrid : : On1122Recombine )
EVT_MENU ( MENU_12_2_RECOMBINE , SubtitlesGrid : : On122Recombine )
EVT_MENU ( MENU_1_12_RECOMBINE , SubtitlesGrid : : On112Recombine )
END_EVENT_TABLE ( )
///////////////
// Constructor
SubtitlesGrid : : SubtitlesGrid ( FrameMain * parentFr , wxWindow * parent , wxWindowID id , VideoDisplay * _video , const wxPoint & pos , const wxSize & size , long style , const wxString & name )
2006-02-18 22:55:58 +01:00
: BaseGrid ( parent , id , pos , size , style , name )
2006-01-16 22:02:54 +01:00
{
// Vars
byFrame = false ;
ass = NULL ;
video = _video ;
editBox = NULL ;
parentFrame = parentFr ;
}
//////////////
// Destructor
SubtitlesGrid : : ~ SubtitlesGrid ( ) {
}
//////////////
// Popup menu
2006-02-18 22:55:58 +01:00
void SubtitlesGrid : : OnPopupMenu ( ) {
2006-01-16 22:02:54 +01:00
// Get selections
bool continuous ;
wxArrayInt selections = GetSelection ( & continuous ) ;
int sels = selections . Count ( ) ;
// Show menu if at least one is selected
if ( sels > 0 ) {
wxMenu menu ;
bool state ;
// Insert
state = ( sels = = 1 ) ;
menu . Append ( MENU_INSERT_BEFORE , _ ( " &Insert (before) " ) , _T ( " Inserts a line before current " ) ) - > Enable ( state ) ;
menu . Append ( MENU_INSERT_AFTER , _ ( " Insert (after) " ) , _T ( " Inserts a line after current " ) ) - > Enable ( state ) ;
state = ( sels = = 1 & & video & & video - > loaded ) ;
menu . Append ( MENU_INSERT_BEFORE_VIDEO , _ ( " Insert at video time (before) " ) , _T ( " Inserts a line after current, starting at video time " ) ) - > Enable ( state ) ;
menu . Append ( MENU_INSERT_AFTER_VIDEO , _ ( " Insert at video time (after) " ) , _T ( " Inserts a line after current, starting at video time " ) ) - > Enable ( state ) ;
menu . AppendSeparator ( ) ;
// Video/time sync
2006-03-06 00:01:02 +01:00
//state = (video && video->loaded);
//menu.Append(MENU_SET_VIDEO_TO_START,_("Jump video to start"),_T("Sets current video time to start time"))->Enable(state);
//menu.Append(MENU_SET_VIDEO_TO_END,_("Jump video to end"),_T("Sets current video time to end time"))->Enable(state);
//menu.Append(MENU_SET_START_TO_VIDEO,_("Set start to video"),_T("Sets start times to current video time"))->Enable(state);
//menu.Append(MENU_SET_END_TO_VIDEO,_("Set end to video"),_T("Sets end times to current video time"))->Enable(state);
//menu.AppendSeparator();
2006-01-16 22:02:54 +01:00
// Duplicate selection
menu . Append ( MENU_DUPLICATE , _ ( " &Duplicate " ) , _T ( " Duplicate the selected lines " ) ) - > Enable ( continuous ) ;
2006-02-24 17:45:10 +01:00
menu . Append ( MENU_DUPLICATE_NEXT_FRAME , _ ( " &Duplicate and shift by 1 frame " ) , _T ( " Duplicate lines and shift by one frame " ) ) - > Enable ( continuous & & VFR_Output . IsLoaded ( ) ) ;
2006-01-16 22:02:54 +01:00
// Swaps selection
state = ( sels = = 2 ) ;
menu . Append ( MENU_SWAP , _ ( " &Swap " ) , _T ( " Swaps the two selected lines " ) ) - > Enable ( state ) ;
// Join selection
state = ( sels > = 2 & & continuous ) ;
menu . Append ( MENU_JOIN_CONCAT , _ ( " &Join (concatenate) " ) , _T ( " Joins selected lines in a single one, concatenating text together " ) ) - > Enable ( state ) ;
menu . Append ( MENU_JOIN_REPLACE , _ ( " Join (keep first) " ) , _T ( " Joins selected lines in a single one, keeping text of first and discarding remaining " ) ) - > Enable ( state ) ;
menu . Append ( MENU_JOIN_AS_KARAOKE , _ ( " Join (as Karaoke) " ) , _T ( " " ) ) - > Enable ( state ) ;
// Adjoin selection
menu . Append ( MENU_ADJOIN , _ ( " &Make times continuous (change start) " ) , _T ( " Changes times of subs so start times begin on previous's end time " ) ) - > Enable ( state ) ;
menu . Append ( MENU_ADJOIN2 , _ ( " &Make times continuous (change end) " ) , _T ( " Changes times of subs so end times begin on next's start time " ) ) - > Enable ( state ) ;
menu . AppendSeparator ( ) ;
// Recombine selection
state = ( sels = = 2 & & continuous ) ;
menu . Append ( MENU_1_12_RECOMBINE , _ ( " Recombine (1, 1+2) into (1, 2) " ) , _T ( " Recombine subtitles when first one is actually first plus second " ) ) - > Enable ( state ) ;
menu . Append ( MENU_12_2_RECOMBINE , _ ( " Recombine (1+2, 2) into (1, 2) " ) , _T ( " Recombine subtitles when second one is actually first plus second " ) ) - > Enable ( state ) ;
state = ( sels = = 3 & & continuous ) ;
menu . Append ( MENU_1_12_2_RECOMBINE , _ ( " Recombine (1, 1+2, 2) into (1, 2) " ) , _T ( " Recombine subtitles when middle one is actually first plus second " ) ) - > Enable ( state ) ;
menu . AppendSeparator ( ) ;
// Copy/cut/paste
menu . Append ( MENU_COPY , _ ( " &Copy " ) , _T ( " Copies selected lines to clipboard " ) ) ;
menu . Append ( MENU_CUT , _ ( " C&ut " ) , _T ( " Cuts selected lines to clipboard " ) ) ;
menu . Append ( MENU_PASTE , _ ( " &Paste " ) , _T ( " Paste lines from clipboard " ) ) ;
menu . AppendSeparator ( ) ;
// Delete
menu . Append ( MENU_DELETE , _ ( " Delete " ) , _T ( " Delete currently selected lines " ) ) ;
PopupMenu ( & menu ) ;
}
}
///////////////////////////
// Process keyboard events
void SubtitlesGrid : : OnKeyDown ( wxKeyEvent & event ) {
// Get key
Hotkeys . SetPressed ( event . GetKeyCode ( ) , event . m_controlDown , event . m_altDown , event . m_shiftDown ) ;
// Get selection
bool continuous = false ;
wxArrayInt sels = GetSelection ( & continuous ) ;
int n_found = sels . Count ( ) ;
int n = 0 ;
int n2 = 0 ;
int nrows = GetRows ( ) ;
if ( n_found > 0 ) {
n = sels [ 0 ] ;
n2 = sels [ n_found - 1 ] ;
}
if ( n_found = = 1 ) {
// Move down
if ( Hotkeys . IsPressed ( _T ( " Grid move row down " ) ) ) {
if ( n < nrows - 1 ) {
SwapLines ( n , n + 1 ) ;
SelectRow ( n + 1 ) ;
editBox - > SetToLine ( n + 1 ) ;
}
return ;
}
// Move up
if ( Hotkeys . IsPressed ( _T ( " Grid move row up " ) ) ) {
if ( n > 0 ) {
SwapLines ( n - 1 , n ) ;
SelectRow ( n - 1 ) ;
editBox - > SetToLine ( n - 1 ) ;
}
return ;
}
}
if ( n_found > = 1 ) {
// Copy
if ( Hotkeys . IsPressed ( _T ( " Copy " ) ) ) {
2006-02-23 20:26:14 +01:00
CopyLines ( GetSelection ( ) ) ;
2006-01-16 22:02:54 +01:00
}
// Cut
if ( Hotkeys . IsPressed ( _T ( " Cut " ) ) ) {
2006-02-23 20:26:14 +01:00
CutLines ( GetSelection ( ) ) ;
2006-01-16 22:02:54 +01:00
}
// Paste
if ( Hotkeys . IsPressed ( _T ( " Paste " ) ) ) {
2006-02-23 20:26:14 +01:00
PasteLines ( GetFirstSelRow ( ) ) ;
2006-01-16 22:02:54 +01:00
}
// Delete
if ( Hotkeys . IsPressed ( _T ( " Grid delete rows " ) ) ) {
2006-02-22 07:08:35 +01:00
DeleteLines ( GetSelection ( ) ) ;
2006-01-16 22:02:54 +01:00
return ;
}
if ( continuous ) {
// Duplicate
if ( Hotkeys . IsPressed ( _T ( " Grid duplicate rows " ) ) ) {
DuplicateLines ( n , n2 , false ) ;
return ;
}
// Duplicate and shift
2006-02-24 17:45:10 +01:00
if ( VFR_Output . IsLoaded ( ) ) {
2006-01-16 22:02:54 +01:00
if ( Hotkeys . IsPressed ( _T ( " Grid duplicate and shift one frame " ) ) ) {
DuplicateLines ( n , n2 , true ) ;
return ;
}
}
}
}
event . Skip ( ) ;
}
///////////////////////
// Duplicate selection
void SubtitlesGrid : : OnDuplicate ( wxCommandEvent & WXUNUSED ( & event ) ) {
2006-02-22 07:49:20 +01:00
wxArrayInt sels = GetSelection ( ) ;
DuplicateLines ( sels . front ( ) , sels . back ( ) ) ;
2006-01-16 22:02:54 +01:00
}
//////////////////////////////////////////////
// Duplicate selection and shift by one frame
void SubtitlesGrid : : OnDuplicateNextFrame ( wxCommandEvent & WXUNUSED ( & event ) ) {
2006-02-22 07:49:20 +01:00
wxArrayInt sels = GetSelection ( ) ;
DuplicateLines ( sels . front ( ) , sels . back ( ) , true ) ;
2006-01-16 22:02:54 +01:00
}
/////////////
// Call swap
void SubtitlesGrid : : OnSwap ( wxCommandEvent & event ) {
2006-02-22 07:49:20 +01:00
wxArrayInt sels = GetSelection ( ) ;
SwapLines ( sels . front ( ) , sels . back ( ) ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////////////
// Call join (concatenate)
void SubtitlesGrid : : OnJoinConcat ( wxCommandEvent & event ) {
2006-02-22 07:49:20 +01:00
wxArrayInt sels = GetSelection ( ) ;
JoinLines ( sels . front ( ) , sels . back ( ) , true ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////////
// Call join (replace)
void SubtitlesGrid : : OnJoinReplace ( wxCommandEvent & event ) {
2006-02-22 07:49:20 +01:00
wxArrayInt sels = GetSelection ( ) ;
JoinLines ( sels . front ( ) , sels . back ( ) , false ) ;
2006-01-16 22:02:54 +01:00
}
////////////////
// Adjoin lines
void SubtitlesGrid : : OnAdjoin ( wxCommandEvent & event ) {
2006-02-22 07:49:20 +01:00
wxArrayInt sels = GetSelection ( ) ;
AdjoinLines ( sels . front ( ) , sels . back ( ) , true ) ;
2006-01-16 22:02:54 +01:00
}
void SubtitlesGrid : : OnAdjoin2 ( wxCommandEvent & event ) {
2006-02-22 07:49:20 +01:00
wxArrayInt sels = GetSelection ( ) ;
AdjoinLines ( sels . front ( ) , sels . back ( ) , false ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////
// Call join as karaoke
void SubtitlesGrid : : OnJoinAsKaraoke ( wxCommandEvent & event ) {
2006-02-22 07:49:20 +01:00
wxArrayInt sels = GetSelection ( ) ;
JoinAsKaraoke ( sels . front ( ) , sels . back ( ) ) ;
2006-01-16 22:02:54 +01:00
}
//////////////////////
// Call insert before
void SubtitlesGrid : : OnInsertBefore ( wxCommandEvent & event ) {
// Find line
2006-02-22 07:49:20 +01:00
int n = GetFirstSelRow ( ) ;
2006-01-16 22:02:54 +01:00
// Create line to add
AssDialogue * def = new AssDialogue ;
if ( n = = 0 ) {
def - > Start . SetMS ( 0 ) ;
def - > End = GetDialogue ( n ) - > Start ;
}
else {
def - > Start = GetDialogue ( n - 1 ) - > End ;
def - > End = GetDialogue ( n ) - > Start ;
}
if ( def - > End . GetMS ( ) < def - > Start . GetMS ( ) ) def - > End . SetMS ( def - > Start . GetMS ( ) + 5000 ) ;
def - > Style = GetDialogue ( n ) - > Style ;
// Insert it
InsertLine ( def , n , false ) ;
2006-02-21 22:23:52 +01:00
SelectRow ( n ) ;
editBox - > SetToLine ( n ) ;
2006-01-16 22:02:54 +01:00
}
/////////////////////
// Call insert after
void SubtitlesGrid : : OnInsertAfter ( wxCommandEvent & event ) {
// Find line
2006-02-22 07:49:20 +01:00
int n = GetFirstSelRow ( ) ;
2006-01-16 22:02:54 +01:00
int nrows = GetRows ( ) ;
// Create line to add
AssDialogue * def = new AssDialogue ;
if ( n = = nrows - 1 ) {
def - > Start = GetDialogue ( n ) - > End ;
def - > End = GetDialogue ( n ) - > End ;
def - > End . SetMS ( def - > End . GetMS ( ) + 5000 ) ;
}
else {
def - > Start = GetDialogue ( n ) - > End ;
def - > End = GetDialogue ( n + 1 ) - > Start ;
}
if ( def - > End . GetMS ( ) < def - > Start . GetMS ( ) ) def - > End . SetMS ( def - > Start . GetMS ( ) + 5000 ) ;
def - > Style = GetDialogue ( n ) - > Style ;
// Insert it
InsertLine ( def , n , true ) ;
2006-02-21 22:23:52 +01:00
SelectRow ( n + 1 ) ;
editBox - > SetToLine ( n + 1 ) ;
2006-01-16 22:02:54 +01:00
}
/////////////////////////////////
// Call insert before with video
void SubtitlesGrid : : OnInsertBeforeVideo ( wxCommandEvent & event ) {
// Find line
2006-02-22 07:49:20 +01:00
int n = GetFirstSelRow ( ) ;
2006-01-16 22:02:54 +01:00
// Create line to add
AssDialogue * def = new AssDialogue ;
2006-02-24 17:45:10 +01:00
int video_ms = VFR_Output . GetTimeAtFrame ( video - > frame_n , true ) ;
2006-01-16 22:02:54 +01:00
def - > Start . SetMS ( video_ms ) ;
def - > End . SetMS ( video_ms + 5000 ) ;
def - > Style = GetDialogue ( n ) - > Style ;
// Insert it
InsertLine ( def , n , false ) ;
2006-02-21 22:23:52 +01:00
SelectRow ( n ) ;
editBox - > SetToLine ( n ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////////////
// Call insert after with video
void SubtitlesGrid : : OnInsertAfterVideo ( wxCommandEvent & event ) {
// Find line
2006-02-22 07:49:20 +01:00
int n = GetFirstSelRow ( ) ;
2006-01-16 22:02:54 +01:00
// Create line to add
AssDialogue * def = new AssDialogue ;
2006-02-24 17:45:10 +01:00
int video_ms = VFR_Output . GetTimeAtFrame ( video - > frame_n , true ) ;
2006-01-16 22:02:54 +01:00
def - > Start . SetMS ( video_ms ) ;
def - > End . SetMS ( video_ms + 5000 ) ;
def - > Style = GetDialogue ( n ) - > Style ;
// Insert it
InsertLine ( def , n , true ) ;
2006-02-21 22:23:52 +01:00
SelectRow ( n + 1 ) ;
editBox - > SetToLine ( n + 1 ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////////////////
// Copy selection to clipboard
void SubtitlesGrid : : OnCopyLines ( wxCommandEvent & WXUNUSED ( & event ) ) {
2006-02-22 07:49:20 +01:00
CopyLines ( GetSelection ( ) ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////////////////
// Cuts selection to clipboard
void SubtitlesGrid : : OnCutLines ( wxCommandEvent & WXUNUSED ( & event ) ) {
2006-02-22 07:49:20 +01:00
CutLines ( GetSelection ( ) ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////
// Paste from clipboard
void SubtitlesGrid : : OnPasteLines ( wxCommandEvent & WXUNUSED ( & event ) ) {
2006-02-22 05:59:39 +01:00
PasteLines ( GetFirstSelRow ( ) ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////////////////
// Copy selection to clipboard
void SubtitlesGrid : : OnDeleteLines ( wxCommandEvent & WXUNUSED ( & event ) ) {
2006-02-22 07:08:35 +01:00
DeleteLines ( GetSelection ( ) ) ;
2006-01-16 22:02:54 +01:00
}
//////////////////////////
// Set start to video pos
void SubtitlesGrid : : OnSetStartToVideo ( wxCommandEvent & event ) {
2006-02-22 05:59:39 +01:00
SetSubsToVideo ( true ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////
// Set end to video pos
void SubtitlesGrid : : OnSetEndToVideo ( wxCommandEvent & event ) {
2006-02-22 05:59:39 +01:00
SetSubsToVideo ( false ) ;
2006-01-16 22:02:54 +01:00
}
//////////////////////////
// Set video pos to start
void SubtitlesGrid : : OnSetVideoToStart ( wxCommandEvent & event ) {
2006-02-22 05:59:39 +01:00
SetVideoToSubs ( true ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////
// Set video pos to end
void SubtitlesGrid : : OnSetVideoToEnd ( wxCommandEvent & event ) {
2006-02-22 05:59:39 +01:00
SetVideoToSubs ( false ) ;
2006-01-16 22:02:54 +01:00
}
/////////////////////
// 1,1+2,2 Recombine
void SubtitlesGrid : : On1122Recombine ( wxCommandEvent & event ) {
// Get selection
bool cont ;
wxArrayInt sel = GetSelection ( & cont ) ;
if ( sel . Count ( ) ! = 3 | | ! cont ) throw _T ( " Invalid number of selections " ) ;
int n = sel [ 0 ] ;
// Update
AssDialogue * n1 , * n2 , * n3 ;
n1 = GetDialogue ( n ) ;
n2 = GetDialogue ( n + 1 ) ;
n3 = GetDialogue ( n + 2 ) ;
n1 - > End = n2 - > End ;
n3 - > Start = n2 - > Start ;
n1 - > UpdateData ( ) ;
n3 - > UpdateData ( ) ;
// Delete middle
2006-02-22 07:08:35 +01:00
DeleteLines ( GetRangeArray ( n + 1 , n + 1 ) ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////
// 1+2,2 Recombine
void SubtitlesGrid : : On122Recombine ( wxCommandEvent & event ) {
// Get selection
bool cont ;
wxArrayInt sel = GetSelection ( & cont ) ;
if ( sel . Count ( ) ! = 2 | | ! cont ) throw _T ( " Invalid number of selections " ) ;
int n = sel [ 0 ] ;
// Update
AssDialogue * n1 , * n2 ;
n1 = GetDialogue ( n ) ;
n2 = GetDialogue ( n + 1 ) ;
2006-02-01 03:16:57 +01:00
n1 - > Text . Trim ( true ) . Trim ( false ) ;
n2 - > Text . Trim ( true ) . Trim ( false ) ;
// Check if n2 is a suffix of n1
if ( n1 - > Text . Right ( n2 - > Text . Length ( ) ) = = n2 - > Text ) {
n1 - > Text = n1 - > Text . SubString ( 0 , n1 - > Text . Length ( ) - n2 - > Text . Length ( ) - 1 ) . Trim ( true ) . Trim ( false ) ;
while ( n1 - > Text . Left ( 2 ) = = _T ( " \\ N " ) | | n1 - > Text . Left ( 2 ) = = _T ( " \\ n " ) )
n1 - > Text = n1 - > Text . Mid ( 2 ) ;
while ( n1 - > Text . Right ( 2 ) = = _T ( " \\ N " ) | | n1 - > Text . Right ( 2 ) = = _T ( " \\ n " ) )
n1 - > Text = n1 - > Text . Mid ( 0 , n1 - > Text . Length ( ) - 2 ) ;
n2 - > Start = n1 - > Start ;
2006-02-21 04:13:35 +01:00
//n1->ParseASSTags();
2006-02-01 03:16:57 +01:00
n1 - > UpdateData ( ) ;
n2 - > UpdateData ( ) ;
// Commit
ass - > FlagAsModified ( ) ;
CommitChanges ( ) ;
} else {
parentFrame - > StatusTimeout ( _T ( " Unable to recombine: Second line is not a suffix of first one. " ) ) ;
}
2006-01-16 22:02:54 +01:00
}
///////////////////
// 1,1+2 Recombine
void SubtitlesGrid : : On112Recombine ( wxCommandEvent & event ) {
// Get selection
bool cont ;
wxArrayInt sel = GetSelection ( & cont ) ;
if ( sel . Count ( ) ! = 2 | | ! cont ) throw _T ( " Invalid number of selections " ) ;
int n = sel [ 0 ] ;
// Update
AssDialogue * n1 , * n2 ;
n1 = GetDialogue ( n ) ;
n2 = GetDialogue ( n + 1 ) ;
2006-02-01 03:16:57 +01:00
n1 - > Text . Trim ( true ) . Trim ( false ) ;
n2 - > Text . Trim ( true ) . Trim ( false ) ;
// Check if n1 is a prefix of n2 and recombine
if ( n2 - > Text . Left ( n1 - > Text . Length ( ) ) = = n1 - > Text ) {
n2 - > Text = n2 - > Text . Mid ( n1 - > Text . Length ( ) ) . Trim ( true ) . Trim ( false ) ;
while ( n2 - > Text . Left ( 2 ) = = _T ( " \\ N " ) | | n2 - > Text . Left ( 2 ) = = _T ( " \\ n " ) )
n2 - > Text = n2 - > Text . Mid ( 2 ) ;
while ( n2 - > Text . Right ( 2 ) = = _T ( " \\ N " ) | | n2 - > Text . Right ( 2 ) = = _T ( " \\ n " ) )
n2 - > Text = n2 - > Text . Mid ( 0 , n2 - > Text . Length ( ) - 2 ) ;
n1 - > End = n2 - > End ;
2006-02-21 04:13:35 +01:00
//n2->ParseASSTags();
2006-02-01 03:16:57 +01:00
n1 - > UpdateData ( ) ;
n2 - > UpdateData ( ) ;
// Commit
ass - > FlagAsModified ( ) ;
CommitChanges ( ) ;
} else {
parentFrame - > StatusTimeout ( _T ( " Unable to recombine: First line is not a prefix of second one. " ) ) ;
}
2006-01-16 22:02:54 +01:00
}
//////////////////////////////////////
// Clears grid and sets it to default
void SubtitlesGrid : : LoadDefault ( AssFile * _ass ) {
if ( _ass ) {
ass = _ass ;
}
ass - > LoadDefault ( ) ;
LoadFromAss ( NULL , false , true ) ;
}
/////////////////////////////////////
// Read data from ASS file structure
void SubtitlesGrid : : LoadFromAss ( AssFile * _ass , bool keepSelection , bool dontModify ) {
// Store selected rows
std : : vector < int > srows ;
if ( keepSelection ) {
int nrows = GetRows ( ) ;
for ( int i = 0 ; i < nrows ; i + + ) {
if ( IsInSelection ( i , 0 ) ) {
srows . push_back ( i ) ;
}
}
}
2006-02-25 04:04:52 +01:00
// Clear grid
2006-01-16 22:02:54 +01:00
BeginBatch ( ) ;
2006-02-25 04:04:52 +01:00
int oldPos = yPos ;
2006-01-16 22:02:54 +01:00
Clear ( ) ;
2006-02-25 04:04:52 +01:00
if ( keepSelection ) yPos = oldPos ;
// Get subtitles
2006-01-16 22:02:54 +01:00
if ( _ass ) ass = _ass ;
else {
if ( ! ass ) throw _T ( " Trying to set subs grid to current ass file, but there is none " ) ;
}
// Run through subs adding them
int n = 0 ;
AssDialogue * curdiag ;
ready = false ;
for ( entryIter cur = ass - > Line . begin ( ) ; cur ! = ass - > Line . end ( ) ; cur + + ) {
curdiag = AssEntry : : GetAsDialogue ( * cur ) ;
if ( curdiag ) {
diagMap . push_back ( cur ) ;
2006-02-21 03:01:42 +01:00
diagPtrMap . push_back ( curdiag ) ;
2006-02-18 22:55:58 +01:00
selMap . push_back ( false ) ;
2006-01-16 22:02:54 +01:00
n + + ;
}
}
ready = true ;
// Restore selection
if ( keepSelection ) {
for ( size_t i = 0 ; i < srows . size ( ) ; i + + ) {
SelectRow ( srows . at ( i ) , true ) ;
}
}
// Select first
else {
SelectRow ( 0 ) ;
}
// Commit
if ( ! AssFile : : Popping ) {
if ( dontModify ) AssFile : : StackPush ( ) ;
else ass - > FlagAsModified ( ) ;
}
CommitChanges ( ) ;
// Set edit box
if ( editBox ) {
int nrows = GetRows ( ) ;
int firstsel = - 1 ;
for ( int i = 0 ; i < nrows ; i + + ) {
if ( IsInSelection ( i , 0 ) ) {
firstsel = i ;
break ;
}
}
editBox - > UpdateGlobals ( ) ;
if ( _ass ) editBox - > SetToLine ( firstsel ) ;
}
2006-02-25 04:04:52 +01:00
// Finish setting layout
AdjustScrollbar ( ) ;
EndBatch ( ) ;
2006-01-16 22:02:54 +01:00
}
///////////////////
// Swaps two lines
void SubtitlesGrid : : SwapLines ( int n1 , int n2 ) {
// Check bounds and get iterators
int rows = GetRows ( ) ;
if ( n1 < 0 | | n2 < 0 | | n1 > = rows | | n2 > = rows ) return ;
entryIter src1 = diagMap . at ( n1 ) ;
entryIter src2 = diagMap . at ( n2 ) ;
// Swaps
iter_swap ( src1 , src2 ) ;
// Update mapping
diagMap [ n1 ] = src1 ;
2006-02-22 07:08:35 +01:00
diagPtrMap [ n1 ] = ( AssDialogue * ) * src1 ;
2006-01-16 22:02:54 +01:00
diagMap [ n2 ] = src2 ;
2006-02-22 07:08:35 +01:00
diagPtrMap [ n2 ] = ( AssDialogue * ) * src2 ;
2006-01-16 22:02:54 +01:00
ass - > FlagAsModified ( ) ;
CommitChanges ( ) ;
}
/////////////////
// Insert a line
void SubtitlesGrid : : InsertLine ( AssDialogue * line , int n , bool after , bool update ) {
// Check bounds and get iterators
entryIter pos = diagMap . at ( n ) ;
// Insert
if ( after ) {
n + + ;
pos + + ;
}
line - > UpdateData ( ) ;
entryIter newIter = ass - > Line . insert ( pos , line ) ;
2006-02-18 22:55:58 +01:00
//InsertRows(n);
//SetRowToLine(n,line);
2006-01-16 22:02:54 +01:00
diagMap . insert ( diagMap . begin ( ) + n , newIter ) ;
2006-02-22 07:08:35 +01:00
diagPtrMap . insert ( diagPtrMap . begin ( ) + n , ( AssDialogue * ) ( * newIter ) ) ;
2006-02-18 22:55:58 +01:00
selMap . insert ( selMap . begin ( ) + n , false ) ;
2006-01-16 22:02:54 +01:00
// Update
if ( update ) {
ass - > FlagAsModified ( ) ;
CommitChanges ( ) ;
}
}
///////////////////////////
// Copy lines to clipboard
2006-02-22 07:49:20 +01:00
void SubtitlesGrid : : CopyLines ( wxArrayInt target ) {
2006-01-16 22:02:54 +01:00
// Prepare text
wxString data = _T ( " " ) ;
AssDialogue * cur ;
2006-02-22 07:49:20 +01:00
int nrows = target . Count ( ) ;
2006-01-16 22:02:54 +01:00
bool first = true ;
for ( int i = 0 ; i < nrows ; i + + ) {
2006-02-22 07:49:20 +01:00
if ( ! first ) data + = _T ( " \r \n " ) ;
first = false ;
cur = GetDialogue ( target [ i ] ) ;
2006-02-27 03:23:50 +01:00
data + = cur - > GetEntryData ( ) ;
2006-01-16 22:02:54 +01:00
}
// Send to clipboard
if ( wxTheClipboard - > Open ( ) ) {
wxTheClipboard - > SetData ( new wxTextDataObject ( data ) ) ;
wxTheClipboard - > Close ( ) ;
}
}
2006-02-22 05:59:39 +01:00
////////////////////
// Cut to clipboard
2006-02-22 07:49:20 +01:00
void SubtitlesGrid : : CutLines ( wxArrayInt target ) {
CopyLines ( target ) ;
DeleteLines ( target ) ;
2006-02-22 05:59:39 +01:00
}
2006-01-16 22:02:54 +01:00
//////////////////////////////
// Paste lines from clipboard
void SubtitlesGrid : : PasteLines ( int n ) {
// Prepare text
wxString data = _T ( " " ) ;
// Read from clipboard
if ( wxTheClipboard - > Open ( ) ) {
if ( wxTheClipboard - > IsSupported ( wxDF_TEXT ) ) {
wxTextDataObject rawdata ;
wxTheClipboard - > GetData ( rawdata ) ;
data = rawdata . GetText ( ) ;
}
wxTheClipboard - > Close ( ) ;
}
// Check if it actually got anything
if ( ! data . empty ( ) ) {
int inserted = 0 ;
wxStringTokenizer token ( data , _T ( " \r \n " ) , wxTOKEN_STRTOK ) ;
while ( token . HasMoreTokens ( ) ) {
wxString curdata = token . GetNextToken ( ) ;
curdata . Trim ( true ) ;
curdata . Trim ( false ) ;
try {
AssDialogue * curdiag = new AssDialogue ( curdata ) ;
InsertLine ( curdiag , n + inserted , false , false ) ;
inserted + + ;
}
catch ( . . . ) {
}
}
if ( inserted > 0 ) {
// Commit
2006-02-22 07:08:35 +01:00
UpdateMaps ( ) ;
2006-02-23 20:26:14 +01:00
AdjustScrollbar ( ) ;
2006-01-16 22:02:54 +01:00
ass - > FlagAsModified ( ) ;
CommitChanges ( ) ;
// Set selection
SelectRow ( n ) ;
for ( int i = n + 1 ; i < n + inserted ; i + + ) {
SelectRow ( i , true ) ;
}
editBox - > SetToLine ( n + 1 ) ;
}
}
}
/////////////////////////
// Delete selected lines
2006-02-22 07:08:35 +01:00
void SubtitlesGrid : : DeleteLines ( wxArrayInt target ) {
2006-01-16 22:02:54 +01:00
// Check if it's wiping file
int deleted = 0 ;
2006-02-22 07:08:35 +01:00
// Delete lines
int size = target . Count ( ) ;
for ( int i = 0 ; i < size ; i + + ) {
delete ( * diagMap . at ( target [ i ] ) ) ;
ass - > Line . erase ( diagMap . at ( target [ i ] ) ) ;
deleted + + ;
2006-01-16 22:02:54 +01:00
}
// Add default line if file was wiped
if ( GetRows ( ) = = deleted ) {
AssDialogue * def = new AssDialogue ;
ass - > Line . push_back ( def ) ;
}
// Update
2006-02-21 03:01:42 +01:00
UpdateMaps ( ) ;
AdjustScrollbar ( ) ;
ass - > FlagAsModified ( ) ;
CommitChanges ( ) ;
2006-03-01 04:17:31 +01:00
// Update editbox
editBox - > SetToLine ( MID ( 0 , editBox - > linen , GetRows ( ) - 1 ) ) ;
2006-01-16 22:02:54 +01:00
}
////////////////////////
// Joins selected lines
void SubtitlesGrid : : JoinLines ( int n1 , int n2 , bool concat ) {
// Initialize
int min_ms = 0x0FFFFFFF ;
int max_ms = - 1 ;
wxString finalText = _T ( " " ) ;
// Collect data
AssDialogue * cur ;
int start , end ;
bool gotfirst = false ;
for ( int i = n1 ; i < = n2 ; i + + ) {
cur = GetDialogue ( i ) ;
start = cur - > Start . GetMS ( ) ;
end = cur - > End . GetMS ( ) ;
if ( start < min_ms ) min_ms = start ;
if ( end > max_ms ) max_ms = end ;
if ( concat | | ! gotfirst ) {
if ( gotfirst ) finalText + = _T ( " \\ N " ) ;
gotfirst = true ;
finalText + = cur - > Text ;
}
}
// Apply settings to first line
cur = GetDialogue ( n1 ) ;
cur - > Start . SetMS ( min_ms ) ;
cur - > End . SetMS ( max_ms ) ;
cur - > Text = finalText ;
cur - > UpdateData ( ) ;
// Delete remaining lines (this will auto commit)
2006-02-22 07:08:35 +01:00
DeleteLines ( GetRangeArray ( n1 + 1 , n2 ) ) ;
2006-01-16 22:02:54 +01:00
// Select new line
editBox - > SetToLine ( n1 ) ;
SelectRow ( n1 ) ;
}
//////////////////////////
// Adjoins selected lines
void SubtitlesGrid : : AdjoinLines ( int n1 , int n2 , bool setStart ) {
// Set start
if ( setStart ) {
AssDialogue * prev = GetDialogue ( n1 ) ;
AssDialogue * cur ;
for ( int i = n1 + 1 ; i < = n2 ; i + + ) {
cur = GetDialogue ( i ) ;
if ( ! cur ) return ;
cur - > Start = prev - > End ;
cur - > UpdateData ( ) ;
prev = cur ;
}
}
// Set end
else {
AssDialogue * next ;
AssDialogue * cur = GetDialogue ( n1 ) ;
for ( int i = n1 ; i < n2 ; i + + ) {
next = GetDialogue ( i + 1 ) ;
if ( ! next ) return ;
cur - > End = next - > Start ;
cur - > UpdateData ( ) ;
cur = next ;
}
}
// Commit
AssFile : : top - > FlagAsModified ( ) ;
CommitChanges ( ) ;
}
///////////////////////////////////
// Joins selected lines as karaoke
void SubtitlesGrid : : JoinAsKaraoke ( int n1 , int n2 ) {
// Initialize
wxString finalText = _T ( " " ) ;
// Collect data
AssDialogue * cur ;
int start , end ;
int firststart ;
int lastend = - 1 ;
int len1 , len2 ;
for ( int i = n1 ; i < = n2 ; i + + ) {
cur = GetDialogue ( i ) ;
// Get times
start = cur - > Start . GetMS ( ) ;
end = cur - > End . GetMS ( ) ;
// Get len
if ( lastend = = - 1 ) {
lastend = start ;
firststart = start ;
}
len1 = ( start - lastend ) / 10 ;
len2 = ( end - lastend ) / 10 ;
// Create text
if ( len1 ! = 0 ) finalText + = _T ( " { \\ k " ) + wxString : : Format ( _T ( " %i " ) , len1 ) + _T ( " } " ) ;
finalText + = _T ( " { \\ k " ) + wxString : : Format ( _T ( " %i " ) , len2 ) + _T ( " } " ) + cur - > Text ;
lastend = end ;
}
// Apply settings to first line
cur = GetDialogue ( n1 ) ;
cur - > Start . SetMS ( firststart ) ;
cur - > End . SetMS ( lastend ) ;
cur - > Text = finalText ;
cur - > UpdateData ( ) ;
// Delete remaining lines (this will auto commit)
2006-02-22 07:08:35 +01:00
DeleteLines ( GetRangeArray ( n1 + 1 , n2 ) ) ;
2006-01-16 22:02:54 +01:00
// Select new line
editBox - > SetToLine ( n1 ) ;
SelectRow ( n1 ) ;
}
///////////////////
// Duplicate lines
void SubtitlesGrid : : DuplicateLines ( int n1 , int n2 , bool nextFrame ) {
AssDialogue * cur ;
bool update = false ;
int step = 0 ;
for ( int i = n1 ; i < = n2 ; i + + ) {
// Create
if ( i = = n2 ) update = true ;
//cur = new AssDialogue(GetDialogue(i+step)->data);
2006-02-27 03:23:50 +01:00
cur = new AssDialogue ( GetDialogue ( i ) - > GetEntryData ( ) ) ;
2006-01-16 22:02:54 +01:00
// Shift to next frame
if ( nextFrame ) {
2006-02-24 17:45:10 +01:00
int posFrame = VFR_Output . GetFrameAtTime ( cur - > End . GetMS ( ) , false ) + 1 ;
2006-03-05 03:47:20 +01:00
cur - > Start . SetMS ( VFR_Output . GetTimeAtFrame ( posFrame , true ) ) ;
cur - > End . SetMS ( VFR_Output . GetTimeAtFrame ( posFrame , false ) ) ;
2006-01-16 22:02:54 +01:00
cur - > UpdateData ( ) ;
}
// Insert
//InsertLine(cur,n1+step,false,update);
InsertLine ( cur , n2 + step , true , update ) ;
step + + ;
}
// Select new lines
SelectRow ( n1 + step , false ) ;
for ( int i = n1 + 1 ; i < = n2 ; i + + ) {
SelectRow ( i + step , true ) ;
}
editBox - > SetToLine ( n1 + step ) ;
}
///////////////////////
// Shifts line by time
// -------------------
// Where type =
// 0: Start + End
// 1: Start
// 2: End
//
void SubtitlesGrid : : ShiftLineByTime ( int n , int len , int type ) {
AssDialogue * cur = GetDialogue ( n ) ;
// Start
if ( type ! = 2 ) cur - > Start . SetMS ( cur - > Start . GetMS ( ) + len ) ;
// End
if ( type ! = 1 ) cur - > End . SetMS ( cur - > End . GetMS ( ) + len ) ;
// Update data
cur - > UpdateData ( ) ;
}
////////////////////////
// Shifts line by frame
// -------------------
// Where type =
// 0: Start + End
// 1: Start
// 2: End
//
void SubtitlesGrid : : ShiftLineByFrames ( int n , int len , int type ) {
AssDialogue * cur = GetDialogue ( n ) ;
// Start
2006-02-24 17:45:10 +01:00
if ( type ! = 2 ) cur - > Start . SetMS ( VFR_Output . GetTimeAtFrame ( len + VFR_Output . GetFrameAtTime ( cur - > Start . GetMS ( ) , true ) , true ) ) ;
2006-01-16 22:02:54 +01:00
// End
2006-02-24 17:45:10 +01:00
if ( type ! = 1 ) cur - > End . SetMS ( VFR_Output . GetTimeAtFrame ( len + VFR_Output . GetFrameAtTime ( cur - > End . GetMS ( ) , false ) , false ) ) ;
2006-01-16 22:02:54 +01:00
// Update data
cur - > UpdateData ( ) ;
}
//////////////
// Split line
void SubtitlesGrid : : SplitLine ( int n , int pos , int mode ) {
// Split
AssDialogue * n1 , * n2 ;
n1 = GetDialogue ( n ) ;
2006-02-27 03:23:50 +01:00
n2 = new AssDialogue ( n1 - > GetEntryData ( ) ) ;
2006-01-16 22:02:54 +01:00
InsertLine ( n2 , n , true , false ) ;
// Modify text
wxString orig = n1 - > Text ;
n1 - > Text = orig . Left ( pos ) ;
n2 - > Text = orig . Mid ( pos ) ;
// Modify time
if ( mode = = 1 ) {
double splitPos = double ( pos ) / orig . Length ( ) ;
int splitTime = ( n1 - > End . GetMS ( ) - n1 - > Start . GetMS ( ) ) * splitPos + n1 - > Start . GetMS ( ) ;
n1 - > End . SetMS ( splitTime ) ;
n2 - > Start . SetMS ( splitTime ) ;
}
// Update data
n1 - > UpdateData ( ) ;
n2 - > UpdateData ( ) ;
// Update editbox and audio
editBox - > SetToLine ( n ) ;
// Commit
ass - > FlagAsModified ( ) ;
CommitChanges ( ) ;
}
//////////////////
// Commit changes
// --------------
2006-02-23 05:19:57 +01:00
// This will save the work .ass and refresh it
2006-01-16 22:02:54 +01:00
void SubtitlesGrid : : CommitChanges ( bool force ) {
if ( video - > loaded | | force ) {
// Check if it's playing
bool playing = false ;
if ( video - > IsPlaying ) {
playing = true ;
video - > Stop ( ) ;
}
// Export
2006-02-22 07:49:20 +01:00
wxString workfile = video - > GetTempWorkFile ( ) ;
2006-01-16 22:02:54 +01:00
ass - > Export ( workfile ) ;
2006-01-22 13:44:53 +01:00
if ( video - > loaded )
video - > RefreshSubtitles ( ) ;
2006-01-16 22:02:54 +01:00
// Resume play
if ( playing ) video - > Play ( ) ;
}
parentFrame - > UpdateTitle ( ) ;
2006-02-22 06:30:09 +01:00
SetColumnWidths ( ) ;
2006-02-19 01:54:35 +01:00
Refresh ( false ) ;
2006-01-16 22:02:54 +01:00
}
2006-02-22 05:59:39 +01:00
//////////////////////////
// Set start to video pos
void SubtitlesGrid : : SetSubsToVideo ( bool start ) {
// Check if it's OK to do it
2006-02-24 17:45:10 +01:00
if ( ! VFR_Output . IsLoaded ( ) ) return ;
2006-02-22 05:59:39 +01:00
// Get new time
2006-02-24 17:45:10 +01:00
int ms = VFR_Output . GetTimeAtFrame ( video - > frame_n , start ) ;
2006-02-22 05:59:39 +01:00
// Update selection
wxArrayInt sel = GetSelection ( ) ;
AssDialogue * cur ;
int modified = 0 ;
for ( size_t i = 0 ; i < sel . Count ( ) ; i + + ) {
cur = GetDialogue ( sel [ i ] ) ;
if ( cur ) {
modified + + ;
if ( start ) cur - > Start . SetMS ( ms ) ;
else cur - > End . SetMS ( ms ) ;
cur - > UpdateData ( ) ;
}
}
// Commit
if ( modified ) {
ass - > FlagAsModified ( ) ;
CommitChanges ( ) ;
editBox - > Update ( ) ;
}
}
//////////////////////////////
// Set video pos to start/end
void SubtitlesGrid : : SetVideoToSubs ( bool start ) {
wxArrayInt sel = GetSelection ( ) ;
if ( sel . Count ( ) = = 0 ) return ;
AssDialogue * cur = GetDialogue ( sel [ 0 ] ) ;
if ( cur ) {
2006-02-24 17:45:10 +01:00
if ( start )
video - > JumpToFrame ( VFR_Output . GetFrameAtTime ( cur - > Start . GetMS ( ) , true ) ) ;
else
video - > JumpToFrame ( VFR_Output . GetFrameAtTime ( cur - > End . GetMS ( ) , false ) ) ;
2006-02-22 05:59:39 +01:00
}
}