mirror of https://github.com/odrling/Aegisub
Rewrite the shift times dialog, detangling it from the grid and making it modeless, and add support for characters outside the local charset in the shift history file path. Closes #1269.
Originally committed to SVN as r5596.
This commit is contained in:
parent
1f095b0a01
commit
0c4eb020a4
|
@ -161,7 +161,7 @@ struct time_shift : public Command {
|
||||||
|
|
||||||
void operator()(agi::Context *c) {
|
void operator()(agi::Context *c) {
|
||||||
c->videoController->Stop();
|
c->videoController->Stop();
|
||||||
DialogShiftTimes(c).ShowModal();
|
(new DialogShiftTimes(c))->Show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,16 @@
|
||||||
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
// Copyright (c) 2011, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
// All rights reserved.
|
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// modification, are permitted provided that the following conditions are met:
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
// this list of conditions and the following disclaimer.
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
// and/or other materials provided with the distribution.
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// may be used to endorse or promote products derived from this software
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 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 Project http://www.aegisub.org/
|
// Aegisub Project http://www.aegisub.org/
|
||||||
//
|
//
|
||||||
|
@ -36,10 +23,11 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "dialog_shift_times.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
#include <vector>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <wx/filefn.h>
|
#include <wx/filefn.h>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
|
@ -49,357 +37,303 @@
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <libaegisub/access.h>
|
||||||
|
#include <libaegisub/io.h>
|
||||||
|
#include <libaegisub/log.h>
|
||||||
|
#include <libaegisub/scoped_ptr.h>
|
||||||
|
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "ass_time.h"
|
#include "ass_time.h"
|
||||||
#include "charset_conv.h"
|
#include "compat.h"
|
||||||
#include "dialog_shift_times.h"
|
|
||||||
#include "include/aegisub/context.h"
|
#include "include/aegisub/context.h"
|
||||||
#include "help_button.h"
|
#include "help_button.h"
|
||||||
#include "libresrc/libresrc.h"
|
#include "libresrc/libresrc.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "standard_paths.h"
|
#include "standard_paths.h"
|
||||||
#include "subs_grid.h"
|
|
||||||
#include "timeedit_ctrl.h"
|
#include "timeedit_ctrl.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
|
||||||
// IDs
|
DialogShiftTimes::DialogShiftTimes(agi::Context *context)
|
||||||
enum {
|
: wxDialog(context->parent, -1, _("Shift Times"))
|
||||||
TEXT_SHIFT_TIME = 1100,
|
|
||||||
TEXT_SHIFT_FRAME,
|
|
||||||
RADIO_BACKWARD,
|
|
||||||
RADIO_FORWARD,
|
|
||||||
RADIO_TIME,
|
|
||||||
RADIO_FRAME,
|
|
||||||
SHIFT_CLEAR_HISTORY
|
|
||||||
};
|
|
||||||
|
|
||||||
DialogShiftTimes::DialogShiftTimes (agi::Context *context)
|
|
||||||
: wxDialog(context->parent, -1, _("Shift Times"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE, _T("JumpTo"))
|
|
||||||
, context(context)
|
, context(context)
|
||||||
|
, history_filename(STD_STR(StandardPaths::DecodePath("?user/shift_history.txt")))
|
||||||
|
, timecodes_loaded_slot(context->videoController->AddTimecodesListener(&DialogShiftTimes::OnTimecodesLoaded, this))
|
||||||
{
|
{
|
||||||
// Set icon
|
|
||||||
SetIcon(BitmapToIcon(GETIMAGE(shift_times_toolbutton_24)));
|
SetIcon(BitmapToIcon(GETIMAGE(shift_times_toolbutton_24)));
|
||||||
|
|
||||||
// Set initial values
|
// Create controls
|
||||||
ready = true;
|
shift_by_time = new wxRadioButton(this, -1, _("Time: "), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
|
||||||
shiftframe = 0;
|
shift_by_time->SetToolTip(_("Shift by time"));
|
||||||
|
shift_by_time->Bind(wxEVT_COMMAND_RADIOBUTTON_SELECTED, &DialogShiftTimes::OnByTime, this);
|
||||||
// Static-box sizers before anything else
|
|
||||||
wxSizer *TimesSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Shift by"));
|
|
||||||
wxSizer *HistorySizer = new wxStaticBoxSizer(wxVERTICAL,this,_("History"));
|
|
||||||
|
|
||||||
// Times
|
shift_by_frames = new wxRadioButton(this, -1 , _("Frames: "));
|
||||||
RadioTime = new wxRadioButton(this,RADIO_TIME,_("Time: "),wxDefaultPosition,wxDefaultSize, wxRB_GROUP);
|
shift_by_frames->SetToolTip(_("Shift by frames"));
|
||||||
RadioFrames = new wxRadioButton(this,RADIO_FRAME,_("Frames: "),wxDefaultPosition,wxDefaultSize);
|
shift_by_frames->Bind(wxEVT_COMMAND_RADIOBUTTON_SELECTED, &DialogShiftTimes::OnByFrames, this);
|
||||||
ShiftTime = new TimeEdit(this,TEXT_SHIFT_TIME,_T(""),wxDefaultPosition,wxDefaultSize);
|
|
||||||
ShiftFrame = new wxTextCtrl(this,TEXT_SHIFT_FRAME,wxString::Format(_T("%i"),shiftframe),wxDefaultPosition,wxDefaultSize);
|
|
||||||
ShiftTime->SetToolTip(_("Enter time in h:mm:ss.cs notation"));
|
|
||||||
RadioTime->SetToolTip(_("Shift by time"));
|
|
||||||
ShiftFrame->Disable();
|
|
||||||
if (!context->videoController->TimecodesLoaded()) RadioFrames->Disable();
|
|
||||||
else {
|
|
||||||
ShiftFrame->SetToolTip(_("Enter number of frames to shift by"));
|
|
||||||
RadioFrames->SetToolTip(_("Shift by frames"));
|
|
||||||
}
|
|
||||||
wxSizer *TimeFrameSizer = new wxFlexGridSizer(2,2,5,5);
|
|
||||||
TimeFrameSizer->Add(RadioTime,0,wxALIGN_CENTER_VERTICAL,0);
|
|
||||||
TimeFrameSizer->Add(ShiftTime,1);
|
|
||||||
TimeFrameSizer->Add(RadioFrames,0,wxALIGN_CENTER_VERTICAL,0);
|
|
||||||
TimeFrameSizer->Add(ShiftFrame,1);
|
|
||||||
|
|
||||||
// Direction
|
shift_time = new TimeEdit(this, -1);
|
||||||
DirectionForward = new wxRadioButton(this,-1,_("Forward"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
|
shift_time->SetToolTip(_("Enter time in h:mm:ss.cs notation"));
|
||||||
DirectionBackward = new wxRadioButton(this,-1,_("Backward"), wxDefaultPosition, wxDefaultSize);
|
|
||||||
DirectionForward->SetToolTip(_("Shifts subs forward, making them appear later. Use if they are appearing too soon."));
|
|
||||||
DirectionBackward->SetToolTip(_("Shifts subs backward, making them appear earlier. Use if they are appearing too late."));
|
|
||||||
wxSizer *DirectionSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
DirectionSizer->Add(DirectionForward,1,wxEXPAND,0);
|
|
||||||
DirectionSizer->Add(DirectionBackward,1,wxLEFT | wxEXPAND,5);
|
|
||||||
TimesSizer->Add(TimeFrameSizer,0,wxEXPAND,0);
|
|
||||||
TimesSizer->Add(DirectionSizer,0,wxEXPAND | wxTOP,5);
|
|
||||||
|
|
||||||
// Selection
|
shift_frames = new wxTextCtrl(this, -1);
|
||||||
wxString SelChoices[3] = { _("All rows"), _("Selected rows"), _("Selection onward") };
|
shift_frames->SetToolTip(_("Enter number of frames to shift by"));
|
||||||
SelChoice = new wxRadioBox(this,-1,_("Affect"), wxDefaultPosition, wxDefaultSize, 3, SelChoices, 3, wxRA_SPECIFY_ROWS);
|
|
||||||
|
|
||||||
// Times
|
shift_forward = new wxRadioButton(this, -1, _("Forward"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
|
||||||
wxString TimesChoices[3] = { _("Start and End times"), _("Start times only"), _("End times only") };
|
shift_forward->SetToolTip(_("Shifts subs forward, making them appear later. Use if they are appearing too soon."));
|
||||||
TimesChoice = new wxRadioBox(this,-1,_("Times"), wxDefaultPosition, wxDefaultSize, 3, TimesChoices, 3, wxRA_SPECIFY_ROWS);
|
|
||||||
|
|
||||||
// History
|
shift_backward = new wxRadioButton(this, -1, _("Backward"));
|
||||||
History = new wxListBox(this,-1,wxDefaultPosition,wxSize(350,100), 0, NULL, wxLB_HSCROLL);
|
shift_backward->SetToolTip(_("Shifts subs backward, making them appear earlier. Use if they are appearing too late."));
|
||||||
wxButton *ClearButton = new wxButton(this,SHIFT_CLEAR_HISTORY,_("Clear"));
|
|
||||||
HistorySizer->Add(History,1,wxEXPAND,0);
|
|
||||||
HistorySizer->Add(ClearButton,0,wxEXPAND,0);
|
|
||||||
|
|
||||||
// Buttons
|
wxString selection_mode_vals[] = { _("All rows"), _("Selected rows"), _("Selection onward") };
|
||||||
wxStdDialogButtonSizer *ButtonSizer = new wxStdDialogButtonSizer();
|
selection_mode = new wxRadioBox(this, -1, _("Affect"), wxDefaultPosition, wxDefaultSize, 3, selection_mode_vals, 1);
|
||||||
ButtonSizer->AddButton(new wxButton(this,wxID_OK));
|
|
||||||
ButtonSizer->AddButton(new wxButton(this,wxID_CANCEL));
|
|
||||||
ButtonSizer->AddButton(new HelpButton(this,_T("Shift Times")));
|
|
||||||
ButtonSizer->Realize();
|
|
||||||
|
|
||||||
// General layout
|
wxString time_field_vals[] = { _("Start and End times"), _("Start times only"), _("End times only") };
|
||||||
wxSizer *LeftSizer = new wxBoxSizer(wxVERTICAL);
|
time_fields = new wxRadioBox(this, -1, _("Times"), wxDefaultPosition, wxDefaultSize, 3, time_field_vals, 1);
|
||||||
wxSizer *RightSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
wxSizer *TopSizer = new wxBoxSizer(wxHORIZONTAL);
|
history = new wxListBox(this, -1, wxDefaultPosition, wxSize(350, 100), 0, NULL, wxLB_HSCROLL);
|
||||||
wxSizer *MainSizer = new wxBoxSizer(wxVERTICAL);
|
|
||||||
LeftSizer->Add(TimesSizer,0,wxEXPAND | wxBOTTOM,5);
|
wxButton *clear_button = new wxButton(this, -1, _("Clear"));
|
||||||
LeftSizer->Add(SelChoice,0,wxEXPAND | wxBOTTOM,5);
|
clear_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogShiftTimes::OnClear, this);
|
||||||
LeftSizer->Add(TimesChoice,0,wxEXPAND,5);
|
|
||||||
RightSizer->Add(HistorySizer,0,wxEXPAND,0);
|
// Set initial control states
|
||||||
TopSizer->Add(LeftSizer,0,wxEXPAND | wxRIGHT,5);
|
OnTimecodesLoaded(context->videoController->FPS());
|
||||||
TopSizer->Add(RightSizer,0,wxEXPAND,0);
|
OnSelectedSetChanged(Selection(), Selection());
|
||||||
MainSizer->Add(TopSizer,0,wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT,5);
|
LoadHistory();
|
||||||
MainSizer->Add(ButtonSizer,0,wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT,5);
|
|
||||||
|
shift_time->SetTime(OPT_GET("Tool/Shift Times/Time")->GetInt());
|
||||||
// Set sizer
|
*shift_frames << (int)OPT_GET("Tool/Shift Times/Frames")->GetInt();
|
||||||
SetSizer(MainSizer);
|
shift_frames->Disable();
|
||||||
MainSizer->SetSizeHints(this);
|
shift_by_frames->SetValue(!OPT_GET("Tool/Shift Times/ByTime")->GetBool() && shift_by_frames->IsEnabled());
|
||||||
|
time_fields->SetSelection(OPT_GET("Tool/Shift Times/Type")->GetInt());
|
||||||
|
selection_mode->SetSelection(OPT_GET("Tool/Shift Times/Affect")->GetInt());
|
||||||
|
shift_backward->SetValue(OPT_GET("Tool/Shift Times/Direction")->GetBool());
|
||||||
|
|
||||||
|
// Position controls
|
||||||
|
wxSizer *shift_amount_sizer = new wxFlexGridSizer(2, 2, 5, 5);
|
||||||
|
shift_amount_sizer->Add(shift_by_time, wxSizerFlags(0).Align(wxALIGN_CENTER_VERTICAL));
|
||||||
|
shift_amount_sizer->Add(shift_time, wxSizerFlags(1));
|
||||||
|
shift_amount_sizer->Add(shift_by_frames, wxSizerFlags(0).Align(wxALIGN_CENTER_VERTICAL));
|
||||||
|
shift_amount_sizer->Add(shift_frames, wxSizerFlags(1));
|
||||||
|
|
||||||
|
wxSizer *shift_direction_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
shift_direction_sizer->Add(shift_forward, wxSizerFlags(1).Expand());
|
||||||
|
shift_direction_sizer->Add(shift_backward, wxSizerFlags(1).Expand().Border(wxLEFT));
|
||||||
|
|
||||||
|
wxSizer *shift_by_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Shift by"));
|
||||||
|
shift_by_sizer->Add(shift_amount_sizer, wxSizerFlags().Expand());
|
||||||
|
shift_by_sizer->Add(shift_direction_sizer, wxSizerFlags().Expand().Border(wxTOP));
|
||||||
|
|
||||||
|
wxSizer *left_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
left_sizer->Add(shift_by_sizer, wxSizerFlags().Expand().Border(wxBOTTOM));
|
||||||
|
left_sizer->Add(selection_mode, wxSizerFlags().Expand().Border(wxBOTTOM));
|
||||||
|
left_sizer->Add(time_fields, wxSizerFlags().Expand());
|
||||||
|
|
||||||
|
wxSizer *history_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("History"));
|
||||||
|
history_sizer->Add(history, wxSizerFlags(1).Expand());
|
||||||
|
history_sizer->Add(clear_button, wxSizerFlags().Expand().Border(wxTOP));
|
||||||
|
|
||||||
|
wxSizer *top_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
|
top_sizer->Add(left_sizer, wxSizerFlags().Border(wxALL & ~wxRIGHT).Expand());
|
||||||
|
top_sizer->Add(history_sizer, wxSizerFlags().Border().Expand());
|
||||||
|
|
||||||
|
wxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||||
|
main_sizer->Add(top_sizer, wxSizerFlags().Border(wxALL & ~wxBOTTOM));
|
||||||
|
main_sizer->Add(CreateButtonSizer(wxOK | wxCANCEL | wxHELP), wxSizerFlags().Right().Border());
|
||||||
|
SetSizerAndFit(main_sizer);
|
||||||
CenterOnParent();
|
CenterOnParent();
|
||||||
|
|
||||||
// Load values from options
|
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogShiftTimes::Process, this, wxID_OK);
|
||||||
if (!OPT_GET("Tool/Shift Times/ByTime")->GetBool()) {
|
Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogShiftTimes::OnClose, this, wxID_CANCEL);
|
||||||
if (RadioFrames->IsEnabled()) {
|
Bind(wxEVT_COMMAND_BUTTON_CLICKED, std::tr1::bind(&HelpButton::OpenPage, "Shift Times"), wxID_HELP);
|
||||||
RadioFrames->SetValue(true);
|
context->selectionController->AddSelectionListener(this);
|
||||||
ShiftFrame->Enable(true);
|
}
|
||||||
ShiftTime->Enable(false);
|
|
||||||
ShiftFrame->SetValue(AegiIntegerToString(OPT_GET("Tool/Shift Times/Length")->GetInt()));
|
DialogShiftTimes::~DialogShiftTimes() {
|
||||||
}
|
context->selectionController->RemoveSelectionListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogShiftTimes::OnTimecodesLoaded(agi::vfr::Framerate const& new_fps) {
|
||||||
|
fps = new_fps;
|
||||||
|
if (fps.IsLoaded()) {
|
||||||
|
shift_by_frames->Enable();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ShiftTime->SetTime(OPT_GET("Tool/Shift Times/Length")->GetInt());
|
shift_by_time->SetValue(true);
|
||||||
|
shift_by_frames->Disable();
|
||||||
|
shift_time->Enable();
|
||||||
|
shift_frames->Disable();
|
||||||
}
|
}
|
||||||
TimesChoice->SetSelection(OPT_GET("Tool/Shift Times/Type")->GetInt());
|
}
|
||||||
SelChoice->SetSelection(OPT_GET("Tool/Shift Times/Affect")->GetInt());
|
|
||||||
if (OPT_GET("Tool/Shift Times/Direction")->GetBool()) DirectionBackward->SetValue(true);
|
|
||||||
|
|
||||||
// Has selection?
|
void DialogShiftTimes::OnSelectedSetChanged(Selection const&, Selection const&) {
|
||||||
wxArrayInt sel = context->subsGrid->GetSelection();
|
if (context->selectionController->GetSelectedSet().empty()) {
|
||||||
if (sel.Count() == 0) {
|
selection_mode->Enable(1, false);
|
||||||
SelChoice->Enable(1,false);
|
selection_mode->Enable(2, false);
|
||||||
SelChoice->Enable(2,false);
|
selection_mode->SetSelection(0);
|
||||||
SelChoice->SetSelection(0);
|
}
|
||||||
|
else {
|
||||||
|
selection_mode->Enable(1, true);
|
||||||
|
selection_mode->Enable(2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load history
|
|
||||||
LoadHistory(StandardPaths::DecodePath(_T("?user/shift_history.txt")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
void DialogShiftTimes::OnClear(wxCommandEvent &) {
|
||||||
// Event table
|
wxRemoveFile(lagi_wxString(history_filename));
|
||||||
BEGIN_EVENT_TABLE(DialogShiftTimes, wxDialog)
|
history->Clear();
|
||||||
EVT_BUTTON(wxID_CANCEL,DialogShiftTimes::OnClose)
|
|
||||||
EVT_BUTTON(wxID_OK,DialogShiftTimes::OnOK)
|
|
||||||
EVT_BUTTON(SHIFT_CLEAR_HISTORY,DialogShiftTimes::OnClear)
|
|
||||||
EVT_RADIOBUTTON(RADIO_TIME,DialogShiftTimes::OnRadioTime)
|
|
||||||
EVT_RADIOBUTTON(RADIO_FRAME,DialogShiftTimes::OnRadioFrame)
|
|
||||||
END_EVENT_TABLE()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Clear History
|
|
||||||
/// @param event
|
|
||||||
///
|
|
||||||
void DialogShiftTimes::OnClear(wxCommandEvent &event) {
|
|
||||||
wxRemoveFile(StandardPaths::DecodePath(_T("?user/shift_history.txt")));
|
|
||||||
History->Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogShiftTimes::OnClose(wxCommandEvent &) {
|
||||||
|
long shift;
|
||||||
|
shift_frames->GetValue().ToLong(&shift);
|
||||||
|
|
||||||
/// @brief Cancel
|
OPT_SET("Tool/Shift Times/Time")->SetInt(shift_time->time.GetMS());
|
||||||
/// @param event
|
OPT_SET("Tool/Shift Times/Frames")->SetInt(shift);
|
||||||
///
|
OPT_SET("Tool/Shift Times/ByTime")->SetBool(shift_by_time->GetValue());
|
||||||
void DialogShiftTimes::OnClose(wxCommandEvent &event) {
|
OPT_SET("Tool/Shift Times/Type")->SetInt(time_fields->GetSelection());
|
||||||
EndModal(0);
|
OPT_SET("Tool/Shift Times/Affect")->SetInt(selection_mode->GetSelection());
|
||||||
|
OPT_SET("Tool/Shift Times/Direction")->SetBool(shift_backward->GetValue());
|
||||||
|
|
||||||
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogShiftTimes::OnByTime(wxCommandEvent &) {
|
||||||
|
shift_time->Enable(true);
|
||||||
|
shift_frames->Enable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogShiftTimes::OnByFrames(wxCommandEvent &) {
|
||||||
|
shift_time->Enable(false);
|
||||||
|
shift_frames->Enable(true);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Apply
|
void DialogShiftTimes::SaveHistory(std::vector<std::pair<int, int> > const& shifted_blocks) {
|
||||||
/// @param event
|
wxString filename = wxFileName(context->ass->filename).GetFullName();
|
||||||
/// @return
|
int fields = time_fields->GetSelection();
|
||||||
///
|
|
||||||
void DialogShiftTimes::OnOK(wxCommandEvent &event) {
|
|
||||||
// General values
|
|
||||||
int type = TimesChoice->GetSelection();
|
|
||||||
int affect = SelChoice->GetSelection();
|
|
||||||
bool allrows = affect == 0;
|
|
||||||
bool selOnward = affect == 2;
|
|
||||||
long len;
|
|
||||||
bool byTime = RadioTime->GetValue();
|
|
||||||
bool backward = DirectionBackward->GetValue();
|
|
||||||
bool didSomething = false;
|
|
||||||
|
|
||||||
// Selection
|
wxString new_line = wxString::Format("%s, %s %s, %s, ",
|
||||||
int nrows = context->subsGrid->GetRows();
|
filename.empty() ? _("unsaved") : filename,
|
||||||
wxArrayInt sel = context->subsGrid->GetSelection();
|
shift_by_time->GetValue() ? shift_time->GetValue() : shift_frames->GetValue() + _(" frames"),
|
||||||
int firstSel = 0;
|
shift_backward->GetValue() ? _("backward") : _("forward"),
|
||||||
if (sel.Count()) firstSel = sel[0];
|
fields == 0 ? _("s+e") : fields == 1 ? _("s") : _("e"));
|
||||||
|
|
||||||
// Get length
|
int sel_mode = selection_mode->GetSelection();
|
||||||
if (byTime) len = ShiftTime->time.GetMS();
|
if (sel_mode == 0)
|
||||||
else ShiftFrame->GetValue().ToLong(&len);
|
new_line += _("all");
|
||||||
|
else if (sel_mode == 2)
|
||||||
if (byTime && len == 0) {
|
new_line += wxString::Format(_("from %d onward"), shifted_blocks.front().first);
|
||||||
// Shift zero milliseconds in time mode
|
else {
|
||||||
// Equivalent to doing nothing at all, so just dismiss
|
new_line += _("sel ");
|
||||||
EndModal(0);
|
for (size_t i = 0; i < shifted_blocks.size(); ++i) {
|
||||||
return;
|
std::pair<int, int> const& b = shifted_blocks[i];
|
||||||
}
|
wxString term = i == shifted_blocks.size() - 1 ? "" : ";";
|
||||||
|
if (b.first == b.second)
|
||||||
// If backwards, invert
|
new_line += wxString::Format("%d%s", b.first, term);
|
||||||
if (backward) len = -len;
|
else
|
||||||
|
new_line += wxString::Format("%d-%d%s", b.first, b.second, term);
|
||||||
// Shift
|
|
||||||
for (int i=0;i<nrows;i++) {
|
|
||||||
if (allrows || (i >= firstSel && selOnward) || context->subsGrid->IsInSelection(i)) {
|
|
||||||
if (byTime) context->subsGrid->ShiftLineByTime(i,len,type);
|
|
||||||
else context->subsGrid->ShiftLineByFrames(i,len,type);
|
|
||||||
didSomething = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add entry to history
|
try {
|
||||||
if (didSomething) {
|
agi::io::Save file(history_filename);
|
||||||
if (backward) len = -len;
|
|
||||||
wxString message;
|
|
||||||
wxFileName assfile(context->ass->filename);
|
|
||||||
wxString filename = assfile.GetFullName();
|
|
||||||
|
|
||||||
// File
|
for (size_t i = 0; i < history->GetCount(); ++i)
|
||||||
if (filename.IsEmpty()) message << _("unsaved, ");
|
file.Get() << history->GetString(i).utf8_str() << std::endl;
|
||||||
else message << filename << _T(", ");
|
file.Get() << new_line.utf8_str() << std::endl;
|
||||||
|
}
|
||||||
|
catch (agi::acs::AcsError const& e) {
|
||||||
|
LOG_E("dialog_shift_times/save_history") << "Cannot save shift times history: " << e.GetChainedMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Time/frames
|
void DialogShiftTimes::LoadHistory() {
|
||||||
if (byTime) message << ShiftTime->GetValue() << _T(" ");
|
history->Clear();
|
||||||
else message << len << _(" frames ");
|
history->Freeze();
|
||||||
|
|
||||||
// Forward/backwards
|
try {
|
||||||
if (backward) message << _("backward, ");
|
agi::scoped_ptr<std::istream> file(agi::io::Open(history_filename));
|
||||||
else message << _("forward, ");
|
std::string buffer;
|
||||||
|
while(!file->eof()) {
|
||||||
|
getline(*file, buffer);
|
||||||
|
if (buffer.size())
|
||||||
|
history->Insert(lagi_wxString(buffer), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (agi::acs::AcsError const& e) {
|
||||||
|
LOG_E("dialog_shift_times/save_history") << "Cannot load shift times history: " << e.GetChainedMessage();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
history->Thaw();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
// Start/end
|
history->Thaw();
|
||||||
if (type == 0) message << _("s+e, ");
|
}
|
||||||
if (type == 1) message << _("s, ");
|
|
||||||
if (type == 2) message << _("e, ");
|
|
||||||
|
|
||||||
// Selection range
|
void DialogShiftTimes::Process(wxCommandEvent &) {
|
||||||
if (affect == 0) message << _("all");
|
int mode = selection_mode->GetSelection();
|
||||||
else if (affect == 2) message << wxString::Format(_("from %i onward"),sel[0]+1);
|
int type = time_fields->GetSelection();
|
||||||
else { // This huge block of code prints the selected ranges of subs
|
bool reverse = shift_backward->GetValue();
|
||||||
message << _("sel ");
|
bool by_time = shift_by_time->GetValue();
|
||||||
int last = sel[0]-1;
|
|
||||||
int first = sel[0];
|
bool start = type != 2;
|
||||||
for (unsigned int i=0;i<sel.Count();i++) {
|
bool end = type != 1;
|
||||||
if (sel[i] != last+1) {
|
|
||||||
if (first != last) message << wxString::Format(_T("%i"),first+1) << _T("-") << wxString::Format(_T("%i"),last+1) << _T(";");
|
Selection sel = context->selectionController->GetSelectedSet();
|
||||||
else message << wxString::Format(_T("%i"),first+1) << _T(";");
|
|
||||||
first = sel[i];
|
long shift;
|
||||||
}
|
if (by_time) {
|
||||||
last = sel[i];
|
shift = shift_time->time.GetMS();
|
||||||
|
if (shift == 0) {
|
||||||
|
Close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
shift_frames->GetValue().ToLong(&shift);
|
||||||
|
|
||||||
|
if (reverse)
|
||||||
|
shift = -shift;
|
||||||
|
|
||||||
|
// Track which rows were shifted for the log
|
||||||
|
int row_number = 0;
|
||||||
|
int block_start = 0;
|
||||||
|
std::vector<std::pair<int, int> > shifted_blocks;
|
||||||
|
|
||||||
|
for (entryIter it = context->ass->Line.begin(); it != context->ass->Line.end(); ++it) {
|
||||||
|
AssDialogue *line = dynamic_cast<AssDialogue*>(*it);
|
||||||
|
if (!line) continue;
|
||||||
|
++row_number;
|
||||||
|
|
||||||
|
if (!sel.count(line)) {
|
||||||
|
if (block_start) {
|
||||||
|
shifted_blocks.push_back(std::make_pair(block_start, row_number - 1));
|
||||||
|
block_start = 0;
|
||||||
}
|
}
|
||||||
if (first != last) message << wxString::Format(_T("%i"),first+1) << _T("-") << wxString::Format(_T("%i"),last+1);
|
if (mode == 1) continue;
|
||||||
else message << wxString::Format(_T("%i"),first+1);
|
if (mode == 2 && shifted_blocks.empty()) continue;
|
||||||
}
|
}
|
||||||
|
else if (!block_start)
|
||||||
|
block_start = row_number;
|
||||||
|
|
||||||
// Done, append
|
if (start)
|
||||||
AppendToHistory(message);
|
line->Start.SetMS(Shift(line->Start.GetMS(), shift, by_time, agi::vfr::START));
|
||||||
|
if (end)
|
||||||
|
line->End.SetMS(Shift(line->End.GetMS(), shift, by_time, agi::vfr::END));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store modifications
|
|
||||||
OPT_SET("Tool/Shift Times/ByTime")->SetBool(byTime);
|
|
||||||
OPT_SET("Tool/Shift Times/Type")->SetInt(type);
|
|
||||||
OPT_SET("Tool/Shift Times/Length")->SetInt(len);
|
|
||||||
OPT_SET("Tool/Shift Times/Affect")->SetInt(affect);
|
|
||||||
OPT_SET("Tool/Shift Times/Direction")->SetBool(backward);
|
|
||||||
|
|
||||||
// End dialog
|
|
||||||
context->ass->Commit(_("shifting"), AssFile::COMMIT_DIAG_TIME);
|
context->ass->Commit(_("shifting"), AssFile::COMMIT_DIAG_TIME);
|
||||||
EndModal(0);
|
|
||||||
|
if (block_start)
|
||||||
|
shifted_blocks.push_back(std::make_pair(block_start, row_number - 1));
|
||||||
|
|
||||||
|
SaveHistory(shifted_blocks);
|
||||||
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DialogShiftTimes::Shift(int initial_time, int shift, bool by_time, agi::vfr::Time type) {
|
||||||
|
if (by_time)
|
||||||
/// @brief Set to time
|
return initial_time + shift;
|
||||||
/// @param event
|
else
|
||||||
///
|
return fps.TimeAtFrame(shift + fps.FrameAtTime(initial_time, type), type);
|
||||||
void DialogShiftTimes::OnRadioTime(wxCommandEvent &event) {
|
|
||||||
ShiftTime->Enable(true);
|
|
||||||
ShiftFrame->Enable(false);
|
|
||||||
event.Skip();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Set to frame
|
|
||||||
/// @param event
|
|
||||||
///
|
|
||||||
void DialogShiftTimes::OnRadioFrame(wxCommandEvent &event) {
|
|
||||||
ShiftTime->Enable(false);
|
|
||||||
ShiftFrame->Enable(true);
|
|
||||||
event.Skip();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Appends a line to history
|
|
||||||
/// @param text
|
|
||||||
/// @return
|
|
||||||
///
|
|
||||||
void DialogShiftTimes::AppendToHistory(wxString text) {
|
|
||||||
// Open file
|
|
||||||
if (HistoryFile.IsEmpty()) return;
|
|
||||||
using namespace std;
|
|
||||||
ofstream file;
|
|
||||||
file.open(HistoryFile.mb_str(csConvLocal),ios::out | ios::app);
|
|
||||||
if (!file.is_open()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert line
|
|
||||||
file << text.mb_str(wxConvUTF8) << endl;
|
|
||||||
|
|
||||||
// Close
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Loads history from disk
|
|
||||||
/// @param filename
|
|
||||||
///
|
|
||||||
void DialogShiftTimes::LoadHistory(wxString filename) {
|
|
||||||
// Open file
|
|
||||||
using namespace std;
|
|
||||||
HistoryFile = filename;
|
|
||||||
ifstream file;
|
|
||||||
file.open(filename.mb_str(csConvLocal));
|
|
||||||
if (!file.is_open()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup
|
|
||||||
string buffer;
|
|
||||||
History->Clear();
|
|
||||||
History->Freeze();
|
|
||||||
|
|
||||||
// Get lines
|
|
||||||
while (!file.eof()) {
|
|
||||||
getline(file,buffer);
|
|
||||||
wxString curLine(buffer.c_str(),wxConvUTF8);
|
|
||||||
if (curLine != _T("")) History->Insert(curLine,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finish updating
|
|
||||||
History->Thaw();
|
|
||||||
//History->SetFirstItem(History->GetCount()-1);
|
|
||||||
|
|
||||||
// Close
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,16 @@
|
||||||
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
// Copyright (c) 2011, Thomas Goyne <plorkyeran@aegisub.org>
|
||||||
// All rights reserved.
|
|
||||||
//
|
//
|
||||||
// Redistribution and use in source and binary forms, with or without
|
// Permission to use, copy, modify, and distribute this software for any
|
||||||
// modification, are permitted provided that the following conditions are met:
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
|
// copyright notice and this permission notice appear in all copies.
|
||||||
//
|
//
|
||||||
// * Redistributions of source code must retain the above copyright notice,
|
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
// this list of conditions and the following disclaimer.
|
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
// this list of conditions and the following disclaimer in the documentation
|
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
// and/or other materials provided with the distribution.
|
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
// * Neither the name of the Aegisub Group nor the names of its contributors
|
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
// may be used to endorse or promote products derived from this software
|
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 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 Project http://www.aegisub.org/
|
// Aegisub Project http://www.aegisub.org/
|
||||||
//
|
//
|
||||||
|
@ -38,71 +25,56 @@
|
||||||
#include <wx/dialog.h>
|
#include <wx/dialog.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace agi { struct Context; }
|
#include <libaegisub/signal.h>
|
||||||
|
#include <libaegisub/vfr.h>
|
||||||
|
|
||||||
|
#include "selection_controller.h"
|
||||||
|
|
||||||
|
class AssDialogue;
|
||||||
class TimeEdit;
|
class TimeEdit;
|
||||||
class wxListBox;
|
class wxListBox;
|
||||||
class wxRadioBox;
|
class wxRadioBox;
|
||||||
class wxRadioButton;
|
class wxRadioButton;
|
||||||
class wxTextCtrl;
|
class wxTextCtrl;
|
||||||
|
namespace agi { struct Context; }
|
||||||
|
|
||||||
/// DOCME
|
/// DOCME
|
||||||
/// @class DialogShiftTimes
|
/// @class DialogShiftTimes
|
||||||
/// @brief DOCME
|
/// @brief DOCME
|
||||||
///
|
///
|
||||||
/// DOCME
|
/// DOCME
|
||||||
class DialogShiftTimes : public wxDialog {
|
class DialogShiftTimes : public wxDialog, private SelectionListener<AssDialogue> {
|
||||||
agi::Context *context;
|
agi::Context *context;
|
||||||
|
|
||||||
/// DOCME
|
std::string history_filename;
|
||||||
bool ready;
|
agi::vfr::Framerate fps;
|
||||||
|
agi::signal::Connection timecodes_loaded_slot;
|
||||||
|
|
||||||
/// DOCME
|
TimeEdit *shift_time;
|
||||||
int shiftframe;
|
wxTextCtrl *shift_frames;
|
||||||
|
wxRadioButton *shift_by_time;
|
||||||
|
wxRadioButton *shift_by_frames;
|
||||||
|
wxRadioButton *shift_forward;
|
||||||
|
wxRadioButton *shift_backward;
|
||||||
|
wxRadioBox *selection_mode;
|
||||||
|
wxRadioBox *time_fields;
|
||||||
|
wxListBox *history;
|
||||||
|
|
||||||
/// DOCME
|
void SaveHistory(std::vector<std::pair<int, int> > const& shifted_blocks);
|
||||||
wxString HistoryFile;
|
void LoadHistory();
|
||||||
|
void Process(wxCommandEvent&);
|
||||||
|
int Shift(int initial_time, int shift, bool by_time, agi::vfr::Time type);
|
||||||
|
|
||||||
|
void OnClear(wxCommandEvent&);
|
||||||
|
void OnClose(wxCommandEvent&);
|
||||||
|
void OnByTime(wxCommandEvent&);
|
||||||
|
void OnByFrames(wxCommandEvent&);
|
||||||
|
|
||||||
/// DOCME
|
void OnActiveLineChanged(AssDialogue*) { }
|
||||||
TimeEdit *ShiftTime;
|
void OnSelectedSetChanged(Selection const&, Selection const&);
|
||||||
|
void OnTimecodesLoaded(agi::vfr::Framerate const& new_fps);
|
||||||
/// DOCME
|
|
||||||
wxTextCtrl *ShiftFrame;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxRadioButton *RadioTime;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxRadioButton *RadioFrames;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxRadioButton *DirectionForward;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxRadioButton *DirectionBackward;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxRadioBox *SelChoice;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxRadioBox *TimesChoice;
|
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
wxListBox *History;
|
|
||||||
|
|
||||||
void AppendToHistory(wxString text);
|
|
||||||
void LoadHistory(wxString filename);
|
|
||||||
void OnClear(wxCommandEvent &event);
|
|
||||||
void OnKey(wxKeyEvent &event);
|
|
||||||
void OnClose(wxCommandEvent &event);
|
|
||||||
void OnOK(wxCommandEvent &event);
|
|
||||||
void OnEditTime(wxCommandEvent &event);
|
|
||||||
void OnEditFrame(wxCommandEvent &event);
|
|
||||||
void OnRadioTime(wxCommandEvent &event);
|
|
||||||
void OnRadioFrame(wxCommandEvent &event);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DialogShiftTimes (agi::Context *context);
|
DialogShiftTimes(agi::Context *context);
|
||||||
|
~DialogShiftTimes();
|
||||||
DECLARE_EVENT_TABLE()
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -338,7 +338,8 @@
|
||||||
"Affect" : 0,
|
"Affect" : 0,
|
||||||
"ByTime" : true,
|
"ByTime" : true,
|
||||||
"Direction" : true,
|
"Direction" : true,
|
||||||
"Length" : 0,
|
"Frames" : 0,
|
||||||
|
"Time" : 0,
|
||||||
"Type" : 0
|
"Type" : 0
|
||||||
},
|
},
|
||||||
"Spell Checker" : {
|
"Spell Checker" : {
|
||||||
|
|
|
@ -496,22 +496,6 @@ void SubtitlesGrid::DuplicateLines(int n1,int n2,bool nextFrame) {
|
||||||
SetActiveLine(GetDialogue(n1+step));
|
SetActiveLine(GetDialogue(n1+step));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubtitlesGrid::ShiftLineByTime(int n,int len,int type) {
|
|
||||||
assert(type >= 0 && type <= 2);
|
|
||||||
AssDialogue *cur = GetDialogue(n);
|
|
||||||
|
|
||||||
if (type != 2) cur->Start.SetMS(cur->Start.GetMS() + len);
|
|
||||||
if (type != 1) cur->End.SetMS(cur->End.GetMS() + len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SubtitlesGrid::ShiftLineByFrames(int n,int len,int type) {
|
|
||||||
assert(type >= 0 && type <= 2);
|
|
||||||
AssDialogue *cur = GetDialogue(n);
|
|
||||||
|
|
||||||
if (type != 2) cur->Start.SetMS(context->videoController->TimeAtFrame(len + context->videoController->FrameAtTime(cur->Start.GetMS(),agi::vfr::START),agi::vfr::START));
|
|
||||||
if (type != 1) cur->End.SetMS(context->videoController->TimeAtFrame(len + context->videoController->FrameAtTime(cur->End.GetMS(),agi::vfr::END),agi::vfr::END));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SubtitlesGrid::SplitLine(AssDialogue *n1,int pos,bool estimateTimes) {
|
void SubtitlesGrid::SplitLine(AssDialogue *n1,int pos,bool estimateTimes) {
|
||||||
AssDialogue *n2 = new AssDialogue(*n1);
|
AssDialogue *n2 = new AssDialogue(*n1);
|
||||||
InsertLine(n2,GetDialogueIndex(n1),true,false);
|
InsertLine(n2,GetDialogueIndex(n1),true,false);
|
||||||
|
|
|
@ -102,17 +102,6 @@ public:
|
||||||
/// @param nextFrame Set the new lines to start and end on the next frame
|
/// @param nextFrame Set the new lines to start and end on the next frame
|
||||||
void DuplicateLines(int first,int last,bool nextFrame=false);
|
void DuplicateLines(int first,int last,bool nextFrame=false);
|
||||||
|
|
||||||
/// @brief Shift line by time
|
|
||||||
/// @param n Line to shift
|
|
||||||
/// @param len ms to shift by
|
|
||||||
/// @param type 0: Start + End; 1: Start; 2: End
|
|
||||||
void ShiftLineByTime(int lineNumber,int len,int type);
|
|
||||||
/// @brief Shift line by frames
|
|
||||||
/// @param n Line to shift
|
|
||||||
/// @param len frames to shift by
|
|
||||||
/// @param type 0: Start + End; 1: Start; 2: End
|
|
||||||
void ShiftLineByFrames(int lineNumber,int len,int type);
|
|
||||||
|
|
||||||
void InsertLine(AssDialogue *line,int position,bool insertAfter,bool update=true);
|
void InsertLine(AssDialogue *line,int position,bool insertAfter,bool update=true);
|
||||||
/// @brief Delete selected lines
|
/// @brief Delete selected lines
|
||||||
/// @param target Lines to delete
|
/// @param target Lines to delete
|
||||||
|
|
Loading…
Reference in New Issue