Skip to content
Extraits de code Groupes Projets
Valider 55bdbf8d rédigé par Thomas Goyne's avatar Thomas Goyne
Parcourir les fichiers

Add scroll arrows to the karaoke syllable bar when the contents are too wide to fit. Closes #1516.

parent b020322a
Branches
Étiquettes
Aucune requête de fusion associée trouvée
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
#include "libresrc/libresrc.h" #include "libresrc/libresrc.h"
#include "main.h" #include "main.h"
#include "selection_controller.h" #include "selection_controller.h"
#include "utils.h"
template<class Container, class Value> template<class Container, class Value>
static inline size_t last_lt_or_eq(Container const& c, Value const& v) { static inline size_t last_lt_or_eq(Container const& c, Value const& v) {
...@@ -70,11 +71,11 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c) ...@@ -70,11 +71,11 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c)
, audio_closed(c->audioController->AddAudioCloseListener(&AudioKaraoke::OnAudioClosed, this)) , audio_closed(c->audioController->AddAudioCloseListener(&AudioKaraoke::OnAudioClosed, this))
, active_line(0) , active_line(0)
, kara(new AssKaraoke) , kara(new AssKaraoke)
, scroll_x(0)
, enabled(false) , enabled(false)
{ {
using std::tr1::bind; using std::tr1::bind;
cancel_button = new wxBitmapButton(this, -1, GETIMAGE(kara_split_cancel_16)); cancel_button = new wxBitmapButton(this, -1, GETIMAGE(kara_split_cancel_16));
cancel_button->SetToolTip(_("Discard all uncommitted splits")); cancel_button->SetToolTip(_("Discard all uncommitted splits"));
cancel_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, bind(&AudioKaraoke::CancelSplit, this)); cancel_button->Bind(wxEVT_COMMAND_BUTTON_CLICKED, bind(&AudioKaraoke::CancelSplit, this));
...@@ -102,6 +103,7 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c) ...@@ -102,6 +103,7 @@ AudioKaraoke::AudioKaraoke(wxWindow *parent, agi::Context *c)
split_area->Bind(wxEVT_MOTION, &AudioKaraoke::OnMouse, this); split_area->Bind(wxEVT_MOTION, &AudioKaraoke::OnMouse, this);
split_area->Bind(wxEVT_LEAVE_WINDOW, &AudioKaraoke::OnMouse, this); split_area->Bind(wxEVT_LEAVE_WINDOW, &AudioKaraoke::OnMouse, this);
split_area->Bind(wxEVT_CONTEXT_MENU, &AudioKaraoke::OnContextMenu, this); split_area->Bind(wxEVT_CONTEXT_MENU, &AudioKaraoke::OnContextMenu, this);
scroll_timer.Bind(wxEVT_TIMER, &AudioKaraoke::OnScrollTimer, this);
c->selectionController->AddSelectionListener(this); c->selectionController->AddSelectionListener(this);
...@@ -141,8 +143,6 @@ void AudioKaraoke::SetEnabled(bool en) { ...@@ -141,8 +143,6 @@ void AudioKaraoke::SetEnabled(bool en) {
enabled = en; enabled = en;
c->audioBox->ShowKaraokeBar(enabled); c->audioBox->ShowKaraokeBar(enabled);
split_area->SetSize(GetSize().GetWidth(), -1);
if (enabled) { if (enabled) {
LoadFromLine(); LoadFromLine();
c->audioController->SetTimingController(CreateKaraokeTimingController(c, kara.get(), file_changed)); c->audioController->SetTimingController(CreateKaraokeTimingController(c, kara.get(), file_changed));
...@@ -166,19 +166,54 @@ void AudioKaraoke::OnPaint(wxPaintEvent &) { ...@@ -166,19 +166,54 @@ void AudioKaraoke::OnPaint(wxPaintEvent &) {
wxMemoryDC bmp_dc(rendered_line); wxMemoryDC bmp_dc(rendered_line);
// Draw the text and split lines // Draw the text and split lines
dc.Blit(0, 0, w, h, &bmp_dc, 0, 0); dc.Blit(-scroll_x, 0, rendered_line.GetWidth(), h, &bmp_dc, 0, 0);
// Draw the split line under the mouse // Draw the split line under the mouse
dc.SetPen(*wxRED); dc.SetPen(*wxRED);
dc.DrawLine(mouse_pos, 0, mouse_pos, h); dc.DrawLine(mouse_pos, 0, mouse_pos, h);
dc.SetPen(*wxTRANSPARENT_PEN);
int width_past_bmp = w + scroll_x - rendered_line.GetWidth();
dc.SetBrush(*wxWHITE_BRUSH);
if (width_past_bmp > 0)
dc.DrawRectangle(w - width_past_bmp, 0, width_past_bmp, h);
// Draw scroll arrows if needed
if (scroll_x > 0) {
dc.DrawRectangle(0, 0, 20, h);
wxPoint triangle[] = {
wxPoint(10, h / 2 - 6),
wxPoint(4, h / 2),
wxPoint(10, h / 2 + 6)
};
dc.SetBrush(*wxBLACK_BRUSH);
dc.DrawPolygon(3, triangle);
}
if (rendered_line.GetWidth() - scroll_x > w) {
dc.SetBrush(*wxWHITE_BRUSH);
dc.DrawRectangle(w - 20, 0, 20, h);
wxPoint triangle[] = {
wxPoint(w - 10, h / 2 - 6),
wxPoint(w - 4, h / 2),
wxPoint(w - 10, h / 2 + 6)
};
dc.SetBrush(*wxBLACK_BRUSH);
dc.DrawPolygon(3, triangle);
}
} }
void AudioKaraoke::RenderText() { void AudioKaraoke::RenderText() {
int w, h; wxSize bmp_size = split_area->GetClientSize();
split_area->GetClientSize(&w, &h); int line_width = spaced_text.size() * char_width + 5;
if (line_width > bmp_size.GetWidth())
bmp_size.SetWidth(line_width);
if (!rendered_line.IsOk() || split_area->GetClientSize() != rendered_line.GetSize()) { if (!rendered_line.IsOk() || bmp_size != rendered_line.GetSize()) {
rendered_line = wxBitmap(w, h); rendered_line = wxBitmap(bmp_size);
} }
wxMemoryDC dc(rendered_line); wxMemoryDC dc(rendered_line);
...@@ -186,13 +221,13 @@ void AudioKaraoke::RenderText() { ...@@ -186,13 +221,13 @@ void AudioKaraoke::RenderText() {
// Draw background // Draw background
dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW))); dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
dc.SetPen(*wxTRANSPARENT_PEN); dc.SetPen(*wxTRANSPARENT_PEN);
dc.DrawRectangle(0, 0, w, h); dc.DrawRectangle(wxPoint(), bmp_size);
dc.SetFont(split_font); dc.SetFont(split_font);
dc.SetTextForeground(wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT))); dc.SetTextForeground(wxColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)));
// Draw each character in the line // Draw each character in the line
int y = (h - char_height) / 2; int y = (bmp_size.GetHeight() - char_height) / 2;
for (size_t i = 0; i < spaced_text.size(); ++i) { for (size_t i = 0; i < spaced_text.size(); ++i) {
dc.DrawText(spaced_text[i], char_x[i], y); dc.DrawText(spaced_text[i], char_x[i], y);
} }
...@@ -200,7 +235,7 @@ void AudioKaraoke::RenderText() { ...@@ -200,7 +235,7 @@ void AudioKaraoke::RenderText() {
// Draw the lines between each syllable // Draw the lines between each syllable
dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT)); dc.SetPen(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
for (size_t i = 0; i < syl_lines.size(); ++i) { for (size_t i = 0; i < syl_lines.size(); ++i) {
dc.DrawLine(syl_lines[i], 0, syl_lines[i], h); dc.DrawLine(syl_lines[i], 0, syl_lines[i], bmp_size.GetHeight());
} }
} }
...@@ -228,8 +263,45 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) { ...@@ -228,8 +263,45 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) {
mouse_pos = event.GetX(); mouse_pos = event.GetX();
if (event.Leaving()) if (event.Leaving()) {
mouse_pos = -1;
split_area->Refresh(false);
return;
}
if (scroll_timer.IsRunning() || split_area->HasCapture()) {
if (event.LeftUp()) {
scroll_timer.Stop();
split_area->ReleaseMouse();
}
return;
}
// Check if the mouse is over a scroll arrow
int client_width = split_area->GetClientSize().GetWidth();
if (scroll_x > 0 && mouse_pos < 20) {
scroll_dir = -1;
}
else if (scroll_x + client_width < rendered_line.GetWidth() && mouse_pos > client_width - 20) {
scroll_dir = 1;
}
else {
scroll_dir = 0;
}
if (scroll_dir) {
mouse_pos = -1; mouse_pos = -1;
if (event.LeftDown()) {
split_area->Refresh(false);
scroll_timer.Start(50);
split_area->CaptureMouse();
wxTimerEvent evt;
OnScrollTimer(evt);
}
return;
}
int shifted_pos = mouse_pos + scroll_x;
if (!event.LeftDown()) { if (!event.LeftDown()) {
// Erase the old line and draw the new one // Erase the old line and draw the new one
...@@ -238,14 +310,14 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) { ...@@ -238,14 +310,14 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) {
} }
// Character to insert the new split point before // Character to insert the new split point before
int split_pos = std::min<int>((mouse_pos - char_width / 2) / char_width, spaced_text.size()); int split_pos = std::min<int>((shifted_pos - char_width / 2) / char_width, spaced_text.size());
// Syllable this character is in // Syllable this character is in
int syl = last_lt_or_eq(syl_start_points, split_pos); int syl = last_lt_or_eq(syl_start_points, split_pos);
// If the click is sufficiently close to a line of a syllable split, // If the click is sufficiently close to a line of a syllable split,
// remove that split rather than adding a new one // remove that split rather than adding a new one
if ((syl > 0 && mouse_pos <= syl_lines[syl - 1] + 2) || (syl < (int)syl_lines.size() && mouse_pos >= syl_lines[syl] - 2)) { if ((syl > 0 && shifted_pos <= syl_lines[syl - 1] + 2) || (syl < (int)syl_lines.size() && shifted_pos >= syl_lines[syl] - 2)) {
kara->RemoveSplit(syl); kara->RemoveSplit(syl);
} }
else { else {
...@@ -258,7 +330,21 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) { ...@@ -258,7 +330,21 @@ void AudioKaraoke::OnMouse(wxMouseEvent &event) {
split_area->Refresh(false); split_area->Refresh(false);
} }
void AudioKaraoke::OnScrollTimer(wxTimerEvent &) {
scroll_x += scroll_dir * char_width * 3;
int max_scroll = rendered_line.GetWidth() + 20 - split_area->GetClientSize().GetWidth();
if (scroll_x < 0 || scroll_x > max_scroll) {
scroll_x = mid(0, scroll_x, max_scroll);
scroll_timer.Stop();
}
split_area->Refresh(false);
}
void AudioKaraoke::LoadFromLine() { void AudioKaraoke::LoadFromLine() {
scroll_x = 0;
scroll_timer.Stop();
kara->SetLine(active_line, true); kara->SetLine(active_line, true);
SetDisplayText(); SetDisplayText();
accept_button->Enable(kara->GetText() != active_line->Text); accept_button->Enable(kara->GetText() != active_line->Text);
......
...@@ -97,6 +97,10 @@ class AudioKaraoke : public wxWindow, private SelectionListener<AssDialogue> { ...@@ -97,6 +97,10 @@ class AudioKaraoke : public wxWindow, private SelectionListener<AssDialogue> {
/// Left x coordinate of each character in spaced_text in pixels /// Left x coordinate of each character in spaced_text in pixels
std::vector<int> char_x; std::vector<int> char_x;
int scroll_x;
int scroll_dir;
wxTimer scroll_timer;
int char_height; ///< Maximum character height in pixels int char_height; ///< Maximum character height in pixels
int char_width; ///< Maximum character width in pixels int char_width; ///< Maximum character width in pixels
int mouse_pos; ///< Last x coordinate of the mouse int mouse_pos; ///< Last x coordinate of the mouse
...@@ -142,6 +146,7 @@ class AudioKaraoke : public wxWindow, private SelectionListener<AssDialogue> { ...@@ -142,6 +146,7 @@ class AudioKaraoke : public wxWindow, private SelectionListener<AssDialogue> {
void OnSelectedSetChanged(Selection const&, Selection const&) { } void OnSelectedSetChanged(Selection const&, Selection const&) { }
void OnAudioOpened(); void OnAudioOpened();
void OnAudioClosed(); void OnAudioClosed();
void OnScrollTimer(wxTimerEvent &event);
public: public:
/// Constructor /// Constructor
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter