forked from mia/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
6 changed files with 302 additions and 422 deletions
|
@ -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
|
shift_by_frames = new wxRadioButton(this, -1 , _("Frames: "));
|
||||||
wxSizer *TimesSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Shift by"));
|
shift_by_frames->SetToolTip(_("Shift by frames"));
|
||||||
wxSizer *HistorySizer = new wxStaticBoxSizer(wxVERTICAL,this,_("History"));
|
shift_by_frames->Bind(wxEVT_COMMAND_RADIOBUTTON_SELECTED, &DialogShiftTimes::OnByFrames, this);
|
||||||
|
|
||||||
// Times
|
shift_time = new TimeEdit(this, -1);
|
||||||
RadioTime = new wxRadioButton(this,RADIO_TIME,_("Time: "),wxDefaultPosition,wxDefaultSize, wxRB_GROUP);
|
shift_time->SetToolTip(_("Enter time in h:mm:ss.cs notation"));
|
||||||
RadioFrames = new wxRadioButton(this,RADIO_FRAME,_("Frames: "),wxDefaultPosition,wxDefaultSize);
|
|
||||||
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_frames = new wxTextCtrl(this, -1);
|
||||||
DirectionForward = new wxRadioButton(this,-1,_("Forward"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
|
shift_frames->SetToolTip(_("Enter number of frames to shift by"));
|
||||||
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_forward = new wxRadioButton(this, -1, _("Forward"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
|
||||||
wxString SelChoices[3] = { _("All rows"), _("Selected rows"), _("Selection onward") };
|
shift_forward->SetToolTip(_("Shifts subs forward, making them appear later. Use if they are appearing too soon."));
|
||||||
SelChoice = new wxRadioBox(this,-1,_("Affect"), wxDefaultPosition, wxDefaultSize, 3, SelChoices, 3, wxRA_SPECIFY_ROWS);
|
|
||||||
|
|
||||||
// Times
|
shift_backward = new wxRadioButton(this, -1, _("Backward"));
|
||||||
wxString TimesChoices[3] = { _("Start and End times"), _("Start times only"), _("End times only") };
|
shift_backward->SetToolTip(_("Shifts subs backward, making them appear earlier. Use if they are appearing too late."));
|
||||||
TimesChoice = new wxRadioBox(this,-1,_("Times"), wxDefaultPosition, wxDefaultSize, 3, TimesChoices, 3, wxRA_SPECIFY_ROWS);
|
|
||||||
|
|
||||||
// History
|
wxString selection_mode_vals[] = { _("All rows"), _("Selected rows"), _("Selection onward") };
|
||||||
History = new wxListBox(this,-1,wxDefaultPosition,wxSize(350,100), 0, NULL, wxLB_HSCROLL);
|
selection_mode = new wxRadioBox(this, -1, _("Affect"), wxDefaultPosition, wxDefaultSize, 3, selection_mode_vals, 1);
|
||||||
wxButton *ClearButton = new wxButton(this,SHIFT_CLEAR_HISTORY,_("Clear"));
|
|
||||||
HistorySizer->Add(History,1,wxEXPAND,0);
|
|
||||||
HistorySizer->Add(ClearButton,0,wxEXPAND,0);
|
|
||||||
|
|
||||||
// Buttons
|
wxString time_field_vals[] = { _("Start and End times"), _("Start times only"), _("End times only") };
|
||||||
wxStdDialogButtonSizer *ButtonSizer = new wxStdDialogButtonSizer();
|
time_fields = new wxRadioBox(this, -1, _("Times"), wxDefaultPosition, wxDefaultSize, 3, time_field_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
|
history = new wxListBox(this, -1, wxDefaultPosition, wxSize(350, 100), 0, NULL, wxLB_HSCROLL);
|
||||||
wxSizer *LeftSizer = new wxBoxSizer(wxVERTICAL);
|
|
||||||
wxSizer *RightSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
wxSizer *TopSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
||||||
wxSizer *MainSizer = new wxBoxSizer(wxVERTICAL);
|
|
||||||
LeftSizer->Add(TimesSizer,0,wxEXPAND | wxBOTTOM,5);
|
|
||||||
LeftSizer->Add(SelChoice,0,wxEXPAND | wxBOTTOM,5);
|
|
||||||
LeftSizer->Add(TimesChoice,0,wxEXPAND,5);
|
|
||||||
RightSizer->Add(HistorySizer,0,wxEXPAND,0);
|
|
||||||
TopSizer->Add(LeftSizer,0,wxEXPAND | wxRIGHT,5);
|
|
||||||
TopSizer->Add(RightSizer,0,wxEXPAND,0);
|
|
||||||
MainSizer->Add(TopSizer,0,wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT,5);
|
|
||||||
MainSizer->Add(ButtonSizer,0,wxEXPAND | wxLEFT | wxBOTTOM | wxRIGHT,5);
|
|
||||||
|
|
||||||
// Set sizer
|
wxButton *clear_button = new wxButton(this, -1, _("Clear"));
|
||||||
SetSizer(MainSizer);
|
clear_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &DialogShiftTimes::OnClear, this);
|
||||||
MainSizer->SetSizeHints(this);
|
|
||||||
|
// Set initial control states
|
||||||
|
OnTimecodesLoaded(context->videoController->FPS());
|
||||||
|
OnSelectedSetChanged(Selection(), Selection());
|
||||||
|
LoadHistory();
|
||||||
|
|
||||||
|
shift_time->SetTime(OPT_GET("Tool/Shift Times/Time")->GetInt());
|
||||||
|
*shift_frames << (int)OPT_GET("Tool/Shift Times/Frames")->GetInt();
|
||||||
|
shift_frames->Disable();
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DialogShiftTimes::OnClear(wxCommandEvent &) {
|
||||||
|
wxRemoveFile(lagi_wxString(history_filename));
|
||||||
|
history->Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogShiftTimes::OnClose(wxCommandEvent &) {
|
||||||
|
long shift;
|
||||||
|
shift_frames->GetValue().ToLong(&shift);
|
||||||
|
|
||||||
|
OPT_SET("Tool/Shift Times/Time")->SetInt(shift_time->time.GetMS());
|
||||||
|
OPT_SET("Tool/Shift Times/Frames")->SetInt(shift);
|
||||||
|
OPT_SET("Tool/Shift Times/ByTime")->SetBool(shift_by_time->GetValue());
|
||||||
|
OPT_SET("Tool/Shift Times/Type")->SetInt(time_fields->GetSelection());
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DialogShiftTimes::SaveHistory(std::vector<std::pair<int, int> > const& shifted_blocks) {
|
||||||
|
wxString filename = wxFileName(context->ass->filename).GetFullName();
|
||||||
|
int fields = time_fields->GetSelection();
|
||||||
|
|
||||||
|
wxString new_line = wxString::Format("%s, %s %s, %s, ",
|
||||||
|
filename.empty() ? _("unsaved") : filename,
|
||||||
|
shift_by_time->GetValue() ? shift_time->GetValue() : shift_frames->GetValue() + _(" frames"),
|
||||||
|
shift_backward->GetValue() ? _("backward") : _("forward"),
|
||||||
|
fields == 0 ? _("s+e") : fields == 1 ? _("s") : _("e"));
|
||||||
|
|
||||||
|
int sel_mode = selection_mode->GetSelection();
|
||||||
|
if (sel_mode == 0)
|
||||||
|
new_line += _("all");
|
||||||
|
else if (sel_mode == 2)
|
||||||
|
new_line += wxString::Format(_("from %d onward"), shifted_blocks.front().first);
|
||||||
|
else {
|
||||||
|
new_line += _("sel ");
|
||||||
|
for (size_t i = 0; i < shifted_blocks.size(); ++i) {
|
||||||
|
std::pair<int, int> const& b = shifted_blocks[i];
|
||||||
|
wxString term = i == shifted_blocks.size() - 1 ? "" : ";";
|
||||||
|
if (b.first == b.second)
|
||||||
|
new_line += wxString::Format("%d%s", b.first, term);
|
||||||
|
else
|
||||||
|
new_line += wxString::Format("%d-%d%s", b.first, b.second, term);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load history
|
try {
|
||||||
LoadHistory(StandardPaths::DecodePath(_T("?user/shift_history.txt")));
|
agi::io::Save file(history_filename);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < history->GetCount(); ++i)
|
||||||
|
file.Get() << history->GetString(i).utf8_str() << std::endl;
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogShiftTimes::LoadHistory() {
|
||||||
|
history->Clear();
|
||||||
|
history->Freeze();
|
||||||
|
|
||||||
///////////////
|
try {
|
||||||
// Event table
|
agi::scoped_ptr<std::istream> file(agi::io::Open(history_filename));
|
||||||
BEGIN_EVENT_TABLE(DialogShiftTimes, wxDialog)
|
std::string buffer;
|
||||||
EVT_BUTTON(wxID_CANCEL,DialogShiftTimes::OnClose)
|
while(!file->eof()) {
|
||||||
EVT_BUTTON(wxID_OK,DialogShiftTimes::OnOK)
|
getline(*file, buffer);
|
||||||
EVT_BUTTON(SHIFT_CLEAR_HISTORY,DialogShiftTimes::OnClear)
|
if (buffer.size())
|
||||||
EVT_RADIOBUTTON(RADIO_TIME,DialogShiftTimes::OnRadioTime)
|
history->Insert(lagi_wxString(buffer), 0);
|
||||||
EVT_RADIOBUTTON(RADIO_FRAME,DialogShiftTimes::OnRadioFrame)
|
}
|
||||||
END_EVENT_TABLE()
|
}
|
||||||
|
catch (agi::acs::AcsError const& e) {
|
||||||
|
LOG_E("dialog_shift_times/save_history") << "Cannot load shift times history: " << e.GetChainedMessage();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
history->Thaw();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
history->Thaw();
|
||||||
|
|
||||||
/// @brief Clear History
|
|
||||||
/// @param event
|
|
||||||
///
|
|
||||||
void DialogShiftTimes::OnClear(wxCommandEvent &event) {
|
|
||||||
wxRemoveFile(StandardPaths::DecodePath(_T("?user/shift_history.txt")));
|
|
||||||
History->Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DialogShiftTimes::Process(wxCommandEvent &) {
|
||||||
|
int mode = selection_mode->GetSelection();
|
||||||
|
int type = time_fields->GetSelection();
|
||||||
|
bool reverse = shift_backward->GetValue();
|
||||||
|
bool by_time = shift_by_time->GetValue();
|
||||||
|
|
||||||
/// @brief Cancel
|
bool start = type != 2;
|
||||||
/// @param event
|
bool end = type != 1;
|
||||||
///
|
|
||||||
void DialogShiftTimes::OnClose(wxCommandEvent &event) {
|
|
||||||
EndModal(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Selection sel = context->selectionController->GetSelectedSet();
|
||||||
|
|
||||||
|
long shift;
|
||||||
/// @brief Apply
|
if (by_time) {
|
||||||
/// @param event
|
shift = shift_time->time.GetMS();
|
||||||
/// @return
|
if (shift == 0) {
|
||||||
///
|
Close();
|
||||||
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
|
|
||||||
int nrows = context->subsGrid->GetRows();
|
|
||||||
wxArrayInt sel = context->subsGrid->GetSelection();
|
|
||||||
int firstSel = 0;
|
|
||||||
if (sel.Count()) firstSel = sel[0];
|
|
||||||
|
|
||||||
// Get length
|
|
||||||
if (byTime) len = ShiftTime->time.GetMS();
|
|
||||||
else ShiftFrame->GetValue().ToLong(&len);
|
|
||||||
|
|
||||||
if (byTime && len == 0) {
|
|
||||||
// Shift zero milliseconds in time mode
|
|
||||||
// Equivalent to doing nothing at all, so just dismiss
|
|
||||||
EndModal(0);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If backwards, invert
|
|
||||||
if (backward) len = -len;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
}
|
||||||
|
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 (mode == 1) continue;
|
||||||
|
if (mode == 2 && shifted_blocks.empty()) continue;
|
||||||
|
}
|
||||||
|
else if (!block_start)
|
||||||
|
block_start = row_number;
|
||||||
|
|
||||||
|
if (start)
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add entry to history
|
|
||||||
if (didSomething) {
|
|
||||||
if (backward) len = -len;
|
|
||||||
wxString message;
|
|
||||||
wxFileName assfile(context->ass->filename);
|
|
||||||
wxString filename = assfile.GetFullName();
|
|
||||||
|
|
||||||
// File
|
|
||||||
if (filename.IsEmpty()) message << _("unsaved, ");
|
|
||||||
else message << filename << _T(", ");
|
|
||||||
|
|
||||||
// Time/frames
|
|
||||||
if (byTime) message << ShiftTime->GetValue() << _T(" ");
|
|
||||||
else message << len << _(" frames ");
|
|
||||||
|
|
||||||
// Forward/backwards
|
|
||||||
if (backward) message << _("backward, ");
|
|
||||||
else message << _("forward, ");
|
|
||||||
|
|
||||||
// Start/end
|
|
||||||
if (type == 0) message << _("s+e, ");
|
|
||||||
if (type == 1) message << _("s, ");
|
|
||||||
if (type == 2) message << _("e, ");
|
|
||||||
|
|
||||||
// Selection range
|
|
||||||
if (affect == 0) message << _("all");
|
|
||||||
else if (affect == 2) message << wxString::Format(_("from %i onward"),sel[0]+1);
|
|
||||||
else { // This huge block of code prints the selected ranges of subs
|
|
||||||
message << _("sel ");
|
|
||||||
int last = sel[0]-1;
|
|
||||||
int first = sel[0];
|
|
||||||
for (unsigned int i=0;i<sel.Count();i++) {
|
|
||||||
if (sel[i] != last+1) {
|
|
||||||
if (first != last) message << wxString::Format(_T("%i"),first+1) << _T("-") << wxString::Format(_T("%i"),last+1) << _T(";");
|
|
||||||
else message << wxString::Format(_T("%i"),first+1) << _T(";");
|
|
||||||
first = sel[i];
|
|
||||||
}
|
|
||||||
last = sel[i];
|
|
||||||
}
|
|
||||||
if (first != last) message << wxString::Format(_T("%i"),first+1) << _T("-") << wxString::Format(_T("%i"),last+1);
|
|
||||||
else message << wxString::Format(_T("%i"),first+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Done, append
|
|
||||||
AppendToHistory(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 a new issue