Coloured clips basics

These basics add a colour index to each clip and track, and allow for a choice of four colours to be set from the track menu drop down.  The additional wave colours (red, green and black) are not currently configurable, and the colour index is not currently saved.
This commit is contained in:
James Crook 2017-11-04 17:46:31 +00:00
parent fd3813fa30
commit 42c52de7f1
7 changed files with 174 additions and 15 deletions

View File

@ -275,7 +275,7 @@ TrackArtist::TrackArtist()
mSampleDisplay = 1;// Stem plots by default.
UpdatePrefs();
SetColours();
SetColours(0);
vruler = std::make_unique<Ruler>();
}
@ -283,7 +283,7 @@ TrackArtist::~TrackArtist()
{
}
void TrackArtist::SetColours()
void TrackArtist::SetColours( int iColorIndex)
{
theTheme.SetBrushColour( blankBrush, clrBlank );
theTheme.SetBrushColour( unselectedBrush, clrUnselected);
@ -296,17 +296,38 @@ void TrackArtist::SetColours()
theTheme.SetPenColour( blankPen, clrBlank);
theTheme.SetPenColour( unselectedPen, clrUnselected);
theTheme.SetPenColour( selectedPen, clrSelected);
theTheme.SetPenColour( samplePen, clrSample);
theTheme.SetPenColour( selsamplePen, clrSelSample);
theTheme.SetPenColour( muteSamplePen, clrMuteSample);
theTheme.SetPenColour( odProgressDonePen, clrProgressDone);
theTheme.SetPenColour( odProgressNotYetPen, clrProgressNotYet);
theTheme.SetPenColour( rmsPen, clrRms);
theTheme.SetPenColour( muteRmsPen, clrMuteRms);
theTheme.SetPenColour( shadowPen, clrShadow);
theTheme.SetPenColour( clippedPen, clrClipped);
theTheme.SetPenColour( muteClippedPen, clrMuteClipped);
theTheme.SetPenColour( blankSelectedPen,clrBlankSelected);
theTheme.SetPenColour( selsamplePen, clrSelSample);
theTheme.SetPenColour( muteRmsPen, clrMuteRms);
switch( iColorIndex %4 )
{
default:
case 0:
theTheme.SetPenColour( samplePen, clrSample);
theTheme.SetPenColour( rmsPen, clrRms);
break;
case 1: // RED
samplePen.SetColour( wxColor( 160,10,10 ) );
rmsPen.SetColour( wxColor( 230,80,80 ) );
break;
case 2: // GREEN
samplePen.SetColour( wxColor( 35,110,35 ) );
rmsPen.SetColour( wxColor( 75,200,75 ) );
break;
case 3: //BLACK
samplePen.SetColour( wxColor( 0,0,0 ) );
rmsPen.SetColour( wxColor( 100,100,100 ) );
break;
}
}
void TrackArtist::SetMargins(int left, int top, int right, int bottom)
@ -1827,6 +1848,8 @@ void TrackArtist::DrawClipWaveform(TrackPanelDrawingContext &context,
const float dBRange = track->GetWaveformSettings().dBRange;
dc.SetPen(*wxTRANSPARENT_PEN);
int iColorIndex = clip->GetColourIndex();
SetColours( iColorIndex );
// If we get to this point, the clip is actually visible on the
// screen, so remember the display rectangle.
@ -3304,7 +3327,7 @@ void TrackArtist::UpdatePrefs()
mdBrange = gPrefs->Read(ENV_DB_KEY, mdBrange);
mShowClipping = gPrefs->Read(wxT("/GUI/ShowClipping"), mShowClipping);
gPrefs->Read(wxT("/GUI/SampleView"), &mSampleDisplay, 1);
SetColours();
SetColours(0);
}
// Draws the sync-lock bitmap, tiled; always draws stationary relative to the DC

View File

@ -53,7 +53,7 @@ class AUDACITY_DLL_API TrackArtist {
TrackArtist();
~TrackArtist();
void SetColours();
void SetColours(int iColorIndex);
void DrawTracks(TrackPanelDrawingContext &context,
TrackList *tracks, Track *start,
const wxRegion & reg,

View File

@ -298,9 +298,10 @@ static void ComputeSpectrumUsingRealFFTf
}
WaveClip::WaveClip(const std::shared_ptr<DirManager> &projDirManager,
sampleFormat format, int rate)
sampleFormat format, int rate, int colourIndex)
{
mRate = rate;
mColourIndex = colourIndex;
mSequence = std::make_unique<Sequence>(projDirManager, format);
mEnvelope = std::make_unique<Envelope>(true, 1e-7, 2.0, 1.0);
@ -320,6 +321,7 @@ WaveClip::WaveClip(const WaveClip& orig,
mOffset = orig.mOffset;
mRate = orig.mRate;
mColourIndex = orig.mColourIndex;
mSequence = std::make_unique<Sequence>(*orig.mSequence, projDirManager);
mEnvelope = std::make_unique<Envelope>(*orig.mEnvelope);
@ -345,6 +347,7 @@ WaveClip::WaveClip(const WaveClip& orig,
mOffset = orig.mOffset;
mRate = orig.mRate;
mColourIndex = orig.mColourIndex;
mWaveCache = std::make_unique<WaveCache>();
mSpecCache = std::make_unique<SpecCache>();
@ -1540,7 +1543,7 @@ XMLTagHandler *WaveClip::HandleXMLChild(const wxChar *tag)
// Nested wave clips are cut lines
mCutLines.push_back(
make_movable<WaveClip>(mSequence->GetDirManager(),
mSequence->GetSampleFormat(), mRate));
mSequence->GetSampleFormat(), mRate, 0 /*colourindex*/));
return mCutLines.back().get();
}
else

View File

@ -184,7 +184,8 @@ private:
public:
// typical constructor
WaveClip(const std::shared_ptr<DirManager> &projDirManager, sampleFormat format, int rate);
WaveClip(const std::shared_ptr<DirManager> &projDirManager, sampleFormat format,
int rate, int colourIndex);
// essentially a copy constructor - but you must pass in the
// current project's DirManager, because we might be copying
@ -213,6 +214,8 @@ public:
// the length of the clip
void Resample(int rate, ProgressDialog *progress = NULL);
void SetColourIndex( int index ){ mColourIndex = index;};
int GetColourIndex( ) const { return mColourIndex;};
void SetOffset(double offset);
double GetOffset() const { return mOffset; }
void Offset(double delta) // NOFAIL-GUARANTEE
@ -369,6 +372,8 @@ protected:
double mOffset { 0 };
int mRate;
int mDirty { 0 };
int mColourIndex;
std::unique_ptr<Sequence> mSequence;
std::unique_ptr<Envelope> mEnvelope;

View File

@ -108,6 +108,7 @@ WaveTrack::WaveTrack(const std::shared_ptr<DirManager> &projDirManager, sampleFo
mRate = (int) rate;
mGain = 1.0;
mPan = 0.0;
mWaveColorIndex = 0;
SetDefaultName(TracksPrefs::GetDefaultAudioTrackNamePreference());
SetName(GetDefaultName());
mDisplayMin = -1.0;
@ -148,6 +149,7 @@ void WaveTrack::Init(const WaveTrack &orig)
{
PlayableTrack::Init(orig);
mFormat = orig.mFormat;
mWaveColorIndex = orig.mWaveColorIndex;
mRate = orig.mRate;
mGain = orig.mGain;
mPan = orig.mPan;
@ -538,6 +540,15 @@ float WaveTrack::GetChannelGain(int channel) const
return right*mGain;
}
void WaveTrack::SetWaveColorIndex(int colorIndex)
// STRONG-GUARANTEE
{
for (const auto &clip : mClips)
clip->SetColourIndex( colorIndex );
mWaveColorIndex = colorIndex;
}
void WaveTrack::ConvertToSampleFormat(sampleFormat format)
// WEAK-GUARANTEE
// might complete on only some tracks
@ -711,7 +722,8 @@ Track::Holder WaveTrack::Copy(double t0, double t1, bool forClipboard) const
{
auto placeholder = make_movable<WaveClip>(mDirManager,
newTrack->GetSampleFormat(),
static_cast<int>(newTrack->GetRate()));
static_cast<int>(newTrack->GetRate()),
0 /*colourindex*/);
placeholder->SetIsPlaceholder(true);
placeholder->InsertSilence(0, (t1 - t0) - newTrack->GetEndTime());
placeholder->Offset(newTrack->GetEndTime());
@ -1425,7 +1437,7 @@ void WaveTrack::InsertSilence(double t, double len)
if (mClips.empty())
{
// Special case if there is no clip yet
auto clip = make_movable<WaveClip>(mDirManager, mFormat, mRate);
auto clip = make_movable<WaveClip>(mDirManager, mFormat, mRate, 0 /*colourindex*/);
clip->InsertSilence(0, len);
// use NOFAIL-GUARANTEE
mClips.push_back( std::move( clip ) );
@ -2261,7 +2273,7 @@ Sequence* WaveTrack::GetSequenceAtX(int xcoord)
WaveClip* WaveTrack::CreateClip()
{
mClips.push_back(make_movable<WaveClip>(mDirManager, mFormat, mRate));
mClips.push_back(make_movable<WaveClip>(mDirManager, mFormat, mRate,0 /*colurindex*/));
return mClips.back().get();
}

View File

@ -161,6 +161,10 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
#ifdef EXPERIMENTAL_OUTPUT_DISPLAY
void SetVirtualState(bool state, bool half=false);
#endif
int GetWaveColorIndex() const { return mWaveColorIndex; };
void SetWaveColorIndex(int colorIndex);
sampleFormat GetSampleFormat() const { return mFormat; }
void ConvertToSampleFormat(sampleFormat format);
@ -606,6 +610,7 @@ class AUDACITY_DLL_API WaveTrack final : public PlayableTrack {
int mRate;
float mGain;
float mPan;
int mWaveColorIndex;
//

View File

@ -121,6 +121,11 @@ enum {
OnChannelMonoID,
OnMergeStereoID,
OnWaveColorID,
OnInstrument1ID,
OnInstrument2ID,
OnInstrument3ID,
OnInstrument4ID,
OnSwapChannelsID,
OnSplitStereoID,
@ -129,6 +134,106 @@ enum {
ChannelMenuID,
};
//=============================================================================
// Table class for a sub-menu
class WaveColorMenuTable : public PopupMenuTable
{
WaveColorMenuTable() : mpData(NULL) {}
DECLARE_POPUP_MENU(WaveColorMenuTable);
public:
static WaveColorMenuTable &Instance();
private:
void InitMenu(Menu *pMenu, void *pUserData) override;
void DestroyMenu() override
{
mpData = NULL;
}
TrackControls::InitMenuData *mpData;
int IdOfWaveColor(int WaveColor);
void OnWaveColorChange(wxCommandEvent & event);
};
WaveColorMenuTable &WaveColorMenuTable::Instance()
{
static WaveColorMenuTable instance;
return instance;
}
void WaveColorMenuTable::InitMenu(Menu *pMenu, void *pUserData)
{
mpData = static_cast<TrackControls::InitMenuData*>(pUserData);
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpData->pTrack);
auto WaveColorId = IdOfWaveColor( pTrack->GetWaveColorIndex());
SetMenuChecks(*pMenu, [=](int id){ return id == WaveColorId; });
AudacityProject *const project = ::GetActiveProject();
bool unsafe = project->IsAudioActive();
for (int i = OnInstrument1ID; i <= OnInstrument4ID; i++) {
pMenu->Enable(i, !unsafe);
}
}
const wxString GetWaveColorStr(int colorIndex)
{
return wxString::Format( _("Instrument %i"), colorIndex+1 );
}
BEGIN_POPUP_MENU(WaveColorMenuTable)
POPUP_MENU_RADIO_ITEM(OnInstrument1ID,
GetWaveColorStr(0), OnWaveColorChange)
POPUP_MENU_RADIO_ITEM(OnInstrument2ID,
GetWaveColorStr(1), OnWaveColorChange)
POPUP_MENU_RADIO_ITEM(OnInstrument3ID,
GetWaveColorStr(2), OnWaveColorChange)
POPUP_MENU_RADIO_ITEM(OnInstrument4ID,
GetWaveColorStr(3), OnWaveColorChange)
END_POPUP_MENU()
/// Converts a WaveColor enumeration to a wxWidgets menu item Id.
int WaveColorMenuTable::IdOfWaveColor(int WaveColor)
{ return OnInstrument1ID + WaveColor;}
/// Handles the selection from the WaveColor submenu of the
/// track menu.
void WaveColorMenuTable::OnWaveColorChange(wxCommandEvent & event)
{
int id = event.GetId();
wxASSERT(id >= OnInstrument1ID && id <= OnInstrument4ID);
WaveTrack *const pTrack = static_cast<WaveTrack*>(mpData->pTrack);
wxASSERT(pTrack && pTrack->GetKind() == Track::Wave);
int newWaveColor = id - OnInstrument1ID;
AudacityProject *const project = ::GetActiveProject();
// TrackList *const tracks = project->GetTracks();
pTrack->SetWaveColorIndex(newWaveColor);
// Assume partner is wave or null
const auto partner = static_cast<WaveTrack*>(pTrack->GetLink());
if (partner)
partner->SetWaveColorIndex(newWaveColor);
project->PushState(wxString::Format(_("Changed '%s' to %s"),
pTrack->GetName().
c_str(),
GetWaveColorStr(newWaveColor)),
_("WaveColor Change"));
using namespace RefreshCode;
mpData->result = RefreshAll | FixScrollbars;
}
//=============================================================================
// Table class for a sub-menu
class FormatMenuTable : public PopupMenuTable
@ -550,8 +655,12 @@ void WaveTrackMenuTable::InitMenu(Menu *pMenu, void *pUserData)
pMenu->Enable(OnSwapChannelsID, !isMono && !unsafe);
pMenu->Enable(OnSplitStereoID, !isMono && !unsafe);
// Several menu items no longer needed....
#ifndef EXPERIMENTAL_DA
// Can be achieved by split stereo and then dragging pan slider.
pMenu->Enable(OnSplitStereoMonoID, !isMono && !unsafe);
#endif
// Several menu items no longer needed....
#if 0
pMenu->Enable(OnChannelMonoID, isMono);
pMenu->Enable(OnChannelLeftID, isMono);
@ -580,7 +689,9 @@ BEGIN_POPUP_MENU(WaveTrackMenuTable)
POPUP_MENU_ITEM(OnSplitStereoMonoID, _("Split Stereo to Mo&no"), OnSplitStereoMono)
#endif
POPUP_MENU_SEPARATOR()
POPUP_MENU_SUB_MENU(0, _("&Wave Color"), WaveColorMenuTable)
POPUP_MENU_SEPARATOR()
POPUP_MENU_SUB_MENU(0, _("&Format"), FormatMenuTable)
POPUP_MENU_SEPARATOR()
POPUP_MENU_SUB_MENU(0, _("Rat&e"), RateMenuTable)