mirror of
https://github.com/cookiengineer/audacity
synced 2025-06-16 16:10:06 +02:00
Reorganize code for drawing cursor and indicator, so it can generalize to...
... other things (like scrub speed)
This commit is contained in:
parent
7ee8032f3c
commit
9ba6e03bd4
@ -484,7 +484,6 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id,
|
||||
UpdatePrefs();
|
||||
|
||||
mRedrawAfterStop = false;
|
||||
mIndicatorShowing = false;
|
||||
|
||||
mPencilCursor = MakeCursor( wxCURSOR_PENCIL, DrawCursorXpm, 12, 22);
|
||||
mSelectCursor = MakeCursor( wxCURSOR_IBEAM, IBeamCursorXpm, 17, 16);
|
||||
@ -565,8 +564,9 @@ TrackPanel::TrackPanel(wxWindow * parent, wxWindowID id,
|
||||
mSnapLeft = -1;
|
||||
mSnapRight = -1;
|
||||
|
||||
mLastCursorX = -1;
|
||||
mLastIndicatorX = -1;
|
||||
mLastCursorX = mNewCursorX = -1;
|
||||
mLastIndicatorX = mNewIndicatorX = -1;
|
||||
mCursorTime = -1.0;
|
||||
mOldQPIndicatorPos = -1;
|
||||
|
||||
// Register for tracklist updates
|
||||
@ -1106,20 +1106,8 @@ void TrackPanel::OnTimer()
|
||||
DisplaySelection();
|
||||
}
|
||||
|
||||
// AS: The "indicator" is the little graphical mark shown in the ruler
|
||||
// that indicates where the current play/record position is. (This also
|
||||
// draws the moving vertical line.)
|
||||
|
||||
if (!gAudioIO->IsPaused() && // Don't redraw paused indicator needlessly for timer
|
||||
( mIndicatorShowing || IsAudioActive())
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
&& !mSmoothScrollingScrub
|
||||
#endif
|
||||
)
|
||||
{
|
||||
DrawIndicator();
|
||||
}
|
||||
TimerUpdateIndicator();
|
||||
DrawOverlays(false);
|
||||
|
||||
if(IsAudioActive() && gAudioIO->GetNumCaptureChannels()) {
|
||||
|
||||
@ -1182,6 +1170,8 @@ void TrackPanel::ScrollDuringDrag()
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// now unused
|
||||
/// This updates the indicator (on a timer tick) that shows
|
||||
/// where the current play or record position is. To do this,
|
||||
/// we cheat a little. The indicator is drawn during the ruler
|
||||
@ -1194,6 +1184,7 @@ void TrackPanel::DrawIndicator()
|
||||
wxClientDC dc( this );
|
||||
DoDrawIndicator( dc );
|
||||
}
|
||||
#endif
|
||||
|
||||
void TrackPanel::DrawQuickPlayIndicator(wxDC & dc, double pos)
|
||||
{
|
||||
@ -1225,53 +1216,31 @@ void TrackPanel::DrawQuickPlayIndicator(wxDC & dc, double pos)
|
||||
}
|
||||
}
|
||||
|
||||
/// Second level DrawIndicator()
|
||||
void TrackPanel::DoDrawIndicator
|
||||
(wxDC & dc, bool repairOld /* = false */, double indicator /* = -1 */)
|
||||
void TrackPanel::TimerUpdateIndicator()
|
||||
{
|
||||
bool onScreen;
|
||||
double pos;
|
||||
double pos = 0.0;
|
||||
|
||||
if (!repairOld)
|
||||
{
|
||||
// Erase the old indicator.
|
||||
if (mLastIndicatorX != -1)
|
||||
{
|
||||
onScreen = between_inclusive(GetLeftOffset(),
|
||||
mLastIndicatorX,
|
||||
GetLeftOffset() + mViewInfo->GetScreenWidth());
|
||||
if (onScreen)
|
||||
{
|
||||
// LL: Keep from trying to blit outsize of the source DC. This results in a crash on
|
||||
// OSX due to allocating memory using negative sizes and can be caused by resizing
|
||||
// the project window while recording or playing.
|
||||
int w = dc.GetSize().GetWidth();
|
||||
if (mLastIndicatorX >= w) {
|
||||
mLastIndicatorX = w - 1;
|
||||
}
|
||||
if (!IsAudioActive())
|
||||
mNewIndicatorX = -1;
|
||||
else {
|
||||
// Calculate the horizontal position of the indicator
|
||||
pos = gAudioIO->GetStreamTime();
|
||||
|
||||
dc.Blit(mLastIndicatorX, 0, 1, mBacking->GetHeight(), &mBackingDC, mLastIndicatorX, 0);
|
||||
}
|
||||
|
||||
// Nothing's ever perfect...
|
||||
//
|
||||
// Redraw the cursor since we may have just wiped it out
|
||||
if (mLastCursorX == mLastIndicatorX)
|
||||
{
|
||||
DoDrawCursor( dc );
|
||||
}
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
if (mSmoothScrollingScrub) {
|
||||
// Pan the view, so that we center the play indicator.
|
||||
mViewInfo->h = pos - mViewInfo->screen / 2.0;
|
||||
if (!mScrollBeyondZero)
|
||||
// Can't scroll too far left
|
||||
mViewInfo->h = std::max(0.0, mViewInfo->h);
|
||||
Refresh(false);
|
||||
}
|
||||
|
||||
pos = indicator;
|
||||
if (pos < 0.0)
|
||||
// The stream time can be < 0 if the audio is currently stopped
|
||||
pos = gAudioIO->GetStreamTime();
|
||||
|
||||
#endif
|
||||
AudacityProject *p = GetProject();
|
||||
bool audioActive = IsAudioActive();
|
||||
onScreen = between_inclusive( mViewInfo->h,
|
||||
pos,
|
||||
mViewInfo->h + mViewInfo->screen );
|
||||
const bool
|
||||
onScreen = between_inclusive(mViewInfo->h,
|
||||
pos,
|
||||
mViewInfo->h + mViewInfo->screen);
|
||||
|
||||
// This displays the audio time, too...
|
||||
DisplaySelection();
|
||||
@ -1281,7 +1250,6 @@ void TrackPanel::DoDrawIndicator
|
||||
if( mViewInfo->bUpdateTrackIndicator &&
|
||||
p->mLastPlayMode != loopedPlay &&
|
||||
p->mLastPlayMode != oneSecondPlay &&
|
||||
audioActive &&
|
||||
pos >= 0 &&
|
||||
!onScreen &&
|
||||
!gAudioIO->IsPaused() )
|
||||
@ -1294,13 +1262,55 @@ void TrackPanel::DoDrawIndicator
|
||||
// length of the project and therefore the appearance of the scrollbar.
|
||||
MakeParentRedrawScrollbars();
|
||||
|
||||
mIndicatorShowing = ( onScreen && audioActive );
|
||||
|
||||
// Calculate the horizontal position of the indicator
|
||||
mLastIndicatorX = mViewInfo->TimeToPosition(pos, GetLeftOffset());
|
||||
mNewIndicatorX = mViewInfo->TimeToPosition(pos, GetLeftOffset());
|
||||
}
|
||||
else
|
||||
pos = mViewInfo->PositionToTime(mLastIndicatorX, GetLeftOffset());
|
||||
}
|
||||
|
||||
std::pair<wxRect, bool> TrackPanel::GetIndicatorRectangle()
|
||||
{
|
||||
return std::make_pair(
|
||||
wxRect(mLastIndicatorX, 0, 1, mBacking->GetHeight()),
|
||||
mLastIndicatorX != mNewIndicatorX
|
||||
);
|
||||
}
|
||||
|
||||
void TrackPanel::UndrawIndicator(wxDC & dc)
|
||||
{
|
||||
// AS: The "indicator" is the little graphical mark shown in the ruler
|
||||
// that indicates where the current play/record position is. (This also
|
||||
// draws the moving vertical line.)
|
||||
|
||||
// Erase the old indicator.
|
||||
if (mLastIndicatorX != -1)
|
||||
{
|
||||
const bool
|
||||
onScreen = between_inclusive(GetLeftOffset(),
|
||||
mLastIndicatorX,
|
||||
GetLeftOffset() + mViewInfo->GetScreenWidth());
|
||||
if (onScreen)
|
||||
{
|
||||
// LL: Keep from trying to blit outsize of the source DC. This results in a crash on
|
||||
// OSX due to allocating memory using negative sizes and can be caused by resizing
|
||||
// the project window while recording or playing.
|
||||
int w = dc.GetSize().GetWidth();
|
||||
if (mLastIndicatorX >= w) {
|
||||
mLastIndicatorX = w - 1;
|
||||
}
|
||||
|
||||
dc.Blit(mLastIndicatorX, 0, 1, mBacking->GetHeight(), &mBackingDC, mLastIndicatorX, 0);
|
||||
}
|
||||
|
||||
mRuler->ClearIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
void TrackPanel::DoDrawIndicator(wxDC & dc)
|
||||
{
|
||||
mLastIndicatorX = mNewIndicatorX;
|
||||
if (mLastIndicatorX == -1)
|
||||
return;
|
||||
|
||||
double pos = mViewInfo->PositionToTime(mLastIndicatorX, GetLeftOffset());
|
||||
|
||||
// Set play/record color
|
||||
bool rec = (gAudioIO->GetNumCaptureChannels() > 0);
|
||||
@ -1340,6 +1350,8 @@ void TrackPanel::DoDrawIndicator
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
// now unused
|
||||
/// This method draws the cursor things, both in the
|
||||
/// ruler as seen at the top of the screen, but also in each of the
|
||||
/// selected tracks.
|
||||
@ -1349,12 +1361,27 @@ void TrackPanel::DrawCursor()
|
||||
wxClientDC dc( this );
|
||||
DoDrawCursor( dc );
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Second level DrawCursor()
|
||||
void TrackPanel::DoDrawCursor(wxDC & dc)
|
||||
std::pair<wxRect, bool> TrackPanel::GetCursorRectangle()
|
||||
{
|
||||
DisableAntialiasing(dc);
|
||||
if (!mViewInfo->selectedRegion.isPoint()) {
|
||||
mCursorTime = -1.0;
|
||||
mNewCursorX = -1;
|
||||
}
|
||||
else {
|
||||
mCursorTime = mViewInfo->selectedRegion.t0();
|
||||
mNewCursorX = mViewInfo->TimeToPosition(mCursorTime, GetLeftOffset());
|
||||
}
|
||||
|
||||
return std::make_pair(
|
||||
wxRect(mLastCursorX, 0, 1, mBacking->GetHeight()),
|
||||
mLastCursorX != mNewCursorX
|
||||
);
|
||||
}
|
||||
|
||||
void TrackPanel::UndrawCursor(wxDC & dc)
|
||||
{
|
||||
bool onScreen;
|
||||
|
||||
if( mLastCursorX != -1 )
|
||||
@ -1365,18 +1392,23 @@ void TrackPanel::DoDrawCursor(wxDC & dc)
|
||||
if( onScreen )
|
||||
dc.Blit(mLastCursorX, 0, 1, mBacking->GetHeight(), &mBackingDC, mLastCursorX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const double time = mViewInfo->selectedRegion.t0();
|
||||
mLastCursorX = mViewInfo->TimeToPosition(time, GetLeftOffset());
|
||||
void TrackPanel::DoDrawCursor(wxDC & dc)
|
||||
{
|
||||
mLastCursorX = mNewCursorX;
|
||||
if (mLastCursorX == -1)
|
||||
return;
|
||||
|
||||
const bool
|
||||
onScreen = between_inclusive( mViewInfo->h,
|
||||
time,
|
||||
mCursorTime,
|
||||
mViewInfo->h + mViewInfo->screen );
|
||||
|
||||
if( !onScreen )
|
||||
return;
|
||||
|
||||
AColor::CursorColor( &dc );
|
||||
AColor::CursorColor(&dc);
|
||||
|
||||
// Draw cursor in all selected tracks
|
||||
VisibleTrackIterator iter( GetProject() );
|
||||
@ -1404,7 +1436,7 @@ void TrackPanel::DoDrawCursor(wxDC & dc)
|
||||
}
|
||||
|
||||
// AS: Ah, no, this is where we draw the blinky thing in the ruler.
|
||||
mRuler->DrawCursor( time );
|
||||
mRuler->DrawCursor(mCursorTime);
|
||||
|
||||
DisplaySelection();
|
||||
}
|
||||
@ -1462,8 +1494,6 @@ void TrackPanel::OnPaint(wxPaintEvent & /* event */)
|
||||
// Retrieve the damage rectangle
|
||||
wxRect box = GetUpdateRegion().GetBox();
|
||||
|
||||
double indicator = -1;
|
||||
|
||||
// Recreate the backing bitmap if we have a full refresh
|
||||
// (See TrackPanel::Refresh())
|
||||
if (mRefreshBacking || (box == GetRect()))
|
||||
@ -1471,22 +1501,6 @@ void TrackPanel::OnPaint(wxPaintEvent & /* event */)
|
||||
// Reset (should a mutex be used???)
|
||||
mRefreshBacking = false;
|
||||
|
||||
#ifdef EXPERIMENTAL_SCRUBBING_SMOOTH_SCROLL
|
||||
if (mSmoothScrollingScrub && IsAudioActive()) {
|
||||
// Pan the view, so that we center the play indicator.
|
||||
// By the time DoDrawIndicator() is reached, gAudioIO->GetStreamTime()
|
||||
// may be a little different.
|
||||
// Cause DoDrawIndicator to show the value as it was at this time when we begin
|
||||
// the drawing of the tracks. This prevents flashing of the indicator
|
||||
// at higher magnifications, and keeps the green line still in the middle.
|
||||
indicator = gAudioIO->GetStreamTime();
|
||||
mViewInfo->h = indicator - mViewInfo->screen / 2.0;
|
||||
if (!mScrollBeyondZero)
|
||||
// Can't scroll too far left
|
||||
mViewInfo->h = std::max(0.0, mViewInfo->h);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Redraw the backing bitmap
|
||||
DrawTracks(&mBackingDC);
|
||||
|
||||
@ -1503,23 +1517,7 @@ void TrackPanel::OnPaint(wxPaintEvent & /* event */)
|
||||
delete dc;
|
||||
|
||||
// Drawing now goes directly to the client area
|
||||
wxClientDC cdc(this);
|
||||
DisableAntialiasing(cdc);
|
||||
|
||||
// Update the indicator in case it was damaged if this project is playing
|
||||
|
||||
if (// !gAudioIO->IsPaused() && // Bug1139: do repaint the line even if paused.
|
||||
(mIndicatorShowing || IsAudioActive()))
|
||||
{
|
||||
// If not smooth scrolling, then
|
||||
// we just want to repair, not update the old, so set the second param to true.
|
||||
// This is important because this onPaint could be for just some of the tracks.
|
||||
DoDrawIndicator(cdc, (indicator < 0), indicator);
|
||||
}
|
||||
|
||||
// Draw the cursor
|
||||
if (mViewInfo->selectedRegion.isPoint())
|
||||
DoDrawCursor(cdc);
|
||||
DrawOverlays(true);
|
||||
|
||||
#if DEBUG_DRAW_TIMING
|
||||
sw.Pause();
|
||||
@ -7592,6 +7590,67 @@ void TrackPanel::DrawOutsideOfTrack(Track * t, wxDC * dc, const wxRect & rect)
|
||||
#endif
|
||||
}
|
||||
|
||||
void TrackPanel::DrawOverlays(bool repaint)
|
||||
{
|
||||
bool isOutdated = false;
|
||||
|
||||
// Determine which overlays are outdated.
|
||||
enum { n_pairs = 2 };
|
||||
std::pair<wxRect, bool> pairs[n_pairs] = {
|
||||
GetIndicatorRectangle(),
|
||||
GetCursorRectangle(),
|
||||
};
|
||||
|
||||
{
|
||||
// Drawing now goes directly to the client area
|
||||
wxClientDC dc(this);
|
||||
DisableAntialiasing(dc);
|
||||
|
||||
// See what requires redrawing. If repainting, all.
|
||||
// If not, then whatever is outdated, and whatever will be damaged by
|
||||
// undrawing.
|
||||
// By redrawing only what needs it, we avoid flashing things like
|
||||
// the cursor that are drawn with xor.
|
||||
if (!repaint) {
|
||||
bool done;
|
||||
do {
|
||||
done = true;
|
||||
for (int ii = 0; ii < n_pairs; ++ii) {
|
||||
for (int jj = ii + 1; jj < n_pairs; ++jj) {
|
||||
if (pairs[ii].second != pairs[jj].second &&
|
||||
pairs[ii].first.Intersects(pairs[jj].first)) {
|
||||
done = false;
|
||||
pairs[ii].second = pairs[jj].second = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (!done);
|
||||
}
|
||||
}
|
||||
|
||||
if (repaint || pairs[0].second) {
|
||||
wxClientDC dc(this);
|
||||
DisableAntialiasing(dc);
|
||||
UndrawIndicator(dc);
|
||||
}
|
||||
if (repaint || pairs[1].second) {
|
||||
wxClientDC dc(this);
|
||||
DisableAntialiasing(dc);
|
||||
UndrawCursor(dc);
|
||||
}
|
||||
|
||||
if (repaint || pairs[0].second) {
|
||||
wxClientDC dc(this);
|
||||
DisableAntialiasing(dc);
|
||||
DoDrawIndicator(dc);
|
||||
}
|
||||
if (repaint || pairs[1].second) {
|
||||
wxClientDC dc(this);
|
||||
DisableAntialiasing(dc);
|
||||
DoDrawCursor(dc);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a three-level highlight gradient around the focused track.
|
||||
void TrackPanel::HighlightFocusedTrack(wxDC * dc, const wxRect & rect)
|
||||
{
|
||||
@ -8153,7 +8212,7 @@ void TrackPanel::SeekLeftOrRight
|
||||
mViewInfo->selectedRegion.collapseToT0();
|
||||
|
||||
// Move the visual cursor
|
||||
DrawCursor();
|
||||
DrawOverlays(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -237,7 +237,7 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel {
|
||||
* initial items.
|
||||
*
|
||||
* Ensures that all pop-down menus start with Name, and the commands for moving
|
||||
* the track around, via a single set of code.
|
||||
* the track around, via a single set of c ode.
|
||||
* @param menu the menu to add the commands to.
|
||||
*/
|
||||
virtual void BuildCommonDropMenuItems(wxMenu * menu);
|
||||
@ -250,12 +250,17 @@ class AUDACITY_DLL_API TrackPanel:public wxPanel {
|
||||
virtual bool HandleTrackLocationMouseEvent(WaveTrack * track, wxRect &rect, wxMouseEvent &event);
|
||||
virtual bool IsOverCutline(WaveTrack * track, wxRect &rect, wxMouseEvent &event);
|
||||
virtual void HandleTrackSpecificMouseEvent(wxMouseEvent & event);
|
||||
virtual void DrawIndicator();
|
||||
|
||||
virtual void TimerUpdateIndicator();
|
||||
// Second member of pair indicates whether the indicator is out of date:
|
||||
virtual std::pair<wxRect, bool> GetIndicatorRectangle();
|
||||
virtual void UndrawIndicator(wxDC & dc);
|
||||
/// draws the green line on the tracks to show playback position
|
||||
/// @param repairOld if true the playback position is not updated/erased, and simply redrawn
|
||||
/// @param indicator if nonnegative, overrides the indicator value obtainable from AudioIO
|
||||
virtual void DoDrawIndicator(wxDC & dc, bool repairOld = false, double indicator = -1);
|
||||
virtual void DrawCursor();
|
||||
virtual void DoDrawIndicator(wxDC & dc);
|
||||
|
||||
// Second member of pair indicates whether the cursor is out of date:
|
||||
virtual std::pair<wxRect, bool> GetCursorRectangle();
|
||||
virtual void UndrawCursor(wxDC & dc);
|
||||
virtual void DoDrawCursor(wxDC & dc);
|
||||
|
||||
virtual void ScrollDuringDrag();
|
||||
@ -540,6 +545,10 @@ protected:
|
||||
virtual void DrawBordersAroundTrack(Track *t, wxDC* dc, const wxRect & rect, const int labelw, const int vrul);
|
||||
virtual void DrawOutsideOfTrack (Track *t, wxDC* dc, const wxRect & rect);
|
||||
|
||||
// Erase and redraw things like the cursor, cheaply and directly to the
|
||||
// client area, without full refresh.
|
||||
virtual void DrawOverlays(bool repaint);
|
||||
|
||||
virtual int IdOfRate( int rate );
|
||||
virtual int IdOfFormat( int format );
|
||||
|
||||
@ -581,7 +590,10 @@ protected:
|
||||
// This stores the parts of the screen that get overwritten by the indicator
|
||||
// and cursor
|
||||
int mLastIndicatorX;
|
||||
int mNewIndicatorX;
|
||||
int mLastCursorX;
|
||||
double mCursorTime;
|
||||
int mNewCursorX;
|
||||
|
||||
// Quick-Play indicator postion
|
||||
double mOldQPIndicatorPos;
|
||||
@ -664,8 +676,6 @@ protected:
|
||||
|
||||
bool mRedrawAfterStop;
|
||||
|
||||
bool mIndicatorShowing;
|
||||
|
||||
wxMouseEvent mLastMouseEvent;
|
||||
|
||||
int mMouseClickX;
|
||||
|
Loading…
x
Reference in New Issue
Block a user