mirror of https://github.com/odrling/Aegisub
1270 lines
34 KiB
C++
1270 lines
34 KiB
C++
// Copyright (c) 2005, Rodrigo Braz Monteiro
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright notice,
|
|
// this list of conditions and the following disclaimer in the documentation
|
|
// and/or other materials provided with the distribution.
|
|
// * Neither the name of the Aegisub Group nor the names of its contributors
|
|
// may be used to endorse or promote products derived from 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
|
|
//
|
|
// Website: http://aegisub.cellosoft.com
|
|
// Contact: mailto:zeratul@cellosoft.com
|
|
//
|
|
|
|
|
|
////////////
|
|
// Includes
|
|
#include "setup.h"
|
|
#include <wx/colordlg.h>
|
|
#include <wx/fontdlg.h>
|
|
#include "subs_edit_box.h"
|
|
#include "subs_edit_ctrl.h"
|
|
#include "subs_grid.h"
|
|
#include "ass_file.h"
|
|
#include "ass_dialogue.h"
|
|
#include "ass_style.h"
|
|
#include "ass_override.h"
|
|
#include "timeedit_ctrl.h"
|
|
#include "vfr.h"
|
|
#include "options.h"
|
|
#include "audio_display.h"
|
|
#include "hilimod_textctrl.h"
|
|
#include "video_display.h"
|
|
#include "validators.h"
|
|
#include "dialog_colorpicker.h"
|
|
#include "main.h"
|
|
#include "frame_main.h"
|
|
#include "utils.h"
|
|
#include "dialog_search_replace.h"
|
|
#include "idle_field_event.h"
|
|
|
|
|
|
|
|
///////////////
|
|
// Constructor
|
|
SubsEditBox::SubsEditBox (wxWindow *parent,SubtitlesGrid *gridp) : wxPanel(parent, -1, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL | wxRAISED_BORDER, _T("SubsEditBox"))
|
|
{
|
|
// Setup
|
|
audio = NULL;
|
|
grid = gridp;
|
|
grid->editBox = this;
|
|
enabled = false;
|
|
textEditReady = true;
|
|
controlState = true;
|
|
setupDone = false;
|
|
linen = -2;
|
|
|
|
// Top controls
|
|
wxArrayString styles;
|
|
styles.Add(_T(""));
|
|
CommentBox = new wxCheckBox(this,COMMENT_CHECKBOX,_("Comment"));
|
|
CommentBox->SetToolTip(_("Comment this line out. Commented lines don't show up on screen."));
|
|
StyleBox = new wxComboBox(this,STYLE_COMBOBOX,_T(""),wxDefaultPosition,wxSize(110,25),styles,wxCB_READONLY | wxTE_PROCESS_ENTER);
|
|
StyleBox->SetToolTip(_("Style for this line."));
|
|
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->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 HiliModTextCtrl(this,LAYER_BOX,_T(""),wxDefaultPosition,wxSize(40,20),wxTE_PROCESS_ENTER,NumValidator());
|
|
Layer->SetToolTip(_("Layer number"));
|
|
StartTime = new TimeEdit(this,STARTTIME_BOX,_T(""),wxDefaultPosition,wxSize(75,20),wxTE_PROCESS_ENTER,NumValidator());
|
|
StartTime->SetToolTip(_("Start time"));
|
|
StartTime->showModified = true;
|
|
EndTime = new TimeEdit(this,ENDTIME_BOX,_T(""),wxDefaultPosition,wxSize(75,20),wxTE_PROCESS_ENTER,NumValidator());
|
|
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->SetToolTip(_("Line duration"));
|
|
Duration->showModified = true;
|
|
MarginL = new HiliModTextCtrl(this,MARGINL_BOX,_T(""),wxDefaultPosition,wxSize(40,20),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator());
|
|
MarginL->SetToolTip(_("Left Margin (0 = default)"));
|
|
MarginL->SetMaxLength(4);
|
|
MarginR = new HiliModTextCtrl(this,MARGINR_BOX,_T(""),wxDefaultPosition,wxSize(40,20),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator());
|
|
MarginR->SetToolTip(_("Right Margin (0 = default)"));
|
|
MarginR->SetMaxLength(4);
|
|
MarginV = new HiliModTextCtrl(this,MARGINV_BOX,_T(""),wxDefaultPosition,wxSize(40,20),wxTE_CENTRE | wxTE_PROCESS_ENTER,NumValidator());
|
|
MarginV->SetToolTip(_("Vertical Margin (0 = default)"));
|
|
MarginV->SetMaxLength(4);
|
|
|
|
// Middle-bottom controls
|
|
Bold = new wxBitmapButton(this,BUTTON_BOLD,wxBITMAP(button_bold),wxDefaultPosition,wxSize(20,20));
|
|
Bold->SetToolTip(_("Bold"));
|
|
Italics = new wxBitmapButton(this,BUTTON_ITALICS,wxBITMAP(button_italics),wxDefaultPosition,wxSize(20,20));
|
|
Italics->SetToolTip(_("Italics"));
|
|
Underline = new wxBitmapButton(this,BUTTON_UNDERLINE,wxBITMAP(button_underline),wxDefaultPosition,wxSize(20,20));
|
|
Underline->SetToolTip(_("Underline"));
|
|
Strikeout = new wxBitmapButton(this,BUTTON_STRIKEOUT,wxBITMAP(button_strikeout),wxDefaultPosition,wxSize(20,20));
|
|
Strikeout->SetToolTip(_("Strikeout"));
|
|
FontName = new wxBitmapButton(this,BUTTON_FONT_NAME,wxBITMAP(button_fontname),wxDefaultPosition,wxSize(30,20));
|
|
FontName->SetToolTip(_("Font Face Name"));
|
|
Color1 = new wxBitmapButton(this,BUTTON_COLOR1,wxBITMAP(button_color1),wxDefaultPosition,wxSize(30,20));
|
|
Color1->SetToolTip(_("Primary color"));
|
|
Color2 = new wxBitmapButton(this,BUTTON_COLOR2,wxBITMAP(button_color2),wxDefaultPosition,wxSize(30,20));
|
|
Color2->SetToolTip(_("Secondary color"));
|
|
Color3 = new wxBitmapButton(this,BUTTON_COLOR3,wxBITMAP(button_color3),wxDefaultPosition,wxSize(30,20));
|
|
Color3->SetToolTip(_("Outline color"));
|
|
Color4 = new wxBitmapButton(this,BUTTON_COLOR4,wxBITMAP(button_color4),wxDefaultPosition,wxSize(30,20));
|
|
Color4->SetToolTip(_("Shadow color"));
|
|
ByTime = new wxRadioButton(this,RADIO_TIME_BY_TIME,_("Time"),wxDefaultPosition,wxDefaultSize,wxRB_GROUP);
|
|
ByTime->SetToolTip(_("Time by h:mm:ss.cs"));
|
|
ByFrame = new wxRadioButton(this,RADIO_TIME_BY_FRAME,_("Frame"));
|
|
ByFrame->SetToolTip(_("Time by frame number"));
|
|
|
|
// Top sizer
|
|
TopSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
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);
|
|
|
|
// Middle sizer
|
|
splitLineMode = true;
|
|
MiddleSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
MiddleSizer->Add(Layer,0,wxRIGHT,5);
|
|
MiddleSizer->Add(StartTime,0,wxRIGHT,0);
|
|
MiddleSizer->Add(EndTime,0,wxRIGHT,5);
|
|
MiddleSizer->Add(Duration,0,wxRIGHT,5);
|
|
MiddleSizer->Add(MarginL,0,0,0);
|
|
MiddleSizer->Add(MarginR,0,0,0);
|
|
MiddleSizer->Add(MarginV,0,0,0);
|
|
MiddleSizer->AddSpacer(5);
|
|
|
|
// Middle-bottom sizer
|
|
MiddleBotSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
MiddleBotSizer->Add(Bold);
|
|
MiddleBotSizer->Add(Italics);
|
|
MiddleBotSizer->Add(Underline);
|
|
MiddleBotSizer->Add(Strikeout);
|
|
MiddleBotSizer->Add(FontName);
|
|
MiddleBotSizer->AddSpacer(5);
|
|
MiddleBotSizer->Add(Color1);
|
|
MiddleBotSizer->Add(Color2);
|
|
MiddleBotSizer->Add(Color3);
|
|
MiddleBotSizer->Add(Color4,0,wxRIGHT,10);
|
|
MiddleBotSizer->Add(ByTime,0,wxRIGHT | wxALIGN_CENTER,5);
|
|
MiddleBotSizer->Add(ByFrame,0,wxRIGHT | wxALIGN_CENTER,5);
|
|
|
|
// Text editor
|
|
TextEdit = new SubsTextEditCtrl(this,EDIT_BOX,_T(""),wxDefaultPosition,wxSize(300,50));
|
|
TextEdit->PushEventHandler(new SubsEditBoxEvent(this));
|
|
TextEdit->control = this;
|
|
BottomSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
BottomSizer->Add(TextEdit,1,wxEXPAND,0);
|
|
|
|
// Main sizer
|
|
MainSizer = new wxBoxSizer(wxVERTICAL);
|
|
MainSizer->Add(TopSizer,0,wxEXPAND | wxLEFT | wxRIGHT | wxTOP,3);
|
|
MainSizer->Add(MiddleSizer,0,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3);
|
|
MainSizer->Add(MiddleBotSizer,0,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3);
|
|
MainSizer->Add(BottomSizer,1,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3);
|
|
|
|
// Set sizer
|
|
SetSizer(MainSizer);
|
|
MainSizer->SetSizeHints(this);
|
|
|
|
// HACK: Fix colour of bg of editbox
|
|
origBgColour = TextEdit->GetBackgroundColour();
|
|
disabledBgColour = GetBackgroundColour();
|
|
|
|
// Set split mode
|
|
setupDone = true;
|
|
SetSplitLineMode();
|
|
Update();
|
|
}
|
|
|
|
|
|
/////////////////////////////////
|
|
// Set split or single line mode
|
|
void SubsEditBox::SetSplitLineMode(wxSize newSize) {
|
|
// Widths
|
|
int topWidth;
|
|
if (newSize.GetWidth() == -1) topWidth = TopSizer->GetSize().GetWidth();
|
|
else topWidth = newSize.GetWidth()-GetSize().GetWidth()+GetClientSize().GetWidth();
|
|
int midMin = MiddleSizer->GetMinSize().GetWidth();
|
|
int botMin = MiddleBotSizer->GetMinSize().GetWidth();
|
|
|
|
// Currently split
|
|
if (splitLineMode) {
|
|
|
|
if (topWidth >= midMin + botMin) {
|
|
MainSizer->Detach(MiddleBotSizer);
|
|
MiddleSizer->Add(MiddleBotSizer);
|
|
Layout();
|
|
splitLineMode = false;
|
|
}
|
|
}
|
|
|
|
// Currently joined
|
|
else {
|
|
if (topWidth < midMin) {
|
|
MiddleSizer->Detach(MiddleBotSizer);
|
|
MainSizer->Insert(2,MiddleBotSizer,0,wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM,3);
|
|
Layout();
|
|
splitLineMode = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////
|
|
// Update function
|
|
void SubsEditBox::Update (bool timeOnly,bool weak) {
|
|
if (enabled) {
|
|
AssDialogue *curdiag = grid->GetDialogue(linen);
|
|
if (curdiag) {
|
|
// Controls
|
|
SetControlsState(true);
|
|
int start = curdiag->Start.GetMS();
|
|
int end = curdiag->End.GetMS();
|
|
StartTime->SetTime(start);
|
|
EndTime->SetTime(end);
|
|
Duration->SetTime(end-start);
|
|
if (!timeOnly) {
|
|
TextEdit->SetTextTo(curdiag->Text);
|
|
Layer->SetValue(wxString::Format(_T("%i"),curdiag->Layer));
|
|
MarginL->SetValue(curdiag->GetMarginString(0,false));
|
|
MarginR->SetValue(curdiag->GetMarginString(1,false));
|
|
MarginV->SetValue(curdiag->GetMarginString(2,false));
|
|
Effect->SetValue(curdiag->Effect);
|
|
CommentBox->SetValue(curdiag->Comment);
|
|
StyleBox->Select(StyleBox->FindString(curdiag->Style));
|
|
ActorBox->SetValue(curdiag->Actor);
|
|
ActorBox->SetStringSelection(curdiag->Actor);
|
|
|
|
// Force actor box to update its idle status
|
|
wxCommandEvent changeEvent(wxEVT_COMMAND_TEXT_UPDATED,ActorBox->GetId());
|
|
ActorBox->GetEventHandler()->AddPendingEvent(changeEvent);
|
|
}
|
|
|
|
// Audio
|
|
if (!weak) audio->SetDialogue(grid,curdiag,linen);
|
|
|
|
// Video
|
|
video->curLine = curdiag;
|
|
video->UpdateSubsRelativeTime();
|
|
}
|
|
else enabled = false;
|
|
}
|
|
|
|
else {
|
|
SetControlsState(false);
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////
|
|
// Update globals
|
|
void SubsEditBox::UpdateGlobals () {
|
|
// Styles
|
|
StyleBox->Clear();
|
|
StyleBox->Append(grid->ass->GetStyles());
|
|
|
|
// Actors
|
|
ActorBox->Freeze();
|
|
ActorBox->Clear();
|
|
int nrows = grid->GetRows();
|
|
wxString actor;
|
|
for (int i=0;i<nrows;i++) {
|
|
actor = grid->GetDialogue(i)->Actor;
|
|
if (ActorBox->FindString(actor) == wxNOT_FOUND) {
|
|
ActorBox->Append(actor);
|
|
}
|
|
}
|
|
ActorBox->Thaw();
|
|
|
|
// Set subs update
|
|
linen = -2;
|
|
TextEdit->SetSelection(0,0);
|
|
SetToLine(grid->GetFirstSelRow());
|
|
}
|
|
|
|
|
|
//////////////////
|
|
// Jump to a line
|
|
void SubsEditBox::SetToLine(int n,bool weak) {
|
|
// Set to nothing
|
|
if (n == -1) {
|
|
enabled = false;
|
|
}
|
|
|
|
// Set line
|
|
else if (grid->GetDialogue(n)) {
|
|
enabled = true;
|
|
if (n != linen) {
|
|
linen = n;
|
|
StartTime->Update();
|
|
EndTime->Update();
|
|
Duration->Update();
|
|
}
|
|
}
|
|
|
|
// Update controls
|
|
Update();
|
|
|
|
// Set video
|
|
if (video->loaded && !weak) {
|
|
wxString sync;
|
|
if (Search.hasFocus) sync = _T("Find update video");
|
|
else sync = _T("Sync video with subs");
|
|
|
|
if (Options.AsBool(sync) == true) {
|
|
video->Stop();
|
|
AssDialogue *cur = grid->GetDialogue(n);
|
|
if (cur) video->JumpToFrame(VFR_Output.GetFrameAtTime(cur->Start.GetMS(),true));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////
|
|
// Event table
|
|
BEGIN_EVENT_TABLE(SubsEditBox, wxPanel)
|
|
EVT_SCI_MODIFIED(EDIT_BOX,SubsEditBox::OnEditText)
|
|
EVT_SCI_STYLENEEDED(EDIT_BOX,SubsEditBox::OnNeedStyle)
|
|
EVT_SCI_KEY(EDIT_BOX,SubsEditBox::OnKeyDown)
|
|
EVT_SCI_CHARADDED(EDIT_BOX,SubsEditBox::OnCharAdded)
|
|
EVT_SCI_UPDATEUI(EDIT_BOX,SubsEditBox::OnUpdateUI)
|
|
|
|
EVT_CHECKBOX(SYNTAX_BOX, SubsEditBox::OnSyntaxBox)
|
|
EVT_RADIOBUTTON(RADIO_TIME_BY_FRAME, SubsEditBox::OnFrameRadio)
|
|
EVT_RADIOBUTTON(RADIO_TIME_BY_TIME, SubsEditBox::OnTimeRadio)
|
|
EVT_COMBOBOX(STYLE_COMBOBOX, SubsEditBox::OnStyleChange)
|
|
EVT_COMBOBOX(ACTOR_COMBOBOX, SubsEditBox::OnActorChange)
|
|
EVT_TEXT_ENTER(ACTOR_COMBOBOX, SubsEditBox::OnActorChange)
|
|
EVT_TEXT_ENTER(LAYER_BOX, SubsEditBox::OnLayerChange)
|
|
EVT_TEXT_ENTER(STARTTIME_BOX, SubsEditBox::OnStartTimeChange)
|
|
EVT_TEXT_ENTER(ENDTIME_BOX, SubsEditBox::OnEndTimeChange)
|
|
EVT_TEXT_ENTER(DURATION_BOX, SubsEditBox::OnDurationChange)
|
|
EVT_TEXT_ENTER(MARGINL_BOX, SubsEditBox::OnMarginLChange)
|
|
EVT_TEXT_ENTER(MARGINR_BOX, SubsEditBox::OnMarginRChange)
|
|
EVT_TEXT_ENTER(MARGINV_BOX, SubsEditBox::OnMarginVChange)
|
|
EVT_TEXT_ENTER(EFFECT_BOX, SubsEditBox::OnEffectChange)
|
|
EVT_CHECKBOX(COMMENT_CHECKBOX, SubsEditBox::OnCommentChange)
|
|
|
|
EVT_BUTTON(BUTTON_COLOR1,SubsEditBox::OnButtonColor1)
|
|
EVT_BUTTON(BUTTON_COLOR2,SubsEditBox::OnButtonColor2)
|
|
EVT_BUTTON(BUTTON_COLOR3,SubsEditBox::OnButtonColor3)
|
|
EVT_BUTTON(BUTTON_COLOR4,SubsEditBox::OnButtonColor4)
|
|
EVT_BUTTON(BUTTON_FONT_NAME,SubsEditBox::OnButtonFontFace)
|
|
EVT_BUTTON(BUTTON_BOLD,SubsEditBox::OnButtonBold)
|
|
EVT_BUTTON(BUTTON_ITALICS,SubsEditBox::OnButtonItalics)
|
|
EVT_BUTTON(BUTTON_UNDERLINE,SubsEditBox::OnButtonUnderline)
|
|
EVT_BUTTON(BUTTON_STRIKEOUT,SubsEditBox::OnButtonStrikeout)
|
|
|
|
EVT_SIZE(SubsEditBox::OnSize)
|
|
END_EVENT_TABLE()
|
|
|
|
|
|
///////////
|
|
// On size
|
|
void SubsEditBox::OnSize(wxSizeEvent &event) {
|
|
if (setupDone) SetSplitLineMode(event.GetSize());
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
/////////////////////
|
|
// Text edited event
|
|
void SubsEditBox::OnEditText(wxScintillaEvent &event) {
|
|
int modType = event.GetModificationType();
|
|
if (modType == (wxSCI_MOD_INSERTTEXT | wxSCI_PERFORMED_USER) || modType == (wxSCI_MOD_DELETETEXT | wxSCI_PERFORMED_USER)) {
|
|
//TextEdit->UpdateCallTip();
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////
|
|
// User Interface updated
|
|
void SubsEditBox::OnUpdateUI(wxScintillaEvent &event) {
|
|
TextEdit->UpdateCallTip();
|
|
}
|
|
|
|
|
|
//////////////
|
|
// Need style
|
|
void SubsEditBox::OnNeedStyle(wxScintillaEvent &event) {
|
|
// Check if it needs to fix text
|
|
wxString text = TextEdit->GetText();
|
|
if (text.Contains(_T("\n")) || text.Contains(_T("\r"))) {
|
|
TextEdit->SetTextTo(TextEdit->GetText());
|
|
}
|
|
|
|
// Just update style
|
|
else TextEdit->UpdateStyle();
|
|
}
|
|
|
|
|
|
///////////////////
|
|
// Character added
|
|
void SubsEditBox::OnCharAdded(wxScintillaEvent &event) {
|
|
int character = event.GetKey();
|
|
}
|
|
|
|
|
|
////////////
|
|
// Key down
|
|
void SubsEditBox::OnKeyDown(wxScintillaEvent &event) {
|
|
}
|
|
|
|
|
|
/////////////////////////////
|
|
// Syntax highlight checkbox
|
|
void SubsEditBox::OnSyntaxBox(wxCommandEvent &event) {
|
|
TextEdit->UpdateStyle();
|
|
Options.SetBool(_T("Syntax Highlight Enabled"),SyntaxHighlight->GetValue());
|
|
Options.Save();
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
//////////////////////////
|
|
// Time by frame radiobox
|
|
void SubsEditBox::OnFrameRadio(wxCommandEvent &event) {
|
|
if (ByFrame->GetValue()) {
|
|
StartTime->SetByFrame(true);
|
|
EndTime->SetByFrame(true);
|
|
Duration->SetByFrame(true);
|
|
grid->SetByFrame(true);
|
|
}
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
//////////////////////////
|
|
// Standard time radiobox
|
|
void SubsEditBox::OnTimeRadio(wxCommandEvent &event) {
|
|
if (ByTime->GetValue()) {
|
|
StartTime->SetByFrame(false);
|
|
EndTime->SetByFrame(false);
|
|
Duration->SetByFrame(false);
|
|
grid->SetByFrame(false);
|
|
}
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
// Sets state (enabled/disabled) for all controls
|
|
void SubsEditBox::SetControlsState (bool state) {
|
|
if (state == controlState) return;
|
|
controlState = state;
|
|
|
|
// HACK: TextEdit workaround the stupid colour lock bug
|
|
TextEdit->SetReadOnly(!state);
|
|
if (state) TextEdit->SetBackgroundColour(origBgColour);
|
|
else TextEdit->SetBackgroundColour(disabledBgColour);
|
|
|
|
// Sets controls
|
|
StartTime->Enable(state);
|
|
EndTime->Enable(state);
|
|
Duration->Enable(state);
|
|
Layer->Enable(state);
|
|
MarginL->Enable(state);
|
|
MarginR->Enable(state);
|
|
MarginV->Enable(state);
|
|
Effect->Enable(state);
|
|
CommentBox->Enable(state);
|
|
StyleBox->Enable(state);
|
|
ActorBox->Enable(state);
|
|
ByTime->Enable(state);
|
|
//SyntaxHighlight->Enable(state);
|
|
Bold->Enable(state);
|
|
Italics->Enable(state);
|
|
Underline->Enable(state);
|
|
Strikeout->Enable(state);
|
|
Color1->Enable(state);
|
|
Color2->Enable(state);
|
|
Color3->Enable(state);
|
|
Color4->Enable(state);
|
|
FontName->Enable(state);
|
|
|
|
UpdateFrameTiming();
|
|
|
|
// Clear values if it's false
|
|
if (state==false) {
|
|
TextEdit->SetTextTo(_T(""));
|
|
StartTime->SetTime(0);
|
|
EndTime->SetTime(0);
|
|
Duration->SetTime(0);
|
|
Layer->SetValue(_T(""));
|
|
MarginL->SetValue(_T(""));
|
|
MarginR->SetValue(_T(""));
|
|
MarginV->SetValue(_T(""));
|
|
Effect->SetValue(_T(""));
|
|
CommentBox->SetValue(false);
|
|
}
|
|
}
|
|
|
|
|
|
////////////////////////////////////
|
|
// Disables or enables frame timing
|
|
void SubsEditBox::UpdateFrameTiming () {
|
|
if (VFR_Output.IsLoaded()) ByFrame->Enable(enabled);
|
|
else {
|
|
ByFrame->Enable(false);
|
|
ByTime->SetValue(true);
|
|
StartTime->SetByFrame(false);
|
|
EndTime->SetByFrame(false);
|
|
grid->SetByFrame(false);
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////
|
|
// Style changed
|
|
void SubsEditBox::OnStyleChange(wxCommandEvent &event) {
|
|
grid->BeginBatch();
|
|
wxArrayInt sel = grid->GetSelection();
|
|
int n = sel.Count();
|
|
AssDialogue *cur;
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
cur->Style = StyleBox->GetValue();
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
}
|
|
|
|
|
|
/////////////////
|
|
// Style changed
|
|
void SubsEditBox::OnActorChange(wxCommandEvent &event) {
|
|
grid->BeginBatch();
|
|
wxArrayInt sel = grid->GetSelection();
|
|
AssDialogue *cur;
|
|
wxString actor = ActorBox->GetValue();
|
|
|
|
// Update rows
|
|
int n = sel.Count();
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
cur->Actor = actor;
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
|
|
// Add actor to list
|
|
if (ActorBox->GetString(0).IsEmpty()) ActorBox->Delete(0);
|
|
if (ActorBox->FindString(actor) == wxNOT_FOUND) {
|
|
ActorBox->Append(actor);
|
|
}
|
|
|
|
// Update grid
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
}
|
|
|
|
|
|
/////////////////
|
|
// Layer changed
|
|
void SubsEditBox::OnLayerChange(wxCommandEvent &event) {
|
|
// Value
|
|
long temp;
|
|
Layer->GetValue().ToLong(&temp);
|
|
|
|
// Update
|
|
Layer->Commited();
|
|
grid->BeginBatch();
|
|
|
|
// Get selection
|
|
wxArrayInt sel = grid->GetSelection();
|
|
|
|
// Update
|
|
int n = sel.Count();
|
|
AssDialogue *cur;
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
cur->Layer = temp;
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
|
|
// Done
|
|
Layer->SetValue(wxString::Format(_("%i"),temp));
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
}
|
|
|
|
|
|
//////////////////////
|
|
// Start time changed
|
|
void SubsEditBox::OnStartTimeChange(wxCommandEvent &event) {
|
|
if (StartTime->time > EndTime->time) StartTime->SetTime(EndTime->time.GetMS());
|
|
bool join = Options.AsBool(_T("Link Time Boxes Commit")) && EndTime->HasBeenModified();
|
|
StartTime->Update();
|
|
if (join) EndTime->Update();
|
|
CommitTimes(true,join,true);
|
|
}
|
|
|
|
|
|
////////////////////
|
|
// End time changed
|
|
void SubsEditBox::OnEndTimeChange(wxCommandEvent &event) {
|
|
if (StartTime->time > EndTime->time) EndTime->SetTime(StartTime->time.GetMS());
|
|
bool join = Options.AsBool(_T("Link Time Boxes Commit")) && StartTime->HasBeenModified();
|
|
EndTime->Update();
|
|
if (join) StartTime->Update();
|
|
CommitTimes(join,true,false);
|
|
}
|
|
|
|
|
|
////////////////////
|
|
// Duration changed
|
|
void SubsEditBox::OnDurationChange(wxCommandEvent &event) {
|
|
EndTime->SetTime(StartTime->time.GetMS() + Duration->time.GetMS());
|
|
Duration->Update();
|
|
CommitTimes(false,true,true);
|
|
}
|
|
|
|
|
|
///////////////////////
|
|
// Commit time changes
|
|
void SubsEditBox::CommitTimes(bool start,bool end,bool fromStart) {
|
|
// Get selection
|
|
if (!start && !end) return;
|
|
grid->BeginBatch();
|
|
wxArrayInt sel = grid->GetSelection();
|
|
int n = sel.Count();
|
|
if (n == 0) return;
|
|
AssDialogue *cur;
|
|
Duration->SetTime(EndTime->time.GetMS() - StartTime->time.GetMS());
|
|
|
|
// Update lines
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
// Set times
|
|
if (start) cur->Start = StartTime->time;
|
|
if (end) cur->End = EndTime->time;
|
|
|
|
// Ensure that they have positive length
|
|
if (cur->Start > cur->End) {
|
|
if (fromStart) cur->End = cur->Start;
|
|
else cur->Start = cur->End;
|
|
}
|
|
|
|
// Update
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
|
|
// Commit
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
audio->SetDialogue(grid,grid->GetDialogue(sel[0]),sel[0]);
|
|
video->UpdateSubsRelativeTime();
|
|
}
|
|
|
|
|
|
////////////////////
|
|
// Margin L changed
|
|
void SubsEditBox::OnMarginLChange(wxCommandEvent &event) {
|
|
MarginL->Commited();
|
|
grid->BeginBatch();
|
|
wxArrayInt sel = grid->GetSelection();
|
|
int n = sel.Count();
|
|
AssDialogue *cur;
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
cur->SetMarginString(MarginL->GetValue(),0);
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
MarginL->SetValue(cur->GetMarginString(0,false));
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
}
|
|
|
|
|
|
////////////////////
|
|
// Margin R changed
|
|
void SubsEditBox::OnMarginRChange(wxCommandEvent &event) {
|
|
MarginR->Commited();
|
|
grid->BeginBatch();
|
|
wxArrayInt sel = grid->GetSelection();
|
|
int n = sel.Count();
|
|
AssDialogue *cur;
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
cur->SetMarginString(MarginR->GetValue(),1);
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
MarginR->SetValue(cur->GetMarginString(1,false));
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
}
|
|
|
|
|
|
////////////////////
|
|
// Margin V changed
|
|
void SubsEditBox::OnMarginVChange(wxCommandEvent &event) {
|
|
MarginV->Commited();
|
|
grid->BeginBatch();
|
|
wxArrayInt sel = grid->GetSelection();
|
|
int n = sel.Count();
|
|
AssDialogue *cur;
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
cur->SetMarginString(MarginV->GetValue(),2);
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
MarginV->SetValue(cur->GetMarginString(2,false));
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
}
|
|
|
|
|
|
//////////////////
|
|
// Effect changed
|
|
void SubsEditBox::OnEffectChange(wxCommandEvent &event) {
|
|
Effect->Commited();
|
|
grid->BeginBatch();
|
|
wxArrayInt sel = grid->GetSelection();
|
|
int n = sel.Count();
|
|
AssDialogue *cur;
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
cur->Effect = Effect->GetValue();
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
}
|
|
|
|
|
|
/////////////////////////
|
|
// Comment state changed
|
|
void SubsEditBox::OnCommentChange(wxCommandEvent &event) {
|
|
grid->BeginBatch();
|
|
wxArrayInt sel = grid->GetSelection();
|
|
int n = sel.Count();
|
|
AssDialogue *cur;
|
|
for (int i=0;i<n;i++) {
|
|
cur = grid->GetDialogue(sel[i]);
|
|
if (cur) {
|
|
cur->Comment = CommentBox->GetValue();
|
|
cur->UpdateData();
|
|
}
|
|
}
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
grid->EndBatch();
|
|
}
|
|
|
|
|
|
///////////////////////
|
|
// Event handler class
|
|
SubsEditBoxEvent::SubsEditBoxEvent(SubsEditBox *_control) {
|
|
control = _control;
|
|
}
|
|
|
|
BEGIN_EVENT_TABLE(SubsEditBoxEvent, wxEvtHandler)
|
|
EVT_KEY_DOWN(SubsEditBoxEvent::OnKeyPress)
|
|
END_EVENT_TABLE()
|
|
|
|
void SubsEditBoxEvent::OnKeyPress(wxKeyEvent &event) {
|
|
control->KeyPress(event);
|
|
}
|
|
|
|
|
|
///////////////////////
|
|
// Actual text changed
|
|
void SubsEditBox::KeyPress(wxKeyEvent &event) {
|
|
int key = event.GetKeyCode();
|
|
|
|
if (key == WXK_RETURN || key == WXK_NUMPAD_ENTER) {
|
|
if (enabled) {
|
|
// Update line
|
|
CommitText();
|
|
|
|
// Next line if control is not held down
|
|
bool updated = false;
|
|
if (!event.m_controlDown) {
|
|
AssDialogue *cur = grid->GetDialogue(linen);
|
|
int nrows = grid->GetRows();
|
|
int next = linen+1;
|
|
if (next >= nrows) {
|
|
AssDialogue *newline = new AssDialogue;
|
|
newline->Start = cur->End;
|
|
newline->End.SetMS(cur->End.GetMS()+5000);
|
|
newline->Style = cur->Style;
|
|
newline->UpdateData();
|
|
grid->InsertLine(newline,next-1,true,true);
|
|
updated = true;
|
|
}
|
|
grid->SelectRow(next);
|
|
grid->MakeCellVisible(next,0);
|
|
SetToLine(next);
|
|
if (next >= nrows) return;
|
|
}
|
|
|
|
// Update file
|
|
if (!updated) {
|
|
grid->ass->FlagAsModified();
|
|
grid->CommitChanges();
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
event.Skip();
|
|
}
|
|
|
|
|
|
///////////////
|
|
// Commit text
|
|
void SubsEditBox::CommitText(bool weak) {
|
|
AssDialogue *cur = grid->GetDialogue(linen);
|
|
|
|
// Update line
|
|
if (cur) {
|
|
cur->Text = TextEdit->GetText();
|
|
cur->UpdateData();
|
|
if (!weak) {
|
|
grid->Refresh(false);
|
|
audio->SetDialogue(grid,cur,linen);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////
|
|
// Gets block number at text position
|
|
int SubsEditBox::BlockAtPos(int pos) {
|
|
// Prepare
|
|
int n=0;
|
|
wxString text = TextEdit->GetText();;
|
|
int max = text.Length()-1;
|
|
|
|
// Find block number at pos
|
|
for (int i=0;i<=pos;i++) {
|
|
if (i > 0 && text[i] == _T('{')) n++;
|
|
if (text[i] == _T('}') && i != max && i != pos && i != pos -1 && (i+1 == max || text[i+1] != _T('{'))) n++;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
|
|
////////////////
|
|
// Set override
|
|
void SubsEditBox::SetOverride (wxString tagname,wxString preValue,int forcePos) {
|
|
// Selection
|
|
int selstart, selend;
|
|
if (forcePos != -1) {
|
|
selstart = forcePos;
|
|
selend = forcePos;
|
|
}
|
|
else TextEdit->GetSelection(&selstart,&selend);
|
|
int len = TextEdit->GetText().Length();
|
|
selstart = MID(0,selstart,len);
|
|
selend = MID(0,selend,len);
|
|
|
|
// Current tag name
|
|
wxString alttagname = tagname;
|
|
if (tagname == _T("\\1c")) tagname = _T("\\c");
|
|
if (tagname == _T("\\fr")) tagname = _T("\\frz");
|
|
|
|
// Get block at start
|
|
size_t blockn = BlockAtPos(selstart);
|
|
AssDialogue *line = new AssDialogue();
|
|
line->Text = TextEdit->GetText();
|
|
line->ParseASSTags();
|
|
AssDialogueBlock *block = line->Blocks.at(blockn);
|
|
|
|
// Insert variables
|
|
wxString insert;
|
|
wxString insert2;
|
|
int shift;
|
|
int nInserted = 1;
|
|
|
|
// Default value
|
|
wxColour startcolor;
|
|
wxFont startfont;
|
|
float startangle;
|
|
float startScale;
|
|
bool isColor = false;
|
|
bool isFont = false;
|
|
bool isGeneric = false;
|
|
bool isFlag = false;
|
|
bool isAngle = false;
|
|
bool isScale = false;
|
|
bool state = false;
|
|
AssStyle *style = grid->ass->GetStyle(grid->GetDialogue(linen)->Style);
|
|
AssStyle defStyle;
|
|
if (style == NULL) style = &defStyle;
|
|
if (tagname == _T("\\b")) {
|
|
state = style->bold;
|
|
isFlag = true;
|
|
}
|
|
else if (tagname == _T("\\i")) {
|
|
state = style->italic;
|
|
isFlag = true;
|
|
}
|
|
else if (tagname == _T("\\u")) {
|
|
state = style->underline;
|
|
isFlag = true;
|
|
}
|
|
else if (tagname == _T("\\s")) {
|
|
state = style->strikeout;
|
|
isFlag = true;
|
|
}
|
|
else if (tagname == _T("\\fn")) {
|
|
startfont.SetFaceName(style->font);
|
|
startfont.SetPointSize(style->fontsize);
|
|
startfont.SetWeight(style->bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL);
|
|
startfont.SetStyle(style->italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL);
|
|
startfont.SetUnderlined(style->underline);
|
|
isFont = true;
|
|
}
|
|
else if (tagname == _T("\\c")) {
|
|
startcolor = style->primary.GetWXColor();
|
|
isColor = true;
|
|
}
|
|
else if (tagname == _T("\\2c")) {
|
|
startcolor = style->secondary.GetWXColor();
|
|
isColor = true;
|
|
}
|
|
else if (tagname == _T("\\3c")) {
|
|
startcolor = style->outline.GetWXColor();
|
|
isColor = true;
|
|
}
|
|
else if (tagname == _T("\\4c")) {
|
|
startcolor = style->shadow.GetWXColor();
|
|
isColor = true;
|
|
}
|
|
else if (tagname == _T("\\pos")) {
|
|
isGeneric = true;
|
|
}
|
|
else if (tagname == _T("\\frz")) {
|
|
startangle = style->angle;
|
|
isAngle = true;
|
|
}
|
|
else if (tagname == _T("\\frx") || tagname == _T("\\fry")) {
|
|
startangle = 0.0;
|
|
isAngle = true;
|
|
}
|
|
else if (tagname == _T("\\fscx")) {
|
|
startScale = style->scalex;
|
|
isScale = true;
|
|
}
|
|
else if (tagname == _T("\\fscy")) {
|
|
startScale = style->scaley;
|
|
isScale = true;
|
|
}
|
|
else if (tagname == _T("\\clip")) {
|
|
isGeneric = true;
|
|
}
|
|
bool hasEnd = isFlag;
|
|
|
|
// Find current value of style
|
|
AssDialogueBlockOverride *override;
|
|
AssOverrideTag *tag;
|
|
if (isFont || isColor || isFlag || isAngle) {
|
|
for (size_t i=0;i<=blockn;i++) {
|
|
override = AssDialogueBlock::GetAsOverride(line->Blocks.at(i));
|
|
if (override) {
|
|
for (size_t j=0;j<override->Tags.size();j++) {
|
|
tag = override->Tags.at(j);
|
|
if (tag->Name == tagname || tag->Name == alttagname || tagname == _T("\\fn")) {
|
|
if (isColor) startcolor = tag->Params.at(0)->AsColour();
|
|
if (isFlag) state = tag->Params.at(0)->AsBool();
|
|
if (isFont) {
|
|
if (tag->Name == _T("\\fn")) startfont.SetFaceName(tag->Params.at(0)->AsText());
|
|
if (tag->Name == _T("\\fs")) startfont.SetPointSize(tag->Params.at(0)->AsInt());
|
|
if (tag->Name == _T("\\b")) startfont.SetWeight((tag->Params.at(0)->AsInt() > 0) ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL);
|
|
if (tag->Name == _T("\\i")) startfont.SetStyle(tag->Params.at(0)->AsBool() ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL);
|
|
if (tag->Name == _T("\\u")) startfont.SetUnderlined(tag->Params.at(0)->AsBool());
|
|
}
|
|
if (isAngle) startangle = tag->Params.at(0)->AsFloat();
|
|
if (isScale) startScale = tag->Params.at(0)->AsFloat();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Overrides being inserted
|
|
wxArrayString insertTags;
|
|
|
|
// Toggle value
|
|
if (isFlag) {
|
|
state = !state;
|
|
int stateval = 0;
|
|
if (state) stateval = 1;
|
|
|
|
// Generate insert string
|
|
insert = tagname + wxString::Format(_T("%i"),stateval);
|
|
insert2 = tagname + wxString::Format(_T("%i"),1-stateval);
|
|
insertTags.Add(tagname);
|
|
}
|
|
|
|
// Choose color
|
|
if (isColor) {
|
|
// Pick from dialog
|
|
//wxColour color = wxGetColourFromUser(this,startcolor);
|
|
wxColour color = GetColorFromUser(((AegisubApp*)wxTheApp)->frame, startcolor);
|
|
if (!color.Ok() || color == startcolor) {
|
|
delete line;
|
|
return;
|
|
}
|
|
|
|
// Generate insert string
|
|
AssColor asscolor(color);
|
|
insert = tagname + asscolor.GetASSFormatted(false);
|
|
insertTags.Add(tagname);
|
|
}
|
|
|
|
// Choose font
|
|
if (isFont) {
|
|
// Pick from dialog
|
|
wxFont font = wxGetFontFromUser(this,startfont);
|
|
if (!font.Ok()) {
|
|
delete line;
|
|
return;
|
|
}
|
|
|
|
// Generate insert string
|
|
nInserted = 0;
|
|
if (font.GetFaceName() != startfont.GetFaceName()) {
|
|
insert = _T("\\fn") + font.GetFaceName();
|
|
nInserted++;
|
|
insertTags.Add(_T("\\fn"));
|
|
}
|
|
if (font.GetPointSize() != startfont.GetPointSize()) {
|
|
insert += _T("\\fs") + wxString::Format(_T("%i"),font.GetPointSize());
|
|
nInserted++;
|
|
insertTags.Add(_T("\\fs"));
|
|
}
|
|
if (font.GetWeight() != startfont.GetWeight()) {
|
|
insert += _T("\\b") + wxString::Format(_T("%i"),font.GetWeight() == wxFONTWEIGHT_BOLD ? 1 : 0);
|
|
nInserted++;
|
|
insertTags.Add(_T("\\b"));
|
|
}
|
|
if (font.GetStyle() != startfont.GetStyle()) {
|
|
insert += _T("\\i") + wxString::Format(_T("%i"),font.GetStyle() == wxFONTSTYLE_ITALIC ? 1 : 0);
|
|
nInserted++;
|
|
insertTags.Add(_T("\\i"));
|
|
}
|
|
if (font.GetUnderlined() != startfont.GetUnderlined()) {
|
|
insert += _T("\\u") + wxString::Format(_T("%i"),font.GetUnderlined() ? 1 : 0);
|
|
nInserted++;
|
|
insertTags.Add(_T("\\u"));
|
|
}
|
|
if (insert.IsEmpty()) {
|
|
delete line;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Generic tag
|
|
if (isGeneric) {
|
|
insert = tagname + preValue;
|
|
insertTags.Add(tagname);
|
|
}
|
|
|
|
// Angle
|
|
if (isAngle) {
|
|
insert = tagname + preValue;
|
|
insertTags.Add(tagname);
|
|
}
|
|
|
|
// Scale
|
|
if (isScale) {
|
|
insert = tagname + preValue;
|
|
insertTags.Add(tagname);
|
|
}
|
|
|
|
// Get current block as plain or override
|
|
AssDialogueBlockPlain *plain = AssDialogueBlock::GetAsPlain(block);
|
|
override = AssDialogueBlock::GetAsOverride(block);
|
|
|
|
// Plain
|
|
if (plain) {
|
|
// Insert in text
|
|
line->Text = line->Text.Left(selstart) + _T("{") + insert + _T("}") + line->Text.Mid(selstart);
|
|
shift = 2 + insert.Length();
|
|
line->ParseASSTags();
|
|
}
|
|
|
|
// Override
|
|
else if (override) {
|
|
// Insert new tag
|
|
override->text += insert;
|
|
override->ParseTags();
|
|
shift = insert.Length();
|
|
|
|
// Remove old of same
|
|
for (size_t i=0;i<override->Tags.size()-nInserted;i++) {
|
|
//if (insert.Contains(override->Tags.at(i)->Name)) {
|
|
if (insertTags.Index(override->Tags.at(i)->Name) != wxNOT_FOUND) {
|
|
shift -= override->Tags.at(i)->ToString().Length();
|
|
override->Tags.erase(override->Tags.begin() + i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
// Update line
|
|
line->UpdateText();
|
|
}
|
|
|
|
// End
|
|
if (hasEnd && selend != selstart) {
|
|
// Prepare variables again
|
|
int origStart = selstart;
|
|
selstart = selend + shift;
|
|
insert = insert2;
|
|
TextEdit->SetTextTo(line->Text);
|
|
blockn = BlockAtPos(selstart);
|
|
block = line->Blocks.at(blockn);
|
|
plain = AssDialogueBlock::GetAsPlain(block);
|
|
override = AssDialogueBlock::GetAsOverride(block);
|
|
|
|
// Plain
|
|
if (plain) {
|
|
// Insert in text
|
|
line->Text = line->Text.Left(selstart) + _T("{") + insert + _T("}") + line->Text.Mid(selstart);
|
|
}
|
|
|
|
// Override
|
|
else if (override) {
|
|
// Insert new tag
|
|
override->text += insert;
|
|
override->ParseTags();
|
|
|
|
// Remove old of same
|
|
for (size_t i=0;i<override->Tags.size()-nInserted;i++) {
|
|
if (insert.Contains(override->Tags.at(i)->Name)) {
|
|
shift -= override->Tags.at(i)->ToString().Length();
|
|
override->Tags.erase(override->Tags.begin() + i);
|
|
i--;
|
|
}
|
|
}
|
|
|
|
// Update line
|
|
line->UpdateText();
|
|
}
|
|
|
|
// Shift selection
|
|
selstart = origStart;
|
|
TextEdit->SetSelectionU(origStart+shift,selend+shift);
|
|
}
|
|
|
|
// Commit changes and shift selection
|
|
TextEdit->SetTextTo(line->Text);
|
|
delete line;
|
|
TextEdit->SetSelectionU(selstart+shift,selend+shift);
|
|
TextEdit->SetFocus();
|
|
}
|
|
|
|
|
|
/////////////////////
|
|
// Set primary color
|
|
void SubsEditBox::OnButtonColor1(wxCommandEvent &event) {
|
|
SetOverride(_T("\\1c"));
|
|
}
|
|
|
|
|
|
///////////////////////
|
|
// Set secondary color
|
|
void SubsEditBox::OnButtonColor2(wxCommandEvent &event) {
|
|
SetOverride(_T("\\2c"));
|
|
}
|
|
|
|
|
|
/////////////////////
|
|
// Set outline color
|
|
void SubsEditBox::OnButtonColor3(wxCommandEvent &event) {
|
|
SetOverride(_T("\\3c"));
|
|
}
|
|
|
|
|
|
////////////////////
|
|
// Set shadow color
|
|
void SubsEditBox::OnButtonColor4(wxCommandEvent &event) {
|
|
SetOverride(_T("\\4c"));
|
|
}
|
|
|
|
|
|
/////////////////
|
|
// Set font face
|
|
void SubsEditBox::OnButtonFontFace(wxCommandEvent &event) {
|
|
SetOverride(_T("\\fn"));
|
|
}
|
|
|
|
|
|
////////
|
|
// Bold
|
|
void SubsEditBox::OnButtonBold(wxCommandEvent &event) {
|
|
SetOverride(_T("\\b"));
|
|
}
|
|
|
|
|
|
///////////
|
|
// Italics
|
|
void SubsEditBox::OnButtonItalics(wxCommandEvent &event) {
|
|
SetOverride(_T("\\i"));
|
|
}
|
|
|
|
|
|
/////////////
|
|
// Underline
|
|
void SubsEditBox::OnButtonUnderline(wxCommandEvent &event) {
|
|
SetOverride(_T("\\u"));
|
|
}
|
|
|
|
|
|
/////////////
|
|
// Strikeout
|
|
void SubsEditBox::OnButtonStrikeout(wxCommandEvent &event) {
|
|
SetOverride(_T("\\s"));
|
|
}
|
|
|