diff --git a/aegisub/src/command/edit.cpp b/aegisub/src/command/edit.cpp index 69e125f0a..921e29ffb 100644 --- a/aegisub/src/command/edit.cpp +++ b/aegisub/src/command/edit.cpp @@ -49,10 +49,14 @@ #include "../ass_dialogue.h" #include "../ass_file.h" #include "../ass_karaoke.h" +#include "../ass_override.h" +#include "../ass_style.h" +#include "../dialog_colorpicker.h" #include "../dialog_search_replace.h" #include "../include/aegisub/context.h" #include "../subs_edit_ctrl.h" #include "../subs_grid.h" +#include "../text_selection_controller.h" #include "../video_context.h" namespace { @@ -74,16 +78,319 @@ struct validate_sel_multiple : public Command { } }; +template +T get_value(AssDialogue const& line, int blockn, T initial, wxString const& tag, wxString alt = wxString()) { + for (int i = blockn; i >= 0; i--) { + AssDialogueBlockOverride *ovr = dynamic_cast(line.Blocks[i]); + if (!ovr) continue; + + for (int j = (int)ovr->Tags.size() - 1; j >= 0; j--) { + if (ovr->Tags[j]->Name == tag || ovr->Tags[j]->Name == alt) { + return ovr->Tags[j]->Params[0]->Get(initial); + } + } + } + return initial; +} + +/// Get the block index in the text of the position +int block_at_pos(wxString const& text, int pos) { + int n = 0; + int max = text.size() - 1; + for (int i = 0; i <= pos && i <= max; ++i) { + if (i > 0 && text[i] == '{') + n++; + if (text[i] == '}' && i != max && i != pos && i != pos -1 && (i+1 == max || text[i+1] != '{')) + n++; + } + + return n; +} + +void set_tag(const agi::Context *c, wxString const& tag, wxString const& value, bool at_end = false) { + AssDialogue * const line = c->selectionController->GetActiveLine(); + if (line->Blocks.empty()) + line->ParseASSTags(); + + int sel_start = c->textSelectionController->GetSelectionStart(); + int sel_end = c->textSelectionController->GetSelectionEnd(); + int start = at_end ? sel_end : sel_start; + int blockn = block_at_pos(line->Text, start); + + AssDialogueBlockPlain *plain = 0; + AssDialogueBlockOverride *ovr = 0; + while (blockn >= 0) { + AssDialogueBlock *block = line->Blocks[blockn]; + if (dynamic_cast(block)) + --blockn; + else if ((plain = dynamic_cast(block))) { + // Cursor is in a comment block, so try the previous block instead + if (plain->GetText().StartsWith("{")) { + --blockn; + start = line->Text.rfind('{', start); + } + else + break; + } + else { + ovr = dynamic_cast(block); + assert(ovr); + break; + } + } + + // If we didn't hit a suitable block for inserting the override just put + // it at the beginning of the line + if (blockn < 0) + start = 0; + + wxString insert = tag + value; + int shift = insert.size(); + if (plain || blockn < 0) { + line->Text = line->Text.Left(start) + "{" + insert + "}" + line->Text.Mid(start); + shift += 2; + line->ParseASSTags(); + } + else if(ovr) { + wxString alt; + if (tag == "\\c") alt = "\\1c"; + // Remove old of same + bool found = false; + for (size_t i = 0; i < ovr->Tags.size(); i++) { + wxString name = ovr->Tags[i]->Name; + if (tag == name || alt == name) { + shift -= ((wxString)*ovr->Tags[i]).size(); + if (found) { + delete ovr->Tags[i]; + ovr->Tags.erase(ovr->Tags.begin() + i); + i--; + } + else { + ovr->Tags[i]->Params[0]->Set(value); + ovr->Tags[i]->Params[0]->omitted = false; + found = true; + } + } + } + if (!found) + ovr->AddTag(insert); + + line->UpdateText(); + } + else + assert(false); + + if (!at_end) + c->textSelectionController->SetSelection(sel_start + shift, sel_end + shift); +} + +void set_text(AssDialogue *line, wxString const& value) { + line->Text = value; +} + +void commit_text(agi::Context const * const c, wxString const& desc, int *commit_id = 0) { + SubtitleSelection const& sel = c->selectionController->GetSelectedSet(); + for_each(sel.begin(), sel.end(), + bind(set_text, std::tr1::placeholders::_1, c->selectionController->GetActiveLine()->Text)); + int new_commit_id = c->ass->Commit(desc, AssFile::COMMIT_DIAG_TEXT, commit_id ? *commit_id : -1, sel.size() == 1 ? *sel.begin() : 0); + if (commit_id) + *commit_id = new_commit_id; +} + +void toggle_override_tag(const agi::Context *c, bool (AssStyle::*field), const char *tag, wxString const& undo_msg) { + AssDialogue *const line = c->selectionController->GetActiveLine(); + AssStyle const* const style = c->ass->GetStyle(line->Style); + bool state = style ? style->*field : AssStyle().*field; + + line->ParseASSTags(); + int sel_start = c->textSelectionController->GetSelectionStart(); + int sel_end = c->textSelectionController->GetSelectionEnd(); + int blockn = block_at_pos(line->Text, sel_start); + + state = get_value(*line, blockn, state, tag); + + set_tag(c, tag, state ? "0" : "1"); + if (sel_start != sel_end) + set_tag(c, tag, state ? "1" : "0", true); + + line->ClearBlocks(); + commit_text(c, undo_msg); +} + +void got_color(const agi::Context *c, const char *tag, int *commit_id, wxColour new_color) { + if (new_color.Ok()) { + set_tag(c, tag, AssColor(new_color).GetASSFormatted(false)); + commit_text(c, _("set color"), commit_id); + } +} + +void show_color_picker(const agi::Context *c, AssColor (AssStyle::*field), const char *tag, const char *alt) { + AssDialogue *const line = c->selectionController->GetActiveLine(); + AssStyle const* const style = c->ass->GetStyle(line->Style); + wxColor color = (style ? style->*field : AssStyle().*field).GetWXColor(); + + line->ParseASSTags(); + + int sel_start = c->textSelectionController->GetSelectionStart(); + int sel_end = c->textSelectionController->GetSelectionEnd(); + int blockn = block_at_pos(line->Text, sel_start); + + color = get_value(*line, blockn, color, tag, alt); + int commit_id = -1; + const wxColor newColor = GetColorFromUser(c->parent, color, bind(got_color, c, tag, &commit_id, std::tr1::placeholders::_1)); + line->ClearBlocks(); + commit_text(c, _("set color"), &commit_id); + + if (!newColor.IsOk()) { + c->ass->Undo(); + c->textSelectionController->SetSelection(sel_start, sel_end); + } +} + +struct edit_color_primary : public Command { + CMD_NAME("edit/color/primary") + STR_MENU("Primary Color...") + STR_DISP("Primary Color") + STR_HELP("Primary Color") + + void operator()(agi::Context *c) { + show_color_picker(c, &AssStyle::primary, "\\c", "\\1c"); + } +}; + +struct edit_color_secondary : public Command { + CMD_NAME("edit/color/secondary") + STR_MENU("Secondary Color...") + STR_DISP("Secondary Color") + STR_HELP("Secondary Color") + + void operator()(agi::Context *c) { + show_color_picker(c, &AssStyle::secondary, "\\c", "\\1c"); + } +}; + +struct edit_color_outline : public Command { + CMD_NAME("edit/color/outline") + STR_MENU("Outline Color...") + STR_DISP("Outline Color") + STR_HELP("Outline Color") + + void operator()(agi::Context *c) { + show_color_picker(c, &AssStyle::outline, "\\c", "\\1c"); + } +}; + +struct edit_color_shadow : public Command { + CMD_NAME("edit/color/shadow") + STR_MENU("Shadow Color...") + STR_DISP("Shadow Color") + STR_HELP("Shadow Color") + + void operator()(agi::Context *c) { + show_color_picker(c, &AssStyle::shadow, "\\c", "\\1c"); + } +}; + +struct edit_style_bold : public Command { + CMD_NAME("edit/style/bold") + STR_MENU("Bold") + STR_DISP("Bold") + STR_HELP("Bold") + + void operator()(agi::Context *c) { + toggle_override_tag(c, &AssStyle::bold, "\\b", _("toggle bold")); + } +}; + +struct edit_style_italic : public Command { + CMD_NAME("edit/style/italic") + STR_MENU("Italics") + STR_DISP("Italics") + STR_HELP("Italics") + + void operator()(agi::Context *c) { + toggle_override_tag(c, &AssStyle::italic, "\\i", _("toggle italic")); + } +}; + +struct edit_style_underline : public Command { + CMD_NAME("edit/style/underline") + STR_MENU("Underline") + STR_DISP("Underline") + STR_HELP("Underline") + + void operator()(agi::Context *c) { + toggle_override_tag(c, &AssStyle::underline, "\\u", _("toggle underline")); + } +}; + +struct edit_style_strikeout : public Command { + CMD_NAME("edit/style/strikeout") + STR_MENU("Strikeout") + STR_DISP("Strikeout") + STR_HELP("Strikeout") + + void operator()(agi::Context *c) { + toggle_override_tag(c, &AssStyle::strikeout, "\\s", _("toggle strikeout")); + } +}; + +struct edit_font : public Command { + CMD_NAME("edit/font") + STR_MENU("Font Face...") + STR_DISP("Font Face") + STR_HELP("Font Face") + + void operator()(agi::Context *c) { + AssDialogue *const line = c->selectionController->GetActiveLine(); + line->ParseASSTags(); + const int blockn = block_at_pos(line->Text, c->textSelectionController->GetInsertionPoint()); + + const AssStyle *style = c->ass->GetStyle(line->Style); + const AssStyle default_style; + if (!style) + style = &default_style; + + const wxFont startfont( + get_value(*line, blockn, (int)style->fontsize, "\\fs"), + wxFONTFAMILY_DEFAULT, + get_value(*line, blockn, style->italic, "\\i") ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL, + get_value(*line, blockn, style->bold, "\\b") ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL, + get_value(*line, blockn, style->underline, "\\u"), + get_value(*line, blockn, style->font, "\\fn")); + + const wxFont font = wxGetFontFromUser(c->parent, startfont); + if (!font.Ok() || font == startfont) { + line->ClearBlocks(); + return; + } + + if (font.GetFaceName() != startfont.GetFaceName()) + set_tag(c, "\\fn", font.GetFaceName()); + if (font.GetPointSize() != startfont.GetPointSize()) + set_tag(c, "\\fs", wxString::Format("%d", font.GetPointSize())); + if (font.GetWeight() != startfont.GetWeight()) + set_tag(c, "\\b", wxString::Format("%d", font.GetWeight() == wxFONTWEIGHT_BOLD)); + if (font.GetStyle() != startfont.GetStyle()) + set_tag(c, "\\i", wxString::Format("%d", font.GetStyle() == wxFONTSTYLE_ITALIC)); + if (font.GetUnderlined() != startfont.GetUnderlined()) + set_tag(c, "\\i", wxString::Format("%d", font.GetUnderlined())); + + line->ClearBlocks(); + commit_text(c, _("set font")); + } +}; + /// Find and replace words in subtitles. struct edit_find_replace : public Command { CMD_NAME("edit/find_replace") - STR_MENU("Find and R&eplace...") - STR_DISP("Find and Replace") - STR_HELP("Find and replace words in subtitles") + STR_MENU("Find and R&eplace...") + STR_DISP("Find and Replace") + STR_HELP("Find and replace words in subtitles") - void operator()(agi::Context *c) { - c->videoController->Stop(); - Search.OpenDialog(true); + void operator()(agi::Context *c) { + c->videoController->Stop(); + Search.OpenDialog(true); } }; @@ -432,6 +739,11 @@ struct edit_undo : public Command { namespace cmd { void init_edit() { + reg(new edit_color_primary); + reg(new edit_color_secondary); + reg(new edit_color_outline); + reg(new edit_color_shadow); + reg(new edit_font); reg(new edit_find_replace); reg(new edit_line_copy); reg(new edit_line_cut); @@ -445,6 +757,10 @@ namespace cmd { reg(new edit_line_paste_over); reg(new edit_line_recombine); reg(new edit_line_split_by_karaoke); + reg(new edit_style_bold); + reg(new edit_style_italic); + reg(new edit_style_underline); + reg(new edit_style_strikeout); reg(new edit_redo); reg(new edit_undo); } diff --git a/aegisub/src/command/icon.cpp b/aegisub/src/command/icon.cpp index e837d39e2..1ceb74d4e 100644 --- a/aegisub/src/command/icon.cpp +++ b/aegisub/src/command/icon.cpp @@ -99,14 +99,24 @@ INSERT_ICON("audio/play/selection/begin", button_playfirstfiveh) INSERT_ICON("audio/play/selection/end", button_playlastfiveh) INSERT_ICON("audio/play/to_end", button_playtoend) INSERT_ICON("audio/stop", button_stop) +INSERT_ICON("edit/color/primary", button_color_one); +INSERT_ICON("edit/color/secondary", button_color_two); +INSERT_ICON("edit/color/outline", button_color_three); +INSERT_ICON("edit/color/shadow", button_color_four); +INSERT_ICON("edit/font", button_fontname); INSERT_ICON("edit/line/copy", copy_button) INSERT_ICON("edit/line/cut", cut_button) INSERT_ICON("edit/line/delete", delete_button) INSERT_ICON("edit/line/paste", paste_button) INSERT_ICON("edit/line/swap", arrow_sort) +INSERT_ICON("edit/style/bold", button_bold) +INSERT_ICON("edit/style/italic", button_italics) +INSERT_ICON("edit/style/strikeout", button_strikeout) +INSERT_ICON("edit/style/underline", button_underline) INSERT_ICON("edit/redo", redo_button) INSERT_ICON("edit/search_replace", find_replace_menu) INSERT_ICON("edit/undo", undo_button) +INSERT_ICON("grid/line/next/create", button_audio_commit) INSERT_ICON("grid/tag/cycle_hiding", toggle_tag_hiding) INSERT_ICON("help/bugs", bugtracker_button) INSERT_ICON("help/contents", contents_button) diff --git a/aegisub/src/dialog_colorpicker.cpp b/aegisub/src/dialog_colorpicker.cpp index 7dc618812..ed16d8566 100644 --- a/aegisub/src/dialog_colorpicker.cpp +++ b/aegisub/src/dialog_colorpicker.cpp @@ -267,11 +267,10 @@ class DialogColorPicker : public wxDialog { void OnMouse(wxMouseEvent &evt); void OnCaptureLost(wxMouseCaptureLostEvent&); - ColorCallback callback; - void *callbackUserdata; + std::tr1::function callback; public: - DialogColorPicker(wxWindow *parent, wxColour initial_color, ColorCallback callback = NULL, void *userdata = NULL); + DialogColorPicker(wxWindow *parent, wxColour initial_color, std::tr1::function callback); ~DialogColorPicker(); void SetColor(wxColour new_color); @@ -625,15 +624,15 @@ void ColorPickerScreenDropper::DropFromScreenXY(int x, int y) Refresh(false); } -wxColour GetColorFromUser(wxWindow *parent, wxColour original, ColorCallback callback, void* userdata) +wxColour GetColorFromUser(wxWindow* parent, wxColour original, std::tr1::function callback) { - DialogColorPicker dialog(parent, original, callback, userdata); + DialogColorPicker dialog(parent, original, callback); if (dialog.ShowModal() == wxID_OK) original = dialog.GetColor(); else original = wxNullColour; - if (callback) - callback(userdata, original); + + callback(original); return original; } @@ -650,10 +649,9 @@ static wxBitmap *make_rgb_image(int width, int offset) { return new wxBitmap(img); } -DialogColorPicker::DialogColorPicker(wxWindow *parent, wxColour initial_color, ColorCallback callback, void* userdata) +DialogColorPicker::DialogColorPicker(wxWindow *parent, wxColour initial_color, std::tr1::function callback) : wxDialog(parent, -1, _("Select Color")) , callback(callback) -, callbackUserdata(userdata) { memset(rgb_spectrum, 0, sizeof rgb_spectrum); hsl_spectrum = 0; @@ -1035,7 +1033,7 @@ void DialogColorPicker::UpdateSpectrumDisplay() } preview_box->SetBitmap(tempBmp); - if (callback) callback(callbackUserdata, cur_color); + callback(cur_color); } wxBitmap *DialogColorPicker::MakeGBSpectrum() diff --git a/aegisub/src/dialog_colorpicker.h b/aegisub/src/dialog_colorpicker.h index 77a3b91ea..d0060821b 100644 --- a/aegisub/src/dialog_colorpicker.h +++ b/aegisub/src/dialog_colorpicker.h @@ -35,25 +35,17 @@ /// #ifndef AGI_PRE +#include + #include #endif -/// Callback function for GetColorFromUser -typedef void (*ColorCallback)(void* userdata, wxColor color); - -/// Wrapper used by templated version of GetColorFromUser -template -void ColorCallbackWrapper(void* obj, wxColor color) { - (static_cast(obj)->*method)(color); -} - /// @brief Get a color from the user via a color picker dialog /// @param parent Parent window /// @param original Initial color to select -/// @param callback Function called whenever the selected color changes if not NULL -/// @param userdata Passed to callback function -/// @return Last selected color when dialog is closed, or wxNullColour if the dialog was cancelled -wxColor GetColorFromUser(wxWindow* parent, wxColor original, ColorCallback callback = NULL, void* userdata = NULL); +/// @param callback Function called whenever the selected color changes +/// @return Last selected color when dialog is closed, or wxNullColour if the dialog was canceled +wxColour GetColorFromUser(wxWindow* parent, wxColour original, std::tr1::function callback); /// @brief Get a color from the user via a color picker dialog /// @param T Class which the callback method belongs to @@ -61,8 +53,8 @@ wxColor GetColorFromUser(wxWindow* parent, wxColor original, ColorCallback callb /// @param parent Parent window /// @param original Initial color to select /// @param callbackObj Object to call callback method on. Must be of type T. -/// @return Last selected color when dialog is closed, or wxNullColour if the dialog was cancelled -template -wxColor GetColorFromUser(wxWindow* parent, wxColor original, T* callbackObj) { - return GetColorFromUser(parent, original, &ColorCallbackWrapper, callbackObj); +/// @return Last selected color when dialog is closed, or wxNullColour if the dialog was canceled +template +wxColour GetColorFromUser(wxWindow* parent, wxColour original, T* callbackObj) { + return GetColorFromUser(parent, original, bind(method, callbackObj, std::tr1::placeholders::_1)); } diff --git a/aegisub/src/subs_edit_box.cpp b/aegisub/src/subs_edit_box.cpp index 369cc7321..438d7b825 100644 --- a/aegisub/src/subs_edit_box.cpp +++ b/aegisub/src/subs_edit_box.cpp @@ -54,10 +54,7 @@ #include "ass_dialogue.h" #include "ass_file.h" -#include "ass_override.h" -#include "ass_style.h" #include "command/command.h" -#include "dialog_colorpicker.h" #include "dialog_search_replace.h" #include "include/aegisub/context.h" #include "include/aegisub/hotkey.h" @@ -82,41 +79,6 @@ struct field_setter : public std::binary_function { } }; -/// @brief Get the value of a tag at a specified position in a line -/// @param line Line to get the value from -/// @param blockn Block number in the line -/// @param initial Value from style to use if the tag does not exist -/// @param tag Tag to get the value of -/// @param alt Alternate name of the tag, if any -template -static T get_value(AssDialogue const& line, int blockn, T initial, wxString tag, wxString alt = wxString()) { - for (int i = blockn; i >= 0; i--) { - AssDialogueBlockOverride *ovr = dynamic_cast(line.Blocks[i]); - if (!ovr) continue; - - for (int j = (int)ovr->Tags.size() - 1; j >= 0; j--) { - if (ovr->Tags[j]->Name == tag || ovr->Tags[j]->Name == alt) { - return ovr->Tags[j]->Params[0]->Get(initial); - } - } - } - return initial; -} - -/// Get the block index in the text of the position -int block_at_pos(wxString const& text, int pos) { - int n = 0; - int max = text.size() - 1; - for (int i = 0; i <= pos && i <= max; ++i) { - if (i > 0 && text[i] == '{') - n++; - if (text[i] == '}' && i != max && i != pos && i != pos -1 && (i+1 == max || text[i+1] != '{')) - n++; - } - - return n; -} - /// Work around wxGTK's fondness for generating events from ChangeValue void change_value(wxTextCtrl *ctrl, wxString const& value) { if (value != ctrl->GetValue()) @@ -189,18 +151,18 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context) // Middle-bottom controls MiddleBotSizer = new wxBoxSizer(wxHORIZONTAL); - MakeButton(GETIMAGE(button_bold_16), _("Bold"), bind(&SubsEditBox::OnFlagButton, this, &AssStyle::bold, "\\b", _("toggle bold"))); - MakeButton(GETIMAGE(button_italics_16), _("Italics"), bind(&SubsEditBox::OnFlagButton, this, &AssStyle::italic, "\\i", _("toggle italic"))); - MakeButton(GETIMAGE(button_underline_16), _("Underline"), bind(&SubsEditBox::OnFlagButton, this, &AssStyle::underline, "\\u", _("toggle underline"))); - MakeButton(GETIMAGE(button_strikeout_16), _("Strikeout"), bind(&SubsEditBox::OnFlagButton, this, &AssStyle::strikeout, "\\s", _("toggle strikeout"))); - MakeButton(GETIMAGE(button_fontname_16), _("Font Face"), bind(&SubsEditBox::OnFontButton, this)); + MakeButton("edit/style/bold"); + MakeButton("edit/style/italic"); + MakeButton("edit/style/underline"); + MakeButton("edit/style/strikeout"); + MakeButton("edit/font"); MiddleBotSizer->AddSpacer(5); - MakeButton(GETIMAGE(button_color_one_16), _("Primary color"), bind(&SubsEditBox::OnColorButton, this, &AssStyle::primary, "\\c", "\\1c")); - MakeButton(GETIMAGE(button_color_two_16), _("Secondary color"), bind(&SubsEditBox::OnColorButton, this, &AssStyle::secondary, "\\2c", "")); - MakeButton(GETIMAGE(button_color_three_16), _("Outline color"), bind(&SubsEditBox::OnColorButton, this, &AssStyle::outline, "\\3c", "")); - MakeButton(GETIMAGE(button_color_four_16), _("Shadow color"), bind(&SubsEditBox::OnColorButton, this, &AssStyle::shadow, "\\4c", "")); + MakeButton("edit/color/primary"); + MakeButton("edit/color/secondary"); + MakeButton("edit/color/outline"); + MakeButton("edit/color/shadow"); MiddleBotSizer->AddSpacer(5); - MakeButton(GETIMAGE(button_audio_commit_16), _("Commits the text (Enter)"), bind(&cmd::call, "grid/line/next/create", c)); + MakeButton("grid/line/next/create"); MiddleBotSizer->AddSpacer(10); ByTime = MakeRadio(_("T&ime"), true, _("Time by h:mm:ss.cs")); @@ -227,7 +189,7 @@ SubsEditBox::SubsEditBox(wxWindow *parent, agi::Context *context) TextEdit->SetModEventMask(wxSTC_MOD_INSERTTEXT | wxSTC_MOD_DELETETEXT | wxSTC_STARTACTION); Bind(wxEVT_COMMAND_TEXT_UPDATED, &SubsEditBox::OnLayerEnter, this, Layer->GetId()); - Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &SubsEditBox::OnLayerChange, this, Layer->GetId()); + Bind(wxEVT_COMMAND_SPINCTRL_UPDATED, &SubsEditBox::OnLayerEnter, this, Layer->GetId()); Bind(wxEVT_COMMAND_CHECKBOX_CLICKED, &SubsEditBox::OnCommentChange, this, CommentBox->GetId()); Bind(wxEVT_SIZE, &SubsEditBox::OnSize, this); @@ -267,13 +229,13 @@ TimeEdit *SubsEditBox::MakeTimeCtrl(bool end, wxString const& tooltip, void (Sub return ctrl; } -template -void SubsEditBox::MakeButton(wxBitmap const& icon, wxString const& tooltip, Handler const& handler) { - wxBitmapButton *btn = new wxBitmapButton(this, -1, icon); - btn->SetToolTip(tooltip); +void SubsEditBox::MakeButton(const char *cmd_name) { + cmd::Command *command = cmd::get(cmd_name); + wxBitmapButton *btn = new wxBitmapButton(this, -1, command->Icon(16)); + btn->SetToolTip(command->StrHelp()); MiddleBotSizer->Add(btn, wxSizerFlags().Center().Expand()); - Bind(wxEVT_COMMAND_BUTTON_CLICKED, handler, btn->GetId()); + btn->Bind(wxEVT_COMMAND_BUTTON_CLICKED, std::tr1::bind(cmd::call, cmd_name, c)); } wxComboBox *SubsEditBox::MakeComboBox(wxString const& initial_text, int style, void (SubsEditBox::*handler)(wxCommandEvent&), wxString const& tooltip) { @@ -445,7 +407,7 @@ void SubsEditBox::SetSelectedRows(T AssDialogue::*field, T value, wxString desc, SetSelectedRows(field_setter(field), value, desc, type, amend); } -void SubsEditBox::CommitText(wxString desc) { +void SubsEditBox::CommitText(wxString const& desc) { SetSelectedRows(&AssDialogue::Text, TextEdit->GetText(), desc, AssFile::COMMIT_DIAG_TEXT, true); } @@ -537,7 +499,6 @@ void SubsEditBox::SetControlsState(bool state) { } } - void SubsEditBox::OnStyleChange(wxCommandEvent &) { SetSelectedRows(&AssDialogue::Style, StyleBox->GetValue(), _("style change"), AssFile::COMMIT_DIAG_META); } @@ -548,10 +509,6 @@ void SubsEditBox::OnActorChange(wxCommandEvent &evt) { PopulateActorList(); } -void SubsEditBox::OnLayerChange(wxSpinEvent &event) { - OnLayerEnter(event); -} - void SubsEditBox::OnLayerEnter(wxCommandEvent &) { SetSelectedRows(&AssDialogue::Layer, Layer->GetValue(), _("layer change"), AssFile::COMMIT_DIAG_META); } @@ -567,6 +524,7 @@ void SubsEditBox::OnEndTimeChange(wxCommandEvent &) { void SubsEditBox::OnDurationChange(wxCommandEvent &) { CommitTimes(TIME_DURATION); } + void SubsEditBox::OnMarginLChange(wxCommandEvent &) { SetSelectedRows(std::mem_fun(&AssDialogue::SetMarginString<0>), MarginL->GetValue(), _("MarginL change"), AssFile::COMMIT_DIAG_META); if (line) change_value(MarginL, line->GetMarginString(0, false)); @@ -594,171 +552,3 @@ void SubsEditBox::OnEffectChange(wxCommandEvent &) { void SubsEditBox::OnCommentChange(wxCommandEvent &) { SetSelectedRows(&AssDialogue::Comment, CommentBox->GetValue(), _("comment change"), AssFile::COMMIT_DIAG_META); } - -void SubsEditBox::SetTag(wxString tag, wxString value, bool atEnd) { - assert(line); - if (line->Blocks.empty()) - line->ParseASSTags(); - - int sel_start = c->textSelectionController->GetSelectionStart(); - int sel_end = c->textSelectionController->GetSelectionEnd(); - int start = atEnd ? sel_end : sel_start; - int blockn = block_at_pos(line->Text, start); - - AssDialogueBlockPlain *plain = 0; - AssDialogueBlockOverride *ovr = 0; - while (blockn >= 0) { - AssDialogueBlock *block = line->Blocks[blockn]; - if (dynamic_cast(block)) - --blockn; - else if ((plain = dynamic_cast(block))) { - // Cursor is in a comment block, so try the previous block instead - if (plain->GetText().StartsWith("{")) { - --blockn; - start = line->Text.rfind('{', start); - } - else - break; - } - else { - ovr = dynamic_cast(block); - assert(ovr); - break; - } - } - - // If we didn't hit a suitable block for inserting the override just put - // it at the beginning of the line - if (blockn < 0) - start = 0; - - wxString insert = tag + value; - int shift = insert.size(); - if (plain || blockn < 0) { - line->Text = line->Text.Left(start) + "{" + insert + "}" + line->Text.Mid(start); - shift += 2; - line->ParseASSTags(); - } - else if(ovr) { - wxString alt; - if (tag == "\\c") alt = "\\1c"; - // Remove old of same - bool found = false; - for (size_t i = 0; i < ovr->Tags.size(); i++) { - wxString name = ovr->Tags[i]->Name; - if (tag == name || alt == name) { - shift -= ((wxString)*ovr->Tags[i]).size(); - if (found) { - delete ovr->Tags[i]; - ovr->Tags.erase(ovr->Tags.begin() + i); - i--; - } - else { - ovr->Tags[i]->Params[0]->Set(value); - ovr->Tags[i]->Params[0]->omitted = false; - found = true; - } - } - } - if (!found) { - ovr->AddTag(insert); - } - - line->UpdateText(); - } - else - assert(false); - - TextEdit->SetTextTo(line->Text); - if (!atEnd) c->textSelectionController->SetSelection(sel_start + shift, sel_end + shift); - TextEdit->SetFocus(); -} - -void SubsEditBox::OnFlagButton(bool (AssStyle::*field), const char *tag, wxString const& undo_msg) { - AssStyle *style = c->ass->GetStyle(line->Style); - bool state = style ? style->*field : AssStyle().*field; - - line->ParseASSTags(); - int sel_start = c->textSelectionController->GetSelectionStart(); - int sel_end = c->textSelectionController->GetSelectionEnd(); - int blockn = block_at_pos(line->Text, sel_start); - - state = get_value(*line, blockn, state, tag); - - SetTag(tag, state ? "0" : "1"); - if (sel_start != sel_end) - SetTag(tag, state ? "1" : "0", true); - - line->ClearBlocks(); - commitId = -1; - CommitText(undo_msg); -} - -void SubsEditBox::OnFontButton() { - line->ParseASSTags(); - int blockn = block_at_pos(line->Text, c->textSelectionController->GetInsertionPoint()); - - AssStyle *style = c->ass->GetStyle(line->Style); - AssStyle defStyle; - if (!style) style = &defStyle; - - wxFont startfont( - get_value(*line, blockn, (int)style->fontsize, "\\fs"), - wxFONTFAMILY_DEFAULT, - get_value(*line, blockn, style->italic, "\\i") ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL, - get_value(*line, blockn, style->bold, "\\b") ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL, - get_value(*line, blockn, style->underline, "\\u"), - get_value(*line, blockn, style->font, "\\fn")); - - wxFont font = wxGetFontFromUser(this, startfont); - if (!font.Ok() || font == startfont) { - line->ClearBlocks(); - return; - } - - if (font.GetFaceName() != startfont.GetFaceName()) - SetTag("\\fn", font.GetFaceName()); - if (font.GetPointSize() != startfont.GetPointSize()) - SetTag("\\fs", wxString::Format("%d", font.GetPointSize())); - if (font.GetWeight() != startfont.GetWeight()) - SetTag("\\b", wxString::Format("%d", font.GetWeight() == wxFONTWEIGHT_BOLD)); - if (font.GetStyle() != startfont.GetStyle()) - SetTag("\\i", wxString::Format("%d", font.GetStyle() == wxFONTSTYLE_ITALIC)); - if (font.GetUnderlined() != startfont.GetUnderlined()) - SetTag("\\i", wxString::Format("%d", font.GetUnderlined())); - - line->ClearBlocks(); - commitId = -1; - CommitText(_("set font")); -} - -void SubsEditBox::OnColorButton(AssColor (AssStyle::*field), const char *tag, const char *alt) { - AssStyle *style = c->ass->GetStyle(line->Style); - wxColor color = (style ? style->*field : AssStyle().*field).GetWXColor(); - - colorTag = tag; - commitId = -1; - - line->ParseASSTags(); - - int sel_start = c->textSelectionController->GetSelectionStart(); - int sel_end = c->textSelectionController->GetSelectionEnd(); - int blockn = block_at_pos(line->Text, sel_start); - - color = get_value(*line, blockn, color, colorTag, alt); - wxColor newColor = GetColorFromUser(c->parent, color, this); - line->ClearBlocks(); - CommitText(_("set color")); - - if (!newColor.IsOk()) { - c->ass->Undo(); - c->textSelectionController->SetSelection(sel_start, sel_end); - } -} - -void SubsEditBox::SetColorCallback(wxColor newColor) { - if (newColor.Ok()) { - SetTag(colorTag, AssColor(newColor).GetASSFormatted(false)); - CommitText(_("set color")); - } -} diff --git a/aegisub/src/subs_edit_box.h b/aegisub/src/subs_edit_box.h index 3743ceae9..1ba5cea35 100644 --- a/aegisub/src/subs_edit_box.h +++ b/aegisub/src/subs_edit_box.h @@ -50,9 +50,7 @@ namespace agi { namespace vfr { class Framerate; } } namespace agi { struct Context; } -struct AssColor; class AssDialogue; -class AssStyle; class AssTime; class SubsTextEditCtrl; class TextSelectionController; @@ -123,7 +121,7 @@ class SubsEditBox : public wxPanel { void CommitTimes(TimeField field); /// @brief Commits the current edit box contents /// @param desc Undo description to use - void CommitText(wxString desc); + void CommitText(wxString const& desc); /// Last commit ID for undo coalescing int commitId; @@ -145,8 +143,7 @@ class SubsEditBox : public wxPanel { // Constructor helpers wxTextCtrl *MakeMarginCtrl(wxString const& tooltip, void (SubsEditBox::*handler)(wxCommandEvent&)); TimeEdit *MakeTimeCtrl(bool end, wxString const& tooltip, void (SubsEditBox::*handler)(wxCommandEvent&)); - template - void MakeButton(wxBitmap const& icon, wxString const& tooltip, Handler const& handler); + void MakeButton(const char *cmd_name); wxComboBox *MakeComboBox(wxString const& initial_text, int style, void (SubsEditBox::*handler)(wxCommandEvent&), wxString const& tooltip); wxRadioButton *MakeRadio(wxString const& text, bool start, wxString const& tooltip); @@ -160,7 +157,6 @@ class SubsEditBox : public wxPanel { void OnStyleChange(wxCommandEvent &event); void OnActorChange(wxCommandEvent &event); void OnLayerEnter(wxCommandEvent &event); - void OnLayerChange(wxSpinEvent &event); void OnStartTimeChange(wxCommandEvent &); void OnEndTimeChange(wxCommandEvent &); void OnDurationChange(wxCommandEvent &); @@ -172,25 +168,8 @@ class SubsEditBox : public wxPanel { void OnSize(wxSizeEvent &event); void OnUndoTimer(wxTimerEvent&); - void OnFlagButton(bool (AssStyle::*field), const char *tag, wxString const& undo_msg); - void OnColorButton(AssColor (AssStyle::*field), const char *tag, const char *alt); - void OnFontButton(); - void SetPlaceholderCtrl(wxControl *ctrl, wxString const& value); - /// @brief Set the value of a tag for the currently selected text - /// @param tag Tag to set - /// @param value New value of tag - /// @param atEnd Set the value at the end of the selection rather than beginning - void SetTag(wxString tag, wxString value, bool atEnd = false); - - /// @brief Callback function for the color picker - /// @param newColor New color selected in the picker - void SetColorCallback(wxColor newColor); - - /// Which color is currently being set - wxString colorTag; - /// @brief Set a field in each selected line to a specified value /// @param set Callable which does the setting /// @param value Value to pass to set