2007-01-13 03:42:19 +01:00
|
|
|
// Copyright (c) 2005, Dan Donovan (Dansolo)
|
2009-06-08 04:37:09 +02:00
|
|
|
// Copyright (c) 2009, Niels Martin Hansen
|
2007-01-13 03:22:28 +01:00
|
|
|
// 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.
|
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
2009-08-04 03:53:26 +02:00
|
|
|
/// @file dialog_kara_timing_copy.cpp
|
2009-08-04 04:00:30 +02:00
|
|
|
/// @brief Karaoke timing copier dialogue box and logic
|
|
|
|
/// @ingroup tools_ui kara_timing_copy
|
2009-07-29 07:43:02 +02:00
|
|
|
///
|
2007-01-15 00:34:27 +01:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
#include "dialog_kara_timing_copy.h"
|
|
|
|
|
|
|
|
#include "ass_dialogue.h"
|
2007-01-13 03:22:28 +01:00
|
|
|
#include "ass_file.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "ass_karaoke.h"
|
2012-12-30 00:53:56 +01:00
|
|
|
#include "compat.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "help_button.h"
|
2011-01-16 08:17:36 +01:00
|
|
|
#include "include/aegisub/context.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "libresrc/libresrc.h"
|
2013-01-07 02:50:09 +01:00
|
|
|
#include "options.h"
|
2010-12-08 04:36:10 +01:00
|
|
|
#include "selection_controller.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "utils.h"
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2013-07-13 17:26:09 +02:00
|
|
|
#include <libaegisub/karaoke_matcher.h>
|
|
|
|
|
|
|
|
#include <boost/algorithm/string/case_conv.hpp>
|
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
|
|
|
#include <boost/locale/boundary.hpp>
|
|
|
|
#include <boost/range/algorithm_ext.hpp>
|
2013-01-04 16:01:50 +01:00
|
|
|
#include <deque>
|
|
|
|
|
|
|
|
#include <wx/checkbox.h>
|
|
|
|
#include <wx/combobox.h>
|
|
|
|
#include <wx/dcclient.h>
|
|
|
|
#include <wx/listctrl.h>
|
|
|
|
#include <wx/msgdlg.h>
|
|
|
|
#include <wx/settings.h>
|
|
|
|
#include <wx/sizer.h>
|
|
|
|
#include <wx/stattext.h>
|
|
|
|
#include <wx/string.h>
|
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
#define TEXT_LABEL_SOURCE _("Source: ")
|
|
|
|
#define TEXT_LABEL_DEST _("Dest: ")
|
|
|
|
|
2014-03-13 02:39:07 +01:00
|
|
|
class KaraokeLineMatchDisplay final : public wxControl {
|
2011-09-28 21:44:07 +02:00
|
|
|
typedef AssKaraoke::Syllable MatchSyllable;
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
struct MatchGroup {
|
2009-06-25 04:31:35 +02:00
|
|
|
std::vector<MatchSyllable> src;
|
2013-01-04 16:01:50 +01:00
|
|
|
std::string dst;
|
2014-04-25 19:01:07 +02:00
|
|
|
int last_render_width = 0;
|
2009-06-08 04:37:09 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
std::vector<MatchGroup> matched_groups;
|
2009-06-25 04:31:35 +02:00
|
|
|
std::deque<MatchSyllable> unmatched_source;
|
2013-07-13 17:26:09 +02:00
|
|
|
std::string destination_str;
|
|
|
|
boost::locale::boundary::ssegment_index destination;
|
|
|
|
boost::locale::boundary::ssegment_index::iterator match_begin, match_end;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
int last_total_matchgroup_render_width;
|
|
|
|
|
2010-06-11 04:24:59 +02:00
|
|
|
size_t source_sel_length;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
void OnPaint(wxPaintEvent &event);
|
|
|
|
|
2014-05-12 18:30:14 +02:00
|
|
|
wxString const& label_source = TEXT_LABEL_SOURCE;
|
|
|
|
wxString const& label_destination = TEXT_LABEL_DEST;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
public:
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Start processing a new line pair
|
|
|
|
void SetInputData(AssDialogue *src, AssDialogue *dst);
|
|
|
|
/// Build and return the output line from the matched syllables
|
2013-01-04 16:01:50 +01:00
|
|
|
std::string GetOutputLine() const;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Number of syllables not yet matched from source
|
|
|
|
size_t GetRemainingSource() const { return unmatched_source.size(); }
|
|
|
|
/// Number of characters not yet matched from destination
|
2013-07-13 17:26:09 +02:00
|
|
|
size_t GetRemainingDestination() const { return distance(match_end, destination.end()); }
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
// Adjust source and destination match lengths
|
|
|
|
void IncreaseSourceMatch();
|
|
|
|
void DecreaseSourceMatch();
|
|
|
|
void IncreseDestinationMatch();
|
|
|
|
void DecreaseDestinationMatch();
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Attempt to treat source as Japanese romaji, destination as Japanese kana+kanji, and make an automatic match
|
2009-06-08 04:37:09 +02:00
|
|
|
void AutoMatchJapanese();
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Accept current selection and save match
|
2009-06-08 04:37:09 +02:00
|
|
|
bool AcceptMatch();
|
2011-09-28 21:44:07 +02:00
|
|
|
/// Undo last match, adding it back to the unmatched input
|
2009-06-08 04:37:09 +02:00
|
|
|
bool UndoMatch();
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
KaraokeLineMatchDisplay(wxWindow *parent);
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
wxSize GetBestSize() const;
|
2009-06-08 04:37:09 +02:00
|
|
|
};
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
KaraokeLineMatchDisplay::KaraokeLineMatchDisplay(wxWindow *parent)
|
2009-06-08 04:37:09 +02:00
|
|
|
: wxControl(parent, -1, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE|wxWANTS_CHARS)
|
|
|
|
{
|
|
|
|
InheritAttributes();
|
2013-07-12 22:39:10 +02:00
|
|
|
SetInputData(nullptr, nullptr);
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
wxSize best_size = GetBestSize();
|
|
|
|
SetMaxSize(wxSize(-1, best_size.GetHeight()));
|
|
|
|
SetMinSize(best_size);
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2012-11-28 16:50:52 +01:00
|
|
|
Bind(wxEVT_SET_FOCUS, std::bind(&wxControl::Refresh, this, true, nullptr));
|
|
|
|
Bind(wxEVT_KILL_FOCUS, std::bind(&wxControl::Refresh, this, true, nullptr));
|
2011-09-28 21:44:07 +02:00
|
|
|
Bind(wxEVT_PAINT, &KaraokeLineMatchDisplay::OnPaint, this);
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
wxSize KaraokeLineMatchDisplay::GetBestSize() const
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
|
|
|
int w_src, h_src, w_dst, h_dst;
|
|
|
|
GetTextExtent(label_source, &w_src, &h_src);
|
|
|
|
GetTextExtent(label_destination, &w_dst, &h_dst);
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
int min_width = std::max(w_dst, w_src);
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
// Magic number 7:
|
|
|
|
// 1 pixel for top black border, 1 pixel white top border in first row, 1 pixel white bottom padding in first row
|
|
|
|
// 1 pixel middle border, 1 pixel top and 1 pixel bottom padding in second row, 1 pixel bottom border
|
|
|
|
return wxSize(min_width * 2, h_src + h_dst + 7);
|
|
|
|
}
|
|
|
|
|
2013-07-13 17:26:09 +02:00
|
|
|
int DrawBoxedText(wxDC &dc, wxString const& txt, int x, int y)
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
|
|
|
int tw, th;
|
|
|
|
// Assume the pen, brush and font properties have already been set in the DC.
|
|
|
|
// Return the advance width, including box margins, borders etc
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
if (txt.empty())
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
|
|
|
// Empty string gets special handling:
|
|
|
|
// The box is drawn in shorter width, to emphasize it's empty
|
|
|
|
// GetTextExtent has to be called with a non-empty string, otherwise it returns the wrong height
|
2011-09-28 21:43:11 +02:00
|
|
|
dc.GetTextExtent(" ", &tw, &th);
|
2009-06-08 04:37:09 +02:00
|
|
|
dc.DrawRectangle(x, y-2, 4, th+4);
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-07-13 17:26:09 +02:00
|
|
|
dc.GetTextExtent(txt, &tw, &th);
|
2009-06-08 04:37:09 +02:00
|
|
|
dc.DrawRectangle(x, y-2, tw+4, th+4);
|
2013-07-13 17:26:09 +02:00
|
|
|
dc.DrawText(txt, x+2, y);
|
2009-06-08 04:37:09 +02:00
|
|
|
return tw+3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void KaraokeLineMatchDisplay::OnPaint(wxPaintEvent &)
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
|
|
|
wxPaintDC dc(this);
|
|
|
|
|
|
|
|
wxColour outer_text(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
|
|
|
|
wxColour outer_back(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE));
|
2009-06-08 05:34:09 +02:00
|
|
|
wxColour outer_frame(wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT));
|
2009-06-08 04:37:09 +02:00
|
|
|
wxColour inner_back(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
|
|
|
|
wxColour inner_text(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
|
|
|
|
wxColour sel_back(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
|
|
|
|
wxColour sel_text(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT));
|
|
|
|
|
|
|
|
// Y coordinates of the top and bottom lines
|
|
|
|
int y_line1, y_line2, y_line3;
|
|
|
|
// Next X coordinate to draw a matched syllable at
|
|
|
|
int next_x;
|
|
|
|
|
|
|
|
wxSize client_size = GetClientSize();
|
|
|
|
|
|
|
|
// Calculate the text line positions
|
|
|
|
{
|
|
|
|
int x, y, x2;
|
|
|
|
GetTextExtent(label_source, &x, &y);
|
|
|
|
y_line1 = 2;
|
|
|
|
y_line2 = y_line1 + y + 3;
|
|
|
|
y_line3 = y_line2 + y + 3;
|
|
|
|
GetTextExtent(label_destination, &x2, &y);
|
|
|
|
next_x = (x2 > x) ? x2 : x;
|
|
|
|
next_x += 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Paint the labels
|
|
|
|
dc.SetTextBackground(outer_back);
|
|
|
|
if (FindFocus() == this)
|
|
|
|
dc.SetTextForeground(outer_text);
|
|
|
|
else
|
|
|
|
dc.SetTextForeground(wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT));
|
|
|
|
dc.SetFont(GetFont());
|
|
|
|
dc.SetBackgroundMode(wxTRANSPARENT);
|
|
|
|
dc.DrawText(label_source, wxPoint(0, y_line1));
|
|
|
|
dc.DrawText(label_destination, wxPoint(0, y_line2));
|
|
|
|
|
|
|
|
// Horizontal lines through the width of the control
|
|
|
|
dc.SetPen(wxPen(outer_frame));
|
|
|
|
dc.DrawLine(next_x-1, y_line1-2, client_size.GetWidth(), y_line1-2);
|
|
|
|
dc.DrawLine(next_x-1, y_line2-2, client_size.GetWidth(), y_line2-2);
|
|
|
|
dc.DrawLine(next_x-1, y_line3-2, client_size.GetWidth(), y_line3-2);
|
|
|
|
|
|
|
|
// Draw matched groups
|
|
|
|
int this_total_matchgroup_render_width = 0;
|
|
|
|
bool scroll_arrows_drawn = false;
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto& grp : matched_groups)
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
|
|
|
int prev_x = next_x;
|
|
|
|
|
|
|
|
// Skip groups that would cause the input part to be too far right
|
|
|
|
this_total_matchgroup_render_width += grp.last_render_width;
|
|
|
|
if (last_total_matchgroup_render_width - this_total_matchgroup_render_width > client_size.x / 2)
|
|
|
|
{
|
|
|
|
// If we're skipping some syllables, show an arrow as feedback that something is scrolled off
|
|
|
|
if (!scroll_arrows_drawn)
|
|
|
|
{
|
|
|
|
dc.SetBrush(wxBrush(outer_frame));
|
|
|
|
wxPoint triangle[3];
|
|
|
|
int height = y_line2 - y_line1;
|
|
|
|
triangle[0] = wxPoint(next_x-3, height/2);
|
|
|
|
triangle[1] = wxPoint(next_x-3+height/2, 0);
|
|
|
|
triangle[2] = wxPoint(next_x-3+height/2, height);
|
|
|
|
dc.DrawPolygon(3, triangle, 0, 0);
|
|
|
|
dc.DrawPolygon(3, triangle, 0, height);
|
|
|
|
next_x += height/2 - 4;
|
|
|
|
}
|
|
|
|
scroll_arrows_drawn = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
dc.SetPen(wxPen(outer_frame));
|
|
|
|
dc.SetBrush(wxBrush(inner_back));
|
|
|
|
dc.SetTextBackground(inner_back);
|
|
|
|
dc.SetTextForeground(inner_text);
|
|
|
|
|
|
|
|
// Matched source syllables
|
|
|
|
int syl_x = next_x;
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto const& syl : grp.src)
|
2013-07-13 17:26:09 +02:00
|
|
|
syl_x += DrawBoxedText(dc, to_wx(syl.text), syl_x, y_line1);
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
// Matched destination text
|
|
|
|
{
|
2013-07-13 17:26:09 +02:00
|
|
|
const int adv = DrawBoxedText(dc, to_wx(grp.dst), next_x, y_line2);
|
2012-03-25 06:05:06 +02:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
// Adjust next_x here while we have the text_w
|
2013-04-17 05:21:06 +02:00
|
|
|
next_x = syl_x > next_x + adv ? syl_x : next_x + adv;
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Spacing between groups
|
|
|
|
next_x += 3;
|
|
|
|
grp.last_render_width = next_x - prev_x;
|
|
|
|
}
|
|
|
|
|
|
|
|
last_total_matchgroup_render_width = this_total_matchgroup_render_width;
|
|
|
|
|
|
|
|
// Spacing between grouped and ungrouped parts
|
|
|
|
next_x += 4;
|
|
|
|
|
|
|
|
// Remaining source syllables
|
|
|
|
int syl_x = next_x;
|
|
|
|
// Start out with highlight colours
|
|
|
|
dc.SetTextBackground(sel_back);
|
|
|
|
dc.SetTextForeground(sel_text);
|
|
|
|
dc.SetBrush(wxBrush(sel_back));
|
|
|
|
for (size_t j = 0; j < unmatched_source.size(); ++j)
|
|
|
|
{
|
|
|
|
// Switch to regular colours after all selected syllables
|
|
|
|
if (j == source_sel_length)
|
|
|
|
{
|
|
|
|
dc.SetTextBackground(inner_back);
|
|
|
|
dc.SetTextForeground(inner_text);
|
|
|
|
dc.SetBrush(wxBrush(inner_back));
|
|
|
|
}
|
|
|
|
|
2013-07-13 17:26:09 +02:00
|
|
|
syl_x += DrawBoxedText(dc, to_wx(unmatched_source[j].text), syl_x, y_line1);
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Remaining destination
|
2013-07-13 17:26:09 +02:00
|
|
|
if (match_begin != match_end)
|
2011-09-28 21:44:07 +02:00
|
|
|
{
|
|
|
|
dc.SetTextBackground(sel_back);
|
|
|
|
dc.SetTextForeground(sel_text);
|
|
|
|
dc.SetBrush(wxBrush(sel_back));
|
2013-07-13 17:26:09 +02:00
|
|
|
wxString str;
|
|
|
|
for (auto it = match_begin; it != match_end; ++it)
|
|
|
|
str += to_wx(it->str());
|
|
|
|
next_x += DrawBoxedText(dc, str, next_x, y_line2);
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2013-07-13 17:26:09 +02:00
|
|
|
if (match_end != destination.end())
|
2011-09-28 21:44:07 +02:00
|
|
|
{
|
|
|
|
dc.SetTextBackground(inner_back);
|
|
|
|
dc.SetTextForeground(inner_text);
|
|
|
|
dc.SetBrush(wxBrush(inner_back));
|
2013-07-13 17:26:09 +02:00
|
|
|
wxString str;
|
|
|
|
for (auto it = match_end; it != destination.end(); ++it)
|
|
|
|
str += to_wx(it->str());
|
|
|
|
DrawBoxedText(dc, str, next_x, y_line2);
|
2011-09-28 21:44:07 +02:00
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:44:07 +02:00
|
|
|
void KaraokeLineMatchDisplay::SetInputData(AssDialogue *src, AssDialogue *dst)
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
|
|
|
last_total_matchgroup_render_width = 0;
|
|
|
|
|
|
|
|
matched_groups.clear();
|
|
|
|
|
|
|
|
unmatched_source.clear();
|
|
|
|
source_sel_length = 0;
|
|
|
|
if (src)
|
|
|
|
{
|
2011-09-28 21:44:07 +02:00
|
|
|
AssKaraoke kara(src);
|
|
|
|
copy(kara.begin(), kara.end(), back_inserter(unmatched_source));
|
|
|
|
source_sel_length = 1;
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
2013-07-13 17:26:09 +02:00
|
|
|
destination_str = dst ? dst->GetStrippedText() : "";
|
|
|
|
using namespace boost::locale::boundary;
|
|
|
|
destination = ssegment_index(character, begin(destination_str), end(destination_str));
|
|
|
|
match_begin = match_end = destination.begin();
|
|
|
|
if (!destination_str.empty())
|
|
|
|
++match_end;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
Refresh(true);
|
|
|
|
}
|
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
std::string KaraokeLineMatchDisplay::GetOutputLine() const
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
2013-01-04 16:01:50 +01:00
|
|
|
std::string res;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto const& match : matched_groups)
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
2011-09-28 21:44:07 +02:00
|
|
|
int duration = 0;
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto const& syl : match.src)
|
|
|
|
duration += syl.duration;
|
2013-01-04 16:01:50 +01:00
|
|
|
res += "{\\k" + std::to_string(duration / 10) + "}" + match.dst;
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KaraokeLineMatchDisplay::IncreaseSourceMatch()
|
|
|
|
{
|
2011-09-28 21:44:07 +02:00
|
|
|
source_sel_length = std::min(source_sel_length + 1, GetRemainingSource());
|
2009-06-08 04:37:09 +02:00
|
|
|
Refresh(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KaraokeLineMatchDisplay::DecreaseSourceMatch()
|
|
|
|
{
|
2011-11-07 05:14:09 +01:00
|
|
|
source_sel_length = std::max<size_t>(source_sel_length, 1) - 1;
|
2009-06-08 04:37:09 +02:00
|
|
|
Refresh(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KaraokeLineMatchDisplay::IncreseDestinationMatch()
|
|
|
|
{
|
2013-07-13 17:26:09 +02:00
|
|
|
if (match_end != destination.end()) {
|
|
|
|
++match_end;
|
|
|
|
Refresh(true);
|
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void KaraokeLineMatchDisplay::DecreaseDestinationMatch()
|
|
|
|
{
|
2013-07-13 17:26:09 +02:00
|
|
|
if (match_end != match_begin) {
|
|
|
|
--match_end;
|
|
|
|
Refresh(true);
|
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void KaraokeLineMatchDisplay::AutoMatchJapanese()
|
|
|
|
{
|
2013-07-13 17:26:09 +02:00
|
|
|
std::vector<std::string> source;
|
|
|
|
for (auto const& syl : unmatched_source)
|
|
|
|
source.emplace_back(syl.text);
|
|
|
|
auto result = agi::auto_match_karaoke(source, match_begin == destination.end() ? "" : &*match_begin->begin());
|
|
|
|
source_sel_length = result.source_length;
|
|
|
|
match_end = std::next(match_begin, result.destination_length);
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool KaraokeLineMatchDisplay::AcceptMatch()
|
|
|
|
{
|
2013-01-04 16:01:50 +01:00
|
|
|
// Completely empty match
|
2013-07-13 17:26:09 +02:00
|
|
|
if (source_sel_length == 0 && match_begin == match_end) return false;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
MatchGroup match;
|
2010-06-11 04:24:59 +02:00
|
|
|
|
|
|
|
assert(source_sel_length <= unmatched_source.size());
|
2011-09-28 21:44:07 +02:00
|
|
|
copy(unmatched_source.begin(), unmatched_source.begin() + source_sel_length, back_inserter(match.src));
|
2012-02-28 02:23:07 +01:00
|
|
|
unmatched_source.erase(unmatched_source.begin(), unmatched_source.begin() + source_sel_length);
|
2011-09-28 21:44:07 +02:00
|
|
|
source_sel_length = 0;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2013-07-13 17:26:09 +02:00
|
|
|
match.dst = std::string(match_begin->begin(), match_end == destination.end() ? destination_str.end() : match_end->begin());
|
|
|
|
match_begin = match_end;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
matched_groups.emplace_back(std::move(match));
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
IncreaseSourceMatch();
|
|
|
|
IncreseDestinationMatch();
|
|
|
|
Refresh(true);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KaraokeLineMatchDisplay::UndoMatch()
|
|
|
|
{
|
|
|
|
if (matched_groups.empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
MatchGroup &group = matched_groups.back();
|
|
|
|
|
|
|
|
source_sel_length = group.src.size();
|
2011-09-28 21:44:07 +02:00
|
|
|
copy(group.src.rbegin(), group.src.rend(), front_inserter(unmatched_source));
|
|
|
|
group.src.clear();
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2013-07-13 17:26:09 +02:00
|
|
|
match_end = match_begin;
|
|
|
|
for (size_t size = group.dst.size(); size > 0; size -= match_begin->length())
|
|
|
|
--match_begin;
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
matched_groups.pop_back();
|
|
|
|
|
|
|
|
Refresh(true);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-01-16 08:17:36 +01:00
|
|
|
DialogKanjiTimer::DialogKanjiTimer(agi::Context *c)
|
2012-10-12 19:16:39 +02:00
|
|
|
: wxDialog(c->parent, -1, _("Kanji timing"))
|
2014-03-25 22:49:26 +01:00
|
|
|
, subs(c->ass.get())
|
2007-01-13 03:22:28 +01:00
|
|
|
{
|
2012-04-03 22:40:24 +02:00
|
|
|
SetIcon(GETICON(kara_timing_copier_16));
|
2007-07-05 01:09:40 +02:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
wxSizer *DisplayBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Text"));
|
|
|
|
wxSizer *StylesBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Styles"));
|
2013-11-21 18:13:36 +01:00
|
|
|
auto StylesGridSizer = new wxFlexGridSizer(2, 2, 6, 6);
|
2009-06-08 04:37:09 +02:00
|
|
|
wxSizer *HelpBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Shortcut Keys"));
|
|
|
|
wxSizer *ButtonsBoxSizer = new wxStaticBoxSizer(wxVERTICAL,this,_("Commands"));
|
|
|
|
wxSizer *MainStackSizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
wxSizer *BottomShelfSizer = new wxBoxSizer(wxHORIZONTAL);
|
|
|
|
wxSizer *BottomLeftStackSizer = new wxBoxSizer(wxVERTICAL);
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
display = new KaraokeLineMatchDisplay(this);
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
//Checkbox
|
2011-11-18 19:49:09 +01:00
|
|
|
Interpolate = new wxCheckBox(this,-1,_("Attempt to &interpolate kanji."),wxDefaultPosition,wxDefaultSize,wxALIGN_LEFT);
|
2010-05-21 03:13:36 +02:00
|
|
|
Interpolate->SetValue(OPT_GET("Tool/Kanji Timer/Interpolation")->GetBool());
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2012-12-30 01:32:36 +01:00
|
|
|
wxArrayString styles = to_wx(subs->GetStyles());
|
2012-03-27 02:48:28 +02:00
|
|
|
SourceStyle = new wxComboBox(this, -1, "", wxDefaultPosition, wxSize(160, -1), styles, wxCB_READONLY);
|
|
|
|
DestStyle = new wxComboBox(this, -1, "", wxDefaultPosition, wxSize(160, -1), styles, wxCB_READONLY);
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
wxStaticText *ShortcutKeys = new wxStaticText(this,-1,_("When the destination textbox has focus, use the following keys:\n\nRight Arrow: Increase dest. selection length\nLeft Arrow: Decrease dest. selection length\nUp Arrow: Increase source selection length\nDown Arrow: Decrease source selection length\nEnter: Link, accept line when done\nBackspace: Unlink last"));
|
2007-01-13 03:42:19 +01:00
|
|
|
|
2007-01-13 03:22:28 +01:00
|
|
|
//Buttons
|
2013-07-12 22:39:10 +02:00
|
|
|
wxButton *Start = new wxButton(this, -1,_("S&tart!"));
|
|
|
|
wxButton *Link = new wxButton(this, -1,_("&Link"));
|
|
|
|
wxButton *Unlink = new wxButton(this, -1,_("&Unlink"));
|
|
|
|
wxButton *SkipSourceLine = new wxButton(this, -1,_("Skip &Source Line"));
|
|
|
|
wxButton *SkipDestLine = new wxButton(this, -1,_("Skip &Dest Line"));
|
|
|
|
wxButton *GoBackLine = new wxButton(this, -1,_("&Go Back a Line"));
|
|
|
|
wxButton *AcceptLine = new wxButton(this, -1,_("&Accept Line"));
|
2011-11-18 19:49:09 +01:00
|
|
|
wxButton *CloseKT = new wxButton(this,wxID_CLOSE,_("&Close"));
|
2007-01-15 00:34:27 +01:00
|
|
|
|
2007-01-13 03:22:28 +01:00
|
|
|
//Frame: Text
|
2009-06-08 04:37:09 +02:00
|
|
|
DisplayBoxSizer->Add(display, 0, wxEXPAND|wxALL, 6);
|
|
|
|
DisplayBoxSizer->Add(Interpolate, 0, wxEXPAND|wxALL, 6);
|
2007-01-13 03:22:28 +01:00
|
|
|
//Frame: Styles
|
2009-06-08 04:37:09 +02:00
|
|
|
StylesGridSizer->Add(new wxStaticText(this, -1, TEXT_LABEL_SOURCE), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
|
|
|
|
StylesGridSizer->Add(SourceStyle, 1, wxEXPAND);
|
|
|
|
StylesGridSizer->Add(new wxStaticText(this, -1, TEXT_LABEL_DEST), 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
|
|
|
|
StylesGridSizer->Add(DestStyle, 1, wxEXPAND);
|
|
|
|
StylesBoxSizer->Add(StylesGridSizer, 1, wxEXPAND|wxALL, 6);
|
|
|
|
//Frame: Shortcut Keys
|
|
|
|
HelpBoxSizer->Add(ShortcutKeys, 1, wxALIGN_CENTER_HORIZONTAL|wxRIGHT, 6);
|
2007-01-13 03:22:28 +01:00
|
|
|
//Frame: Commands
|
2009-06-08 04:37:09 +02:00
|
|
|
ButtonsBoxSizer->AddStretchSpacer(1);
|
|
|
|
ButtonsBoxSizer->Add(Start, 0, wxEXPAND|wxALL, 6);
|
|
|
|
ButtonsBoxSizer->Add(Link, 0, wxEXPAND|(wxALL&~wxTOP), 6);
|
|
|
|
ButtonsBoxSizer->Add(Unlink, 0, wxEXPAND|(wxALL&~wxTOP), 6);
|
|
|
|
ButtonsBoxSizer->Add(SkipSourceLine, 0, wxEXPAND|(wxALL&~wxTOP), 6);
|
|
|
|
ButtonsBoxSizer->Add(SkipDestLine, 0, wxEXPAND|(wxALL&~wxTOP), 6);
|
|
|
|
ButtonsBoxSizer->Add(GoBackLine, 0, wxEXPAND|(wxALL&~wxTOP), 6);
|
|
|
|
ButtonsBoxSizer->Add(AcceptLine, 0, wxEXPAND|(wxALL&~wxTOP), 6);
|
|
|
|
ButtonsBoxSizer->AddStretchSpacer(1);
|
2007-10-31 22:52:51 +01:00
|
|
|
|
|
|
|
// Button sizer
|
2013-11-21 18:13:36 +01:00
|
|
|
auto buttonSizer = new wxStdDialogButtonSizer();
|
2011-09-28 21:43:11 +02:00
|
|
|
buttonSizer->AddButton(new HelpButton(this,"Kanji Timer"));
|
2007-10-31 22:52:51 +01:00
|
|
|
buttonSizer->SetAffirmativeButton(CloseKT);
|
|
|
|
buttonSizer->Realize();
|
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
// Layout it all
|
|
|
|
BottomLeftStackSizer->Add(StylesBoxSizer, 0, wxEXPAND|wxBOTTOM, 6);
|
|
|
|
BottomLeftStackSizer->Add(HelpBoxSizer, 1, wxEXPAND, 6);
|
|
|
|
BottomShelfSizer->Add(BottomLeftStackSizer, 1, wxEXPAND|wxRIGHT, 6);
|
|
|
|
BottomShelfSizer->Add(ButtonsBoxSizer, 0, wxEXPAND, 6);
|
|
|
|
MainStackSizer->Add(DisplayBoxSizer, 0, wxEXPAND|wxALL, 6);
|
|
|
|
MainStackSizer->Add(BottomShelfSizer, 1, wxEXPAND|wxLEFT|wxRIGHT, 6);
|
|
|
|
MainStackSizer->Add(buttonSizer, 0, wxEXPAND|wxALL, 6);
|
|
|
|
|
|
|
|
SetSizerAndFit(MainStackSizer);
|
2007-01-13 03:22:28 +01:00
|
|
|
CenterOnParent();
|
|
|
|
|
2013-07-12 22:39:10 +02:00
|
|
|
Bind(wxEVT_KEY_DOWN, &DialogKanjiTimer::OnKeyDown, this);
|
2011-09-28 21:44:07 +02:00
|
|
|
display->Bind(wxEVT_KEY_DOWN, &DialogKanjiTimer::OnKeyDown, this);
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2013-12-12 03:25:13 +01:00
|
|
|
CloseKT->Bind(wxEVT_BUTTON, &DialogKanjiTimer::OnClose, this);
|
|
|
|
Start->Bind(wxEVT_BUTTON, &DialogKanjiTimer::OnStart, this);
|
|
|
|
Link->Bind(wxEVT_BUTTON, &DialogKanjiTimer::OnLink, this);
|
|
|
|
Unlink->Bind(wxEVT_BUTTON, &DialogKanjiTimer::OnUnlink, this);
|
|
|
|
SkipSourceLine->Bind(wxEVT_BUTTON, &DialogKanjiTimer::OnSkipSource, this);
|
|
|
|
SkipDestLine->Bind(wxEVT_BUTTON, &DialogKanjiTimer::OnSkipDest, this);
|
|
|
|
GoBackLine->Bind(wxEVT_BUTTON, &DialogKanjiTimer::OnGoBack, this);
|
|
|
|
AcceptLine->Bind(wxEVT_BUTTON, &DialogKanjiTimer::OnAccept, this);
|
2013-07-12 22:39:10 +02:00
|
|
|
}
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogKanjiTimer::OnClose(wxCommandEvent &) {
|
2010-05-21 03:13:36 +02:00
|
|
|
OPT_SET("Tool/Kanji Timer/Interpolation")->SetBool(Interpolate->IsChecked());
|
2011-09-28 21:44:07 +02:00
|
|
|
|
2012-11-04 04:53:03 +01:00
|
|
|
for (auto& line : LinesToChange)
|
|
|
|
line.first->Text = line.second;
|
2011-09-28 21:44:07 +02:00
|
|
|
|
|
|
|
if (LinesToChange.size()) {
|
2011-09-15 07:16:32 +02:00
|
|
|
subs->Commit(_("kanji timing"), AssFile::COMMIT_DIAG_TEXT);
|
2007-03-08 19:57:55 +01:00
|
|
|
LinesToChange.clear();
|
|
|
|
}
|
2007-01-15 00:34:27 +01:00
|
|
|
Close();
|
|
|
|
}
|
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogKanjiTimer::OnStart(wxCommandEvent &) {
|
2011-09-28 21:44:07 +02:00
|
|
|
if (SourceStyle->GetValue().empty() || DestStyle->GetValue().empty())
|
2007-01-13 08:04:12 +01:00
|
|
|
wxMessageBox(_("Select source and destination styles first."),_("Error"),wxICON_EXCLAMATION | wxOK);
|
|
|
|
else if (SourceStyle->GetValue() == DestStyle->GetValue())
|
|
|
|
wxMessageBox(_("The source and destination styles must be different."),_("Error"),wxICON_EXCLAMATION | wxOK);
|
|
|
|
else {
|
2014-03-24 20:39:50 +01:00
|
|
|
currentDestinationLine = currentSourceLine = &*subs->Events.begin();
|
|
|
|
auto sourceStyle = from_wx(SourceStyle->GetValue());
|
|
|
|
auto destStyle = from_wx(DestStyle->GetValue());
|
|
|
|
if (currentSourceLine->Style != sourceStyle)
|
|
|
|
currentSourceLine = FindNextStyleMatch(currentSourceLine, sourceStyle);
|
|
|
|
if (currentDestinationLine->Style != destStyle)
|
|
|
|
currentDestinationLine = FindNextStyleMatch(currentDestinationLine, destStyle);
|
2009-06-08 04:37:09 +02:00
|
|
|
ResetForNewLine();
|
2007-01-13 08:04:12 +01:00
|
|
|
}
|
2007-01-25 23:47:29 +01:00
|
|
|
LinesToChange.clear();
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogKanjiTimer::OnLink(wxCommandEvent &) {
|
2009-06-08 04:37:09 +02:00
|
|
|
if (display->AcceptMatch())
|
|
|
|
TryAutoMatch();
|
|
|
|
else
|
|
|
|
wxBell();
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogKanjiTimer::OnUnlink(wxCommandEvent &) {
|
2009-06-08 04:37:09 +02:00
|
|
|
if (!display->UndoMatch())
|
|
|
|
wxBell();
|
|
|
|
// Don't auto-match here, undoing sets the selection to the undone match
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
2007-01-13 08:04:12 +01:00
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogKanjiTimer::OnSkipSource(wxCommandEvent &) {
|
2013-01-04 16:01:50 +01:00
|
|
|
currentSourceLine = FindNextStyleMatch(currentSourceLine, from_wx(SourceStyle->GetValue()));
|
2009-06-08 04:37:09 +02:00
|
|
|
ResetForNewLine();
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
2007-01-24 04:54:32 +01:00
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogKanjiTimer::OnSkipDest(wxCommandEvent &) {
|
2013-01-04 16:01:50 +01:00
|
|
|
currentDestinationLine = FindNextStyleMatch(currentDestinationLine, from_wx(DestStyle->GetValue()));
|
2009-06-08 04:37:09 +02:00
|
|
|
ResetForNewLine();
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogKanjiTimer::OnGoBack(wxCommandEvent &) {
|
2011-09-28 21:44:07 +02:00
|
|
|
if (LinesToChange.size())
|
2007-01-25 23:47:29 +01:00
|
|
|
LinesToChange.pop_back(); //If we go back, then take out the modified line we saved.
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
currentSourceLine = FindPrevStyleMatch(currentSourceLine, from_wx(SourceStyle->GetValue()));
|
|
|
|
currentDestinationLine = FindPrevStyleMatch(currentDestinationLine, from_wx(DestStyle->GetValue()));
|
2009-06-08 04:37:09 +02:00
|
|
|
ResetForNewLine();
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2011-12-22 22:09:31 +01:00
|
|
|
void DialogKanjiTimer::OnAccept(wxCommandEvent &) {
|
2012-10-12 19:16:39 +02:00
|
|
|
if (!currentDestinationLine) return;
|
2012-03-27 02:48:47 +02:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
if (display->GetRemainingSource() > 0)
|
2007-01-13 08:04:12 +01:00
|
|
|
wxMessageBox(_("Group all of the source text."),_("Error"),wxICON_EXCLAMATION | wxOK);
|
2014-03-07 19:58:51 +01:00
|
|
|
else {
|
|
|
|
LinesToChange.push_back(std::make_pair(currentDestinationLine, display->GetOutputLine()));
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
currentSourceLine = FindNextStyleMatch(currentSourceLine, from_wx(SourceStyle->GetValue()));
|
|
|
|
currentDestinationLine = FindNextStyleMatch(currentDestinationLine, from_wx(DestStyle->GetValue()));
|
2009-06-08 04:37:09 +02:00
|
|
|
ResetForNewLine();
|
2007-01-13 08:04:12 +01:00
|
|
|
}
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
|
2007-01-13 03:22:28 +01:00
|
|
|
void DialogKanjiTimer::OnKeyDown(wxKeyEvent &event) {
|
2007-01-24 04:54:32 +01:00
|
|
|
wxCommandEvent evt;
|
2007-01-16 21:55:27 +01:00
|
|
|
switch(event.GetKeyCode()) {
|
2007-01-13 03:22:28 +01:00
|
|
|
case WXK_ESCAPE :
|
2007-01-24 04:54:32 +01:00
|
|
|
OnClose(evt);
|
2007-01-13 03:22:28 +01:00
|
|
|
break;
|
|
|
|
case WXK_BACK :
|
2007-01-24 04:54:32 +01:00
|
|
|
OnUnlink(evt);
|
2007-01-13 03:22:28 +01:00
|
|
|
break;
|
|
|
|
case WXK_RIGHT : //inc dest selection len
|
2009-06-08 04:37:09 +02:00
|
|
|
display->IncreseDestinationMatch();
|
2007-01-13 03:22:28 +01:00
|
|
|
break;
|
|
|
|
case WXK_LEFT : //dec dest selection len
|
2009-06-08 04:37:09 +02:00
|
|
|
display->DecreaseDestinationMatch();
|
2007-01-13 03:22:28 +01:00
|
|
|
break;
|
|
|
|
case WXK_UP : //inc source selection len
|
2009-06-08 04:37:09 +02:00
|
|
|
display->IncreaseSourceMatch();
|
2007-01-13 03:22:28 +01:00
|
|
|
break;
|
|
|
|
case WXK_DOWN : //dec source selection len
|
2009-06-08 04:37:09 +02:00
|
|
|
display->DecreaseSourceMatch();
|
2007-01-13 03:22:28 +01:00
|
|
|
break;
|
|
|
|
case WXK_RETURN :
|
2012-03-27 02:48:38 +02:00
|
|
|
if (display->GetRemainingSource() == 0 && display->GetRemainingDestination() == 0)
|
|
|
|
OnAccept(evt);
|
|
|
|
else
|
|
|
|
OnLink(evt);
|
2007-01-13 03:22:28 +01:00
|
|
|
break;
|
|
|
|
default :
|
|
|
|
event.Skip();
|
|
|
|
}
|
|
|
|
}
|
2009-06-08 04:37:09 +02:00
|
|
|
|
|
|
|
void DialogKanjiTimer::ResetForNewLine()
|
|
|
|
{
|
2014-03-07 19:58:51 +01:00
|
|
|
if (!currentSourceLine || !currentDestinationLine)
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
2014-03-07 19:58:51 +01:00
|
|
|
currentSourceLine = currentDestinationLine = nullptr;
|
2009-06-08 04:37:09 +02:00
|
|
|
wxBell();
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
|
|
|
|
2014-03-07 19:58:51 +01:00
|
|
|
display->SetInputData(currentSourceLine, currentDestinationLine);
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
TryAutoMatch();
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
display->SetFocus();
|
|
|
|
}
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2009-06-08 04:37:09 +02:00
|
|
|
void DialogKanjiTimer::TryAutoMatch()
|
|
|
|
{
|
|
|
|
if (Interpolate->GetValue())
|
|
|
|
display->AutoMatchJapanese();
|
|
|
|
}
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2012-11-24 20:35:51 +01:00
|
|
|
template<typename Iterator>
|
2014-03-07 19:58:51 +01:00
|
|
|
static AssDialogue *find_next(Iterator from, Iterator to, std::string const& style_name) {
|
2013-09-16 00:37:49 +02:00
|
|
|
for (; from != to; ++from)
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
2014-03-07 19:58:51 +01:00
|
|
|
if (from->Style == style_name && !from->Text.get().empty())
|
|
|
|
return &*from;
|
2009-06-08 04:37:09 +02:00
|
|
|
}
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2012-11-24 20:35:51 +01:00
|
|
|
return nullptr;
|
2007-01-13 03:22:28 +01:00
|
|
|
}
|
|
|
|
|
2014-03-07 19:58:51 +01:00
|
|
|
AssDialogue *DialogKanjiTimer::FindNextStyleMatch(AssDialogue *search_from, const std::string &search_style)
|
2009-06-08 04:37:09 +02:00
|
|
|
{
|
2012-10-12 19:16:39 +02:00
|
|
|
if (!search_from) return search_from;
|
2014-04-04 17:11:09 +02:00
|
|
|
return find_next(++subs->iterator_to(*search_from), subs->Events.end(), search_style);
|
2012-11-24 20:35:51 +01:00
|
|
|
}
|
2007-01-13 03:22:28 +01:00
|
|
|
|
2014-03-07 19:58:51 +01:00
|
|
|
AssDialogue *DialogKanjiTimer::FindPrevStyleMatch(AssDialogue *search_from, const std::string &search_style)
|
2012-11-24 20:35:51 +01:00
|
|
|
{
|
|
|
|
if (!search_from) return search_from;
|
2014-04-04 17:11:09 +02:00
|
|
|
return find_next(EntryList<AssDialogue>::reverse_iterator(subs->iterator_to(*search_from)), subs->Events.rend(), search_style);
|
2007-01-13 08:04:12 +01:00
|
|
|
}
|