Split AudioDisplay::OnPaint into several methods

Originally committed to SVN as r6251.
This commit is contained in:
Thomas Goyne 2012-01-08 01:36:58 +00:00
parent 3c62a38c7a
commit 702d1e9c22
2 changed files with 166 additions and 128 deletions

View File

@ -845,12 +845,7 @@ void AudioDisplay::OnPaint(wxPaintEvent&)
return;
}
int client_width, client_height;
GetClientSize(&client_width, &client_height);
wxRect audio_bounds(0, audio_top, client_width, audio_height);
const wxRect &scrollbar_bounds = scrollbar->GetBounds();
const wxRect &timeline_bounds = timeline->GetBounds();
wxRect audio_bounds(0, audio_top, GetClientSize().GetWidth(), audio_height);
bool redraw_scrollbar = false;
bool redraw_timeline = false;
@ -864,136 +859,24 @@ void AudioDisplay::OnPaint(wxPaintEvent&)
updrect.x += client_org.x; updrect.y += client_org.y;
#endif
redraw_scrollbar |= scrollbar_bounds.Intersects(updrect);
redraw_timeline |= timeline_bounds.Intersects(updrect);
redraw_scrollbar |= scrollbar->GetBounds().Intersects(updrect);
redraw_timeline |= timeline->GetBounds().Intersects(updrect);
if (!audio_bounds.Intersects(updrect))
if (audio_bounds.Intersects(updrect))
{
continue;
}
SampleRange updsamples(
SamplesFromRelativeX(updrect.x - foot_size),
SamplesFromRelativeX(updrect.x + updrect.width + foot_size));
SampleRange updsamples(
SamplesFromRelativeX(updrect.x - foot_size),
SamplesFromRelativeX(updrect.x + updrect.width + foot_size));
std::map<int64_t, int>::iterator pt = style_ranges.upper_bound(updsamples.begin());
std::map<int64_t, int>::iterator pe = style_ranges.upper_bound(updsamples.end());
if (pt != style_ranges.begin())
--pt;
while (pt != pe)
{
AudioRenderingStyle range_style = static_cast<AudioRenderingStyle>(pt->second);
int range_x1 = std::max(updrect.x, RelativeXFromSamples(pt->first));
int range_x2 = (++pt == pe) ? updrect.x + updrect.width : RelativeXFromSamples(pt->first);
if (range_x2 > range_x1)
{
audio_renderer->Render(dc, wxPoint(range_x1, audio_top), range_x1 + scroll_left, range_x2 - range_x1, range_style);
}
}
// Draw markers on top of it all
AudioMarkerVector markers;
controller->GetMarkers(updsamples, markers);
wxDCPenChanger pen_retainer(dc, wxPen());
wxDCBrushChanger brush_retainer(dc, wxBrush());
for (AudioMarkerVector::iterator marker_i = markers.begin(); marker_i != markers.end(); ++marker_i)
{
const AudioMarker *marker = *marker_i;
dc.SetPen(marker->GetStyle());
int marker_x = RelativeXFromSamples(marker->GetPosition());
dc.DrawLine(marker_x, audio_top, marker_x, audio_top+audio_height);
dc.SetBrush(wxBrush(marker->GetStyle().GetColour()));
dc.SetPen(*wxTRANSPARENT_PEN);
if (marker->GetFeet() & AudioMarker::Feet_Left)
{
wxPoint foot_top[3] = { wxPoint(-foot_size, 0), wxPoint(0, 0), wxPoint(0, foot_size) };
wxPoint foot_bot[3] = { wxPoint(-foot_size, 0), wxPoint(0, -foot_size), wxPoint(0, 0) };
dc.DrawPolygon(3, foot_top, marker_x, audio_top);
dc.DrawPolygon(3, foot_bot, marker_x, audio_top+audio_height);
}
if (marker->GetFeet() & AudioMarker::Feet_Right)
{
wxPoint foot_top[3] = { wxPoint(foot_size, 0), wxPoint(0, 0), wxPoint(0, foot_size) };
wxPoint foot_bot[3] = { wxPoint(foot_size, 0), wxPoint(0, -foot_size), wxPoint(0, 0) };
dc.DrawPolygon(3, foot_top, marker_x, audio_top);
dc.DrawPolygon(3, foot_bot, marker_x, audio_top+audio_height);
}
}
// Draw labels
std::vector<AudioLabelProvider::AudioLabel> labels;
controller->GetLabels(updsamples, labels);
if (!labels.empty())
{
wxDCFontChanger fc(dc);
wxFont font = dc.GetFont();
font.SetWeight(wxFONTWEIGHT_BOLD);
dc.SetFont(font);
dc.SetTextForeground(*wxWHITE);
for (size_t i = 0; i < labels.size(); ++i)
{
wxSize extent = dc.GetTextExtent(labels[i].text);
int left = RelativeXFromSamples(labels[i].range.begin());
int width = AbsoluteXFromSamples(labels[i].range.length());
// If it doesn't fit, truncate
if (width < extent.GetWidth())
{
dc.SetClippingRegion(left, audio_top + 4, width, extent.GetHeight());
dc.DrawText(labels[i].text, left, audio_top + 4);
dc.DestroyClippingRegion();
}
// Otherwise center in the range
else
{
dc.DrawText(labels[i].text, left + (width - extent.GetWidth()) / 2, audio_top + 4);
}
}
PaintAudio(dc, updsamples, updrect);
PaintMarkers(dc, updsamples);
PaintLabels(dc, updsamples);
}
}
if (track_cursor_pos >= 0)
{
wxDCPenChanger penchanger(dc, wxPen(*wxWHITE));
dc.DrawLine(track_cursor_pos-scroll_left, audio_top, track_cursor_pos-scroll_left, audio_top+audio_height);
if (!track_cursor_label.empty())
{
wxDCFontChanger fc(dc);
wxFont font = dc.GetFont();
font.SetWeight(wxFONTWEIGHT_BOLD);
dc.SetFont(font);
wxSize label_size(dc.GetTextExtent(track_cursor_label));
wxPoint label_pos(track_cursor_pos - scroll_left - label_size.x/2, audio_top + 2);
if (label_pos.x < 2) label_pos.x = 2;
if (label_pos.x + label_size.x >= client_width - 2) label_pos.x = client_width - label_size.x - 2;
int old_bg_mode = dc.GetBackgroundMode();
dc.SetBackgroundMode(wxTRANSPARENT);
// Draw border
dc.SetTextForeground(wxColour(64, 64, 64));
dc.DrawText(track_cursor_label, label_pos.x+1, label_pos.y+1);
dc.DrawText(track_cursor_label, label_pos.x+1, label_pos.y-1);
dc.DrawText(track_cursor_label, label_pos.x-1, label_pos.y+1);
dc.DrawText(track_cursor_label, label_pos.x-1, label_pos.y-1);
// Draw fill
dc.SetTextForeground(*wxWHITE);
dc.DrawText(track_cursor_label, label_pos.x, label_pos.y);
dc.SetBackgroundMode(old_bg_mode);
label_pos.x -= 2; label_pos.y -= 2;
label_size.IncBy(4, 4);
// If the rendered text changes size we have to draw it an extra time to make sure the entire thing was drawn
bool need_extra_redraw = track_cursor_label_rect.GetSize() != label_size;
track_cursor_label_rect.SetPosition(label_pos);
track_cursor_label_rect.SetSize(label_size);
if (need_extra_redraw)
RefreshRect(track_cursor_label_rect, false);
}
PaintTrackCursor(dc);
}
if (redraw_scrollbar)
@ -1002,6 +885,135 @@ void AudioDisplay::OnPaint(wxPaintEvent&)
timeline->Paint(dc);
}
void AudioDisplay::PaintAudio(wxDC &dc, SampleRange updsamples, wxRect updrect)
{
std::map<int64_t, int>::iterator pt = style_ranges.upper_bound(updsamples.begin());
std::map<int64_t, int>::iterator pe = style_ranges.upper_bound(updsamples.end());
if (pt != style_ranges.begin())
--pt;
while (pt != pe)
{
AudioRenderingStyle range_style = static_cast<AudioRenderingStyle>(pt->second);
int range_x1 = std::max(updrect.x, RelativeXFromSamples(pt->first));
int range_x2 = (++pt == pe) ? updrect.x + updrect.width : RelativeXFromSamples(pt->first);
if (range_x2 > range_x1)
{
audio_renderer->Render(dc, wxPoint(range_x1, audio_top), range_x1 + scroll_left, range_x2 - range_x1, range_style);
}
}
}
void AudioDisplay::PaintMarkers(wxDC &dc, SampleRange updsamples)
{
AudioMarkerVector markers;
controller->GetMarkers(updsamples, markers);
if (markers.empty()) return;
wxDCPenChanger pen_retainer(dc, wxPen());
wxDCBrushChanger brush_retainer(dc, wxBrush());
for (AudioMarkerVector::iterator marker_i = markers.begin(); marker_i != markers.end(); ++marker_i)
{
const AudioMarker *marker = *marker_i;
int marker_x = RelativeXFromSamples(marker->GetPosition());
dc.SetPen(marker->GetStyle());
dc.DrawLine(marker_x, audio_top, marker_x, audio_top+audio_height);
if (marker->GetFeet() == AudioMarker::Feet_None) continue;
dc.SetBrush(wxBrush(marker->GetStyle().GetColour()));
dc.SetPen(*wxTRANSPARENT_PEN);
if (marker->GetFeet() & AudioMarker::Feet_Left)
PaintFoot(dc, marker_x, -1);
if (marker->GetFeet() & AudioMarker::Feet_Right)
PaintFoot(dc, marker_x, 1);
}
}
void AudioDisplay::PaintFoot(wxDC &dc, int marker_x, int dir)
{
wxPoint foot_top[3] = { wxPoint(foot_size * dir, 0), wxPoint(0, 0), wxPoint(0, foot_size) };
wxPoint foot_bot[3] = { wxPoint(foot_size * dir, 0), wxPoint(0, -foot_size), wxPoint(0, 0) };
dc.DrawPolygon(3, foot_top, marker_x, audio_top);
dc.DrawPolygon(3, foot_bot, marker_x, audio_top+audio_height);
}
void AudioDisplay::PaintLabels(wxDC &dc, SampleRange updsamples)
{
std::vector<AudioLabelProvider::AudioLabel> labels;
controller->GetLabels(updsamples, labels);
if (labels.empty()) return;
wxDCFontChanger fc(dc);
wxFont font = dc.GetFont();
font.SetWeight(wxFONTWEIGHT_BOLD);
dc.SetFont(font);
dc.SetTextForeground(*wxWHITE);
for (size_t i = 0; i < labels.size(); ++i)
{
wxSize extent = dc.GetTextExtent(labels[i].text);
int left = RelativeXFromSamples(labels[i].range.begin());
int width = AbsoluteXFromSamples(labels[i].range.length());
// If it doesn't fit, truncate
if (width < extent.GetWidth())
{
dc.SetClippingRegion(left, audio_top + 4, width, extent.GetHeight());
dc.DrawText(labels[i].text, left, audio_top + 4);
dc.DestroyClippingRegion();
}
// Otherwise center in the range
else
{
dc.DrawText(labels[i].text, left + (width - extent.GetWidth()) / 2, audio_top + 4);
}
}
}
void AudioDisplay::PaintTrackCursor(wxDC &dc) {
wxDCPenChanger penchanger(dc, wxPen(*wxWHITE));
dc.DrawLine(track_cursor_pos-scroll_left, audio_top, track_cursor_pos-scroll_left, audio_top+audio_height);
if (track_cursor_label.empty()) return;
wxDCFontChanger fc(dc);
wxFont font = dc.GetFont();
font.SetWeight(wxFONTWEIGHT_BOLD);
dc.SetFont(font);
wxSize label_size(dc.GetTextExtent(track_cursor_label));
wxPoint label_pos(track_cursor_pos - scroll_left - label_size.x/2, audio_top + 2);
label_pos.x = mid(2, label_pos.x, GetClientSize().GetWidth() - label_size.x - 2);
int old_bg_mode = dc.GetBackgroundMode();
dc.SetBackgroundMode(wxTRANSPARENT);
// Draw border
dc.SetTextForeground(wxColour(64, 64, 64));
dc.DrawText(track_cursor_label, label_pos.x+1, label_pos.y+1);
dc.DrawText(track_cursor_label, label_pos.x+1, label_pos.y-1);
dc.DrawText(track_cursor_label, label_pos.x-1, label_pos.y+1);
dc.DrawText(track_cursor_label, label_pos.x-1, label_pos.y-1);
// Draw fill
dc.SetTextForeground(*wxWHITE);
dc.DrawText(track_cursor_label, label_pos.x, label_pos.y);
dc.SetBackgroundMode(old_bg_mode);
label_pos.x -= 2;
label_pos.y -= 2;
label_size.IncBy(4, 4);
// If the rendered text changes size we have to draw it an extra time to make sure the entire thing was drawn
bool need_extra_redraw = track_cursor_label_rect.GetSize() != label_size;
track_cursor_label_rect.SetPosition(label_pos);
track_cursor_label_rect.SetSize(label_size);
if (need_extra_redraw)
RefreshRect(track_cursor_label_rect, false);
}
void AudioDisplay::SetDraggedObject(AudioDisplayInteractionObject *new_obj)
{

View File

@ -184,6 +184,32 @@ class AudioDisplay: public wxWindow {
/// @param sample_end Last sample to repaint
void Redraw(int64_t sample_start, int64_t sample_end);
/// Paint the audio data for a range of samples
/// @param dc DC to paint to
/// @param updsamples Sample range to repaint
/// @param updrect Pixel range to repaint
void PaintAudio(wxDC &dc, SampleRange updsamples, wxRect updrect);
/// Paint the markers in a range of samples
/// @param dc DC to paint to
/// @param updsamples Sample range to repaint
void PaintMarkers(wxDC &dc, SampleRange updsamples);
/// Draw a single foot for a marker
/// @param dc DC to paint to
/// @param marker_x Position of the marker whose foot is being painted in pixels
/// @param dir -1 for left, 1 for right
void PaintFoot(wxDC &dc, int marker_x, int dir);
/// Paint the labels in a range of samples
/// @param dc DC to paint to
/// @param updsamples Sample range to repaint
void PaintLabels(wxDC &dc, SampleRange updsamples);
/// Paint the track cursor
/// @param dc DC to paint to
void PaintTrackCursor(wxDC &dc);
/// wxWidgets paint event
void OnPaint(wxPaintEvent &event);
/// wxWidgets mouse input event