diff --git a/aegisub/ass_time.cpp b/aegisub/ass_time.cpp index b85dbcc3e..862bdad44 100644 --- a/aegisub/ass_time.cpp +++ b/aegisub/ass_time.cpp @@ -59,20 +59,42 @@ void AssTime::ParseASS (const wxString text) { // Prepare size_t pos = 0; size_t end = 0; - long th,tm,tms; + long th=0,tm=0,tms=0; + + // Count the number of colons + size_t len = text.Length(); + int colons = 0; + for (pos=0;pos 2) { + for (pos=0;pos= 1) { + while (text[end++] != _T(':')); + tm = StringToInt(text,pos,end); + pos = end; + } // Miliseconds (includes seconds) - pos = end+1; end = text.Length(); tms = StringToFix(text,3,pos,end); } @@ -220,34 +242,6 @@ wxString AssTime::GetSRTFormated () { } -///////////////////////////////////////////////// -// Reads value from a text control and update it -void AssTime::UpdateFromTextCtrl(wxTextCtrl *ctrl) { - long start,end; - wxString text = ctrl->GetValue(); - ctrl->GetSelection(&start,&end); - if (start == end) { - wxString nextChar = text.Mid(start,1); - if (nextChar == _T(":") || nextChar == _T(".")) { - 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 - ParseASS(text); - ctrl->SetValue(GetASSFormated()); - ctrl->SetSelection(start,end); -} - - ////////////////////// // AssTime comparison bool operator < (AssTime &t1, AssTime &t2) { diff --git a/aegisub/ass_time.h b/aegisub/ass_time.h index adcead187..85882a1e8 100644 --- a/aegisub/ass_time.h +++ b/aegisub/ass_time.h @@ -65,7 +65,6 @@ public: void ParseSRT(const wxString text); // Sets value to text-form time, in SRT format wxString GetASSFormated(bool ms=false); // Returns the ASS representation of time wxString GetSRTFormated(); // Returns the SRT representation of time - void UpdateFromTextCtrl(wxTextCtrl *ctrl); // Reads value from text control and updates both }; // Comparison operators diff --git a/aegisub/dialog_jumpto.cpp b/aegisub/dialog_jumpto.cpp index 16ea1771a..993eba517 100644 --- a/aegisub/dialog_jumpto.cpp +++ b/aegisub/dialog_jumpto.cpp @@ -41,6 +41,14 @@ #include "video_context.h" +/////// +// IDs +enum { + TEXT_JUMP_TIME = 1100, + TEXT_JUMP_FRAME +}; + + /////////////// // Constructor DialogJumpTo::DialogJumpTo (wxWindow *parent) @@ -55,9 +63,7 @@ DialogJumpTo::DialogJumpTo (wxWindow *parent) wxStaticText *LabelFrame = new wxStaticText(this,-1,_("Frame: "),wxDefaultPosition,wxSize(60,20)); wxStaticText *LabelTime = new wxStaticText(this,-1,_("Time: "),wxDefaultPosition,wxSize(60,20)); JumpFrame = new wxTextCtrl(this,TEXT_JUMP_FRAME,wxString::Format(_T("%i"),jumpframe),wxDefaultPosition,wxSize(60,20)); - JumpTime = new wxTextCtrl(this,TEXT_JUMP_TIME,jumptime.GetASSFormated(),wxDefaultPosition,wxSize(60,20)); - JumpFrame->SetEventHandler(new DialogJumpToEvent(this)); - JumpTime->SetEventHandler(new DialogJumpToEvent(this)); + JumpTime = new TimeEdit(this,TEXT_JUMP_TIME,jumptime.GetASSFormated(),wxDefaultPosition,wxSize(60,20)); wxSizer *FrameSizer = new wxBoxSizer(wxHORIZONTAL); wxSizer *TimeSizer = new wxBoxSizer(wxHORIZONTAL); FrameSizer->Add(LabelFrame,0,wxALIGN_CENTER_VERTICAL,0); @@ -71,9 +77,6 @@ DialogJumpTo::DialogJumpTo (wxWindow *parent) // Buttons wxButton *CancelButton = new wxButton(this,wxID_CANCEL); wxButton *OKButton = new wxButton(this,wxID_OK); - CancelButton->SetEventHandler(new DialogJumpToEvent(this)); - OKButton->SetEventHandler(new DialogJumpToEvent(this)); - OKButton->SetDefault(); wxSizer *ButtonSizer = new wxBoxSizer(wxHORIZONTAL); ButtonSizer->Add(OKButton,1,wxRIGHT,5); ButtonSizer->Add(CancelButton,0,0,0); @@ -91,29 +94,21 @@ DialogJumpTo::DialogJumpTo (wxWindow *parent) } -///////////////// -// Event handler - -// Constructor -DialogJumpToEvent::DialogJumpToEvent (DialogJumpTo *ctrl) { - control = ctrl; -} - -// Table -BEGIN_EVENT_TABLE(DialogJumpToEvent, wxEvtHandler) - EVT_KEY_DOWN(DialogJumpToEvent::OnKey) - EVT_BUTTON(wxID_CANCEL,DialogJumpToEvent::OnClose) - EVT_BUTTON(wxID_OK,DialogJumpToEvent::OnOK) - EVT_TEXT(TEXT_JUMP_TIME, DialogJumpToEvent::OnEditTime) - EVT_TEXT(TEXT_JUMP_FRAME, DialogJumpToEvent::OnEditFrame) +/////////////// +// Event table +BEGIN_EVENT_TABLE(DialogJumpTo, wxDialog) + EVT_KEY_DOWN(DialogJumpTo::OnKey) + EVT_BUTTON(wxID_CANCEL,DialogJumpTo::OnClose) + EVT_BUTTON(wxID_OK,DialogJumpTo::OnOK) + EVT_TEXT(TEXT_JUMP_TIME, DialogJumpTo::OnEditTime) + EVT_TEXT(TEXT_JUMP_FRAME, DialogJumpTo::OnEditFrame) END_EVENT_TABLE() -// Redirects -void DialogJumpToEvent::OnKey (wxKeyEvent &event) { control->OnKey(event); } -void DialogJumpToEvent::OnClose (wxCommandEvent &event) { control->OnClose(false); } -void DialogJumpToEvent::OnOK (wxCommandEvent &event) { control->OnClose(true); } -void DialogJumpToEvent::OnEditTime (wxCommandEvent &event) { control->OnEditTime(event); } -void DialogJumpToEvent::OnEditFrame (wxCommandEvent &event) { control->OnEditFrame(event); } + +///////// +// Close +void DialogJumpTo::OnClose (wxCommandEvent &event) { OnClose(false); } +void DialogJumpTo::OnOK (wxCommandEvent &event) { OnClose(true); } ////////////////// @@ -142,10 +137,9 @@ void DialogJumpTo::OnClose(bool ok) { void DialogJumpTo::OnEditTime (wxCommandEvent &event) { if (ready) { ready = false; - jumptime.UpdateFromTextCtrl(JumpTime); // Update frame - long newframe = VFR_Output.GetFrameAtTime(jumptime.GetMS()); + long newframe = VFR_Output.GetFrameAtTime(JumpTime->time.GetMS()); if (jumpframe != newframe) { jumpframe = newframe; JumpFrame->SetValue(wxString::Format(_T("%i"),jumpframe)); diff --git a/aegisub/dialog_jumpto.h b/aegisub/dialog_jumpto.h index 01869c001..ca1b6c88a 100644 --- a/aegisub/dialog_jumpto.h +++ b/aegisub/dialog_jumpto.h @@ -42,6 +42,7 @@ // Headers #include #include "ass_time.h" +#include "timeedit_ctrl.h" ///////// @@ -52,43 +53,21 @@ private: long jumpframe; AssTime jumptime; - wxTextCtrl *JumpTime; + TimeEdit *JumpTime; wxTextCtrl *JumpFrame; -public: - DialogJumpTo (wxWindow *parent); - - void OnKey(wxKeyEvent &event); - void OnClose(bool ok); - void OnEditTime(wxCommandEvent &event); - void OnEditFrame(wxCommandEvent &event); -}; - - -///////////////// -// Event handler -class DialogJumpToEvent : public wxEvtHandler { -private: - DialogJumpTo *control; - void OnKey(wxKeyEvent &event); void OnClose(wxCommandEvent &event); void OnOK(wxCommandEvent &event); void OnEditTime(wxCommandEvent &event); void OnEditFrame(wxCommandEvent &event); + void OnClose(bool ok); public: - DialogJumpToEvent(DialogJumpTo *control); + DialogJumpTo (wxWindow *parent); + + DECLARE_EVENT_TABLE() }; - -/////// -// IDs -enum { - TEXT_JUMP_TIME = 1100, - TEXT_JUMP_FRAME -}; - - #endif diff --git a/aegisub/dialog_options.cpp b/aegisub/dialog_options.cpp index ad5e19d1e..9ebb0958f 100644 --- a/aegisub/dialog_options.cpp +++ b/aegisub/dialog_options.cpp @@ -212,8 +212,8 @@ DialogOptions::DialogOptions(wxWindow *parent) wxSizer *editSizer5 = new wxBoxSizer(wxHORIZONTAL); // First static box - wxString labels1[3] = { _("Enable call tips"), _("Enable syntax highlighting"), _("Link commiting of times") }; - wxString options1[3] = { _T("Call Tips Enabled"), _T("Syntax Highlight Enabled"), _T("Link Time Boxes Commit") }; + wxString labels1[4] = { _("Enable call tips"), _("Enable syntax highlighting"), _("Link commiting of times"), _("Overwrite-Insertion in time boxes") }; + wxString options1[4] = { _T("Call Tips Enabled"), _T("Syntax Highlight Enabled"), _T("Link Time Boxes Commit"), _T("Insert Mode on Time Boxes") }; editSizer6->Add(new wxStaticText(editPage,-1,_("Path to dictionary files:")),0,wxALIGN_CENTER_VERTICAL|wxRIGHT,5); wxTextCtrl *edit = new wxTextCtrl(editPage,-1,_T("")); Bind(edit,_T("Dictionaries path")); @@ -221,7 +221,7 @@ DialogOptions::DialogOptions(wxWindow *parent) browse = new BrowseButton(editPage,-1,_T(""),BROWSE_FOLDER); browse->Bind(edit); editSizer6->Add(browse,0,wxEXPAND); - for (int i=0;i<3;i++) { + for (int i=0;i<4;i++) { wxCheckBox *control = new wxCheckBox(editPage,-1,labels1[i]); Bind(control,options1[i]); editSizer2->Add(control,1,wxEXPAND,0); diff --git a/aegisub/options.cpp b/aegisub/options.cpp index e0a14cc87..8a370a37d 100644 --- a/aegisub/options.cpp +++ b/aegisub/options.cpp @@ -110,6 +110,11 @@ void OptionsManager::LoadDefaults(bool onlyDefaults) { SetText(_T("Dictionaries path"),_T("dictionaries")); // don't these require restart? SetText(_T("Spell Checker"),_T("hunspell")); SetBool(_T("Link time boxes commit"),true); +#ifdef WIN32 + SetBool(_T("Insert mode on time boxes"),true); +#else + SetBool(_T("Insert mode on time boxes"),false); +#endif SetModificationType(MOD_EDIT_BOX); SetBool(_T("Call tips enabled"),true); SetBool(_T("Syntax highlight enabled"),true); diff --git a/aegisub/subs_edit_box.cpp b/aegisub/subs_edit_box.cpp index 74d06eb14..af272ee2d 100644 --- a/aegisub/subs_edit_box.cpp +++ b/aegisub/subs_edit_box.cpp @@ -86,21 +86,21 @@ SubsEditBox::SubsEditBox (wxWindow *parent,SubtitlesGrid *gridp) : wxPanel(paren ActorBox = new wxComboBox(this,ACTOR_COMBOBOX,_T(""),wxDefaultPosition,wxSize(110,25),styles,wxCB_DROPDOWN | wxTE_PROCESS_ENTER); ActorBox->SetToolTip(_("Actor name for this speech. This is only for reference, and is mainly useless.")); ActorBox->PushEventHandler(new IdleFieldHandler(ActorBox,_("Actor"))); - Effect = new HiliModTextCtrl(this,EFFECT_BOX,_T(""),wxDefaultPosition,wxSize(120,20),wxTE_PROCESS_ENTER); + Effect = new HiliModTextCtrl(this,EFFECT_BOX,_T(""),wxDefaultPosition,wxSize(80,20),wxTE_PROCESS_ENTER); Effect->SetToolTip(_("Effect for this line. This can be used to store extra information for karaoke scripts, or for the effects supported by the renderer.")); Effect->PushEventHandler(new IdleFieldHandler(Effect,_("Effect"))); // Middle controls Layer = new wxSpinCtrl(this,LAYER_BOX,_T(""),wxDefaultPosition,wxSize(50,20),wxSP_ARROW_KEYS,0,0x7FFFFFFF,0); Layer->SetToolTip(_("Layer number")); - StartTime = new TimeEdit(this,STARTTIME_BOX,_T(""),wxDefaultPosition,wxSize(75,20),wxTE_PROCESS_ENTER,NumValidator()); + StartTime = new TimeEdit(this,STARTTIME_BOX,_T(""),wxDefaultPosition,wxSize(75,20),wxTE_PROCESS_ENTER); StartTime->SetToolTip(_("Start time")); StartTime->showModified = true; - EndTime = new TimeEdit(this,ENDTIME_BOX,_T(""),wxDefaultPosition,wxSize(75,20),wxTE_PROCESS_ENTER,NumValidator()); + EndTime = new TimeEdit(this,ENDTIME_BOX,_T(""),wxDefaultPosition,wxSize(75,20),wxTE_PROCESS_ENTER); EndTime->SetToolTip(_("End time")); EndTime->isEnd = true; EndTime->showModified = true; - Duration = new TimeEdit(this,DURATION_BOX,_T(""),wxDefaultPosition,wxSize(75,20),wxTE_PROCESS_ENTER,NumValidator()); + Duration = new TimeEdit(this,DURATION_BOX,_T(""),wxDefaultPosition,wxSize(75,20),wxTE_PROCESS_ENTER); Duration->SetToolTip(_("Line duration")); Duration->showModified = true; MarginL = new HiliModTextCtrl(this,MARGINL_BOX,_T(""),wxDefaultPosition,wxSize(40,20),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator()); @@ -141,9 +141,9 @@ SubsEditBox::SubsEditBox (wxWindow *parent,SubtitlesGrid *gridp) : wxPanel(paren TopSizer = new wxBoxSizer(wxHORIZONTAL); //TopSizer->Add(new FloatSpinCtrl(this,-1,wxDefaultPosition,wxSize(40,20),0,-20.0,50.0,0.0,0.5)); TopSizer->Add(CommentBox,0,wxRIGHT | wxALIGN_CENTER,5); - TopSizer->Add(StyleBox,1,wxRIGHT,5); - TopSizer->Add(ActorBox,1,wxRIGHT,5); - TopSizer->Add(Effect,1,0,0); + TopSizer->Add(StyleBox,2,wxRIGHT,5); + TopSizer->Add(ActorBox,2,wxRIGHT,5); + TopSizer->Add(Effect,3,0,0); // Middle sizer splitLineMode = true; diff --git a/aegisub/timeedit_ctrl.cpp b/aegisub/timeedit_ctrl.cpp index d32777dda..3d5f6ee30 100644 --- a/aegisub/timeedit_ctrl.cpp +++ b/aegisub/timeedit_ctrl.cpp @@ -48,14 +48,34 @@ TimeEdit::TimeEdit(wxWindow* parent, wxWindowID id, const wxString& value, const wxPoint& pos, const wxSize& size, long style, const wxValidator& validator, const wxString& name) : wxTextCtrl(parent,id,value,pos,size,wxTE_CENTRE | style,validator,name) { + // Set validator + wxTextValidator val(wxFILTER_INCLUDE_CHAR_LIST); + wxArrayString includes; + includes.Add(_T("0")); + includes.Add(_T("1")); + includes.Add(_T("2")); + includes.Add(_T("3")); + includes.Add(_T("4")); + includes.Add(_T("5")); + includes.Add(_T("6")); + includes.Add(_T("7")); + includes.Add(_T("8")); + includes.Add(_T("9")); + includes.Add(_T(".")); + includes.Add(_T(":")); + val.SetIncludes(includes); + SetValidator(val); + + // Other stuff SetValue(time.GetASSFormated()); ready = true; byFrame = false; isEnd = false; modified = false; showModified = false; - time.UpdateFromTextCtrl(this); + UpdateTime(); Connect(wxEVT_COMMAND_TEXT_UPDATED,wxCommandEventHandler(TimeEdit::OnModified)); + Connect(wxEVT_KILL_FOCUS,wxFocusEventHandler(TimeEdit::OnKillFocus)); } @@ -72,9 +92,9 @@ END_EVENT_TABLE() ////////////////// // Modified event void TimeEdit::OnModified(wxCommandEvent &event) { + event.Skip(); if (!ready) return; Modified(); - event.Skip(); } @@ -87,7 +107,7 @@ void TimeEdit::Modified() { // Update if (byFrame) Update(); - else time.UpdateFromTextCtrl(this); + else UpdateTime(); // Colour if (showModified && !modified) { @@ -144,16 +164,128 @@ void TimeEdit::UpdateText() { } +////////// +// Update +void TimeEdit::Update() { + // Update frame + if (byFrame) { + long temp; + GetValue().ToLong(&temp); + time.SetMS(VFR_Output.GetTimeAtFrame(temp,!isEnd)); + } + + // Update time if not on insertion mode + else if (!Options.AsBool(_T("Insert Mode on Time Boxes"))) { + UpdateTime(); + SetValue(time.GetASSFormated()); + } + + // Update modified status + if (modified && showModified) { + SetBackgroundColour(wxNullColour); + Refresh(); + } + modified = false; +} + + +///////////////////////////////////////////////// +// Reads value from a text control and update it +void TimeEdit::UpdateTime() { + bool insertion = Options.AsBool(_T("Insert Mode on Time Boxes")); + wxString text = GetValue(); + long start=0,end=0; + if (insertion) { + GetSelection(&start,&end); + if (start == end) { + wxString nextChar = text.Mid(start,1); + if (nextChar == _T(":") || nextChar == _T(".")) { + 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 + time.ParseASS(text); + if (insertion) { + SetValue(time.GetASSFormated()); + SetSelection(start,end); + } +} + + +/////////////// +// Key pressed +void TimeEdit::OnKeyDown(wxKeyEvent &event) { + // Get key ID + int key = event.GetKeyCode(); + bool insertMode = Options.AsBool(_T("Insert Mode on Time Boxes")); + Refresh(); + + // Check if it's an acceptable key + if (!event.ControlDown()) { + if (byFrame || !insertMode || (key != WXK_BACK && key != WXK_DELETE)) { + // 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(); + } + } + + else { + // Copy + if (key == 'C' || key == 'X') { + CopyTime(); + } + + // Paste + if (key == 'V') { + PasteTime(); + } + } +} + + +////////////// +// Focus lost +void TimeEdit::OnKillFocus(wxFocusEvent &event) { + if (!byFrame && !Options.AsBool(_T("Insert Mode on Time Boxes"))) { + if (time.GetASSFormated() != GetValue()) { + UpdateTime(); + SetValue(time.GetASSFormated()); + } + } + event.Skip(); +} + + +///// Mouse/copy/paste events down here ///// + /////////////// // Mouse event void TimeEdit::OnMouseEvent(wxMouseEvent &event) { // Right click context menu if (event.RightUp()) { - wxMenu menu; - menu.Append(Time_Edit_Copy,_T("&Copy")); - menu.Append(Time_Edit_Paste,_T("&Paste")); - PopupMenu(&menu); - return; + if (!byFrame && Options.AsBool(_T("Insert Mode on Time Boxes"))) { + wxMenu menu; + menu.Append(Time_Edit_Copy,_T("&Copy")); + menu.Append(Time_Edit_Paste,_T("&Paste")); + PopupMenu(&menu); + return; + } } // Allow other events through @@ -180,60 +312,6 @@ void TimeEdit::OnPaste(wxCommandEvent &event) { } -////////// -// Update -void TimeEdit::Update() { - // Update frame - if (byFrame) { - long temp; - GetValue().ToLong(&temp); - time.SetMS(VFR_Output.GetTimeAtFrame(temp,!isEnd)); - } - - // Update modified status - if (modified && showModified) { - SetBackgroundColour(wxNullColour); - Refresh(); - } - modified = false; -} - - -/////////////// -// Key pressed -void TimeEdit::OnKeyDown(wxKeyEvent &event) { - // Get key ID - int key = event.GetKeyCode(); - - // Check if it's an acceptable key - if (!event.ControlDown()) { - if (byFrame || (key != WXK_BACK && key != WXK_DELETE)) { - // Reset selection first, if necessary - if (!byFrame) { - long from=0,to=0; - GetSelection(&from,&to); - if (to != from) SetSelection(from,from); - } - - // Allow it through - event.Skip(); - } - } - - else { - // Copy - if (key == 'C' || key == 'X') { - CopyTime(); - } - - // Paste - if (key == 'V') { - PasteTime(); - } - } -} - - ///////////////////// // Copy to clipboard void TimeEdit::CopyTime() { diff --git a/aegisub/timeedit_ctrl.h b/aegisub/timeedit_ctrl.h index abd1c529d..6777f3cbb 100644 --- a/aegisub/timeedit_ctrl.h +++ b/aegisub/timeedit_ctrl.h @@ -55,12 +55,14 @@ private: void UpdateText(); void CopyTime(); void PasteTime(); + void UpdateTime(); void OnModified(wxCommandEvent &event); void OnMouseEvent(wxMouseEvent &event); void OnKeyDown(wxKeyEvent &event); void OnCopy(wxCommandEvent &event); void OnPaste(wxCommandEvent &event); + void OnKillFocus(wxFocusEvent &event); public: AssTime time;