forked from mia/Aegisub
Clean up TimeEdit
Remove some unused or constant arguments and simplify some overly convoluted logic. Check for whether timecodes are open rather than whether video is open to determine if by-frame mode is enabled. Operate on a project context rather than using VideoContext::Get(). Use non-event-generating setter methods rather than a boolean ready variable. Make all member variables private and add setters rather than relying on the client code calling Update when appropriate. Eliminate flickering in overwrite mode. Originally committed to SVN as r6056.
This commit is contained in:
parent
70d703255b
commit
3a069b7f60
5 changed files with 149 additions and 233 deletions
|
@ -71,7 +71,7 @@ DialogJumpTo::DialogJumpTo(agi::Context *c)
|
||||||
wxStaticText *LabelTime = new wxStaticText(this,-1,_("Time: "),wxDefaultPosition,wxSize(60,20));
|
wxStaticText *LabelTime = new wxStaticText(this,-1,_("Time: "),wxDefaultPosition,wxSize(60,20));
|
||||||
JumpFrame = new wxTextCtrl(this,-1,wxString::Format("%ld",jumpframe),wxDefaultPosition,wxSize(60,20),wxTE_PROCESS_ENTER, NumValidator());
|
JumpFrame = new wxTextCtrl(this,-1,wxString::Format("%ld",jumpframe),wxDefaultPosition,wxSize(60,20),wxTE_PROCESS_ENTER, NumValidator());
|
||||||
JumpFrame->SetMaxLength(maxLength.size());
|
JumpFrame->SetMaxLength(maxLength.size());
|
||||||
JumpTime = new TimeEdit(this,-1,jumptime.GetASSFormated(),wxDefaultPosition,wxSize(60,20),wxTE_PROCESS_ENTER);
|
JumpTime = new TimeEdit(this, -1, c, jumptime.GetASSFormated(), wxSize(60,20));
|
||||||
wxSizer *FrameSizer = new wxBoxSizer(wxHORIZONTAL);
|
wxSizer *FrameSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
wxSizer *TimeSizer = new wxBoxSizer(wxHORIZONTAL);
|
wxSizer *TimeSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||||
FrameSizer->Add(LabelFrame,0,wxALIGN_CENTER_VERTICAL,0);
|
FrameSizer->Add(LabelFrame,0,wxALIGN_CENTER_VERTICAL,0);
|
||||||
|
@ -112,7 +112,7 @@ void DialogJumpTo::OnOK(wxCommandEvent &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DialogJumpTo::OnEditTime (wxCommandEvent &) {
|
void DialogJumpTo::OnEditTime (wxCommandEvent &) {
|
||||||
long newframe = c->videoController->FrameAtTime(JumpTime->time.GetMS());
|
long newframe = c->videoController->FrameAtTime(JumpTime->GetMS());
|
||||||
if (jumpframe != newframe) {
|
if (jumpframe != newframe) {
|
||||||
jumpframe = newframe;
|
jumpframe = newframe;
|
||||||
JumpFrame->ChangeValue(wxString::Format("%i", jumpframe));
|
JumpFrame->ChangeValue(wxString::Format("%i", jumpframe));
|
||||||
|
@ -121,9 +121,5 @@ void DialogJumpTo::OnEditTime (wxCommandEvent &) {
|
||||||
|
|
||||||
void DialogJumpTo::OnEditFrame (wxCommandEvent &event) {
|
void DialogJumpTo::OnEditFrame (wxCommandEvent &event) {
|
||||||
JumpFrame->GetValue().ToLong(&jumpframe);
|
JumpFrame->GetValue().ToLong(&jumpframe);
|
||||||
int newtime = c->videoController->TimeAtFrame(jumpframe);
|
JumpTime->SetMS(c->videoController->TimeAtFrame(jumpframe));
|
||||||
if (JumpTime->time.GetMS() != newtime) {
|
|
||||||
JumpTime->time.SetMS(newtime);
|
|
||||||
JumpTime->ChangeValue(JumpTime->time.GetASSFormated());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ DialogShiftTimes::DialogShiftTimes(agi::Context *context)
|
||||||
shift_by_frames->SetToolTip(_("Shift by frames"));
|
shift_by_frames->SetToolTip(_("Shift by frames"));
|
||||||
shift_by_frames->Bind(wxEVT_COMMAND_RADIOBUTTON_SELECTED, &DialogShiftTimes::OnByFrames, this);
|
shift_by_frames->Bind(wxEVT_COMMAND_RADIOBUTTON_SELECTED, &DialogShiftTimes::OnByFrames, this);
|
||||||
|
|
||||||
shift_time = new TimeEdit(this, -1);
|
shift_time = new TimeEdit(this, -1, context);
|
||||||
shift_time->SetToolTip(_("Enter time in h:mm:ss.cs notation"));
|
shift_time->SetToolTip(_("Enter time in h:mm:ss.cs notation"));
|
||||||
|
|
||||||
shift_frames = new wxTextCtrl(this, -1);
|
shift_frames = new wxTextCtrl(this, -1);
|
||||||
|
@ -193,7 +193,7 @@ void DialogShiftTimes::OnClose(wxCommandEvent &) {
|
||||||
long shift;
|
long shift;
|
||||||
shift_frames->GetValue().ToLong(&shift);
|
shift_frames->GetValue().ToLong(&shift);
|
||||||
|
|
||||||
OPT_SET("Tool/Shift Times/Time")->SetInt(shift_time->time.GetMS());
|
OPT_SET("Tool/Shift Times/Time")->SetInt(shift_time->GetMS());
|
||||||
OPT_SET("Tool/Shift Times/Frames")->SetInt(shift);
|
OPT_SET("Tool/Shift Times/Frames")->SetInt(shift);
|
||||||
OPT_SET("Tool/Shift Times/ByTime")->SetBool(shift_by_time->GetValue());
|
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/Type")->SetInt(time_fields->GetSelection());
|
||||||
|
@ -289,7 +289,7 @@ void DialogShiftTimes::Process(wxCommandEvent &) {
|
||||||
|
|
||||||
long shift;
|
long shift;
|
||||||
if (by_time) {
|
if (by_time) {
|
||||||
shift = shift_time->time.GetMS();
|
shift = shift_time->GetMS();
|
||||||
if (shift == 0) {
|
if (shift == 0) {
|
||||||
Close();
|
Close();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -177,10 +177,9 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context)
|
||||||
|
|
||||||
// Middle controls
|
// Middle controls
|
||||||
Layer = new wxSpinCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(50,-1),wxSP_ARROW_KEYS,0,0x7FFFFFFF,0);
|
Layer = new wxSpinCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(50,-1),wxSP_ARROW_KEYS,0,0x7FFFFFFF,0);
|
||||||
StartTime = new TimeEdit(this,wxID_ANY,"",wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER);
|
StartTime = new TimeEdit(this, wxID_ANY, context, "", wxSize(75,-1));
|
||||||
EndTime = new TimeEdit(this,wxID_ANY,"",wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER);
|
EndTime = new TimeEdit(this, wxID_ANY, context, "", wxSize(75,-1), true);
|
||||||
EndTime->isEnd = true;
|
Duration = new TimeEdit(this,wxID_ANY, context,"",wxSize(75,-1));
|
||||||
Duration = new TimeEdit(this,wxID_ANY,"",wxDefaultPosition,wxSize(75,-1),wxTE_PROCESS_ENTER);
|
|
||||||
MarginL = new wxTextCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator());
|
MarginL = new wxTextCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator());
|
||||||
MarginL->SetMaxLength(4);
|
MarginL->SetMaxLength(4);
|
||||||
MarginR = new wxTextCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator());
|
MarginR = new wxTextCtrl(this,wxID_ANY,"",wxDefaultPosition,wxSize(40,-1),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator());
|
||||||
|
@ -520,21 +519,21 @@ void SubsEditBox::CommitText(wxString desc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::CommitTimes(TimeField field) {
|
void SubsEditBox::CommitTimes(TimeField field) {
|
||||||
Duration->SetTime(EndTime->time - StartTime->time);
|
Duration->SetTime(EndTime->GetTime() - StartTime->GetTime());
|
||||||
|
|
||||||
// Update lines
|
// Update lines
|
||||||
for (Selection::iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
for (Selection::iterator cur = sel.begin(); cur != sel.end(); ++cur) {
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case TIME_START:
|
case TIME_START:
|
||||||
(*cur)->Start = StartTime->time;
|
(*cur)->Start = StartTime->GetTime();
|
||||||
if ((*cur)->Start > (*cur)->End) (*cur)->End = (*cur)->Start;
|
if ((*cur)->Start > (*cur)->End) (*cur)->End = (*cur)->Start;
|
||||||
break;
|
break;
|
||||||
case TIME_END:
|
case TIME_END:
|
||||||
(*cur)->End = EndTime->time;
|
(*cur)->End = EndTime->GetTime();
|
||||||
if ((*cur)->Start > (*cur)->End) (*cur)->Start = (*cur)->End;
|
if ((*cur)->Start > (*cur)->End) (*cur)->Start = (*cur)->End;
|
||||||
break;
|
break;
|
||||||
case TIME_DURATION:
|
case TIME_DURATION:
|
||||||
(*cur)->End = (*cur)->Start + Duration->time;
|
(*cur)->End = (*cur)->Start + Duration->GetTime();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -634,17 +633,17 @@ void SubsEditBox::OnLayerEnter(wxCommandEvent &) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::OnStartTimeChange(wxCommandEvent &) {
|
void SubsEditBox::OnStartTimeChange(wxCommandEvent &) {
|
||||||
if (StartTime->time > EndTime->time) EndTime->SetTime(StartTime->time);
|
if (StartTime->GetTime() > EndTime->GetTime()) EndTime->SetTime(StartTime->GetTime());
|
||||||
CommitTimes(TIME_START);
|
CommitTimes(TIME_START);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::OnEndTimeChange(wxCommandEvent &) {
|
void SubsEditBox::OnEndTimeChange(wxCommandEvent &) {
|
||||||
if (StartTime->time > EndTime->time) StartTime->SetTime(EndTime->time);
|
if (StartTime->GetTime() > EndTime->GetTime()) StartTime->SetTime(EndTime->GetTime());
|
||||||
CommitTimes(TIME_END);
|
CommitTimes(TIME_END);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubsEditBox::OnDurationChange(wxCommandEvent &) {
|
void SubsEditBox::OnDurationChange(wxCommandEvent &) {
|
||||||
EndTime->SetTime(StartTime->time + Duration->time);
|
EndTime->SetTime(StartTime->GetTime() + Duration->GetTime());
|
||||||
CommitTimes(TIME_DURATION);
|
CommitTimes(TIME_DURATION);
|
||||||
}
|
}
|
||||||
void SubsEditBox::OnMarginLChange(wxCommandEvent &) {
|
void SubsEditBox::OnMarginLChange(wxCommandEvent &) {
|
||||||
|
|
|
@ -36,7 +36,11 @@
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "timeedit_ctrl.h"
|
||||||
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
|
#include <tr1/functional>
|
||||||
|
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
#include <wx/dataobj.h>
|
#include <wx/dataobj.h>
|
||||||
#include <wx/menu.h>
|
#include <wx/menu.h>
|
||||||
|
@ -45,31 +49,30 @@
|
||||||
|
|
||||||
#include "ass_time.h"
|
#include "ass_time.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "include/aegisub/context.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "timeedit_ctrl.h"
|
|
||||||
#include "video_context.h"
|
#include "video_context.h"
|
||||||
|
|
||||||
#ifdef __WXGTK__
|
#ifdef __WXGTK__
|
||||||
/// Use the multiline style only on wxGTK to workaround some wxGTK bugs with the default singleline style.
|
/// Use the multiline style only on wxGTK to workaround some wxGTK bugs with the default singleline style.
|
||||||
#define TimeEditWindowStyle wxTE_MULTILINE | wxTE_CENTRE
|
#define TimeEditWindowStyle wxTE_MULTILINE | wxTE_CENTRE
|
||||||
#else
|
#else
|
||||||
|
|
||||||
/// All other platforms than wxGTK.
|
/// All other platforms than wxGTK.
|
||||||
#define TimeEditWindowStyle wxTE_CENTRE
|
#define TimeEditWindowStyle wxTE_CENTRE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief Constructor
|
enum {
|
||||||
/// @param parent
|
Time_Edit_Copy = 1320,
|
||||||
/// @param id
|
Time_Edit_Paste
|
||||||
/// @param value
|
};
|
||||||
/// @param pos
|
|
||||||
/// @param size
|
TimeEdit::TimeEdit(wxWindow* parent, wxWindowID id, agi::Context *c, const wxString& value, const wxSize& size, bool asEnd)
|
||||||
/// @param style
|
: wxTextCtrl(parent, id, value, wxDefaultPosition, size,TimeEditWindowStyle | wxTE_PROCESS_ENTER)
|
||||||
/// @param validator
|
, c(c)
|
||||||
/// @param name
|
, byFrame(false)
|
||||||
///
|
, isEnd(asEnd)
|
||||||
TimeEdit::TimeEdit(wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) :
|
, insert(!OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool())
|
||||||
wxTextCtrl(parent,id,value,pos,size,TimeEditWindowStyle | style,validator,name)
|
, insert_opt(OPT_SUB("Subtitle/Time Edit/Insert Mode", &TimeEdit::OnInsertChanged, this))
|
||||||
{
|
{
|
||||||
// Set validator
|
// Set validator
|
||||||
wxTextValidator val(wxFILTER_INCLUDE_CHAR_LIST);
|
wxTextValidator val(wxFILTER_INCLUDE_CHAR_LIST);
|
||||||
|
@ -99,227 +102,146 @@ wxTextCtrl(parent,id,value,pos,size,TimeEditWindowStyle | style,validator,name)
|
||||||
h += 8;
|
h += 8;
|
||||||
SetSizeHints(w,h,w,h);
|
SetSizeHints(w,h,w,h);
|
||||||
#endif
|
#endif
|
||||||
ready = true;
|
|
||||||
byFrame = false;
|
|
||||||
isEnd = false;
|
|
||||||
|
|
||||||
Bind(wxEVT_COMMAND_TEXT_UPDATED, &TimeEdit::OnModified, this);
|
Bind(wxEVT_COMMAND_TEXT_UPDATED, &TimeEdit::OnModified, this);
|
||||||
Bind(wxEVT_CONTEXT_MENU, &TimeEdit::OnContextMenu, this);
|
Bind(wxEVT_CONTEXT_MENU, &TimeEdit::OnContextMenu, this);
|
||||||
|
Bind(wxEVT_KEY_DOWN, &TimeEdit::OnKeyDown, this);
|
||||||
|
Bind(wxEVT_COMMAND_MENU_SELECTED, std::tr1::bind(&TimeEdit::CopyTime, this), Time_Edit_Copy);
|
||||||
|
Bind(wxEVT_COMMAND_MENU_SELECTED, std::tr1::bind(&TimeEdit::PasteTime, this), Time_Edit_Paste);
|
||||||
}
|
}
|
||||||
|
|
||||||
BEGIN_EVENT_TABLE(TimeEdit, wxTextCtrl)
|
void TimeEdit::SetMS(int ms) {
|
||||||
EVT_KEY_DOWN(TimeEdit::OnKeyDown)
|
if (ms != time.GetMS()) {
|
||||||
EVT_MENU(Time_Edit_Copy,TimeEdit::OnCopy)
|
time.SetMS(ms);
|
||||||
EVT_MENU(Time_Edit_Paste,TimeEdit::OnPaste)
|
|
||||||
END_EVENT_TABLE()
|
|
||||||
|
|
||||||
/// @brief Modified event
|
|
||||||
/// @param event
|
|
||||||
void TimeEdit::OnModified(wxCommandEvent &event) {
|
|
||||||
event.Skip();
|
|
||||||
Modified();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Modified function
|
|
||||||
void TimeEdit::Modified() {
|
|
||||||
if (!ready) return;
|
|
||||||
ready = false;
|
|
||||||
|
|
||||||
if (byFrame) Update();
|
|
||||||
else UpdateTime(true);
|
|
||||||
|
|
||||||
ready = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Set time and update stuff
|
|
||||||
/// @param ms
|
|
||||||
/// @param setModified
|
|
||||||
void TimeEdit::SetTime(AssTime newTime) {
|
|
||||||
if (newTime != time) {
|
|
||||||
time = newTime;
|
|
||||||
UpdateText();
|
UpdateText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Toggles between set by frame and time
|
|
||||||
/// @param enable
|
|
||||||
void TimeEdit::SetByFrame(bool enableByFrame) {
|
void TimeEdit::SetByFrame(bool enableByFrame) {
|
||||||
if (enableByFrame == byFrame) return;
|
if (enableByFrame == byFrame) return;
|
||||||
|
|
||||||
if (enableByFrame) {
|
byFrame = enableByFrame && c->videoController->TimecodesLoaded();
|
||||||
if (VideoContext::Get()->IsLoaded()) {
|
UpdateText();
|
||||||
byFrame = true;
|
|
||||||
UpdateText();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
byFrame = false;
|
|
||||||
UpdateText();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Update text to reflect time value
|
|
||||||
void TimeEdit::UpdateText() {
|
|
||||||
ready = false;
|
|
||||||
if (byFrame) {
|
|
||||||
int frame_n = VideoContext::Get()->FrameAtTime(time.GetMS(),isEnd ? agi::vfr::END : agi::vfr::START);
|
|
||||||
ChangeValue(wxString::Format("%i", frame_n));
|
|
||||||
}
|
|
||||||
else ChangeValue(time.GetASSFormated());
|
|
||||||
ready = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Update
|
void TimeEdit::OnModified(wxCommandEvent &event) {
|
||||||
void TimeEdit::Update() {
|
event.Skip();
|
||||||
if (byFrame) {
|
if (byFrame) {
|
||||||
long temp;
|
long temp;
|
||||||
GetValue().ToLong(&temp);
|
GetValue().ToLong(&temp);
|
||||||
SetTime(VideoContext::Get()->TimeAtFrame(temp,isEnd ? agi::vfr::END : agi::vfr::START));
|
SetTime(c->videoController->TimeAtFrame(temp, isEnd ? agi::vfr::END : agi::vfr::START));
|
||||||
}
|
|
||||||
|
|
||||||
// Update time if not on insertion mode
|
|
||||||
else if (!OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool()) {
|
|
||||||
UpdateTime();
|
|
||||||
}
|
}
|
||||||
|
else if (insert)
|
||||||
|
time.ParseASS(GetValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Reads value from a text control and update it
|
|
||||||
/// @param byUser
|
|
||||||
void TimeEdit::UpdateTime(bool byUser) {
|
|
||||||
bool insertion = OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool();
|
|
||||||
wxString text = GetValue();
|
|
||||||
long start=0,end=0;
|
|
||||||
if (insertion && byUser) {
|
|
||||||
GetSelection(&start,&end);
|
|
||||||
if (start == end) {
|
|
||||||
wxString nextChar = text.Mid(start,1);
|
|
||||||
if (nextChar == ":" || nextChar == ".") {
|
|
||||||
wxString temp = text;
|
|
||||||
text = temp.Left(start-1);
|
|
||||||
text += nextChar;
|
|
||||||
text += temp.Mid(start-1,1);
|
|
||||||
text += temp.Mid(start+2);
|
|
||||||
start++;
|
|
||||||
end++;
|
|
||||||
}
|
|
||||||
else if (nextChar.IsEmpty()) text.Remove(start-1,1);
|
|
||||||
else text.Remove(start,1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update time
|
void TimeEdit::UpdateText() {
|
||||||
time.ParseASS(text);
|
if (byFrame)
|
||||||
if (insertion) {
|
ChangeValue(wxString::Format("%d", c->videoController->FrameAtTime(time.GetMS(), isEnd ? agi::vfr::END : agi::vfr::START)));
|
||||||
|
else
|
||||||
ChangeValue(time.GetASSFormated());
|
ChangeValue(time.GetASSFormated());
|
||||||
SetSelection(start,end);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Key pressed
|
|
||||||
/// @param event
|
|
||||||
void TimeEdit::OnKeyDown(wxKeyEvent &event) {
|
void TimeEdit::OnKeyDown(wxKeyEvent &event) {
|
||||||
// Get key ID
|
|
||||||
int key = event.GetKeyCode();
|
int key = event.GetKeyCode();
|
||||||
bool insertMode = OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool();
|
if (event.CmdDown()) {
|
||||||
Refresh();
|
if (key == 'C' || key == 'X')
|
||||||
|
CopyTime();
|
||||||
// Check if it's an acceptable key
|
else if (key == 'V')
|
||||||
if (!event.CmdDown()) {
|
PasteTime();
|
||||||
if (byFrame || !insertMode || (key != WXK_BACK && key != WXK_DELETE)) {
|
else
|
||||||
// Reset selection first, if necessary
|
|
||||||
if (!byFrame && insertMode) {
|
|
||||||
long from=0,to=0;
|
|
||||||
GetSelection(&from,&to);
|
|
||||||
if (to != from) SetSelection(from,from);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow it through
|
|
||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (key == 'C' || key == 'X') {
|
// Translate numpad presses to normal numbers
|
||||||
CopyTime();
|
if (key >= WXK_NUMPAD0 && key <= WXK_NUMPAD9)
|
||||||
|
key += '0' - WXK_NUMPAD0;
|
||||||
|
|
||||||
|
// If overwriting is disabled, we're in frame mode, or it's a key we
|
||||||
|
// don't care about just let the standard processing happen
|
||||||
|
event.Skip();
|
||||||
|
if (byFrame) return;
|
||||||
|
if (insert) return;
|
||||||
|
if ((key < '0' || key > '9') && key != WXK_BACK && key != WXK_DELETE && key != ';' && key != '.') return;
|
||||||
|
|
||||||
|
event.Skip(false);
|
||||||
|
|
||||||
|
long start = GetInsertionPoint();
|
||||||
|
wxString text = GetValue();
|
||||||
|
|
||||||
|
// Delete does nothing
|
||||||
|
if (key == WXK_DELETE) return;
|
||||||
|
// Back just moves cursor back one without deleting
|
||||||
|
if (key == WXK_BACK) {
|
||||||
|
if (start > 0)
|
||||||
|
SetInsertionPoint(start - 1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else if (key == 'V') {
|
// Cursor is at the end so do nothing
|
||||||
PasteTime();
|
if (start >= (long)text.size()) return;
|
||||||
}
|
|
||||||
else {
|
// If the cursor is at punctuation, move it forward to the next digit
|
||||||
event.Skip();
|
if (text[start] == ':' || text[start] == '.')
|
||||||
|
++start;
|
||||||
|
|
||||||
|
// : and . hop over punctuation but never insert anything
|
||||||
|
if (key == ';' || key == '.') {
|
||||||
|
SetInsertionPoint(start);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Overwrite the digit
|
||||||
|
time.ParseASS(text.Left(start) + (char)key + text.Mid(start + 1));
|
||||||
|
SetValue(time.GetASSFormated());
|
||||||
|
SetInsertionPoint(start + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///// Mouse/copy/paste events down here /////
|
void TimeEdit::OnInsertChanged(agi::OptionValue const& opt) {
|
||||||
|
insert = !opt.GetBool();
|
||||||
/// @brief Mouse event
|
|
||||||
/// @param event
|
|
||||||
void TimeEdit::OnContextMenu(wxContextMenuEvent &) {
|
|
||||||
if (!byFrame && OPT_GET("Subtitle/Time Edit/Insert Mode")->GetBool()) {
|
|
||||||
wxMenu menu;
|
|
||||||
menu.Append(Time_Edit_Copy,_("&Copy"));
|
|
||||||
menu.Append(Time_Edit_Paste,_("&Paste"));
|
|
||||||
PopupMenu(&menu);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Menu Copy
|
void TimeEdit::OnContextMenu(wxContextMenuEvent &evt) {
|
||||||
void TimeEdit::OnCopy(wxCommandEvent &) {
|
if (byFrame || insert) {
|
||||||
SetFocus();
|
evt.Skip();
|
||||||
SetSelection(0,GetValue().Length());
|
|
||||||
CopyTime();
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Menu Paste
|
|
||||||
void TimeEdit::OnPaste(wxCommandEvent &) {
|
|
||||||
SetFocus();
|
|
||||||
PasteTime();
|
|
||||||
Refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief Copy to clipboard
|
|
||||||
void TimeEdit::CopyTime() {
|
|
||||||
if (byFrame) {
|
|
||||||
Copy();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time
|
wxMenu menu;
|
||||||
|
menu.Append(Time_Edit_Copy, _("&Copy"));
|
||||||
|
menu.Append(Time_Edit_Paste, _("&Paste"));
|
||||||
|
PopupMenu(&menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimeEdit::CopyTime() {
|
||||||
if (wxTheClipboard->Open()) {
|
if (wxTheClipboard->Open()) {
|
||||||
wxTheClipboard->SetData(new wxTextDataObject(GetStringSelection()));
|
wxTheClipboard->SetData(new wxTextDataObject(GetValue()));
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Paste from clipboard
|
|
||||||
void TimeEdit::PasteTime() {
|
void TimeEdit::PasteTime() {
|
||||||
if (byFrame) {
|
if (byFrame) {
|
||||||
Paste();
|
Paste();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Time
|
|
||||||
if (wxTheClipboard->Open()) {
|
if (wxTheClipboard->Open()) {
|
||||||
// Read text
|
|
||||||
wxString text;
|
wxString text;
|
||||||
if (wxTheClipboard->IsSupported(wxDF_TEXT)) {
|
if (wxTheClipboard->IsSupported(wxDF_TEXT)) {
|
||||||
wxTextDataObject data;
|
wxTextDataObject data;
|
||||||
wxTheClipboard->GetData(data);
|
wxTheClipboard->GetData(data);
|
||||||
text = data.GetText();
|
text = data.GetText().Trim(false).Trim(true);
|
||||||
text.Trim(false).Trim(true);
|
|
||||||
}
|
}
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
|
|
||||||
// Paste time
|
|
||||||
AssTime tempTime;
|
AssTime tempTime;
|
||||||
tempTime.ParseASS(text);
|
tempTime.ParseASS(text);
|
||||||
if (tempTime.GetASSFormated() == text) {
|
if (tempTime.GetASSFormated() == text) {
|
||||||
ready = false;
|
SetTime(tempTime);
|
||||||
SetValue(text);
|
SetSelection(0, GetValue().size());
|
||||||
SetSelection(0,GetValue().Length());
|
|
||||||
ready = true;
|
|
||||||
Modified();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,65 +34,64 @@
|
||||||
/// @ingroup custom_control
|
/// @ingroup custom_control
|
||||||
///
|
///
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
|
|
||||||
////////////
|
|
||||||
// Includes
|
|
||||||
#ifndef AGI_PRE
|
#ifndef AGI_PRE
|
||||||
#include <wx/textctrl.h>
|
#include <wx/textctrl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "ass_time.h"
|
#include "ass_time.h"
|
||||||
|
|
||||||
|
#include <libaegisub/signal.h>
|
||||||
|
|
||||||
/// @class TimeEdit
|
namespace agi {
|
||||||
/// @brief DOCME
|
class OptionValue;
|
||||||
|
struct Context;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief A text edit control for editing AssTime objects
|
||||||
///
|
///
|
||||||
|
/// This control constrains values to valid times, and can display the time
|
||||||
|
/// being edited as either a h:mm:ss.cc formatted time, or a frame number
|
||||||
class TimeEdit : public wxTextCtrl {
|
class TimeEdit : public wxTextCtrl {
|
||||||
private:
|
agi::Context *c; ///< Project context
|
||||||
/// DOCME
|
bool byFrame; ///< Is the time displayed as a frame number?
|
||||||
bool byFrame;
|
bool isEnd; ///< Should the time be treated as an end time for time <-> frame conversions?
|
||||||
|
AssTime time; ///< The time, which may be displayed as either a frame number or time
|
||||||
|
bool insert; ///< If true, disable overwriting behavior in time mode
|
||||||
|
|
||||||
/// DOCME
|
agi::signal::Connection insert_opt;
|
||||||
bool ready;
|
|
||||||
|
|
||||||
void UpdateText();
|
|
||||||
void CopyTime();
|
void CopyTime();
|
||||||
void PasteTime();
|
void PasteTime();
|
||||||
|
|
||||||
/// DOCME
|
/// Set the value of the text box from the current time and byFrame setting
|
||||||
void UpdateTime(bool byUser=true);
|
void UpdateText();
|
||||||
|
|
||||||
/// DOCME
|
|
||||||
void OnModified(wxCommandEvent &event);
|
|
||||||
void OnContextMenu(wxContextMenuEvent &event);
|
void OnContextMenu(wxContextMenuEvent &event);
|
||||||
|
void OnInsertChanged(agi::OptionValue const& opt);
|
||||||
void OnKeyDown(wxKeyEvent &event);
|
void OnKeyDown(wxKeyEvent &event);
|
||||||
void OnCopy(wxCommandEvent &event);
|
void OnModified(wxCommandEvent &event);
|
||||||
void OnPaste(wxCommandEvent &event);
|
|
||||||
|
|
||||||
void Modified();
|
|
||||||
public:
|
public:
|
||||||
|
/// Get the current time as an AssTime object
|
||||||
|
AssTime GetTime() const { return time; }
|
||||||
|
/// Set the time
|
||||||
|
void SetTime(AssTime time) { SetMS(time.GetMS()); }
|
||||||
|
|
||||||
/// DOCME
|
/// Get the current time as milliseconds
|
||||||
AssTime time;
|
int GetMS() const { return time.GetMS(); }
|
||||||
|
/// Set the time to the specified milliseconds
|
||||||
|
void SetMS(int ms);
|
||||||
|
|
||||||
/// DOCME
|
/// Set whether the time is displayed as a time or the corresponding frame number
|
||||||
bool isEnd;
|
/// @param enableByFrame If true, frame numbers are displayed
|
||||||
|
void SetByFrame(bool enableByFrame);
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
/// DOCME
|
/// @param parent Parent window
|
||||||
TimeEdit(wxWindow* parent, wxWindowID id, const wxString& value = "", const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = 0, const wxValidator& validator = wxDefaultValidator, const wxString& name = wxTextCtrlNameStr);
|
/// @param id Window id
|
||||||
|
/// @param c Project context
|
||||||
void SetByFrame(bool enable);
|
/// @param value Initial value. Must be a valid time string or empty
|
||||||
void SetTime(AssTime time);
|
/// @param size Initial control size
|
||||||
void Update();
|
/// @param asEnd Treat the time as a line end time (rather than start) for time <-> frame number conversions
|
||||||
|
TimeEdit(wxWindow* parent, wxWindowID id, agi::Context *c, const wxString& value = "", const wxSize& size = wxDefaultSize, bool asEnd = false);
|
||||||
DECLARE_EVENT_TABLE()
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
Time_Edit_Copy = 1320,
|
|
||||||
Time_Edit_Paste
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue