From 54f5c82296282d86deabf28dc5a52825287f3d13 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Sat, 23 Jun 2007 06:07:32 +0000 Subject: [PATCH] Added a non-overwrite mode for text edit controls, which can be set on the menu. Some basic testing was done, but not exhaustive, which means that it MIGHT be buggy (also, the old mode might have been bugged) Originally committed to SVN as r1295. --- aegisub/ass_time.cpp | 64 ++++++------ aegisub/ass_time.h | 1 - aegisub/dialog_jumpto.cpp | 52 +++++----- aegisub/dialog_jumpto.h | 33 ++---- aegisub/dialog_options.cpp | 6 +- aegisub/options.cpp | 5 + aegisub/subs_edit_box.cpp | 14 +-- aegisub/timeedit_ctrl.cpp | 202 +++++++++++++++++++++++++------------ aegisub/timeedit_ctrl.h | 2 + 9 files changed, 215 insertions(+), 164 deletions(-) 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;