diff --git a/src/TrackInfo.cpp b/src/TrackInfo.cpp index e69de29bb..ff976619c 100644 --- a/src/TrackInfo.cpp +++ b/src/TrackInfo.cpp @@ -0,0 +1,1191 @@ +/********************************************************************** + +Audacity: A Digital Audio Editor + +TrackInfo.h + +Paul Licameli split from TrackPanel.cpp + +********************************************************************//*! + +\namespace TrackInfo +\brief + Functions for drawing the track control panel, which is shown to the side + of a track + It has the menus, pan and gain controls displayed in it. + So "Info" is somewhat a misnomer. Should possibly be "TrackControls". + + It maintains global slider widget instances that are reparented and + repositioned as needed for drawing and interaction with the user, + interoperating with the custom panel subdivision implemented in CellularPanel + and avoiding wxWidgets sizers + + If we'd instead coded it as a wxWindow, we would have an instance + of this class for each track displayed. + +**********************************************************************/ + +#include "Audacity.h" +#include "TrackInfo.h" + +#include "Experimental.h" + +#include +#include + +#include "AColor.h" +#include "AllThemeResources.h" +#include "NoteTrack.h" +#include "Project.h" +#include "TrackPanelDrawingContext.h" +#include "ViewInfo.h" +#include "WaveTrack.h" +#include "tracks/ui/TrackView.h" +#include "widgets/ASlider.h" + +namespace { + +wxString gSoloPref; +inline bool HasSoloButton() +{ + return gSoloPref!=wxT("None"); +} + +#define RANGE(array) (array), (array) + sizeof(array)/sizeof(*(array)) +using TCPLines = std::vector< TrackInfo::TCPLine >; + +enum : unsigned { + // The sequence is not significant, just keep bits distinct + kItemBarButtons = 1 << 0, + kItemStatusInfo1 = 1 << 1, + kItemMute = 1 << 2, + kItemSolo = 1 << 3, + kItemGain = 1 << 4, + kItemPan = 1 << 5, + kItemVelocity = 1 << 6, + kItemMidiControlsRect = 1 << 7, + kItemMinimize = 1 << 8, + kItemSyncLock = 1 << 9, + kItemStatusInfo2 = 1 << 10, + + kHighestBottomItem = kItemMinimize, +}; + +} + +struct TrackInfo::TCPLine { + using DrawFunction = void (*)( + TrackPanelDrawingContext &context, + const wxRect &rect, + const Track *maybeNULL + ); + + unsigned items; // a bitwise OR of values of the enum above + int height; + int extraSpace; + DrawFunction drawFunction; +}; + +namespace { + +#ifdef EXPERIMENTAL_DA + + #define TITLE_ITEMS \ + { kItemBarButtons, kTrackInfoBtnSize, 4, \ + &TrackInfo::CloseTitleDrawFunction }, + // DA: Has Mute and Solo on separate lines. + #define MUTE_SOLO_ITEMS(extra) \ + { kItemMute, kTrackInfoBtnSize + 1, 1, \ + &TrackInfo::WideMuteDrawFunction }, \ + { kItemSolo, kTrackInfoBtnSize + 1, extra, \ + &TrackInfo::WideSoloDrawFunction }, + // DA: Does not have status information for a track. + #define STATUS_ITEMS + +#else + + #define TITLE_ITEMS \ + { kItemBarButtons, kTrackInfoBtnSize, 0, \ + &TrackInfo::CloseTitleDrawFunction }, + #define MUTE_SOLO_ITEMS(extra) \ + { kItemMute | kItemSolo, kTrackInfoBtnSize + 1, extra, \ + &TrackInfo::MuteAndSoloDrawFunction }, + #define STATUS_ITEMS \ + { kItemStatusInfo1, 12, 0, \ + &TrackInfo::Status1DrawFunction }, \ + { kItemStatusInfo2, 12, 0, \ + &TrackInfo::Status2DrawFunction }, + +#endif + +#define COMMON_ITEMS \ + TITLE_ITEMS + +const TrackInfo::TCPLine defaultCommonTrackTCPLines[] = { + COMMON_ITEMS +}; +TCPLines commonTrackTCPLines{ RANGE(defaultCommonTrackTCPLines) }; + +const TrackInfo::TCPLine defaultWaveTrackTCPLines[] = { + COMMON_ITEMS + MUTE_SOLO_ITEMS(2) + { kItemGain, kTrackInfoSliderHeight, kTrackInfoSliderExtra, + &TrackInfo::GainSliderDrawFunction }, + { kItemPan, kTrackInfoSliderHeight, kTrackInfoSliderExtra, + &TrackInfo::PanSliderDrawFunction }, + STATUS_ITEMS +}; +TCPLines waveTrackTCPLines{ RANGE(defaultWaveTrackTCPLines) }; + +#ifdef USE_MIDI +enum : int { + // PRL: was it correct to include the margin? + kMidiCellWidth = ( ( kTrackInfoWidth + kLeftMargin ) / 4) - 2, + kMidiCellHeight = kTrackInfoBtnSize +}; +#endif + +const TrackInfo::TCPLine defaultNoteTrackTCPLines[] = { + COMMON_ITEMS +#ifdef EXPERIMENTAL_MIDI_OUT + MUTE_SOLO_ITEMS(0) + { kItemMidiControlsRect, kMidiCellHeight * 4, 0, + &TrackInfo::MidiControlsDrawFunction }, + { kItemVelocity, kTrackInfoSliderHeight, kTrackInfoSliderExtra, + &TrackInfo::VelocitySliderDrawFunction }, +#endif +}; +TCPLines noteTrackTCPLines{ RANGE(defaultNoteTrackTCPLines) }; + +int totalTCPLines( const TCPLines &lines, bool omitLastExtra ) +{ + int total = 0; + int lastExtra = 0; + for ( const auto line : lines ) { + lastExtra = line.extraSpace; + total += line.height + lastExtra; + } + if (omitLastExtra) + total -= lastExtra; + return total; +} + +const TCPLines &getTCPLines( const Track &track ) +{ + auto lines = track.TypeSwitch< TCPLines * >( +#ifdef USE_MIDI + [](const NoteTrack*){ + return ¬eTrackTCPLines; + }, +#endif + [](const WaveTrack*){ + return &waveTrackTCPLines; + }, + [](const Track*){ + return &commonTrackTCPLines; + } + ); + + if (lines) + return *lines; + + return commonTrackTCPLines; +} + +// return y value and height +std::pair< int, int > CalcItemY( const TCPLines &lines, unsigned iItem ) +{ + int y = 0; + auto pLines = lines.begin(); + while ( pLines != lines.end() && + 0 == (pLines->items & iItem) ) { + y += pLines->height + pLines->extraSpace; + ++pLines; + } + int height = 0; + if ( pLines != lines.end() ) + height = pLines->height; + return { y, height }; +} + +// Items for the bottom of the panel, listed bottom-upwards +// As also with the top items, the extra space is below the item +const TrackInfo::TCPLine defaultCommonTrackTCPBottomLines[] = { + // The '0' avoids impinging on bottom line of TCP + // Use -1 if you do want to do so. + { kItemSyncLock | kItemMinimize, kTrackInfoBtnSize, 0, + &TrackInfo::MinimizeSyncLockDrawFunction }, +}; +TCPLines commonTrackTCPBottomLines{ RANGE(defaultCommonTrackTCPBottomLines) }; + +// return y value and height +std::pair< int, int > CalcBottomItemY + ( const TCPLines &lines, unsigned iItem, int height ) +{ + int y = height; + auto pLines = lines.begin(); + while ( pLines != lines.end() && + 0 == (pLines->items & iItem) ) { + y -= pLines->height + pLines->extraSpace; + ++pLines; + } + if (pLines != lines.end()) + y -= (pLines->height + pLines->extraSpace ); + return { y, pLines->height }; +} + +} + +unsigned TrackInfo::MinimumTrackHeight() +{ + unsigned height = 0; + if (!commonTrackTCPLines.empty()) + height += commonTrackTCPLines.front().height; + if (!commonTrackTCPBottomLines.empty()) + height += commonTrackTCPBottomLines.front().height; + // + 1 prevents the top item from disappearing for want of enough space, + // according to the rules in HideTopItem. + return height + kTopMargin + kBottomMargin + 1; +} + +bool TrackInfo::HideTopItem( const wxRect &rect, const wxRect &subRect, + int allowance ) { + auto limit = CalcBottomItemY + ( commonTrackTCPBottomLines, kHighestBottomItem, rect.height).first; + // Return true if the rectangle is even touching the limit + // without an overlap. That was the behavior as of 2.1.3. + return subRect.y + subRect.height - allowance >= rect.y + limit; +} + +void TrackInfo::DrawItems +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track &track ) +{ + const auto topLines = getTCPLines( track ); + const auto bottomLines = commonTrackTCPBottomLines; + DrawItems + ( context, rect, &track, topLines, bottomLines ); +} + +void TrackInfo::DrawItems +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack, + const std::vector &topLines, const std::vector &bottomLines ) +{ + auto dc = &context.dc; + TrackInfo::SetTrackInfoFont(dc); + dc->SetTextForeground(theTheme.Colour(clrTrackPanelText)); + + { + int yy = 0; + for ( const auto &line : topLines ) { + wxRect itemRect{ + rect.x, rect.y + yy, + rect.width, line.height + }; + if ( !TrackInfo::HideTopItem( rect, itemRect ) && + line.drawFunction ) + line.drawFunction( context, itemRect, pTrack ); + yy += line.height + line.extraSpace; + } + } + { + int yy = rect.height; + for ( const auto &line : bottomLines ) { + yy -= line.height + line.extraSpace; + if ( line.drawFunction ) { + wxRect itemRect{ + rect.x, rect.y + yy, + rect.width, line.height + }; + line.drawFunction( context, itemRect, pTrack ); + } + } + } +} + +#include "tracks/ui/TrackButtonHandles.h" +void TrackInfo::CloseTitleDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + bool selected = pTrack ? pTrack->GetSelected() : true; + { + wxRect bev = rect; + GetCloseBoxHorizontalBounds( rect, bev ); + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + AColor::Bevel2(*dc, !down, bev, selected, hit ); + +#ifdef EXPERIMENTAL_THEMING + wxPen pen( theTheme.Colour( clrTrackPanelText )); + dc->SetPen( pen ); +#else + dc->SetPen(*wxBLACK_PEN); +#endif + bev.Inflate( -1, -1 ); + // Draw the "X" + const int s = 6; + + int ls = bev.x + ((bev.width - s) / 2); + int ts = bev.y + ((bev.height - s) / 2); + int rs = ls + s; + int bs = ts + s; + + AColor::Line(*dc, ls, ts, rs, bs); + AColor::Line(*dc, ls + 1, ts, rs + 1, bs); + AColor::Line(*dc, rs, ts, ls, bs); + AColor::Line(*dc, rs + 1, ts, ls + 1, bs); + + // bev.Inflate(-1, -1); + } + + { + wxRect bev = rect; + GetTitleBarHorizontalBounds( rect, bev ); + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + wxString titleStr = + pTrack ? pTrack->GetName() : _("Name"); + + //bev.Inflate(-1, -1); + AColor::Bevel2(*dc, !down, bev, selected, hit); + + // Draw title text + SetTrackInfoFont(dc); + + // Bug 1660 The 'k' of 'Audio Track' was being truncated. + // Constant of 32 found by counting pixels on a windows machine. + // I believe it's the size of the X close button + the size of the + // drop down arrow. + int allowableWidth = rect.width - 32; + + wxCoord textWidth, textHeight; + dc->GetTextExtent(titleStr, &textWidth, &textHeight); + while (textWidth > allowableWidth) { + titleStr = titleStr.Left(titleStr.length() - 1); + dc->GetTextExtent(titleStr, &textWidth, &textHeight); + } + + // Pop-up triangle + #ifdef EXPERIMENTAL_THEMING + wxColour c = theTheme.Colour( clrTrackPanelText ); + #else + wxColour c = *wxBLACK; + #endif + + // wxGTK leaves little scraps (antialiasing?) of the + // characters if they are repeatedly drawn. This + // happens when holding down mouse button and moving + // in and out of the title bar. So clear it first. + // AColor::MediumTrackInfo(dc, t->GetSelected()); + // dc->DrawRectangle(bev); + + dc->SetTextForeground( c ); + dc->SetTextBackground( wxTRANSPARENT ); + dc->DrawText(titleStr, bev.x + 2, bev.y + (bev.height - textHeight) / 2); + + + + dc->SetPen(c); + dc->SetBrush(c); + + int s = 10; // Width of dropdown arrow...height is half of width + AColor::Arrow(*dc, + bev.GetRight() - s - 3, // 3 to offset from right border + bev.y + ((bev.height - (s / 2)) / 2), + s); + + } +} + +void TrackInfo::MinimizeSyncLockDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + bool selected = pTrack ? pTrack->GetSelected() : true; + bool syncLockSelected = pTrack ? pTrack->IsSyncLockSelected() : true; + bool minimized = + pTrack ? TrackView::Get( *pTrack ).GetMinimized() : false; + { + wxRect bev = rect; + GetMinimizeHorizontalBounds(rect, bev); + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + + // Clear background to get rid of previous arrow + //AColor::MediumTrackInfo(dc, t->GetSelected()); + //dc->DrawRectangle(bev); + + AColor::Bevel2(*dc, !down, bev, selected, hit); + +#ifdef EXPERIMENTAL_THEMING + wxColour c = theTheme.Colour(clrTrackPanelText); + dc->SetBrush(c); + dc->SetPen(c); +#else + AColor::Dark(dc, selected); +#endif + + AColor::Arrow(*dc, + bev.x - 5 + bev.width / 2, + bev.y - 2 + bev.height / 2, + 10, + minimized); + } + + { + wxRect bev = rect; + GetSelectButtonHorizontalBounds(rect, bev); + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + + AColor::Bevel2(*dc, !down, bev, selected, hit); + +#ifdef EXPERIMENTAL_THEMING + wxColour c = theTheme.Colour(clrTrackPanelText); + dc->SetBrush(c); + dc->SetPen(c); +#else + AColor::Dark(dc, selected); +#endif + + wxString str = _("Select"); + wxCoord textWidth; + wxCoord textHeight; + SetTrackInfoFont(dc); + dc->GetTextExtent(str, &textWidth, &textHeight); + + dc->SetTextForeground( c ); + dc->SetTextBackground( wxTRANSPARENT ); + dc->DrawText(str, bev.x + 2 + (bev.width-textWidth)/2, bev.y + (bev.height - textHeight) / 2); + } + + + // Draw the sync-lock indicator if this track is in a sync-lock selected group. + if (syncLockSelected) + { + wxRect syncLockIconRect = rect; + + GetSyncLockHorizontalBounds( rect, syncLockIconRect ); + wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockIcon)); + // Icon is 12x12 and syncLockIconRect is 16x16. + dc->DrawBitmap(syncLockBitmap, + syncLockIconRect.x + 3, + syncLockIconRect.y + 2, + true); + } +} + +#include "tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.h" +void TrackInfo::MidiControlsDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ +#ifdef EXPERIMENTAL_MIDI_OUT + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + auto channel = hit ? target->GetChannel() : -1; + auto &dc = context.dc; + wxRect midiRect = rect; + GetMidiControlsHorizontalBounds(rect, midiRect); + NoteTrack::DrawLabelControls + ( static_cast(pTrack), dc, midiRect, channel ); +#endif // EXPERIMENTAL_MIDI_OUT +} + +template +void TrackInfo::SliderDrawFunction +( LWSlider *(*Selector) + (const wxRect &sliderRect, const TrackClass *t, bool captured, wxWindow*), + wxDC *dc, const wxRect &rect, const Track *pTrack, + bool captured, bool highlight ) +{ + wxRect sliderRect = rect; + TrackInfo::GetSliderHorizontalBounds( rect.GetTopLeft(), sliderRect ); + auto wt = static_cast( pTrack ); + Selector( sliderRect, wt, captured, nullptr )->OnPaint(*dc, highlight); +} + +#include "tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.h" +void TrackInfo::PanSliderDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto target = dynamic_cast( context.target.get() ); + auto dc = &context.dc; + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + SliderDrawFunction + ( &TrackInfo::PanSlider, dc, rect, pTrack, captured, hit); +} + +void TrackInfo::GainSliderDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto target = dynamic_cast( context.target.get() ); + auto dc = &context.dc; + bool hit = target && target->GetTrack().get() == pTrack; + if( hit ) + hit=hit; + bool captured = hit && target->IsClicked(); + SliderDrawFunction + ( &TrackInfo::GainSlider, dc, rect, pTrack, captured, hit); +} + +#ifdef EXPERIMENTAL_MIDI_OUT +#include "tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.h" +void TrackInfo::VelocitySliderDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + SliderDrawFunction + ( &TrackInfo::VelocitySlider, dc, rect, pTrack, captured, hit); +} +#endif + +void TrackInfo::MuteOrSoloDrawFunction +( wxDC *dc, const wxRect &bev, const Track *pTrack, bool down, + bool WXUNUSED(captured), + bool solo, bool hit ) +{ + //bev.Inflate(-1, -1); + bool selected = pTrack ? pTrack->GetSelected() : true; + auto pt = dynamic_cast(pTrack); + bool value = pt ? (solo ? pt->GetSolo() : pt->GetMute()) : false; + +#if 0 + AColor::MediumTrackInfo( dc, t->GetSelected()); + if( solo ) + { + if( pt && pt->GetSolo() ) + { + AColor::Solo(dc, pt->GetSolo(), t->GetSelected()); + } + } + else + { + if( pt && pt->GetMute() ) + { + AColor::Mute(dc, pt->GetMute(), t->GetSelected(), pt->GetSolo()); + } + } + //(solo) ? AColor::Solo(dc, t->GetSolo(), t->GetSelected()) : + // AColor::Mute(dc, t->GetMute(), t->GetSelected(), t->GetSolo()); + dc->SetPen( *wxTRANSPARENT_PEN );//No border! + dc->DrawRectangle(bev); +#endif + + wxCoord textWidth, textHeight; + wxString str = (solo) ? + /* i18n-hint: This is on a button that will silence all the other tracks.*/ + _("Solo") : + /* i18n-hint: This is on a button that will silence this track.*/ + _("Mute"); + + AColor::Bevel2( + *dc, + value == down, + bev, + selected, hit + ); + + SetTrackInfoFont(dc); + dc->GetTextExtent(str, &textWidth, &textHeight); + dc->DrawText(str, bev.x + (bev.width - textWidth) / 2, bev.y + (bev.height - textHeight) / 2); +} + +#include "tracks/playabletrack/ui/PlayableTrackButtonHandles.h" +void TrackInfo::WideMuteDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + wxRect bev = rect; + GetWideMuteSoloHorizontalBounds( rect, bev ); + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, false, hit ); +} + +void TrackInfo::WideSoloDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + wxRect bev = rect; + GetWideMuteSoloHorizontalBounds( rect, bev ); + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, true, hit ); +} + +void TrackInfo::MuteAndSoloDrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + bool bHasSoloButton = HasSoloButton(); + + wxRect bev = rect; + if ( bHasSoloButton ) + GetNarrowMuteHorizontalBounds( rect, bev ); + else + GetWideMuteSoloHorizontalBounds( rect, bev ); + { + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, false, hit ); + } + + if( !bHasSoloButton ) + return; + + GetNarrowSoloHorizontalBounds( rect, bev ); + { + auto target = dynamic_cast( context.target.get() ); + bool hit = target && target->GetTrack().get() == pTrack; + bool captured = hit && target->IsClicked(); + bool down = captured && bev.Contains( context.lastState.GetPosition()); + MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, true, hit ); + } +} + +void TrackInfo::StatusDrawFunction + ( const wxString &string, wxDC *dc, const wxRect &rect ) +{ + static const int offset = 3; + dc->DrawText(string, rect.x + offset, rect.y); +} + +void TrackInfo::Status1DrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + auto wt = static_cast(pTrack); + + /// Returns the string to be displayed in the track label + /// indicating whether the track is mono, left, right, or + /// stereo and what sample rate it's using. + auto rate = wt ? wt->GetRate() : 44100.0; + wxString s; + if (!pTrack || TrackList::Channels(pTrack).size() > 1) + // TODO: more-than-two-channels-message + // more appropriate strings + s = _("Stereo, %dHz"); + else { + if (wt->GetChannel() == Track::MonoChannel) + s = _("Mono, %dHz"); + else if (wt->GetChannel() == Track::LeftChannel) + s = _("Left, %dHz"); + else if (wt->GetChannel() == Track::RightChannel) + s = _("Right, %dHz"); + } + s = wxString::Format( s, (int) (rate + 0.5) ); + + StatusDrawFunction( s, dc, rect ); +} + +void TrackInfo::Status2DrawFunction +( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ) +{ + auto dc = &context.dc; + auto wt = static_cast(pTrack); + auto format = wt ? wt->GetSampleFormat() : floatSample; + auto s = GetSampleFormatStr(format); + StatusDrawFunction( s, dc, rect ); +} + +namespace { + +wxFont gFont; + +std::unique_ptr + gGainCaptured + , gPanCaptured + , gGain + , gPan +#ifdef EXPERIMENTAL_MIDI_OUT + , gVelocityCaptured + , gVelocity +#endif +; + +} + +void TrackInfo::ReCreateSliders(){ + const wxPoint point{ 0, 0 }; + wxRect sliderRect; + GetGainRect(point, sliderRect); + + float defPos = 1.0; + /* i18n-hint: Title of the Gain slider, used to adjust the volume */ + gGain = std::make_unique(nullptr, _("Gain"), + wxPoint(sliderRect.x, sliderRect.y), + wxSize(sliderRect.width, sliderRect.height), + DB_SLIDER); + gGain->SetDefaultValue(defPos); + + gGainCaptured = std::make_unique(nullptr, _("Gain"), + wxPoint(sliderRect.x, sliderRect.y), + wxSize(sliderRect.width, sliderRect.height), + DB_SLIDER); + gGainCaptured->SetDefaultValue(defPos); + + GetPanRect(point, sliderRect); + + defPos = 0.0; + /* i18n-hint: Title of the Pan slider, used to move the sound left or right */ + gPan = std::make_unique(nullptr, _("Pan"), + wxPoint(sliderRect.x, sliderRect.y), + wxSize(sliderRect.width, sliderRect.height), + PAN_SLIDER); + gPan->SetDefaultValue(defPos); + + gPanCaptured = std::make_unique(nullptr, _("Pan"), + wxPoint(sliderRect.x, sliderRect.y), + wxSize(sliderRect.width, sliderRect.height), + PAN_SLIDER); + gPanCaptured->SetDefaultValue(defPos); + +#ifdef EXPERIMENTAL_MIDI_OUT + GetVelocityRect(point, sliderRect); + + /* i18n-hint: Title of the Velocity slider, used to adjust the volume of note tracks */ + gVelocity = std::make_unique(nullptr, _("Velocity"), + wxPoint(sliderRect.x, sliderRect.y), + wxSize(sliderRect.width, sliderRect.height), + VEL_SLIDER); + gVelocity->SetDefaultValue(0.0); + gVelocityCaptured = std::make_unique(nullptr, _("Velocity"), + wxPoint(sliderRect.x, sliderRect.y), + wxSize(sliderRect.width, sliderRect.height), + VEL_SLIDER); + gVelocityCaptured->SetDefaultValue(0.0); +#endif + +} + +void TrackInfo::GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest ) +{ + dest.x = rect.x; + dest.width = kTrackInfoBtnSize; +} + +void TrackInfo::GetCloseBoxRect(const wxRect & rect, wxRect & dest) +{ + GetCloseBoxHorizontalBounds( rect, dest ); + auto results = CalcItemY( commonTrackTCPLines, kItemBarButtons ); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +static const int TitleSoloBorderOverlap = 1; + +void TrackInfo::GetTitleBarHorizontalBounds( const wxRect & rect, wxRect &dest ) +{ + // to right of CloseBoxRect, plus a little more + wxRect closeRect; + GetCloseBoxHorizontalBounds( rect, closeRect ); + dest.x = rect.x + closeRect.width + 1; + dest.width = rect.x + rect.width - dest.x + TitleSoloBorderOverlap; +} + +void TrackInfo::GetTitleBarRect(const wxRect & rect, wxRect & dest) +{ + GetTitleBarHorizontalBounds( rect, dest ); + auto results = CalcItemY( commonTrackTCPLines, kItemBarButtons ); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +void TrackInfo::GetNarrowMuteHorizontalBounds( const wxRect & rect, wxRect &dest ) +{ + dest.x = rect.x; + dest.width = rect.width / 2 + 1; +} + +void TrackInfo::GetNarrowSoloHorizontalBounds( const wxRect & rect, wxRect &dest ) +{ + wxRect muteRect; + GetNarrowMuteHorizontalBounds( rect, muteRect ); + dest.x = rect.x + muteRect.width; + dest.width = rect.width - muteRect.width + TitleSoloBorderOverlap; +} + +void TrackInfo::GetWideMuteSoloHorizontalBounds( const wxRect & rect, wxRect &dest ) +{ + // Larger button, symmetrically placed intended. + // On windows this gives 15 pixels each side. + dest.width = rect.width - 2 * kTrackInfoBtnSize + 6; + dest.x = rect.x + kTrackInfoBtnSize -3; +} + +void TrackInfo::GetMuteSoloRect +(const wxRect & rect, wxRect & dest, bool solo, bool bHasSoloButton, + const Track *pTrack) +{ + + auto resultsM = CalcItemY( getTCPLines( *pTrack ), kItemMute ); + auto resultsS = CalcItemY( getTCPLines( *pTrack ), kItemSolo ); + dest.height = resultsS.second; + + int yMute = resultsM.first; + int ySolo = resultsS.first; + + bool bSameRow = ( yMute == ySolo ); + bool bNarrow = bSameRow && bHasSoloButton; + + if( bNarrow ) + { + if( solo ) + GetNarrowSoloHorizontalBounds( rect, dest ); + else + GetNarrowMuteHorizontalBounds( rect, dest ); + } + else + GetWideMuteSoloHorizontalBounds( rect, dest ); + + if( bSameRow || !solo ) + dest.y = rect.y + yMute; + else + dest.y = rect.y + ySolo; + +} + +void TrackInfo::GetSliderHorizontalBounds( const wxPoint &topleft, wxRect &dest ) +{ + dest.x = topleft.x + 6; + dest.width = kTrackInfoSliderWidth; +} + +void TrackInfo::GetGainRect(const wxPoint &topleft, wxRect & dest) +{ + GetSliderHorizontalBounds( topleft, dest ); + auto results = CalcItemY( waveTrackTCPLines, kItemGain ); + dest.y = topleft.y + results.first; + dest.height = results.second; +} + +void TrackInfo::GetPanRect(const wxPoint &topleft, wxRect & dest) +{ + GetGainRect( topleft, dest ); + auto results = CalcItemY( waveTrackTCPLines, kItemPan ); + dest.y = topleft.y + results.first; +} + +#ifdef EXPERIMENTAL_MIDI_OUT +void TrackInfo::GetVelocityRect(const wxPoint &topleft, wxRect & dest) +{ + GetSliderHorizontalBounds( topleft, dest ); + auto results = CalcItemY( noteTrackTCPLines, kItemVelocity ); + dest.y = topleft.y + results.first; + dest.height = results.second; +} +#endif + +void TrackInfo::GetMinimizeHorizontalBounds( const wxRect &rect, wxRect &dest ) +{ + const int space = 0;// was 3. + dest.x = rect.x + space; + + wxRect syncLockRect; + GetSyncLockHorizontalBounds( rect, syncLockRect ); + + // Width is rect.width less space on left for track select + // and on right for sync-lock icon. + dest.width = kTrackInfoBtnSize; +// rect.width - (space + syncLockRect.width); +} + +void TrackInfo::GetMinimizeRect(const wxRect & rect, wxRect &dest) +{ + GetMinimizeHorizontalBounds( rect, dest ); + auto results = CalcBottomItemY + ( commonTrackTCPBottomLines, kItemMinimize, rect.height); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +void TrackInfo::GetSelectButtonHorizontalBounds( const wxRect &rect, wxRect &dest ) +{ + const int space = 0;// was 3. + dest.x = rect.x + space; + + wxRect syncLockRect; + GetSyncLockHorizontalBounds( rect, syncLockRect ); + wxRect minimizeRect; + GetMinimizeHorizontalBounds( rect, minimizeRect ); + + dest.x = dest.x + space + minimizeRect.width; + // Width is rect.width less space on left for track select + // and on right for sync-lock icon. + dest.width = rect.width - (space + syncLockRect.width) - (space + minimizeRect.width); +} + + +void TrackInfo::GetSelectButtonRect(const wxRect & rect, wxRect &dest) +{ + GetSelectButtonHorizontalBounds( rect, dest ); + auto results = CalcBottomItemY + ( commonTrackTCPBottomLines, kItemMinimize, rect.height); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +void TrackInfo::GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest ) +{ + dest.width = kTrackInfoBtnSize; + dest.x = rect.x + rect.width - dest.width; +} + +void TrackInfo::GetSyncLockIconRect(const wxRect & rect, wxRect &dest) +{ + GetSyncLockHorizontalBounds( rect, dest ); + auto results = CalcBottomItemY + ( commonTrackTCPBottomLines, kItemSyncLock, rect.height); + dest.y = rect.y + results.first; + dest.height = results.second; +} + +#ifdef USE_MIDI +void TrackInfo::GetMidiControlsHorizontalBounds +( const wxRect &rect, wxRect &dest ) +{ + dest.x = rect.x + 1; // To center slightly + // PRL: TODO: kMidiCellWidth is defined in terms of the other constant + // kTrackInfoWidth but I am trying to avoid use of that constant. + // Can cell width be computed from dest.width instead? + dest.width = kMidiCellWidth * 4; +} + +void TrackInfo::GetMidiControlsRect(const wxRect & rect, wxRect & dest) +{ + GetMidiControlsHorizontalBounds( rect, dest ); + auto results = CalcItemY( noteTrackTCPLines, kItemMidiControlsRect ); + dest.y = rect.y + results.first; + dest.height = results.second; +} +#endif + +/// \todo Probably should move to 'Utils.cpp'. +void TrackInfo::SetTrackInfoFont(wxDC * dc) +{ + dc->SetFont(gFont); +} + +#if 0 +void TrackInfo::DrawBordersWithin + ( wxDC* dc, const wxRect & rect, const Track &track ) const +{ + AColor::Dark(dc, false); // same color as border of toolbars (ToolBar::OnPaint()) + + // below close box and title bar + wxRect buttonRect; + GetTitleBarRect( rect, buttonRect ); + AColor::Line + (*dc, rect.x, buttonRect.y + buttonRect.height, + rect.width - 1, buttonRect.y + buttonRect.height); + + // between close box and title bar + AColor::Line + (*dc, buttonRect.x, buttonRect.y, + buttonRect.x, buttonRect.y + buttonRect.height - 1); + + GetMuteSoloRect( rect, buttonRect, false, true, &track ); + + bool bHasMuteSolo = dynamic_cast( &track ) != NULL; + if( bHasMuteSolo && !TrackInfo::HideTopItem( rect, buttonRect ) ) + { + // above mute/solo + AColor::Line + (*dc, rect.x, buttonRect.y, + rect.width - 1, buttonRect.y); + + // between mute/solo + // Draw this little line; if there is no solo, wide mute button will + // overpaint it later: + AColor::Line + (*dc, buttonRect.x + buttonRect.width, buttonRect.y, + buttonRect.x + buttonRect.width, buttonRect.y + buttonRect.height - 1); + + // below mute/solo + AColor::Line + (*dc, rect.x, buttonRect.y + buttonRect.height, + rect.width - 1, buttonRect.y + buttonRect.height); + } + + // left of and above minimize button + wxRect minimizeRect; + this->GetMinimizeRect(rect, minimizeRect); + AColor::Line + (*dc, minimizeRect.x - 1, minimizeRect.y, + minimizeRect.x - 1, minimizeRect.y + minimizeRect.height - 1); + AColor::Line + (*dc, minimizeRect.x, minimizeRect.y - 1, + minimizeRect.x + minimizeRect.width - 1, minimizeRect.y - 1); +} +#endif + +//#define USE_BEVELS + +// Paint the whole given rectangle some fill color +void TrackInfo::DrawBackground( + wxDC * dc, const wxRect & rect, bool bSelected, const int vrul) +{ + // fill in label + wxRect fill = rect; + fill.width = vrul - kLeftMargin; + AColor::MediumTrackInfo(dc, bSelected); + dc->DrawRectangle(fill); + +#ifdef USE_BEVELS + // This branch is not now used + // PRL: todo: banish magic numbers. + // PRL: vrul was the x coordinate of left edge of the vertical ruler. + // PRL: bHasMuteSolo was true iff the track was WaveTrack. + if( bHasMuteSolo ) + { + int ylast = rect.height-20; + int ybutton = wxMin(32,ylast-17); + int ybuttonEnd = 67; + + fill=wxRect( rect.x+1, rect.y+17, vrul-6, ybutton); + AColor::BevelTrackInfo( *dc, true, fill ); + + if( ybuttonEnd < ylast ){ + fill=wxRect( rect.x+1, rect.y+ybuttonEnd, fill.width, ylast - ybuttonEnd); + AColor::BevelTrackInfo( *dc, true, fill ); + } + } + else + { + fill=wxRect( rect.x+1, rect.y+17, vrul-6, rect.height-37); + AColor::BevelTrackInfo( *dc, true, fill ); + } +#endif +} + +namespace { +unsigned DefaultTrackHeight( const TCPLines &topLines ) +{ + int needed = + kTopMargin + kBottomMargin + + totalTCPLines( topLines, true ) + + totalTCPLines( commonTrackTCPBottomLines, false ) + 1; + return (unsigned) std::max( needed, (int) TrackView::DefaultHeight ); +} +} + +unsigned TrackInfo::DefaultNoteTrackHeight() +{ + return DefaultTrackHeight( noteTrackTCPLines ); +} + +unsigned TrackInfo::DefaultWaveTrackHeight() +{ + return DefaultTrackHeight( waveTrackTCPLines ); +} + +LWSlider * TrackInfo::GainSlider +(const wxRect &sliderRect, const WaveTrack *t, bool captured, wxWindow *pParent) +{ + wxPoint pos = sliderRect.GetPosition(); + float gain = t ? t->GetGain() : 1.0; + + gGain->Move(pos); + gGain->Set(gain); + gGainCaptured->Move(pos); + gGainCaptured->Set(gain); + + auto slider = (captured ? gGainCaptured : gGain).get(); + slider->SetParent( pParent ? pParent : + FindProjectFrame( ::GetActiveProject() ) ); + return slider; +} + +LWSlider * TrackInfo::PanSlider +(const wxRect &sliderRect, const WaveTrack *t, bool captured, wxWindow *pParent) +{ + wxPoint pos = sliderRect.GetPosition(); + float pan = t ? t->GetPan() : 0.0; + + gPan->Move(pos); + gPan->Set(pan); + gPanCaptured->Move(pos); + gPanCaptured->Set(pan); + + auto slider = (captured ? gPanCaptured : gPan).get(); + slider->SetParent( pParent ? pParent : + FindProjectFrame( ::GetActiveProject() ) ); + return slider; +} + +#ifdef EXPERIMENTAL_MIDI_OUT +LWSlider * TrackInfo::VelocitySlider +(const wxRect &sliderRect, const NoteTrack *t, bool captured, wxWindow *pParent) +{ + wxPoint pos = sliderRect.GetPosition(); + float velocity = t ? t->GetVelocity() : 0.0; + + gVelocity->Move(pos); + gVelocity->Set(velocity); + gVelocityCaptured->Move(pos); + gVelocityCaptured->Set(velocity); + + auto slider = (captured ? gVelocityCaptured : gVelocity).get(); + slider->SetParent( pParent ? pParent : + FindProjectFrame( ::GetActiveProject() ) ); + return slider; +} +#endif + +void TrackInfo::UpdatePrefs( wxWindow *pParent ) +{ + gPrefs->Read(wxT("/GUI/Solo"), &gSoloPref, wxT("Simple")); + + // Calculation of best font size depends on language, so it should be redone in case + // the language preference changed. + + int fontSize = 10; + gFont.Create(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); + + int allowableWidth = + // PRL: was it correct to include the margin? + ( kTrackInfoWidth + kLeftMargin ) + - 2; // 2 to allow for left/right borders + int textWidth, textHeight; + do { + gFont.SetPointSize(fontSize); + pParent->GetTextExtent(_("Stereo, 999999Hz"), + &textWidth, + &textHeight, + NULL, + NULL, + &gFont); + fontSize--; + } while (textWidth >= allowableWidth); +} diff --git a/src/TrackInfo.h b/src/TrackInfo.h index 6163da146..5ce00f6f8 100644 --- a/src/TrackInfo.h +++ b/src/TrackInfo.h @@ -34,42 +34,7 @@ namespace TrackInfo unsigned MinimumTrackHeight(); - struct TCPLine { - enum : unsigned { - // The sequence is not significant, just keep bits distinct - kItemBarButtons = 1 << 0, - kItemStatusInfo1 = 1 << 1, - kItemMute = 1 << 2, - kItemSolo = 1 << 3, - kItemGain = 1 << 4, - kItemPan = 1 << 5, - kItemVelocity = 1 << 6, - kItemMidiControlsRect = 1 << 7, - kItemMinimize = 1 << 8, - kItemSyncLock = 1 << 9, - kItemStatusInfo2 = 1 << 10, - - kHighestBottomItem = kItemMinimize, - }; - - using DrawFunction = void (*)( - TrackPanelDrawingContext &context, - const wxRect &rect, - const Track *maybeNULL - ); - - unsigned items; // a bitwise OR of values of the enum above - int height; - int extraSpace; - DrawFunction drawFunction; - }; - - using TCPLines = std::vector< TCPLine >; - - // return y value and height - std::pair< int, int > CalcItemY( const TCPLines &lines, unsigned iItem ); - - unsigned DefaultTrackHeight( const TCPLines &topLines ); + struct TCPLine; void DrawItems ( TrackPanelDrawingContext &context, @@ -89,6 +54,32 @@ namespace TrackInfo ( TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack ); + void MidiControlsDrawFunction + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ); + + template + void SliderDrawFunction + ( LWSlider *(*Selector) + (const wxRect &sliderRect, const TrackClass *t, bool captured, + wxWindow*), + wxDC *dc, const wxRect &rect, const Track *pTrack, + bool captured, bool highlight ); + + void PanSliderDrawFunction + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ); + + void GainSliderDrawFunction + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ); + +#ifdef EXPERIMENTAL_MIDI_OUT + void VelocitySliderDrawFunction + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ); +#endif + void MuteOrSoloDrawFunction ( wxDC *dc, const wxRect &rect, const Track *pTrack, bool down, bool captured, bool solo, bool hit ); @@ -105,6 +96,17 @@ namespace TrackInfo ( TrackPanelDrawingContext &context, const wxRect &rect, const Track *pTrack ); + void StatusDrawFunction + ( const wxString &string, wxDC *dc, const wxRect &rect ); + + void Status1DrawFunction + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ); + + void Status2DrawFunction + ( TrackPanelDrawingContext &context, + const wxRect &rect, const Track *pTrack ); + void SetTrackInfoFont(wxDC *dc); @@ -131,6 +133,14 @@ namespace TrackInfo void GetSliderHorizontalBounds( const wxPoint &topleft, wxRect &dest ); + void GetGainRect(const wxPoint & topLeft, wxRect &dest); + + void GetPanRect(const wxPoint & topLeft, wxRect &dest); + +#ifdef EXPERIMENTAL_MIDI_OUT + void GetVelocityRect(const wxPoint & topLeft, wxRect &dest); +#endif + void GetMinimizeHorizontalBounds( const wxRect &rect, wxRect &dest ); void GetMinimizeRect(const wxRect & rect, wxRect &dest); @@ -140,9 +150,31 @@ namespace TrackInfo void GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest ); void GetSyncLockIconRect(const wxRect & rect, wxRect &dest); +#ifdef USE_MIDI + void GetMidiControlsHorizontalBounds + ( const wxRect &rect, wxRect &dest ); + void GetMidiControlsRect(const wxRect & rect, wxRect &dest); +#endif + bool HideTopItem( const wxRect &rect, const wxRect &subRect, int allowance = 0 ); + unsigned DefaultNoteTrackHeight(); + unsigned DefaultWaveTrackHeight(); + + LWSlider * GainSlider + (const wxRect &sliderRect, const WaveTrack *t, bool captured, + wxWindow *pParent); + LWSlider * PanSlider + (const wxRect &sliderRect, const WaveTrack *t, bool captured, + wxWindow *pParent); + +#ifdef EXPERIMENTAL_MIDI_OUT + LWSlider * VelocitySlider + (const wxRect &sliderRect, const NoteTrack *t, bool captured, + wxWindow *pParent); +#endif + // Non-member, namespace function relying on TrackPanel to invoke it // when it handles preference update events void UpdatePrefs( wxWindow *pParent ); diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index a44bf3d33..46b3e81cb 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -7,13 +7,13 @@ Dominic Mazzoni and lots of other contributors - Implements TrackPanel and TrackInfo. + Implements TrackPanel. ********************************************************************//*! \file TrackPanel.cpp \brief - Implements TrackPanel and TrackInfo. + Implements TrackPanel. *//***************************************************************//** @@ -37,23 +37,6 @@ *//*****************************************************************//** -\namespace TrackInfo -\brief - Functions for drawing the track control panel, which is shown to the side - of a track - It has the menus, pan and gain controls displayed in it. - So "Info" is somewhat a misnomer. Should possibly be "TrackControls". - - It maintains global slider widget instances that are reparented and - repositioned as needed for drawing and interaction with the user, - interoperating with the custom panel subdivision implemented in CellularPanel - and avoiding wxWidgets sizers - - If we'd instead coded it as a wxWindow, we would have an instance - of this class for each track displayed. - -*//**************************************************************//** - \class TrackPanel::AudacityTimer \brief Timer class dedicated to informing the TrackPanel that it is time to refresh some aspect of the screen. @@ -81,15 +64,14 @@ is time to refresh some aspect of the screen. #include "UndoManager.h" #include "AColor.h" -#include "AllThemeResources.h" #include "AudioIO.h" #include "float_cast.h" #include "Prefs.h" #include "RefreshCode.h" #include "TrackArtist.h" +#include "TrackInfo.h" #include "TrackPanelAx.h" -#include "ViewInfo.h" #include "WaveTrack.h" #ifdef EXPERIMENTAL_MIDI_OUT #include "NoteTrack.h" @@ -107,7 +89,6 @@ is time to refresh some aspect of the screen. //This loads the appropriate set of cursors, depending on platform. #include "../images/Cursors.h" -#include "widgets/ASlider.h" #include #include @@ -368,12 +349,8 @@ LWSlider *TrackPanel::VelocitySlider( const NoteTrack *nt ) } #endif -wxString TrackPanel::gSoloPref; - void TrackPanel::UpdatePrefs() { - gPrefs->Read(wxT("/GUI/Solo"), &gSoloPref, wxT("Simple")); - // All vertical rulers must be recalculated since the minimum and maximum // frequences may have been changed. UpdateVRulers(); @@ -832,211 +809,6 @@ void TrackPanel::OnTrackListDeletion(wxEvent & e) e.Skip(); } -struct TrackInfo::TCPLine { - using DrawFunction = void (*)( - TrackPanelDrawingContext &context, - const wxRect &rect, - const Track *maybeNULL - ); - - unsigned items; // a bitwise OR of values of the enum above - int height; - int extraSpace; - DrawFunction drawFunction; -}; - -namespace { - -#define RANGE(array) (array), (array) + sizeof(array)/sizeof(*(array)) -using TCPLines = std::vector< TrackInfo::TCPLine >; - -enum : unsigned { - // The sequence is not significant, just keep bits distinct - kItemBarButtons = 1 << 0, - kItemStatusInfo1 = 1 << 1, - kItemMute = 1 << 2, - kItemSolo = 1 << 3, - kItemGain = 1 << 4, - kItemPan = 1 << 5, - kItemVelocity = 1 << 6, - kItemMidiControlsRect = 1 << 7, - kItemMinimize = 1 << 8, - kItemSyncLock = 1 << 9, - kItemStatusInfo2 = 1 << 10, - - kHighestBottomItem = kItemMinimize, -}; - - -#ifdef EXPERIMENTAL_DA - - #define TITLE_ITEMS \ - { kItemBarButtons, kTrackInfoBtnSize, 4, \ - &TrackInfo::CloseTitleDrawFunction }, - // DA: Has Mute and Solo on separate lines. - #define MUTE_SOLO_ITEMS(extra) \ - { kItemMute, kTrackInfoBtnSize + 1, 1, \ - &TrackInfo::WideMuteDrawFunction }, \ - { kItemSolo, kTrackInfoBtnSize + 1, extra, \ - &TrackInfo::WideSoloDrawFunction }, - // DA: Does not have status information for a track. - #define STATUS_ITEMS - -#else - - #define TITLE_ITEMS \ - { kItemBarButtons, kTrackInfoBtnSize, 0, \ - &TrackInfo::CloseTitleDrawFunction }, - #define MUTE_SOLO_ITEMS(extra) \ - { kItemMute | kItemSolo, kTrackInfoBtnSize + 1, extra, \ - &TrackInfo::MuteAndSoloDrawFunction }, - #define STATUS_ITEMS \ - { kItemStatusInfo1, 12, 0, \ - &TrackInfo::Status1DrawFunction }, \ - { kItemStatusInfo2, 12, 0, \ - &TrackInfo::Status2DrawFunction }, - -#endif - -#define COMMON_ITEMS \ - TITLE_ITEMS - -const TrackInfo::TCPLine defaultCommonTrackTCPLines[] = { - COMMON_ITEMS -}; -TCPLines commonTrackTCPLines{ RANGE(defaultCommonTrackTCPLines) }; - -const TrackInfo::TCPLine defaultWaveTrackTCPLines[] = { - COMMON_ITEMS - MUTE_SOLO_ITEMS(2) - { kItemGain, kTrackInfoSliderHeight, kTrackInfoSliderExtra, - &TrackInfo::GainSliderDrawFunction }, - { kItemPan, kTrackInfoSliderHeight, kTrackInfoSliderExtra, - &TrackInfo::PanSliderDrawFunction }, - STATUS_ITEMS -}; -TCPLines waveTrackTCPLines{ RANGE(defaultWaveTrackTCPLines) }; - -#ifdef USE_MIDI -enum : int { - // PRL: was it correct to include the margin? - kMidiCellWidth = ( ( kTrackInfoWidth + kLeftMargin ) / 4) - 2, - kMidiCellHeight = kTrackInfoBtnSize -}; -#endif - -const TrackInfo::TCPLine defaultNoteTrackTCPLines[] = { - COMMON_ITEMS -#ifdef EXPERIMENTAL_MIDI_OUT - MUTE_SOLO_ITEMS(0) - { kItemMidiControlsRect, kMidiCellHeight * 4, 0, - &TrackInfo::MidiControlsDrawFunction }, - { kItemVelocity, kTrackInfoSliderHeight, kTrackInfoSliderExtra, - &TrackInfo::VelocitySliderDrawFunction }, -#endif -}; -TCPLines noteTrackTCPLines{ RANGE(defaultNoteTrackTCPLines) }; - -int totalTCPLines( const TCPLines &lines, bool omitLastExtra ) -{ - int total = 0; - int lastExtra = 0; - for ( const auto line : lines ) { - lastExtra = line.extraSpace; - total += line.height + lastExtra; - } - if (omitLastExtra) - total -= lastExtra; - return total; -} - -const TCPLines &getTCPLines( const Track &track ) -{ - auto lines = track.TypeSwitch< TCPLines * >( -#ifdef USE_MIDI - [](const NoteTrack*){ - return ¬eTrackTCPLines; - }, -#endif - [](const WaveTrack*){ - return &waveTrackTCPLines; - }, - [](const Track*){ - return &commonTrackTCPLines; - } - ); - - if (lines) - return *lines; - - return commonTrackTCPLines; -} - -// return y value and height -std::pair< int, int > CalcItemY( const TCPLines &lines, unsigned iItem ) -{ - int y = 0; - auto pLines = lines.begin(); - while ( pLines != lines.end() && - 0 == (pLines->items & iItem) ) { - y += pLines->height + pLines->extraSpace; - ++pLines; - } - int height = 0; - if ( pLines != lines.end() ) - height = pLines->height; - return { y, height }; -} - -// Items for the bottom of the panel, listed bottom-upwards -// As also with the top items, the extra space is below the item -const TrackInfo::TCPLine defaultCommonTrackTCPBottomLines[] = { - // The '0' avoids impinging on bottom line of TCP - // Use -1 if you do want to do so. - { kItemSyncLock | kItemMinimize, kTrackInfoBtnSize, 0, - &TrackInfo::MinimizeSyncLockDrawFunction }, -}; -TCPLines commonTrackTCPBottomLines{ RANGE(defaultCommonTrackTCPBottomLines) }; - -// return y value and height -std::pair< int, int > CalcBottomItemY - ( const TCPLines &lines, unsigned iItem, int height ) -{ - int y = height; - auto pLines = lines.begin(); - while ( pLines != lines.end() && - 0 == (pLines->items & iItem) ) { - y -= pLines->height + pLines->extraSpace; - ++pLines; - } - if (pLines != lines.end()) - y -= (pLines->height + pLines->extraSpace ); - return { y, pLines->height }; -} - -} - -unsigned TrackInfo::MinimumTrackHeight() -{ - unsigned height = 0; - if (!commonTrackTCPLines.empty()) - height += commonTrackTCPLines.front().height; - if (!commonTrackTCPBottomLines.empty()) - height += commonTrackTCPBottomLines.front().height; - // + 1 prevents the top item from disappearing for want of enough space, - // according to the rules in HideTopItem. - return height + kTopMargin + kBottomMargin + 1; -} - -bool TrackInfo::HideTopItem( const wxRect &rect, const wxRect &subRect, - int allowance ) { - auto limit = CalcBottomItemY - ( commonTrackTCPBottomLines, kHighestBottomItem, rect.height).first; - // Return true if the rectangle is even touching the limit - // without an overlap. That was the behavior as of 2.1.3. - return subRect.y + subRect.height - allowance >= rect.y + limit; -} - void TrackPanel::OnKeyDown(wxKeyEvent & event) { switch (event.GetKeyCode()) @@ -1298,468 +1070,6 @@ void TrackPanel::DrawEverythingElse(TrackPanelDrawingContext &context, target->DrawExtras(UIHandle::Panel, dc, region, clip); } -void TrackInfo::DrawItems -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track &track ) -{ - const auto topLines = getTCPLines( track ); - const auto bottomLines = commonTrackTCPBottomLines; - DrawItems - ( context, rect, &track, topLines, bottomLines ); -} - -void TrackInfo::DrawItems -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack, - const std::vector &topLines, const std::vector &bottomLines ) -{ - auto dc = &context.dc; - TrackInfo::SetTrackInfoFont(dc); - dc->SetTextForeground(theTheme.Colour(clrTrackPanelText)); - - { - int yy = 0; - for ( const auto &line : topLines ) { - wxRect itemRect{ - rect.x, rect.y + yy, - rect.width, line.height - }; - if ( !TrackInfo::HideTopItem( rect, itemRect ) && - line.drawFunction ) - line.drawFunction( context, itemRect, pTrack ); - yy += line.height + line.extraSpace; - } - } - { - int yy = rect.height; - for ( const auto &line : bottomLines ) { - yy -= line.height + line.extraSpace; - if ( line.drawFunction ) { - wxRect itemRect{ - rect.x, rect.y + yy, - rect.width, line.height - }; - line.drawFunction( context, itemRect, pTrack ); - } - } - } -} - -#include "tracks/ui/TrackButtonHandles.h" -void TrackInfo::CloseTitleDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - bool selected = pTrack ? pTrack->GetSelected() : true; - { - wxRect bev = rect; - GetCloseBoxHorizontalBounds( rect, bev ); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - AColor::Bevel2(*dc, !down, bev, selected, hit ); - -#ifdef EXPERIMENTAL_THEMING - wxPen pen( theTheme.Colour( clrTrackPanelText )); - dc->SetPen( pen ); -#else - dc->SetPen(*wxBLACK_PEN); -#endif - bev.Inflate( -1, -1 ); - // Draw the "X" - const int s = 6; - - int ls = bev.x + ((bev.width - s) / 2); - int ts = bev.y + ((bev.height - s) / 2); - int rs = ls + s; - int bs = ts + s; - - AColor::Line(*dc, ls, ts, rs, bs); - AColor::Line(*dc, ls + 1, ts, rs + 1, bs); - AColor::Line(*dc, rs, ts, ls, bs); - AColor::Line(*dc, rs + 1, ts, ls + 1, bs); - - // bev.Inflate(-1, -1); - } - - { - wxRect bev = rect; - GetTitleBarHorizontalBounds( rect, bev ); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - wxString titleStr = - pTrack ? pTrack->GetName() : _("Name"); - - //bev.Inflate(-1, -1); - AColor::Bevel2(*dc, !down, bev, selected, hit); - - // Draw title text - SetTrackInfoFont(dc); - - // Bug 1660 The 'k' of 'Audio Track' was being truncated. - // Constant of 32 found by counting pixels on a windows machine. - // I believe it's the size of the X close button + the size of the - // drop down arrow. - int allowableWidth = rect.width - 32; - - wxCoord textWidth, textHeight; - dc->GetTextExtent(titleStr, &textWidth, &textHeight); - while (textWidth > allowableWidth) { - titleStr = titleStr.Left(titleStr.length() - 1); - dc->GetTextExtent(titleStr, &textWidth, &textHeight); - } - - // Pop-up triangle - #ifdef EXPERIMENTAL_THEMING - wxColour c = theTheme.Colour( clrTrackPanelText ); - #else - wxColour c = *wxBLACK; - #endif - - // wxGTK leaves little scraps (antialiasing?) of the - // characters if they are repeatedly drawn. This - // happens when holding down mouse button and moving - // in and out of the title bar. So clear it first. - // AColor::MediumTrackInfo(dc, t->GetSelected()); - // dc->DrawRectangle(bev); - - dc->SetTextForeground( c ); - dc->SetTextBackground( wxTRANSPARENT ); - dc->DrawText(titleStr, bev.x + 2, bev.y + (bev.height - textHeight) / 2); - - - - dc->SetPen(c); - dc->SetBrush(c); - - int s = 10; // Width of dropdown arrow...height is half of width - AColor::Arrow(*dc, - bev.GetRight() - s - 3, // 3 to offset from right border - bev.y + ((bev.height - (s / 2)) / 2), - s); - - } -} - -void TrackInfo::MinimizeSyncLockDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - bool selected = pTrack ? pTrack->GetSelected() : true; - bool syncLockSelected = pTrack ? pTrack->IsSyncLockSelected() : true; - bool minimized = - pTrack ? TrackView::Get( *pTrack ).GetMinimized() : false; - { - wxRect bev = rect; - GetMinimizeHorizontalBounds(rect, bev); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - - // Clear background to get rid of previous arrow - //AColor::MediumTrackInfo(dc, t->GetSelected()); - //dc->DrawRectangle(bev); - - AColor::Bevel2(*dc, !down, bev, selected, hit); - -#ifdef EXPERIMENTAL_THEMING - wxColour c = theTheme.Colour(clrTrackPanelText); - dc->SetBrush(c); - dc->SetPen(c); -#else - AColor::Dark(dc, selected); -#endif - - AColor::Arrow(*dc, - bev.x - 5 + bev.width / 2, - bev.y - 2 + bev.height / 2, - 10, - minimized); - } - - { - wxRect bev = rect; - GetSelectButtonHorizontalBounds(rect, bev); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - - AColor::Bevel2(*dc, !down, bev, selected, hit); - -#ifdef EXPERIMENTAL_THEMING - wxColour c = theTheme.Colour(clrTrackPanelText); - dc->SetBrush(c); - dc->SetPen(c); -#else - AColor::Dark(dc, selected); -#endif - - wxString str = _("Select"); - wxCoord textWidth; - wxCoord textHeight; - SetTrackInfoFont(dc); - dc->GetTextExtent(str, &textWidth, &textHeight); - - dc->SetTextForeground( c ); - dc->SetTextBackground( wxTRANSPARENT ); - dc->DrawText(str, bev.x + 2 + (bev.width-textWidth)/2, bev.y + (bev.height - textHeight) / 2); - } - - - // Draw the sync-lock indicator if this track is in a sync-lock selected group. - if (syncLockSelected) - { - wxRect syncLockIconRect = rect; - - GetSyncLockHorizontalBounds( rect, syncLockIconRect ); - wxBitmap syncLockBitmap(theTheme.Image(bmpSyncLockIcon)); - // Icon is 12x12 and syncLockIconRect is 16x16. - dc->DrawBitmap(syncLockBitmap, - syncLockIconRect.x + 3, - syncLockIconRect.y + 2, - true); - } -} - -#include "tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.h" -void TrackInfo::MidiControlsDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ -#ifdef EXPERIMENTAL_MIDI_OUT - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - auto channel = hit ? target->GetChannel() : -1; - auto &dc = context.dc; - wxRect midiRect = rect; - GetMidiControlsHorizontalBounds(rect, midiRect); - NoteTrack::DrawLabelControls - ( static_cast(pTrack), dc, midiRect, channel ); -#endif // EXPERIMENTAL_MIDI_OUT -} - -template -void TrackInfo::SliderDrawFunction -( LWSlider *(*Selector) - (const wxRect &sliderRect, const TrackClass *t, bool captured, wxWindow*), - wxDC *dc, const wxRect &rect, const Track *pTrack, - bool captured, bool highlight ) -{ - wxRect sliderRect = rect; - TrackInfo::GetSliderHorizontalBounds( rect.GetTopLeft(), sliderRect ); - auto wt = static_cast( pTrack ); - Selector( sliderRect, wt, captured, nullptr )->OnPaint(*dc, highlight); -} - -#include "tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.h" -void TrackInfo::PanSliderDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto target = dynamic_cast( context.target.get() ); - auto dc = &context.dc; - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - SliderDrawFunction - ( &TrackInfo::PanSlider, dc, rect, pTrack, captured, hit); -} - -void TrackInfo::GainSliderDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto target = dynamic_cast( context.target.get() ); - auto dc = &context.dc; - bool hit = target && target->GetTrack().get() == pTrack; - if( hit ) - hit=hit; - bool captured = hit && target->IsClicked(); - SliderDrawFunction - ( &TrackInfo::GainSlider, dc, rect, pTrack, captured, hit); -} - -#ifdef EXPERIMENTAL_MIDI_OUT -#include "tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.h" -void TrackInfo::VelocitySliderDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - SliderDrawFunction - ( &TrackInfo::VelocitySlider, dc, rect, pTrack, captured, hit); -} -#endif - -void TrackInfo::MuteOrSoloDrawFunction -( wxDC *dc, const wxRect &bev, const Track *pTrack, bool down, - bool WXUNUSED(captured), - bool solo, bool hit ) -{ - //bev.Inflate(-1, -1); - bool selected = pTrack ? pTrack->GetSelected() : true; - auto pt = dynamic_cast(pTrack); - bool value = pt ? (solo ? pt->GetSolo() : pt->GetMute()) : false; - -#if 0 - AColor::MediumTrackInfo( dc, t->GetSelected()); - if( solo ) - { - if( pt && pt->GetSolo() ) - { - AColor::Solo(dc, pt->GetSolo(), t->GetSelected()); - } - } - else - { - if( pt && pt->GetMute() ) - { - AColor::Mute(dc, pt->GetMute(), t->GetSelected(), pt->GetSolo()); - } - } - //(solo) ? AColor::Solo(dc, t->GetSolo(), t->GetSelected()) : - // AColor::Mute(dc, t->GetMute(), t->GetSelected(), t->GetSolo()); - dc->SetPen( *wxTRANSPARENT_PEN );//No border! - dc->DrawRectangle(bev); -#endif - - wxCoord textWidth, textHeight; - wxString str = (solo) ? - /* i18n-hint: This is on a button that will silence all the other tracks.*/ - _("Solo") : - /* i18n-hint: This is on a button that will silence this track.*/ - _("Mute"); - - AColor::Bevel2( - *dc, - value == down, - bev, - selected, hit - ); - - SetTrackInfoFont(dc); - dc->GetTextExtent(str, &textWidth, &textHeight); - dc->DrawText(str, bev.x + (bev.width - textWidth) / 2, bev.y + (bev.height - textHeight) / 2); -} - -#include "tracks/playabletrack/ui/PlayableTrackButtonHandles.h" -void TrackInfo::WideMuteDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - wxRect bev = rect; - GetWideMuteSoloHorizontalBounds( rect, bev ); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, false, hit ); -} - -void TrackInfo::WideSoloDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - wxRect bev = rect; - GetWideMuteSoloHorizontalBounds( rect, bev ); - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, true, hit ); -} - -void TrackInfo::MuteAndSoloDrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - bool bHasSoloButton = TrackPanel::HasSoloButton(); - - wxRect bev = rect; - if ( bHasSoloButton ) - GetNarrowMuteHorizontalBounds( rect, bev ); - else - GetWideMuteSoloHorizontalBounds( rect, bev ); - { - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, false, hit ); - } - - if( !bHasSoloButton ) - return; - - GetNarrowSoloHorizontalBounds( rect, bev ); - { - auto target = dynamic_cast( context.target.get() ); - bool hit = target && target->GetTrack().get() == pTrack; - bool captured = hit && target->IsClicked(); - bool down = captured && bev.Contains( context.lastState.GetPosition()); - MuteOrSoloDrawFunction( dc, bev, pTrack, down, captured, true, hit ); - } -} - -void TrackInfo::StatusDrawFunction - ( const wxString &string, wxDC *dc, const wxRect &rect ) -{ - static const int offset = 3; - dc->DrawText(string, rect.x + offset, rect.y); -} - -void TrackInfo::Status1DrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - auto wt = static_cast(pTrack); - - /// Returns the string to be displayed in the track label - /// indicating whether the track is mono, left, right, or - /// stereo and what sample rate it's using. - auto rate = wt ? wt->GetRate() : 44100.0; - wxString s; - if (!pTrack || TrackList::Channels(pTrack).size() > 1) - // TODO: more-than-two-channels-message - // more appropriate strings - s = _("Stereo, %dHz"); - else { - if (wt->GetChannel() == Track::MonoChannel) - s = _("Mono, %dHz"); - else if (wt->GetChannel() == Track::LeftChannel) - s = _("Left, %dHz"); - else if (wt->GetChannel() == Track::RightChannel) - s = _("Right, %dHz"); - } - s = wxString::Format( s, (int) (rate + 0.5) ); - - StatusDrawFunction( s, dc, rect ); -} - -void TrackInfo::Status2DrawFunction -( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ) -{ - auto dc = &context.dc; - auto wt = static_cast(pTrack); - auto format = wt ? wt->GetSampleFormat() : floatSample; - auto s = GetSampleFormatStr(format); - StatusDrawFunction( s, dc, rect ); -} - void TrackPanel::DrawOutside (TrackPanelDrawingContext &context, const Track * t, const wxRect & rec) @@ -2407,481 +1717,6 @@ void TrackPanel::SetFocusedTrack( Track *t ) } } -/********************************************************************** - - TrackInfo code is destined to move out of this file. - -**********************************************************************/ - -namespace { - -wxFont gFont; - -std::unique_ptr - gGainCaptured - , gPanCaptured - , gGain - , gPan -#ifdef EXPERIMENTAL_MIDI_OUT - , gVelocityCaptured - , gVelocity -#endif -; - -} - -void TrackInfo::ReCreateSliders(){ - const wxPoint point{ 0, 0 }; - wxRect sliderRect; - GetGainRect(point, sliderRect); - - float defPos = 1.0; - /* i18n-hint: Title of the Gain slider, used to adjust the volume */ - gGain = std::make_unique(nullptr, _("Gain"), - wxPoint(sliderRect.x, sliderRect.y), - wxSize(sliderRect.width, sliderRect.height), - DB_SLIDER); - gGain->SetDefaultValue(defPos); - - gGainCaptured = std::make_unique(nullptr, _("Gain"), - wxPoint(sliderRect.x, sliderRect.y), - wxSize(sliderRect.width, sliderRect.height), - DB_SLIDER); - gGainCaptured->SetDefaultValue(defPos); - - GetPanRect(point, sliderRect); - - defPos = 0.0; - /* i18n-hint: Title of the Pan slider, used to move the sound left or right */ - gPan = std::make_unique(nullptr, _("Pan"), - wxPoint(sliderRect.x, sliderRect.y), - wxSize(sliderRect.width, sliderRect.height), - PAN_SLIDER); - gPan->SetDefaultValue(defPos); - - gPanCaptured = std::make_unique(nullptr, _("Pan"), - wxPoint(sliderRect.x, sliderRect.y), - wxSize(sliderRect.width, sliderRect.height), - PAN_SLIDER); - gPanCaptured->SetDefaultValue(defPos); - -#ifdef EXPERIMENTAL_MIDI_OUT - GetVelocityRect(point, sliderRect); - - /* i18n-hint: Title of the Velocity slider, used to adjust the volume of note tracks */ - gVelocity = std::make_unique(nullptr, _("Velocity"), - wxPoint(sliderRect.x, sliderRect.y), - wxSize(sliderRect.width, sliderRect.height), - VEL_SLIDER); - gVelocity->SetDefaultValue(0.0); - gVelocityCaptured = std::make_unique(nullptr, _("Velocity"), - wxPoint(sliderRect.x, sliderRect.y), - wxSize(sliderRect.width, sliderRect.height), - VEL_SLIDER); - gVelocityCaptured->SetDefaultValue(0.0); -#endif - -} - -void TrackInfo::GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest ) -{ - dest.x = rect.x; - dest.width = kTrackInfoBtnSize; -} - -void TrackInfo::GetCloseBoxRect(const wxRect & rect, wxRect & dest) -{ - GetCloseBoxHorizontalBounds( rect, dest ); - auto results = CalcItemY( commonTrackTCPLines, kItemBarButtons ); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -static const int TitleSoloBorderOverlap = 1; - -void TrackInfo::GetTitleBarHorizontalBounds( const wxRect & rect, wxRect &dest ) -{ - // to right of CloseBoxRect, plus a little more - wxRect closeRect; - GetCloseBoxHorizontalBounds( rect, closeRect ); - dest.x = rect.x + closeRect.width + 1; - dest.width = rect.x + rect.width - dest.x + TitleSoloBorderOverlap; -} - -void TrackInfo::GetTitleBarRect(const wxRect & rect, wxRect & dest) -{ - GetTitleBarHorizontalBounds( rect, dest ); - auto results = CalcItemY( commonTrackTCPLines, kItemBarButtons ); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -void TrackInfo::GetNarrowMuteHorizontalBounds( const wxRect & rect, wxRect &dest ) -{ - dest.x = rect.x; - dest.width = rect.width / 2 + 1; -} - -void TrackInfo::GetNarrowSoloHorizontalBounds( const wxRect & rect, wxRect &dest ) -{ - wxRect muteRect; - GetNarrowMuteHorizontalBounds( rect, muteRect ); - dest.x = rect.x + muteRect.width; - dest.width = rect.width - muteRect.width + TitleSoloBorderOverlap; -} - -void TrackInfo::GetWideMuteSoloHorizontalBounds( const wxRect & rect, wxRect &dest ) -{ - // Larger button, symmetrically placed intended. - // On windows this gives 15 pixels each side. - dest.width = rect.width - 2 * kTrackInfoBtnSize + 6; - dest.x = rect.x + kTrackInfoBtnSize -3; -} - -void TrackInfo::GetMuteSoloRect -(const wxRect & rect, wxRect & dest, bool solo, bool bHasSoloButton, - const Track *pTrack) -{ - - auto resultsM = CalcItemY( getTCPLines( *pTrack ), kItemMute ); - auto resultsS = CalcItemY( getTCPLines( *pTrack ), kItemSolo ); - dest.height = resultsS.second; - - int yMute = resultsM.first; - int ySolo = resultsS.first; - - bool bSameRow = ( yMute == ySolo ); - bool bNarrow = bSameRow && bHasSoloButton; - - if( bNarrow ) - { - if( solo ) - GetNarrowSoloHorizontalBounds( rect, dest ); - else - GetNarrowMuteHorizontalBounds( rect, dest ); - } - else - GetWideMuteSoloHorizontalBounds( rect, dest ); - - if( bSameRow || !solo ) - dest.y = rect.y + yMute; - else - dest.y = rect.y + ySolo; - -} - -void TrackInfo::GetSliderHorizontalBounds( const wxPoint &topleft, wxRect &dest ) -{ - dest.x = topleft.x + 6; - dest.width = kTrackInfoSliderWidth; -} - -void TrackInfo::GetGainRect(const wxPoint &topleft, wxRect & dest) -{ - GetSliderHorizontalBounds( topleft, dest ); - auto results = CalcItemY( waveTrackTCPLines, kItemGain ); - dest.y = topleft.y + results.first; - dest.height = results.second; -} - -void TrackInfo::GetPanRect(const wxPoint &topleft, wxRect & dest) -{ - GetGainRect( topleft, dest ); - auto results = CalcItemY( waveTrackTCPLines, kItemPan ); - dest.y = topleft.y + results.first; -} - -#ifdef EXPERIMENTAL_MIDI_OUT -void TrackInfo::GetVelocityRect(const wxPoint &topleft, wxRect & dest) -{ - GetSliderHorizontalBounds( topleft, dest ); - auto results = CalcItemY( noteTrackTCPLines, kItemVelocity ); - dest.y = topleft.y + results.first; - dest.height = results.second; -} -#endif - -void TrackInfo::GetMinimizeHorizontalBounds( const wxRect &rect, wxRect &dest ) -{ - const int space = 0;// was 3. - dest.x = rect.x + space; - - wxRect syncLockRect; - GetSyncLockHorizontalBounds( rect, syncLockRect ); - - // Width is rect.width less space on left for track select - // and on right for sync-lock icon. - dest.width = kTrackInfoBtnSize; -// rect.width - (space + syncLockRect.width); -} - -void TrackInfo::GetMinimizeRect(const wxRect & rect, wxRect &dest) -{ - GetMinimizeHorizontalBounds( rect, dest ); - auto results = CalcBottomItemY - ( commonTrackTCPBottomLines, kItemMinimize, rect.height); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -void TrackInfo::GetSelectButtonHorizontalBounds( const wxRect &rect, wxRect &dest ) -{ - const int space = 0;// was 3. - dest.x = rect.x + space; - - wxRect syncLockRect; - GetSyncLockHorizontalBounds( rect, syncLockRect ); - wxRect minimizeRect; - GetMinimizeHorizontalBounds( rect, minimizeRect ); - - dest.x = dest.x + space + minimizeRect.width; - // Width is rect.width less space on left for track select - // and on right for sync-lock icon. - dest.width = rect.width - (space + syncLockRect.width) - (space + minimizeRect.width); -} - - -void TrackInfo::GetSelectButtonRect(const wxRect & rect, wxRect &dest) -{ - GetSelectButtonHorizontalBounds( rect, dest ); - auto results = CalcBottomItemY - ( commonTrackTCPBottomLines, kItemMinimize, rect.height); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -void TrackInfo::GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest ) -{ - dest.width = kTrackInfoBtnSize; - dest.x = rect.x + rect.width - dest.width; -} - -void TrackInfo::GetSyncLockIconRect(const wxRect & rect, wxRect &dest) -{ - GetSyncLockHorizontalBounds( rect, dest ); - auto results = CalcBottomItemY - ( commonTrackTCPBottomLines, kItemSyncLock, rect.height); - dest.y = rect.y + results.first; - dest.height = results.second; -} - -#ifdef USE_MIDI -void TrackInfo::GetMidiControlsHorizontalBounds -( const wxRect &rect, wxRect &dest ) -{ - dest.x = rect.x + 1; // To center slightly - // PRL: TODO: kMidiCellWidth is defined in terms of the other constant - // kTrackInfoWidth but I am trying to avoid use of that constant. - // Can cell width be computed from dest.width instead? - dest.width = kMidiCellWidth * 4; -} - -void TrackInfo::GetMidiControlsRect(const wxRect & rect, wxRect & dest) -{ - GetMidiControlsHorizontalBounds( rect, dest ); - auto results = CalcItemY( noteTrackTCPLines, kItemMidiControlsRect ); - dest.y = rect.y + results.first; - dest.height = results.second; -} -#endif - -/// \todo Probably should move to 'Utils.cpp'. -void TrackInfo::SetTrackInfoFont(wxDC * dc) -{ - dc->SetFont(gFont); -} - -#if 0 -void TrackInfo::DrawBordersWithin - ( wxDC* dc, const wxRect & rect, const Track &track ) const -{ - AColor::Dark(dc, false); // same color as border of toolbars (ToolBar::OnPaint()) - - // below close box and title bar - wxRect buttonRect; - GetTitleBarRect( rect, buttonRect ); - AColor::Line - (*dc, rect.x, buttonRect.y + buttonRect.height, - rect.width - 1, buttonRect.y + buttonRect.height); - - // between close box and title bar - AColor::Line - (*dc, buttonRect.x, buttonRect.y, - buttonRect.x, buttonRect.y + buttonRect.height - 1); - - GetMuteSoloRect( rect, buttonRect, false, true, &track ); - - bool bHasMuteSolo = dynamic_cast( &track ) != NULL; - if( bHasMuteSolo && !TrackInfo::HideTopItem( rect, buttonRect ) ) - { - // above mute/solo - AColor::Line - (*dc, rect.x, buttonRect.y, - rect.width - 1, buttonRect.y); - - // between mute/solo - // Draw this little line; if there is no solo, wide mute button will - // overpaint it later: - AColor::Line - (*dc, buttonRect.x + buttonRect.width, buttonRect.y, - buttonRect.x + buttonRect.width, buttonRect.y + buttonRect.height - 1); - - // below mute/solo - AColor::Line - (*dc, rect.x, buttonRect.y + buttonRect.height, - rect.width - 1, buttonRect.y + buttonRect.height); - } - - // left of and above minimize button - wxRect minimizeRect; - this->GetMinimizeRect(rect, minimizeRect); - AColor::Line - (*dc, minimizeRect.x - 1, minimizeRect.y, - minimizeRect.x - 1, minimizeRect.y + minimizeRect.height - 1); - AColor::Line - (*dc, minimizeRect.x, minimizeRect.y - 1, - minimizeRect.x + minimizeRect.width - 1, minimizeRect.y - 1); -} -#endif - -//#define USE_BEVELS - -// Paint the whole given rectangle some fill color -void TrackInfo::DrawBackground( - wxDC * dc, const wxRect & rect, bool bSelected, const int vrul) -{ - // fill in label - wxRect fill = rect; - fill.width = vrul - kLeftMargin; - AColor::MediumTrackInfo(dc, bSelected); - dc->DrawRectangle(fill); - -#ifdef USE_BEVELS - // This branch is not now used - // PRL: todo: banish magic numbers. - // PRL: vrul was the x coordinate of left edge of the vertical ruler. - // PRL: bHasMuteSolo was true iff the track was WaveTrack. - if( bHasMuteSolo ) - { - int ylast = rect.height-20; - int ybutton = wxMin(32,ylast-17); - int ybuttonEnd = 67; - - fill=wxRect( rect.x+1, rect.y+17, vrul-6, ybutton); - AColor::BevelTrackInfo( *dc, true, fill ); - - if( ybuttonEnd < ylast ){ - fill=wxRect( rect.x+1, rect.y+ybuttonEnd, fill.width, ylast - ybuttonEnd); - AColor::BevelTrackInfo( *dc, true, fill ); - } - } - else - { - fill=wxRect( rect.x+1, rect.y+17, vrul-6, rect.height-37); - AColor::BevelTrackInfo( *dc, true, fill ); - } -#endif -} - -namespace { -unsigned DefaultTrackHeight( const TCPLines &topLines ) -{ - int needed = - kTopMargin + kBottomMargin + - totalTCPLines( topLines, true ) + - totalTCPLines( commonTrackTCPBottomLines, false ) + 1; - return (unsigned) std::max( needed, (int) TrackView::DefaultHeight ); -} -} - -unsigned TrackInfo::DefaultNoteTrackHeight() -{ - return DefaultTrackHeight( noteTrackTCPLines ); -} - -unsigned TrackInfo::DefaultWaveTrackHeight() -{ - return DefaultTrackHeight( waveTrackTCPLines ); -} - -LWSlider * TrackInfo::GainSlider -(const wxRect &sliderRect, const WaveTrack *t, bool captured, wxWindow *pParent) -{ - wxPoint pos = sliderRect.GetPosition(); - float gain = t ? t->GetGain() : 1.0; - - gGain->Move(pos); - gGain->Set(gain); - gGainCaptured->Move(pos); - gGainCaptured->Set(gain); - - auto slider = (captured ? gGainCaptured : gGain).get(); - slider->SetParent( pParent ? pParent : - FindProjectFrame( ::GetActiveProject() ) ); - return slider; -} - -LWSlider * TrackInfo::PanSlider -(const wxRect &sliderRect, const WaveTrack *t, bool captured, wxWindow *pParent) -{ - wxPoint pos = sliderRect.GetPosition(); - float pan = t ? t->GetPan() : 0.0; - - gPan->Move(pos); - gPan->Set(pan); - gPanCaptured->Move(pos); - gPanCaptured->Set(pan); - - auto slider = (captured ? gPanCaptured : gPan).get(); - slider->SetParent( pParent ? pParent : - FindProjectFrame( ::GetActiveProject() ) ); - return slider; -} - -#ifdef EXPERIMENTAL_MIDI_OUT -LWSlider * TrackInfo::VelocitySlider -(const wxRect &sliderRect, const NoteTrack *t, bool captured, wxWindow *pParent) -{ - wxPoint pos = sliderRect.GetPosition(); - float velocity = t ? t->GetVelocity() : 0.0; - - gVelocity->Move(pos); - gVelocity->Set(velocity); - gVelocityCaptured->Move(pos); - gVelocityCaptured->Set(velocity); - - auto slider = (captured ? gVelocityCaptured : gVelocity).get(); - slider->SetParent( pParent ? pParent : - FindProjectFrame( ::GetActiveProject() ) ); - return slider; -} -#endif - -void TrackInfo::UpdatePrefs( wxWindow *pParent ) -{ - // Calculation of best font size depends on language, so it should be redone in case - // the language preference changed. - - int fontSize = 10; - gFont.Create(fontSize, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL); - - int allowableWidth = - // PRL: was it correct to include the margin? - ( kTrackInfoWidth + kLeftMargin ) - - 2; // 2 to allow for left/right borders - int textWidth, textHeight; - do { - gFont.SetPointSize(fontSize); - pParent->GetTextExtent(_("Stereo, 999999Hz"), - &textWidth, - &textHeight, - NULL, - NULL, - &gFont); - fontSize--; - } while (textWidth >= allowableWidth); -} - TrackPanelNode::TrackPanelNode() { } diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 52a6a37a5..a0d7f8183 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -60,160 +60,6 @@ enum { kTimerInterval = 50, // milliseconds }; - -namespace TrackInfo -{ - void ReCreateSliders(); - - unsigned MinimumTrackHeight(); - - struct TCPLine; - - void DrawItems - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track &track ); - - void DrawItems - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack, - const std::vector &topLines, - const std::vector &bottomLines ); - - void CloseTitleDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - void MinimizeSyncLockDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - void MidiControlsDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - template - void SliderDrawFunction - ( LWSlider *(*Selector) - (const wxRect &sliderRect, const TrackClass *t, bool captured, - wxWindow*), - wxDC *dc, const wxRect &rect, const Track *pTrack, - bool captured, bool highlight ); - - void PanSliderDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - void GainSliderDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - -#ifdef EXPERIMENTAL_MIDI_OUT - void VelocitySliderDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); -#endif - - void MuteOrSoloDrawFunction - ( wxDC *dc, const wxRect &rect, const Track *pTrack, bool down, - bool captured, bool solo, bool hit ); - - void WideMuteDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - void WideSoloDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - void MuteAndSoloDrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - void StatusDrawFunction - ( const wxString &string, wxDC *dc, const wxRect &rect ); - - void Status1DrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - void Status2DrawFunction - ( TrackPanelDrawingContext &context, - const wxRect &rect, const Track *pTrack ); - - void SetTrackInfoFont(wxDC *dc); - - - void DrawBackground( - wxDC * dc, const wxRect & rect, bool bSelected, const int vrul ); - // void DrawBordersWithin( - // wxDC * dc, const wxRect & rect, const Track &track ) const; - - void GetCloseBoxHorizontalBounds( const wxRect & rect, wxRect &dest ); - void GetCloseBoxRect(const wxRect & rect, wxRect &dest); - - void GetTitleBarHorizontalBounds( const wxRect & rect, wxRect &dest ); - void GetTitleBarRect(const wxRect & rect, wxRect &dest); - - void GetNarrowMuteHorizontalBounds - ( const wxRect & rect, wxRect &dest ); - void GetNarrowSoloHorizontalBounds - ( const wxRect & rect, wxRect &dest ); - void GetWideMuteSoloHorizontalBounds - ( const wxRect & rect, wxRect &dest ); - void GetMuteSoloRect - (const wxRect & rect, wxRect &dest, bool solo, bool bHasSoloButton, - const Track *pTrack); - - void GetSliderHorizontalBounds( const wxPoint &topleft, wxRect &dest ); - - void GetGainRect(const wxPoint & topLeft, wxRect &dest); - - void GetPanRect(const wxPoint & topLeft, wxRect &dest); - -#ifdef EXPERIMENTAL_MIDI_OUT - void GetVelocityRect(const wxPoint & topLeft, wxRect &dest); -#endif - - void GetMinimizeHorizontalBounds( const wxRect &rect, wxRect &dest ); - void GetMinimizeRect(const wxRect & rect, wxRect &dest); - - void GetSelectButtonHorizontalBounds( const wxRect &rect, wxRect &dest ); - void GetSelectButtonRect(const wxRect & rect, wxRect &dest); - - void GetSyncLockHorizontalBounds( const wxRect &rect, wxRect &dest ); - void GetSyncLockIconRect(const wxRect & rect, wxRect &dest); - -#ifdef USE_MIDI - void GetMidiControlsHorizontalBounds - ( const wxRect &rect, wxRect &dest ); - void GetMidiControlsRect(const wxRect & rect, wxRect &dest); -#endif - - bool HideTopItem( const wxRect &rect, const wxRect &subRect, - int allowance = 0 ); - - unsigned DefaultNoteTrackHeight(); - unsigned DefaultWaveTrackHeight(); - - LWSlider * GainSlider - (const wxRect &sliderRect, const WaveTrack *t, bool captured, - wxWindow *pParent); - LWSlider * PanSlider - (const wxRect &sliderRect, const WaveTrack *t, bool captured, - wxWindow *pParent); - -#ifdef EXPERIMENTAL_MIDI_OUT - LWSlider * VelocitySlider - (const wxRect &sliderRect, const NoteTrack *t, bool captured, - wxWindow *pParent); -#endif - - // Non-member, namespace function relying on TrackPanel to invoke it - // when it handles preference update events - void UpdatePrefs( wxWindow *pParent ); -}; - - const int DragThreshold = 3;// Anything over 3 pixels is a drag, else a click. class AUDACITY_DLL_API TrackPanel final @@ -370,10 +216,6 @@ public: (const std::shared_ptr< TrackPanelCell > &pCell); std::shared_ptr< TrackPanelCell > GetBackgroundCell(); -public: - // Accessors... - static bool HasSoloButton(){ return gSoloPref!=wxT("None");} - public: LWSlider *GainSlider( const WaveTrack *wt ); @@ -432,8 +274,6 @@ public: protected: - static wxString gSoloPref; - // The screenshot class needs to access internals friend class ScreenshotCommand; diff --git a/src/menus/ViewMenus.cpp b/src/menus/ViewMenus.cpp index 669942eaf..87e61a596 100644 --- a/src/menus/ViewMenus.cpp +++ b/src/menus/ViewMenus.cpp @@ -11,6 +11,7 @@ #include "../ProjectHistory.h" #include "../ProjectSettings.h" #include "../ProjectWindow.h" +#include "../TrackInfo.h" #include "../TrackPanel.h" #include "../UndoManager.h" #include "../ViewInfo.h" diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp index 3f9ba5c14..f8eb9076b 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackButtonHandle.cpp @@ -17,6 +17,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../../../NoteTrack.h" #include "../../../../ProjectHistory.h" #include "../../../../RefreshCode.h" +#include "../../../../TrackInfo.h" #include "../../../../TrackPanel.h" NoteTrackButtonHandle::NoteTrackButtonHandle diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp index 0db4e8581..bbda8fad5 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackSliderHandles.cpp @@ -17,7 +17,8 @@ #include "../../../../ProjectHistory.h" #include "../../../../RefreshCode.h" -#include "../../../../TrackPanel.h" // for TrackInfo +#include "../../../../TrackInfo.h" +#include "../../../../TrackPanel.h" #include "../../../../UndoManager.h" #include "../../../../NoteTrack.h" #include "../../../../ViewInfo.h" diff --git a/src/tracks/playabletrack/notetrack/ui/NoteTrackView.cpp b/src/tracks/playabletrack/notetrack/ui/NoteTrackView.cpp index 4d6aad951..d070b4670 100644 --- a/src/tracks/playabletrack/notetrack/ui/NoteTrackView.cpp +++ b/src/tracks/playabletrack/notetrack/ui/NoteTrackView.cpp @@ -23,7 +23,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../../../TrackPanelMouseEvent.h" #include "../../../ui/SelectHandle.h" #include "StretchHandle.h" -#include "../../../../TrackPanel.h" +#include "../../../../TrackInfo.h" NoteTrackView::NoteTrackView( const std::shared_ptr &pTrack ) : CommonTrackView{ pTrack } diff --git a/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp b/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp index 91096d1de..a9753315f 100644 --- a/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp +++ b/src/tracks/playabletrack/ui/PlayableTrackButtonHandles.cpp @@ -17,6 +17,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../../ProjectSettings.h" #include "../../../RefreshCode.h" #include "../../../Track.h" +#include "../../../TrackInfo.h" #include "../../../TrackPanel.h" #include "../../../TrackPanelMouseEvent.h" diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp index 787d84334..296b1d4b1 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackSliderHandles.cpp @@ -13,6 +13,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../../../ProjectHistory.h" #include "../../../../RefreshCode.h" +#include "../../../../TrackInfo.h" #include "../../../../TrackPanel.h" #include "../../../../UndoManager.h" #include "../../../../WaveTrack.h" diff --git a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp index f3230cc51..ac6f2f46d 100644 --- a/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp +++ b/src/tracks/playabletrack/wavetrack/ui/WaveTrackView.cpp @@ -20,7 +20,7 @@ Paul Licameli split from TrackPanel.cpp #include "WaveTrackVRulerControls.h" #include "../../../../HitTestResult.h" #include "../../../../prefs/SpectrogramSettings.h" -#include "../../../../TrackPanel.h" +#include "../../../../TrackInfo.h" #include "../../../../TrackPanelMouseEvent.h" #include "CutlineHandle.h" diff --git a/src/tracks/ui/CommonTrackControls.cpp b/src/tracks/ui/CommonTrackControls.cpp index 133da02bf..ff7cd47b6 100644 --- a/src/tracks/ui/CommonTrackControls.cpp +++ b/src/tracks/ui/CommonTrackControls.cpp @@ -16,7 +16,7 @@ Paul Licameli split from TrackControls.cpp #include "../../Menus.h" #include "../../Project.h" #include "../../ProjectHistory.h" -#include "../../TrackPanel.h" // for TrackInfo +#include "../../TrackInfo.h" #include "../../TrackPanelMouseEvent.h" #include #include "../../commands/CommandType.h" diff --git a/src/tracks/ui/CommonTrackView.cpp b/src/tracks/ui/CommonTrackView.cpp index fdbfcfdbf..41bf971e0 100644 --- a/src/tracks/ui/CommonTrackView.cpp +++ b/src/tracks/ui/CommonTrackView.cpp @@ -13,11 +13,11 @@ Paul Licameli split from class TrackView #include "BackgroundCell.h" #include "TimeShiftHandle.h" #include "TrackControls.h" -#include "../../TrackPanel.h" // for TrackInfo #include "ZoomHandle.h" #include "../ui/SelectHandle.h" #include "../../ProjectSettings.h" #include "../../Track.h" +#include "../../TrackInfo.h" #include "../../TrackPanelMouseEvent.h" std::vector CommonTrackView::HitTest diff --git a/src/tracks/ui/TrackButtonHandles.cpp b/src/tracks/ui/TrackButtonHandles.cpp index 5c8e7b7fe..e2db5bc00 100644 --- a/src/tracks/ui/TrackButtonHandles.cpp +++ b/src/tracks/ui/TrackButtonHandles.cpp @@ -17,6 +17,7 @@ Paul Licameli split from TrackPanel.cpp #include "../../ProjectHistory.h" #include "../../RefreshCode.h" #include "../../Track.h" +#include "../../TrackInfo.h" #include "../../TrackPanel.h" #include "../../commands/CommandManager.h" #include "../../tracks/ui/TrackView.h"