From 30d55f476ee6756cde337525352daeca44c3eef5 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 17 Sep 2018 12:53:15 -0400 Subject: [PATCH 1/9] Define abstract classes TrackPanelNode and TrackPanelGroup --- src/TrackPanel.cpp | 16 ++++++++++++++++ src/TrackPanelCell.h | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 0cb9b8785..fd02d99c2 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -2729,6 +2729,22 @@ TrackPanel *(*TrackPanel::FactoryFunction)( TrackPanelListener * listener, AdornedRulerPanel * ruler) = TrackPanelFactory; +TrackPanelNode::TrackPanelNode() +{ +} + +TrackPanelNode::~TrackPanelNode() +{ +} + +TrackPanelGroup::TrackPanelGroup() +{ +} + +TrackPanelGroup::~TrackPanelGroup() +{ +} + TrackPanelCell::~TrackPanelCell() { } diff --git a/src/TrackPanelCell.h b/src/TrackPanelCell.h index 23d3af107..fcca9fa18 100644 --- a/src/TrackPanelCell.h +++ b/src/TrackPanelCell.h @@ -28,9 +28,43 @@ using UIHandlePtr = std::shared_ptr; #include +// A subtree in the subdivision of the CellularPanel's area +class AUDACITY_DLL_API /* not final */ TrackPanelNode +{ +public: + TrackPanelNode(); + virtual ~TrackPanelNode() = 0; +}; + +// A non-leaf +class AUDACITY_DLL_API TrackPanelGroup /* not final */ : public TrackPanelNode +{ +public: + TrackPanelGroup(); + virtual ~TrackPanelGroup(); + + enum class Axis { X, Y }; + + // A refinement of a given rectangle partitions it along one of its axes + // and associates TrackPanelNodes with the partition. + // The sequence of coordinates should be increasing, giving left or top + // coordinates of sub-rectangles. + // Null pointers are permitted to define empty spaces with no cell object. + // If the first coordinate is right of or below the rectangle boundary, + // then that also defines an empty space at the edge. + // Sub-rectangles may be defined partly or wholly out of the bounds of the + // given rectangle. Such portions are ignored. + using Child = std::pair< wxCoord, std::shared_ptr >; + using Refinement = std::vector< Child >; + using Subdivision = std::pair< Axis, Refinement >; + + // Report a subdivision of one of the axes of the given rectangle + virtual Subdivision Children( const wxRect &rect ) = 0; +}; + // Abstract base class defining TrackPanel's access to specialist classes that // implement drawing and user interactions -class AUDACITY_DLL_API TrackPanelCell /* not final */ +class AUDACITY_DLL_API TrackPanelCell /* not final */ : public TrackPanelNode { public: virtual ~TrackPanelCell () = 0; From 4fe97acbc9a4472886c428adfae9613ef6ec490b Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 17 Sep 2018 12:53:34 -0400 Subject: [PATCH 2/9] Define CellularPanel::Root --- src/AdornedRulerPanel.cpp | 5 +++++ src/AdornedRulerPanel.h | 5 +++++ src/CellularPanel.h | 6 ++++++ src/TrackPanel.cpp | 5 +++++ src/TrackPanel.h | 4 ++++ 5 files changed, 25 insertions(+) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index b73343d57..7e8af675f 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -2102,6 +2102,11 @@ void AdornedRulerPanel::GetMaxSize(wxCoord *width, wxCoord *height) } // CellularPanel implementation +std::shared_ptr AdornedRulerPanel::Root() +{ + return {}; +} + auto AdornedRulerPanel::FindCell(int mouseX, int mouseY) -> FoundCell { bool mayScrub = mProject->GetScrubber().CanScrub() && diff --git a/src/AdornedRulerPanel.h b/src/AdornedRulerPanel.h index bbbc86ea2..999b892ae 100644 --- a/src/AdornedRulerPanel.h +++ b/src/AdornedRulerPanel.h @@ -172,6 +172,11 @@ private: // // CellularPanel implementation // + + // Get the root object defining a recursive subdivision of the panel's + // area into cells + std::shared_ptr Root() override; + FoundCell FindCell(int mouseX, int mouseY) override; wxRect FindRect(const TrackPanelCell &cell) override; public: diff --git a/src/CellularPanel.h b/src/CellularPanel.h index 00eda5f5e..19b96e32f 100644 --- a/src/CellularPanel.h +++ b/src/CellularPanel.h @@ -18,6 +18,7 @@ class ViewInfo; class AudacityProject; class TrackPanelCell; +class TrackPanelNode; struct TrackPanelMouseEvent; struct TrackPanelMouseState; @@ -47,6 +48,11 @@ public: std::shared_ptr pCell; wxRect rect; }; + + // Get the root object defining a recursive subdivision of the panel's + // area into cells + virtual std::shared_ptr Root() = 0; + virtual FoundCell FindCell(int mouseX, int mouseY) = 0; virtual wxRect FindRect(const TrackPanelCell &cell) = 0; virtual TrackPanelCell *GetFocusedCell() = 0; diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index fd02d99c2..44c60fda0 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1956,6 +1956,11 @@ void TrackPanel::DrawShadow(const Track * /* t */ , wxDC * dc, const wxRect & re AColor::Line(*dc, right, rect.y, right, rect.y + 1); } +std::shared_ptr TrackPanel::Root() +{ + return {}; +} + /// Determines which cell is under the mouse /// @param mouseX - mouse X position. /// @param mouseY - mouse Y position. diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 12a73bba5..e1bc38b4b 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -337,6 +337,10 @@ protected: void MakeParentModifyState(bool bWantsAutoSave); // if true, writes auto-save file. Should set only if you really want the state change restored after // a crash, as it can take many seconds for large (eg. 10 track-hours) projects + // Get the root object defining a recursive subdivision of the panel's + // area into cells + std::shared_ptr Root() override; + // Find track info by coordinate FoundCell FindCell(int mouseX, int mouseY) override; From 588c050bbb4b5779b69778855626f26d94c6b756 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 1 Nov 2018 11:13:13 -0400 Subject: [PATCH 3/9] Define visitation procedure skeleton for subdivision of CellularPanel --- src/CellularPanel.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++ src/CellularPanel.h | 28 ++++++++++ 2 files changed, 144 insertions(+) diff --git a/src/CellularPanel.cpp b/src/CellularPanel.cpp index 31c3254d6..3614dc021 100644 --- a/src/CellularPanel.cpp +++ b/src/CellularPanel.cpp @@ -860,6 +860,122 @@ void CellularPanel::OnKillFocus(wxFocusEvent & WXUNUSED(event)) Refresh( false); } +// Empty out-of-line default functions to fill Visitor's vtable +CellularPanel::Visitor::~Visitor() {} +void CellularPanel::Visitor::VisitCell( + const wxRect &rect, TrackPanelCell &cell ) {} +void CellularPanel::Visitor::BeginGroup( + const wxRect &rect, TrackPanelGroup &group ) {} +void CellularPanel::Visitor::EndGroup( + const wxRect &rect, TrackPanelGroup &group ) {} + +// Public, top-level entry for generalized Visit +void CellularPanel::Visit( Visitor &visitor ) +{ + Visit( GetClientRect(), Root(), visitor ); +} + +// Common utility class for the functions that follow +namespace { + struct Adaptor : CellularPanel::Visitor { + using SimpleCellVisitor = CellularPanel::SimpleCellVisitor; + using SimpleNodeVisitor = CellularPanel::SimpleNodeVisitor; + + // Visit cells only + Adaptor( const SimpleCellVisitor& function_ ) + : function{ [&](const wxRect &rect, TrackPanelNode &cell) { + return function_( rect, static_cast(cell) ); + } } + {} + + // Visit cells and groups, each once only, choosing pre- or post- ordering + // for the groups + Adaptor( const SimpleNodeVisitor &function_, bool pre_ ) + : function{ function_ }, pre{ pre_ }, post{ ! pre_ } {} + + void VisitCell( const wxRect &rect, TrackPanelCell &cell ) override + { return function( rect, cell ); } + void BeginGroup( const wxRect &rect, TrackPanelGroup &group ) override + { if (pre) return function( rect, group ); } + void EndGroup( const wxRect &rect, TrackPanelGroup &group ) override + { if (post) return function( rect, group ); } + + SimpleNodeVisitor function; + const bool pre{ false }, post{ false }; + }; +} + +// Simplified entry points for visits that don't need all the generality of +// CellularPanel::Visitor +void CellularPanel::VisitCells( const SimpleCellVisitor &visitor ) +{ + Adaptor adaptor{ visitor }; + Visit( adaptor ); +} + +void CellularPanel::VisitPreorder( const SimpleNodeVisitor &visitor ) +{ + Adaptor adaptor{ visitor, true }; + Visit( adaptor ); +} + +void CellularPanel::VisitPostorder( const SimpleNodeVisitor &visitor ) +{ + Adaptor adaptor{ visitor, false }; + Visit( adaptor ); +} + +namespace { + wxRect Subdivide( + const wxRect &rect, bool divideX, + const TrackPanelGroup::Refinement &children, + const TrackPanelGroup::Refinement::const_iterator iter) + { + const auto lowerBound = (divideX ? rect.GetLeft() : rect.GetTop()); + const auto upperBound = (divideX ? rect.GetRight() : rect.GetBottom()); + const auto next = iter + 1; + const auto end = children.end(); + const auto nextCoord = ((next == end) ? upperBound : next->first - 1); + + // Some defense against bad overrides of TrackPanelGroup::Children + auto lesser = std::max(lowerBound, std::min(upperBound, iter->first)); + auto greater = std::max(lesser, std::min(upperBound, nextCoord)); + + auto result = rect; + if (divideX) + result.SetLeft(lesser), result.SetRight(greater); + else + result.SetTop(lesser), result.SetBottom(greater); + + return result; + }; +} + +// Private, recursive implementation function of Visit +void CellularPanel::Visit( + const wxRect &rect, const std::shared_ptr &node, + Visitor &visitor ) +{ + if (auto pCell = dynamic_cast(node.get())) + visitor.VisitCell( rect, *pCell ); + else if (auto pGroup = dynamic_cast(node.get())) { + visitor.BeginGroup( rect, *pGroup ); + + // Recur on children + const auto results = pGroup->Children( rect ); + const bool divideX = results.first == TrackPanelGroup::Axis::X; + const auto &children = results.second; + const auto begin = children.begin(), end = children.end(); + for (auto iter = begin; iter != end; ++iter) + Visit( + Subdivide(rect, divideX, children, iter), iter->second, visitor ); + + visitor.EndGroup( rect, *pGroup ); + } + else + return; +} + UIHandlePtr CellularPanel::Target() { auto &state = *mState; diff --git a/src/CellularPanel.h b/src/CellularPanel.h index 19b96e32f..f5c7595dc 100644 --- a/src/CellularPanel.h +++ b/src/CellularPanel.h @@ -18,6 +18,7 @@ class ViewInfo; class AudacityProject; class TrackPanelCell; +class TrackPanelGroup; class TrackPanelNode; struct TrackPanelMouseEvent; struct TrackPanelMouseState; @@ -55,6 +56,29 @@ public: virtual FoundCell FindCell(int mouseX, int mouseY) = 0; virtual wxRect FindRect(const TrackPanelCell &cell) = 0; + + // Structure and functions for generalized visitation of the subdivision + struct Visitor { + virtual ~Visitor(); + virtual void VisitCell( const wxRect &rect, TrackPanelCell &cell ); + virtual void BeginGroup( const wxRect &rect, TrackPanelGroup &group ); + virtual void EndGroup( const wxRect &rect, TrackPanelGroup &group ); + }; + + // Most general visit + void Visit( Visitor &visitor ); + + // Easier visit when you care only about cells + using SimpleCellVisitor = + std::function< void( const wxRect &rect, TrackPanelCell &cell ) >; + void VisitCells( const SimpleCellVisitor &visitor ); + + // Easier visits when you want to visit each node once only + using SimpleNodeVisitor = + std::function< void( const wxRect &rect, TrackPanelNode &node ) >; + void VisitPreorder( const SimpleNodeVisitor &visitor ); + void VisitPostorder( const SimpleNodeVisitor &visitor ); + virtual TrackPanelCell *GetFocusedCell() = 0; virtual void SetFocusedCell() = 0; @@ -86,6 +110,10 @@ protected: void ClearTargets(); private: + void Visit( + const wxRect &rect, const std::shared_ptr &node, + Visitor &visitor ); + bool HasRotation(); bool ChangeTarget(bool forward, bool cycle); From 08f88ebf2e6b76f54b68ff6526f9b0541d459b8e Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Tue, 18 Sep 2018 10:36:20 -0400 Subject: [PATCH 4/9] Implement AdornedRulerPanel::Root() --- src/AdornedRulerPanel.cpp | 36 +++++++++++++++++++++++++++++++++++- src/AdornedRulerPanel.h | 4 ++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index 7e8af675f..cd6f0eb63 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -2101,10 +2101,44 @@ void AdornedRulerPanel::GetMaxSize(wxCoord *width, wxCoord *height) mRuler.GetMaxSize(width, height); } +// Second-level subdivision includes quick-play region and maybe the scrub bar +// and also shaves little margins above and below +struct AdornedRulerPanel::Subgroup final : TrackPanelGroup { + explicit Subgroup( const AdornedRulerPanel &ruler ) : mRuler{ ruler } {} + Subdivision Children( const wxRect & ) override + { + return { Axis::Y, ( mRuler.mShowScrubbing ) + ? Refinement{ + { mRuler.mInner.GetTop(), mRuler.mQPCell }, + { mRuler.mScrubZone.GetTop(), mRuler.mScrubbingCell }, + { mRuler.mScrubZone.GetBottom() + 1, nullptr } + } + : Refinement{ + { mRuler.mInner.GetTop(), mRuler.mQPCell }, + { mRuler.mInner.GetBottom() + 1, nullptr } + } + }; + } + const AdornedRulerPanel &mRuler; +}; + +// Top-level subdivision shaves little margins off left and right +struct AdornedRulerPanel::MainGroup final : TrackPanelGroup { + explicit MainGroup( const AdornedRulerPanel &ruler ) : mRuler{ ruler } {} + Subdivision Children( const wxRect & ) override + { return { Axis::X, Refinement{ + // Subgroup is a throwaway object + { mRuler.mInner.GetLeft(), std::make_shared< Subgroup >( mRuler ) }, + { mRuler.mInner.GetRight() + 1, nullptr } + } }; } + const AdornedRulerPanel &mRuler; +}; + // CellularPanel implementation std::shared_ptr AdornedRulerPanel::Root() { - return {}; + // Root is a throwaway object + return std::make_shared< MainGroup >( *this ); } auto AdornedRulerPanel::FindCell(int mouseX, int mouseY) -> FoundCell diff --git a/src/AdornedRulerPanel.h b/src/AdornedRulerPanel.h index 999b892ae..9c4c81bff 100644 --- a/src/AdornedRulerPanel.h +++ b/src/AdornedRulerPanel.h @@ -212,6 +212,10 @@ private: class ScrubbingCell; std::shared_ptr mScrubbingCell; + + // classes implementing subdivision for CellularPanel + struct Subgroup; + struct MainGroup; }; #endif //define __AUDACITY_ADORNED_RULER_PANEL__ From 128ba93ae7460e0dbb85950840a6a8caba2c189f Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 1 Nov 2018 12:18:41 -0400 Subject: [PATCH 5/9] Implement TrackPanel::Root() --- src/TrackPanel.cpp | 129 ++++++++++++++++++++++++++++++++++++++++++++- src/TrackPanel.h | 1 + 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 44c60fda0..dfb43eb8e 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1956,9 +1956,136 @@ void TrackPanel::DrawShadow(const Track * /* t */ , wxDC * dc, const wxRect & re AColor::Line(*dc, right, rect.y, right, rect.y + 1); } +namespace { + +// Helper classes to implement the subdivision of TrackPanel area for +// CellularPanel + +struct EmptyCell final : CommonTrackPanelCell { + std::vector< UIHandlePtr > HitTest( + const TrackPanelMouseState &, const AudacityProject *) override + { return {}; } + virtual std::shared_ptr< Track > FindTrack() override { return {}; } + static std::shared_ptr Instance() + { + static auto instance = std::make_shared< EmptyCell >(); + return instance; + } +}; + +// n channels alternating with n - 1 resizers +struct ChannelGroup final : TrackPanelGroup { + ChannelGroup( const std::shared_ptr< Track > &pTrack ) + : mpTrack{ pTrack } {} + Subdivision Children( const wxRect &rect ) override + { + Refinement refinement; + + const auto channels = TrackList::Channels( mpTrack.get() ); + const auto pLast = *channels.rbegin(); + wxCoord yy = rect.GetTop(); + for ( auto channel : channels ) { + refinement.emplace_back( yy, Track::Pointer( channel ) ); + if ( channel != pLast ) { + const auto substitute = + Track::Pointer( channel )->SubstitutePendingChangedTrack(); + yy += substitute->GetHeight(); + refinement.emplace_back( + yy - kSeparatorThickness, channel->GetResizer() ); + } + } + + return { Axis::Y, std::move( refinement ) }; + } + std::shared_ptr< Track > mpTrack; +}; + +// A track control panel left of n channels alternating with n - 1 resizers +struct LabeledChannelGroup final : TrackPanelGroup { + LabeledChannelGroup( + const std::shared_ptr< Track > &pTrack, wxCoord leftOffset ) + : mpTrack{ pTrack }, mLeftOffset{ leftOffset } {} + Subdivision Children( const wxRect &rect ) override + { return { Axis::X, Refinement{ + { rect.GetLeft(), mpTrack->GetTrackControl() }, + { mLeftOffset, std::make_shared< ChannelGroup >( mpTrack ) } + } }; } + std::shared_ptr< Track > mpTrack; + wxCoord mLeftOffset; +}; + +// Stacks a label and a single or multi-channel track on a resizer below, +// which is associated with the last channel +struct ResizingChannelGroup final : TrackPanelGroup { + ResizingChannelGroup( + const std::shared_ptr< Track > &pTrack, wxCoord leftOffset ) + : mpTrack{ pTrack }, mLeftOffset{ leftOffset } {} + Subdivision Children( const wxRect &rect ) override + { return { Axis::Y, Refinement{ + { rect.GetTop(), + std::make_shared< LabeledChannelGroup >( mpTrack, mLeftOffset ) }, + { rect.GetTop() + rect.GetHeight() - kSeparatorThickness, + ( *TrackList::Channels( mpTrack.get() ).rbegin() )->GetResizer() } + } }; } + std::shared_ptr< Track > mpTrack; + wxCoord mLeftOffset; +}; + +// Stacks a dead area at top, the tracks, and the click-to-deselect area below +struct Subgroup final : TrackPanelGroup { + explicit Subgroup( TrackPanel &panel ) : mPanel{ panel } {} + Subdivision Children( const wxRect &rect ) override + { + wxCoord yy = -mPanel.GetViewInfo()->vpos; + Refinement refinement; + + auto &tracks = *mPanel.GetTracks(); + if ( tracks.Any() ) + refinement.emplace_back( yy, EmptyCell::Instance() ), + yy += kTopMargin; + + for ( const auto leader : tracks.Leaders() ) { + wxCoord height = 0; + for ( auto channel : TrackList::Channels( leader ) ) { + auto substitute = + Track::Pointer( channel )->SubstitutePendingChangedTrack(); + height += substitute->GetHeight(); + } + refinement.emplace_back( yy, + std::make_shared< ResizingChannelGroup >( + Track::Pointer( leader ), mPanel.GetLeftOffset() ) + ); + yy += height; + } + + refinement.emplace_back( std::max( 0, yy ), mPanel.GetBackgroundCell() ); + + return { Axis::Y, std::move( refinement ) }; + } + TrackPanel &mPanel; +}; + +// Main group shaves off the left and right margins +struct MainGroup final : TrackPanelGroup { + explicit MainGroup( TrackPanel &panel ) : mPanel{ panel } {} + Subdivision Children( const wxRect &rect ) override + { return { Axis::X, Refinement{ + { 0, EmptyCell::Instance() }, + { kLeftMargin, std::make_shared< Subgroup >( mPanel ) }, + { rect.GetRight() + 1 - kRightMargin, EmptyCell::Instance() } + } }; } + TrackPanel &mPanel; +}; + +} + std::shared_ptr TrackPanel::Root() { - return {}; + // Root and other subgroup objects are throwaways. + // They might instead be cached to avoid repeated allocation. + // That cache would need invalidation when there is addition, deletion, or + // permutation of tracks, or change of width of the vertical rulers. + return std::make_shared< MainGroup >( *this ); } /// Determines which cell is under the mouse diff --git a/src/TrackPanel.h b/src/TrackPanel.h index e1bc38b4b..1d7bce695 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -518,6 +518,7 @@ enum : int { kBottomMargin = kShadowThickness + kBorderThickness, kLeftMargin = kLeftInset + kBorderThickness, kRightMargin = kRightInset + kShadowThickness + kBorderThickness, + kSeparatorThickness = kBottomMargin + kTopMargin, }; enum : int { From cfa7afcb2489dcf30b7070988000daf77a322fe0 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 17 Sep 2018 12:57:18 -0400 Subject: [PATCH 6/9] nonvirtual reimplementation of CellularPanel::FindCell using nodes --- src/AdornedRulerPanel.cpp | 13 ------------- src/AdornedRulerPanel.h | 1 - src/CellularPanel.cpp | 40 ++++++++++++++++++++++++++++++++++++++- src/CellularPanel.h | 15 ++++++++------- src/TrackPanel.cpp | 27 +++----------------------- src/TrackPanel.h | 3 --- 6 files changed, 50 insertions(+), 49 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index cd6f0eb63..f3f5aa31a 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -2141,19 +2141,6 @@ std::shared_ptr AdornedRulerPanel::Root() return std::make_shared< MainGroup >( *this ); } -auto AdornedRulerPanel::FindCell(int mouseX, int mouseY) -> FoundCell -{ - bool mayScrub = mProject->GetScrubber().CanScrub() && - mShowScrubbing; - if (mayScrub && mScrubZone.Contains(mouseX, mouseY)) - return { mScrubbingCell, mScrubZone }; - - if (mInner.Contains(mouseX, mouseY)) - return { mQPCell, mInner }; - - return {}; -} - wxRect AdornedRulerPanel::FindRect(const TrackPanelCell &cell) { if (&cell == mScrubbingCell.get()) diff --git a/src/AdornedRulerPanel.h b/src/AdornedRulerPanel.h index 9c4c81bff..057035a38 100644 --- a/src/AdornedRulerPanel.h +++ b/src/AdornedRulerPanel.h @@ -177,7 +177,6 @@ private: // area into cells std::shared_ptr Root() override; - FoundCell FindCell(int mouseX, int mouseY) override; wxRect FindRect(const TrackPanelCell &cell) override; public: AudacityProject * GetProject() const override; diff --git a/src/CellularPanel.cpp b/src/CellularPanel.cpp index 3614dc021..c569a2699 100644 --- a/src/CellularPanel.cpp +++ b/src/CellularPanel.cpp @@ -937,7 +937,6 @@ namespace { const auto end = children.end(); const auto nextCoord = ((next == end) ? upperBound : next->first - 1); - // Some defense against bad overrides of TrackPanelGroup::Children auto lesser = std::max(lowerBound, std::min(upperBound, iter->first)); auto greater = std::max(lesser, std::min(upperBound, nextCoord)); @@ -976,6 +975,45 @@ void CellularPanel::Visit( return; } +auto CellularPanel::FindCell(int mouseX, int mouseY) -> FoundCell +{ + auto rect = this->GetClientRect(); + auto node = Root(); + while (node) { + if ( auto pCell = std::dynamic_pointer_cast< TrackPanelCell >( node ) ) + // Found the bottom of the hierarchy + return { pCell, rect }; + else if ( auto pGroup = dynamic_cast< TrackPanelGroup* >( node.get() ) ) { + // Ask node for its subdivision + const auto results = pGroup->Children( rect ); + const bool divideX = results.first == TrackPanelGroup::Axis::X; + const auto &children = results.second; + + // Find the correct child + const auto begin = children.begin(), end = children.end(); + auto iter = std::upper_bound( begin, end, + (divideX ? mouseX : mouseY), + [&]( wxCoord coord, const TrackPanelGroup::Child &child ) { + return coord < child.first; + } + ); + if (iter == begin) + break; + --iter; + + // Descend the hierarchy of nodes + rect = Subdivide(rect, divideX, children, iter); + node = iter->second; + } + else + // Nulls in the array of children are allowed, to define a void with + // no cell + break; + } + + return { {}, {} }; +} + UIHandlePtr CellularPanel::Target() { auto &state = *mState; diff --git a/src/CellularPanel.h b/src/CellularPanel.h index f5c7595dc..90bc2e629 100644 --- a/src/CellularPanel.h +++ b/src/CellularPanel.h @@ -44,17 +44,10 @@ public: virtual AudacityProject *GetProject() const = 0; - // Find track info by coordinate - struct FoundCell { - std::shared_ptr pCell; - wxRect rect; - }; - // Get the root object defining a recursive subdivision of the panel's // area into cells virtual std::shared_ptr Root() = 0; - virtual FoundCell FindCell(int mouseX, int mouseY) = 0; virtual wxRect FindRect(const TrackPanelCell &cell) = 0; // Structure and functions for generalized visitation of the subdivision @@ -93,6 +86,14 @@ public: virtual bool TakesFocus() const = 0; public: + // Find cell by coordinate + struct FoundCell { + std::shared_ptr< TrackPanelCell > pCell; + wxRect rect; + }; + + FoundCell FindCell(int mouseX, int mouseY); + UIHandlePtr Target(); std::shared_ptr LastCell() const; diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index dfb43eb8e..bb1d22b5e 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -126,13 +126,13 @@ time, but that width may be adjusted when tracks change their vertical scales. GetLabelWidth() counts columns up to and including the VRuler. GetLeftOffset() is yet one more -- it counts the "one pixel" column. -FindCell() for label returns a rectangle that OMITS left, top, and bottom +Cell for label has a rectangle that OMITS left, top, and bottom margins -FindCell() for vruler returns a rectangle right of the label, +Cell for vruler has a rectangle right of the label, up to and including the One Pixel column, and OMITS top and bottom margins -FindCell() for track returns a rectangle with x == GetLeftOffset(), and OMITS +Cell() for track returns a rectangle with x == GetLeftOffset(), and OMITS right, top, and bottom margins +--------------- ... ------ ... --------------------- ... ... -------------+ @@ -2088,27 +2088,6 @@ std::shared_ptr TrackPanel::Root() return std::make_shared< MainGroup >( *this ); } -/// Determines which cell is under the mouse -/// @param mouseX - mouse X position. -/// @param mouseY - mouse Y position. -auto TrackPanel::FindCell(int mouseX, int mouseY) -> FoundCell -{ - auto range = Cells(); - auto &iter = range.first, &end = range.second; - while - ( iter != end && - !(*iter).second.Contains( mouseX, mouseY ) ) - ++iter; - if (iter == end) - return {}; - - auto found = *iter; - return { - found.first, - found.second - }; -} - wxRect TrackPanel::FindRect( const TrackPanelCell &cell ) { auto range = Cells(); diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 1d7bce695..25a720aa9 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -341,9 +341,6 @@ protected: // area into cells std::shared_ptr Root() override; - // Find track info by coordinate - FoundCell FindCell(int mouseX, int mouseY) override; - // Find rectangle of the given cell wxRect FindRect(const TrackPanelCell &cell) override; From 01551913f0fbd85b1ca46618b22d061ab2a8acfa Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Mon, 17 Sep 2018 18:28:39 -0400 Subject: [PATCH 7/9] nonvirtual reimplementation of CellularPanel::FindRect using nodes --- src/AdornedRulerPanel.cpp | 11 ----------- src/AdornedRulerPanel.h | 2 -- src/CellularPanel.cpp | 14 ++++++++++++++ src/CellularPanel.h | 7 +++++-- src/TrackPanel.cpp | 14 -------------- src/TrackPanel.h | 3 --- 6 files changed, 19 insertions(+), 32 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index f3f5aa31a..f540ca304 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -2141,17 +2141,6 @@ std::shared_ptr AdornedRulerPanel::Root() return std::make_shared< MainGroup >( *this ); } -wxRect AdornedRulerPanel::FindRect(const TrackPanelCell &cell) -{ - if (&cell == mScrubbingCell.get()) - return mScrubZone; - if (&cell == mQPCell.get()) - return mInner; - - return {}; -} - - AudacityProject * AdornedRulerPanel::GetProject() const { return mProject; diff --git a/src/AdornedRulerPanel.h b/src/AdornedRulerPanel.h index 057035a38..2f3966563 100644 --- a/src/AdornedRulerPanel.h +++ b/src/AdornedRulerPanel.h @@ -176,8 +176,6 @@ private: // Get the root object defining a recursive subdivision of the panel's // area into cells std::shared_ptr Root() override; - - wxRect FindRect(const TrackPanelCell &cell) override; public: AudacityProject * GetProject() const override; private: diff --git a/src/CellularPanel.cpp b/src/CellularPanel.cpp index c569a2699..96f11594e 100644 --- a/src/CellularPanel.cpp +++ b/src/CellularPanel.cpp @@ -1014,6 +1014,20 @@ auto CellularPanel::FindCell(int mouseX, int mouseY) -> FoundCell return { {}, {} }; } +wxRect CellularPanel::FindRect( const TrackPanelCell &cell ) +{ + wxRect result; + + struct Stop{}; + try { VisitCells( [&]( const wxRect &rect, TrackPanelCell &visited ) { + if ( &visited == &cell ) + result = rect, throw Stop{}; + } ); } + catch ( const Stop& ) {} + + return result; +} + UIHandlePtr CellularPanel::Target() { auto &state = *mState; diff --git a/src/CellularPanel.h b/src/CellularPanel.h index 90bc2e629..f57cd6acd 100644 --- a/src/CellularPanel.h +++ b/src/CellularPanel.h @@ -48,8 +48,6 @@ public: // area into cells virtual std::shared_ptr Root() = 0; - virtual wxRect FindRect(const TrackPanelCell &cell) = 0; - // Structure and functions for generalized visitation of the subdivision struct Visitor { virtual ~Visitor(); @@ -94,6 +92,11 @@ public: FoundCell FindCell(int mouseX, int mouseY); + // Search the tree of subdivisions of the panel area for the given cell. + // If more than one sub-area is associated with the same cell object, it + // is not specified which rectangle is returned. + wxRect FindRect(const TrackPanelCell &cell); + UIHandlePtr Target(); std::shared_ptr LastCell() const; diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index bb1d22b5e..47f4bc7b0 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -2088,20 +2088,6 @@ std::shared_ptr TrackPanel::Root() return std::make_shared< MainGroup >( *this ); } -wxRect TrackPanel::FindRect( const TrackPanelCell &cell ) -{ - auto range = Cells(); - auto end = range.second, - iter = std::find_if( range.first, end, - [&]( const decltype(*end) &pair ) - { return pair.first.get() == &cell; } - ); - if (iter == end) - return {}; - else - return (*iter).second; -} - // This finds the rectangle of a given track (including all channels), // either that of the label 'adornment' or the track itself // The given track is assumed to be the first channel diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 25a720aa9..31c10b213 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -341,9 +341,6 @@ protected: // area into cells std::shared_ptr Root() override; - // Find rectangle of the given cell - wxRect FindRect(const TrackPanelCell &cell) override; - int GetVRulerWidth() const; int GetVRulerOffset() const { return mTrackInfo.GetTrackInfoWidth(); } From 005abb06d6fbc77d2f1c0e088cff78c3bd2fba79 Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 1 Nov 2018 12:55:06 -0400 Subject: [PATCH 8/9] Replace uses of TrackPanel::Cells() with CellularPanel::VisitCells() --- src/AdornedRulerPanel.cpp | 26 ++++++++++++-------------- src/TrackPanelResizeHandle.h | 1 - src/TrackPanelResizerCell.h | 1 - src/tracks/ui/EditCursorOverlay.cpp | 12 ++++-------- src/tracks/ui/PlayIndicatorOverlay.cpp | 10 +++------- 5 files changed, 19 insertions(+), 31 deletions(-) diff --git a/src/AdornedRulerPanel.cpp b/src/AdornedRulerPanel.cpp index f540ca304..b8a71ae71 100644 --- a/src/AdornedRulerPanel.cpp +++ b/src/AdornedRulerPanel.cpp @@ -33,7 +33,6 @@ #include "RefreshCode.h" #include "Snap.h" #include "TrackPanel.h" -#include "TrackPanelCellIterator.h" #include "TrackPanelMouseEvent.h" #include "UIHandle.h" #include "prefs/TracksBehaviorsPrefs.h" @@ -328,20 +327,19 @@ void AdornedRulerPanel::QuickPlayIndicatorOverlay::Draw( ; // Draw indicator in all visible tracks - for ( const auto &data : static_cast(panel).Cells() ) - { - Track *const pTrack = dynamic_cast(data.first.get()); - if (!pTrack) - continue; - const wxRect &rect = data.second; + static_cast(panel) + .VisitCells( [&]( const wxRect &rect, TrackPanelCell &cell ) { + const auto pTrack = dynamic_cast(&cell); + if (!pTrack) + return; - // Draw the NEW indicator in its NEW location - AColor::Line(dc, - mOldQPIndicatorPos, - rect.GetTop(), - mOldQPIndicatorPos, - rect.GetBottom()); - } + // Draw the NEW indicator in its NEW location + AColor::Line(dc, + mOldQPIndicatorPos, + rect.GetTop(), + mOldQPIndicatorPos, + rect.GetBottom()); + } ); } } diff --git a/src/TrackPanelResizeHandle.h b/src/TrackPanelResizeHandle.h index 47ffc8022..18df6319b 100644 --- a/src/TrackPanelResizeHandle.h +++ b/src/TrackPanelResizeHandle.h @@ -15,7 +15,6 @@ Paul Licameli split from TrackPanel.cpp #include "UIHandle.h" class Track; -class TrackPanelCellIterator; class TrackPanelResizeHandle final : public UIHandle { diff --git a/src/TrackPanelResizerCell.h b/src/TrackPanelResizerCell.h index d32573dc7..3c2a191aa 100644 --- a/src/TrackPanelResizerCell.h +++ b/src/TrackPanelResizerCell.h @@ -29,7 +29,6 @@ public: std::shared_ptr FindTrack() override { return mpTrack.lock(); }; private: - friend class TrackPanelCellIterator; std::weak_ptr mpTrack; std::weak_ptr mResizeHandle; diff --git a/src/tracks/ui/EditCursorOverlay.cpp b/src/tracks/ui/EditCursorOverlay.cpp index bd906b3de..577de1d38 100644 --- a/src/tracks/ui/EditCursorOverlay.cpp +++ b/src/tracks/ui/EditCursorOverlay.cpp @@ -15,8 +15,6 @@ Paul Licameli split from TrackPanel.cpp #include "../../AColor.h" #include "../../AdornedRulerPanel.h" #include "../../Project.h" -#include "../../TrackPanelCell.h" -#include "../../TrackPanelCellIterator.h" #include "../../TrackPanelAx.h" #include "../../ViewInfo.h" @@ -100,21 +98,19 @@ void EditCursorOverlay::Draw(OverlayPanel &panel, wxDC &dc) AColor::CursorColor(&dc); // Draw cursor in all selected tracks - for ( const auto &data : tp->Cells() ) - { - Track *const pTrack = dynamic_cast(data.first.get()); + tp->VisitCells( [&]( const wxRect &rect, TrackPanelCell &cell ) { + const auto pTrack = dynamic_cast(&cell); if (!pTrack) - continue; + return; if (pTrack->GetSelected() || mProject->GetTrackPanel()->GetAx().IsFocused(pTrack)) { - const wxRect &rect = data.second; // AColor::Line includes both endpoints so use GetBottom() AColor::Line(dc, mLastCursorX, rect.GetTop(), mLastCursorX, rect.GetBottom()); // ^^^ The whole point of this routine. } - } + } ); } else if (auto ruler = dynamic_cast(&panel)) { wxASSERT(!mIsMaster); diff --git a/src/tracks/ui/PlayIndicatorOverlay.cpp b/src/tracks/ui/PlayIndicatorOverlay.cpp index 5cc0aee8b..562f10afe 100644 --- a/src/tracks/ui/PlayIndicatorOverlay.cpp +++ b/src/tracks/ui/PlayIndicatorOverlay.cpp @@ -16,8 +16,6 @@ Paul Licameli split from TrackPanel.cpp #include "../../AudioIO.h" #include "../../Project.h" #include "../../TrackPanel.h" -#include "../../TrackPanelCell.h" -#include "../../TrackPanelCellIterator.h" #include "Scrubbing.h" #include @@ -82,9 +80,8 @@ void PlayIndicatorOverlayBase::Draw(OverlayPanel &panel, wxDC &dc) wxASSERT(mIsMaster); // Draw indicator in all visible tracks - for ( const auto &data : tp->Cells() ) - { - Track *const pTrack = dynamic_cast(data.first.get()); + tp->VisitCells( [&]( const wxRect &rect, TrackPanelCell &cell ) { + const auto pTrack = dynamic_cast(&cell); if (pTrack) pTrack->TypeSwitch( [](LabelTrack *) { // Don't draw the indicator in label tracks @@ -92,7 +89,6 @@ void PlayIndicatorOverlayBase::Draw(OverlayPanel &panel, wxDC &dc) [&](Track *) { // Draw the NEW indicator in its NEW location // AColor::Line includes both endpoints so use GetBottom() - const wxRect &rect = data.second; AColor::Line(dc, mLastIndicatorX, rect.GetTop(), @@ -100,7 +96,7 @@ void PlayIndicatorOverlayBase::Draw(OverlayPanel &panel, wxDC &dc) rect.GetBottom()); } ); - } + } ); } else if(auto ruler = dynamic_cast(&panel)) { wxASSERT(!mIsMaster); From 39fc20c5ee956e91998893f600e1aa6951a7dd1d Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 1 Nov 2018 13:10:01 -0400 Subject: [PATCH 9/9] TrackPanelCellIterator is no longer needed --- locale/POTFILES.in | 1 - mac/Audacity.xcodeproj/project.pbxproj | 2 - src/Makefile.am | 1 - src/Makefile.in | 24 +-- src/TrackPanel.cpp | 159 ------------------ src/TrackPanel.h | 3 - src/TrackPanelCellIterator.h | 76 --------- win/Projects/Audacity/Audacity.vcxproj | 1 - .../Audacity/Audacity.vcxproj.filters | 3 - 9 files changed, 12 insertions(+), 258 deletions(-) delete mode 100644 src/TrackPanelCellIterator.h diff --git a/locale/POTFILES.in b/locale/POTFILES.in index fa6a3ccf9..c44e93e0e 100644 --- a/locale/POTFILES.in +++ b/locale/POTFILES.in @@ -205,7 +205,6 @@ src/TrackPanel.h src/TrackPanelAx.cpp src/TrackPanelAx.h src/TrackPanelCell.h -src/TrackPanelCellIterator.h src/TrackPanelDrawingContext.h src/TrackPanelListener.h src/TrackPanelMouseEvent.h diff --git a/mac/Audacity.xcodeproj/project.pbxproj b/mac/Audacity.xcodeproj/project.pbxproj index e178445a1..37f4fe69a 100644 --- a/mac/Audacity.xcodeproj/project.pbxproj +++ b/mac/Audacity.xcodeproj/project.pbxproj @@ -3167,7 +3167,6 @@ 5E73966F1DAFDB9D00BA0A4D /* SelectHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SelectHandle.cpp; sourceTree = ""; }; 5E7396701DAFDB9D00BA0A4D /* SelectHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectHandle.h; sourceTree = ""; }; 5E74D2D91CC4427B00D88B0B /* TrackPanelCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPanelCell.h; sourceTree = ""; }; - 5E74D2DA1CC4427B00D88B0B /* TrackPanelCellIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrackPanelCellIterator.h; sourceTree = ""; }; 5E74D2DD1CC4429700D88B0B /* EditCursorOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EditCursorOverlay.cpp; sourceTree = ""; }; 5E74D2DE1CC4429700D88B0B /* EditCursorOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditCursorOverlay.h; sourceTree = ""; }; 5E74D2DF1CC4429700D88B0B /* PlayIndicatorOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PlayIndicatorOverlay.cpp; sourceTree = ""; }; @@ -4273,7 +4272,6 @@ 1790B0ED09883BFD008A330A /* TrackPanel.h */, 1790B0EF09883BFD008A330A /* TrackPanelAx.h */, 5E74D2D91CC4427B00D88B0B /* TrackPanelCell.h */, - 5E74D2DA1CC4427B00D88B0B /* TrackPanelCellIterator.h */, 5E52335F1EFDD57D001E4BB8 /* TrackPanelDrawingContext.h */, 2803C8B619F35AA000278526 /* TrackPanelListener.h */, 5E15123A1DB000C000702E29 /* TrackPanelMouseEvent.h */, diff --git a/src/Makefile.am b/src/Makefile.am index cc4157ab0..75c7691b7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -251,7 +251,6 @@ audacity_SOURCES = \ TrackPanelAx.cpp \ TrackPanelAx.h \ TrackPanelCell.h \ - TrackPanelCellIterator.h \ TrackPanelDrawingContext.h \ TrackPanelListener.h \ TrackPanelMouseEvent.h \ diff --git a/src/Makefile.in b/src/Makefile.in index 8b0ed7867..4f9152165 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -330,12 +330,12 @@ am__audacity_SOURCES_DIST = BlockFile.cpp BlockFile.h DirManager.cpp \ TimerRecordDialog.cpp TimerRecordDialog.h TimeTrack.cpp \ TimeTrack.h Track.cpp Track.h TrackArtist.cpp TrackArtist.h \ TrackPanel.cpp TrackPanel.h TrackPanelAx.cpp TrackPanelAx.h \ - TrackPanelCell.h TrackPanelCellIterator.h \ - TrackPanelDrawingContext.h TrackPanelListener.h \ - TrackPanelMouseEvent.h TrackPanelResizeHandle.cpp \ - TrackPanelResizeHandle.h TrackPanelResizerCell.cpp \ - TrackPanelResizerCell.h TranslatableStringArray.h UIHandle.h \ - UIHandle.cpp UndoManager.cpp UndoManager.h UserException.cpp \ + TrackPanelCell.h TrackPanelDrawingContext.h \ + TrackPanelListener.h TrackPanelMouseEvent.h \ + TrackPanelResizeHandle.cpp TrackPanelResizeHandle.h \ + TrackPanelResizerCell.cpp TrackPanelResizerCell.h \ + TranslatableStringArray.h UIHandle.h UIHandle.cpp \ + UndoManager.cpp UndoManager.h UserException.cpp \ UserException.h ViewInfo.cpp ViewInfo.h VoiceKey.cpp \ VoiceKey.h WaveClip.cpp WaveClip.h WaveTrack.cpp WaveTrack.h \ WaveTrackLocation.h WrappedType.cpp WrappedType.h \ @@ -1378,12 +1378,12 @@ audacity_SOURCES = $(libaudacity_la_SOURCES) AboutDialog.cpp \ TimerRecordDialog.cpp TimerRecordDialog.h TimeTrack.cpp \ TimeTrack.h Track.cpp Track.h TrackArtist.cpp TrackArtist.h \ TrackPanel.cpp TrackPanel.h TrackPanelAx.cpp TrackPanelAx.h \ - TrackPanelCell.h TrackPanelCellIterator.h \ - TrackPanelDrawingContext.h TrackPanelListener.h \ - TrackPanelMouseEvent.h TrackPanelResizeHandle.cpp \ - TrackPanelResizeHandle.h TrackPanelResizerCell.cpp \ - TrackPanelResizerCell.h TranslatableStringArray.h UIHandle.h \ - UIHandle.cpp UndoManager.cpp UndoManager.h UserException.cpp \ + TrackPanelCell.h TrackPanelDrawingContext.h \ + TrackPanelListener.h TrackPanelMouseEvent.h \ + TrackPanelResizeHandle.cpp TrackPanelResizeHandle.h \ + TrackPanelResizerCell.cpp TrackPanelResizerCell.h \ + TranslatableStringArray.h UIHandle.h UIHandle.cpp \ + UndoManager.cpp UndoManager.h UserException.cpp \ UserException.h ViewInfo.cpp ViewInfo.h VoiceKey.cpp \ VoiceKey.h WaveClip.cpp WaveClip.h WaveTrack.cpp WaveTrack.h \ WaveTrackLocation.h WrappedType.cpp WrappedType.h \ diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 47f4bc7b0..81e35105c 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -71,7 +71,6 @@ is time to refresh some aspect of the screen. #include "Experimental.h" #include "TrackPanel.h" #include "Project.h" -#include "TrackPanelCellIterator.h" #include "TrackPanelMouseEvent.h" #include "TrackPanelResizeHandle.h" //#define DEBUG_DRAW_TIMING 1 @@ -2634,164 +2633,6 @@ void TrackInfo::UpdatePrefs() } while (textWidth >= allowableWidth); } -IteratorRange< TrackPanelCellIterator > TrackPanel::Cells() -{ - return { - TrackPanelCellIterator( this, true ), - TrackPanelCellIterator( this, false ) - }; -} - -TrackPanelCellIterator::TrackPanelCellIterator(TrackPanel *trackPanel, bool begin) - : mPanel{ trackPanel } - , mIter{ - trackPanel->GetTracks()->Any().begin() - .Filter( IsVisibleTrack( trackPanel->GetProject() ) ) - } -{ - if (begin) { - mpTrack = Track::Pointer( *mIter ); - if (mpTrack) - mpCell = mpTrack; - else - mpCell = trackPanel->GetBackgroundCell(); - } - else - mDidBackground = true; - - const auto size = mPanel->GetSize(); - mRect = { 0, 0, size.x, size.y }; - UpdateRect(); -} - -TrackPanelCellIterator &TrackPanelCellIterator::operator++ () -{ - if ( mpTrack ) { - if ( ++ mType == CellType::Background ) - mType = CellType::Track, mpTrack = Track::Pointer( * ++ mIter ); - } - if ( mpTrack ) { - if ( mType == CellType::Label && - !mpTrack->IsLeader() ) - // Visit label of stereo track only once - ++mType; - switch ( mType ) { - case CellType::Track: - mpCell = mpTrack; - break; - case CellType::Label: - mpCell = mpTrack->GetTrackControl(); - break; - case CellType::VRuler: - mpCell = mpTrack->GetVRulerControl(); - break; - case CellType::Resizer: { - mpCell = mpTrack->GetResizer(); - break; - } - default: - // should not happen - mpCell.reset(); - break; - } - } - else if ( !mDidBackground ) - mpCell = mPanel->GetBackgroundCell(), mDidBackground = true; - else - mpCell.reset(); - - UpdateRect(); - - return *this; -} - -TrackPanelCellIterator TrackPanelCellIterator::operator++ (int) -{ - TrackPanelCellIterator copy(*this); - ++ *this; - return copy; -} - -auto TrackPanelCellIterator::operator* () const -> value_type -{ - return { mpCell, mRect }; -} - -void TrackPanelCellIterator::UpdateRect() -{ - const auto size = mPanel->GetSize(); - if ( mpTrack ) { - mRect = { - 0, - mpTrack->GetY() - mPanel->GetViewInfo()->vpos, - size.x, - mpTrack->GetHeight() - }; - switch ( mType ) { - case CellType::Track: - mRect.x = mPanel->GetLeftOffset(); - mRect.width -= (mRect.x + kRightMargin); - mRect.y += kTopMargin; - mRect.height -= (kBottomMargin + kTopMargin); - break; - case CellType::Label: { - mRect.x = kLeftMargin; - mRect.width = kTrackInfoWidth - mRect.x; - mRect.y += kTopMargin; - mRect.height = - TrackList::Channels(mpTrack.get()) - .sum( &Track::GetHeight ); - mRect.height -= (kBottomMargin + kTopMargin); - break; - } - case CellType::VRuler: - { - mRect.x = kTrackInfoWidth; - // Right edge of the VRuler is inactive. - mRect.width = mPanel->GetLeftOffset() - mRect.x; - mRect.y += kTopMargin; - mRect.height -= (kBottomMargin + kTopMargin); - } - break; - case CellType::Resizer: { - // The resizer region encompasses the bottom margin proper to this - // track, plus the top margin of the next track (or, an equally - // tall zone below, in case there is no next track) - if ( mpTrack.get() == - *TrackList::Channels(mpTrack.get()).rbegin() ) - // Last channel has a resizer extending farther leftward - mRect.x = kLeftMargin; - else - mRect.x = kTrackInfoWidth; - mRect.width -= (mRect.x + kRightMargin); - mRect.y += (mRect.height - kBottomMargin); - mRect.height = (kBottomMargin + kTopMargin); - break; - } - default: - // should not happen - break; - } - } - else if ( mpCell ) { - // Find a disjoint, maybe empty, rectangle - // for the empty space appearing at bottom - - mRect.x = kLeftMargin; - mRect.width = size.x - (mRect.x + kRightMargin); - - // Use previous value of the bottom, either the whole area if - // there were no tracks, or else the resizer of the last track - mRect.y = - std::min( size.y, - std::max( 0, - mRect.y + mRect.height ) ); - mRect.height = size.y - mRect.y; - } - else - mRect = {}; -} - static TrackPanel * TrackPanelFactory(wxWindow * parent, wxWindowID id, const wxPoint & pos, diff --git a/src/TrackPanel.h b/src/TrackPanel.h index 31c10b213..552757b48 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -44,7 +44,6 @@ class ControlToolBar; //Needed because state of controls can affect what gets dr class ToolsToolBar; //Needed because state of controls can affect what gets drawn. class TrackPanelAx; -class TrackPanelCellIterator; class NoteTrack; class WaveTrack; @@ -248,8 +247,6 @@ class AUDACITY_DLL_API TrackPanel final : public CellularPanel { virtual ~ TrackPanel(); - IteratorRange< TrackPanelCellIterator > Cells(); - void UpdatePrefs(); void ApplyUpdatedTheme(); diff --git a/src/TrackPanelCellIterator.h b/src/TrackPanelCellIterator.h deleted file mode 100644 index e565be8ec..000000000 --- a/src/TrackPanelCellIterator.h +++ /dev/null @@ -1,76 +0,0 @@ -/********************************************************************** - -Audacity: A Digital Audio Editor - -TrackPanelCellIterator.h - -Paul Licameli - -**********************************************************************/ - -#ifndef __AUDACITY_TRACK_PANEL_CELL_ITERATOR__ -#define __AUDACITY_TRACK_PANEL_CELL_ITERATOR__ - -#include "Track.h" -#include -#include -#include "MemoryX.h" - -class Track; -class TrackPanelCell; - -class TrackPanel; - -// A class that allows iteration over the rectangles of visible cells. -class TrackPanelCellIterator - : public std::iterator< - std::forward_iterator_tag, - const std::pair< std::shared_ptr< TrackPanelCell >, wxRect> - > -{ -public: - enum class CellType { - Track, Label, VRuler, Resizer, Background - }; - - TrackPanelCellIterator(TrackPanel *trackPanel, bool begin); - - // implement the STL iterator idiom - - TrackPanelCellIterator &operator++ (); - TrackPanelCellIterator operator++ (int); - - friend inline bool operator== - (const TrackPanelCellIterator &lhs, const TrackPanelCellIterator &rhs) - { - return lhs.mpCell == rhs.mpCell && - lhs.mDidBackground == rhs.mDidBackground; - } - - value_type operator * () const; - -private: - void UpdateRect(); - - TrackPanel *mPanel; - TrackIter mIter; - std::shared_ptr mpTrack; - std::shared_ptr mpCell; - CellType mType{ CellType::Track }; - bool mDidBackground{ false }; - wxRect mRect; -}; - -inline TrackPanelCellIterator::CellType &operator++ -( TrackPanelCellIterator::CellType &type ) -{ - type = TrackPanelCellIterator::CellType( 1 + int( type ) ); - return type; -} - -inline bool operator != -(const TrackPanelCellIterator &lhs, const TrackPanelCellIterator &rhs) -{ - return !(lhs == rhs); -} -#endif diff --git a/win/Projects/Audacity/Audacity.vcxproj b/win/Projects/Audacity/Audacity.vcxproj index 273f51f43..7f0f42638 100755 --- a/win/Projects/Audacity/Audacity.vcxproj +++ b/win/Projects/Audacity/Audacity.vcxproj @@ -545,7 +545,6 @@ - diff --git a/win/Projects/Audacity/Audacity.vcxproj.filters b/win/Projects/Audacity/Audacity.vcxproj.filters index d40de0f33..1da718369 100755 --- a/win/Projects/Audacity/Audacity.vcxproj.filters +++ b/win/Projects/Audacity/Audacity.vcxproj.filters @@ -1978,9 +1978,6 @@ src\tracks\ui - - src - src\commands