1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-08-02 17:09:26 +02:00

Bug2256: Resizing channels should not change subview proportions

This commit is contained in:
Paul Licameli 2019-12-30 16:16:21 -05:00
parent f39f505205
commit 17ed4899ec
2 changed files with 47 additions and 35 deletions

View File

@ -204,16 +204,18 @@ public:
if ( index < adjuster.mPermutation.size() ) if ( index < adjuster.mPermutation.size() )
return std::make_shared< SubViewAdjustHandle >( return std::make_shared< SubViewAdjustHandle >(
std::move( adjuster ), index, hit.second std::move( adjuster ), index, view.GetLastHeight(), hit.second
); );
else else
return {}; return {};
} }
SubViewAdjustHandle( SubViewAdjustHandle(
SubViewAdjuster &&adjuster, size_t subViewIndex, bool top ) SubViewAdjuster &&adjuster, size_t subViewIndex,
wxCoord viewHeight, bool top )
: mAdjuster{ std::move( adjuster ) } : mAdjuster{ std::move( adjuster ) }
, mMySubView{ subViewIndex } , mMySubView{ subViewIndex }
, mViewHeight{ viewHeight }
, mTop{ top } , mTop{ top }
{ {
if ( mAdjuster.ModifyPermutation( top ) ) if ( mAdjuster.ModifyPermutation( top ) )
@ -233,22 +235,33 @@ public:
const auto height = rect.GetHeight(); const auto height = rect.GetHeight();
mOrigHeight = height; mOrigHeight = height;
wxASSERT( height == // Compute integer-valued heights
mAdjuster.mOrigPlacements[ mAdjuster.mPermutation[ mMySubView ] ] {
.fraction float total = 0;
); for (const auto index : mAdjuster.mPermutation ) {
const auto &placement = mAdjuster.mOrigPlacements[ index ];
// Find the total height of the sub-views that may resize total += std::max( 0.f, placement.fraction );
// Note that this depends on the redenomination of fractions that }
// happened in the last call to GetSubViews float partial = 0;
mTotalHeight = 0; wxCoord lastCoord = 0;
const auto begin = permutation.begin(); for (const auto index : mAdjuster.mPermutation ) {
auto iter = begin + ( mTop ? mAdjuster.mFirstSubView : mMySubView ); const auto &placement = mAdjuster.mOrigPlacements[ index ];
const auto end = ( mTop ? begin + mMySubView + 1 : permutation.end() ); auto fraction = std::max( 0.f, placement.fraction );
for (; iter != end; ++iter) { wxCoord coord = ( (partial + fraction ) / total ) * mViewHeight;
const auto &placement = mAdjuster.mOrigPlacements[ *iter ]; mOrigHeights.emplace_back( coord - lastCoord );
mTotalHeight += placement.fraction; lastCoord = coord;
partial += fraction;
}
} }
// Find the total height of the sub-views that may resize
mTotalHeight = 0;
auto index = ( mTop ? mAdjuster.mFirstSubView : mMySubView );
const auto end = ( mTop ? mMySubView + 1 : permutation.size() );
for (; index != end; ++index)
mTotalHeight += mOrigHeights[ index ];
wxASSERT( height == mOrigHeights[ mMySubView ] );
// Compute the maximum and minimum Y coordinates for drag effect // Compute the maximum and minimum Y coordinates for drag effect
if ( mTop ) { if ( mTop ) {
@ -295,11 +308,9 @@ public:
if (excess == 0) if (excess == 0)
return true; return true;
const auto oldFraction = mOrigHeights[ ii ];
auto index = mAdjuster.mPermutation[ ii ]; auto index = mAdjuster.mPermutation[ ii ];
const auto &origPlacement = mAdjuster.mOrigPlacements[ index ];
const auto oldFraction = origPlacement.fraction;
auto &placement = mAdjuster.mNewPlacements[ index ]; auto &placement = mAdjuster.mNewPlacements[ index ];
auto &fraction = placement.fraction; auto &fraction = placement.fraction;
@ -368,12 +379,14 @@ public:
private: private:
SubViewAdjuster mAdjuster; SubViewAdjuster mAdjuster;
std::vector<wxCoord> mOrigHeights;
// An index into mAdjuster.mPermutation // An index into mAdjuster.mPermutation
size_t mMySubView{}; size_t mMySubView{};
wxCoord mYMin{}, mYMax{}; wxCoord mYMin{}, mYMax{};
wxCoord mTotalHeight{}; wxCoord mViewHeight{}; // Total height of all sub-views
wxCoord mTotalHeight{}; // Total height of adjusting sub-views only
wxCoord mOrigHeight{}; wxCoord mOrigHeight{};
wxCoord mOrigY{}; wxCoord mOrigY{};
@ -531,17 +544,17 @@ auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement
Refinement results; Refinement results;
// Collect the visible views in the right sequence // Collect the visible views in the right sequence
using Pair = std::pair< float*, std::shared_ptr< TrackView > >; using Pair = std::pair< float, std::shared_ptr< TrackView > >;
std::vector< Pair > pairs( mPlacements.size() ); std::vector< Pair > pairs( mPlacements.size() );
size_t ii = 0; size_t ii = 0;
float total = 0; float total = 0;
WaveTrackSubViews::ForEach( [&]( WaveTrackSubView &subView ){ WaveTrackSubViews::ForEach( [&]( WaveTrackSubView &subView ){
auto &placement = mPlacements[ii]; auto &placement = mPlacements[ii];
auto index = placement.index; auto index = placement.index;
auto &fraction = placement.fraction; auto fraction = placement.fraction;
if ( index >= 0 && fraction > 0.0 ) if ( index >= 0 && fraction > 0.0 )
total += fraction, total += fraction,
pairs[ index ] = { &fraction, subView.shared_from_this() }; pairs[ index ] = { fraction, subView.shared_from_this() };
++ii; ++ii;
} ); } );
@ -552,25 +565,20 @@ auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement
pairs.erase( newEnd, end ); pairs.erase( newEnd, end );
results.reserve( pairs.size() ); results.reserve( pairs.size() );
// Assign coordinates // Assign coordinates, redenominating to the total height,
// Also update the stored placements, redenominating to the total height,
// storing integer values // storing integer values
const auto top = rect.GetTop(); const auto top = rect.GetTop();
const auto height = rect.GetHeight(); const auto height = rect.GetHeight();
float partial = 0; float partial = 0;
wxCoord lastCoord = 0; wxCoord lastCoord = 0;
float *lastFraction = nullptr;
for ( const auto &pair : pairs ) { for ( const auto &pair : pairs ) {
wxCoord newCoord = top + (partial / total) * height; wxCoord newCoord = top + (partial / total) * height;
results.emplace_back( newCoord, pair.second ); results.emplace_back( newCoord, pair.second );
partial += *pair.first; partial += pair.first;
if (lastFraction)
*lastFraction = newCoord - lastCoord;
lastFraction = pair.first;
lastCoord = newCoord;
} }
if ( lastFraction )
*lastFraction = top + height - lastCoord; // Cache for the use of sub-view dragging
mLastHeight = height;
return results; return results;
} }

View File

@ -95,6 +95,9 @@ public:
// correspondence with the result of SavePlacements // correspondence with the result of SavePlacements
std::vector< std::shared_ptr< WaveTrackSubView > > GetAllSubViews(); std::vector< std::shared_ptr< WaveTrackSubView > > GetAllSubViews();
// Return cached height of rect in last call of GetSubViews
wxCoord GetLastHeight() const { return mLastHeight; }
private: private:
void BuildSubViews() const; void BuildSubViews() const;
void DoSetDisplay(WaveTrackDisplay display); void DoSetDisplay(WaveTrackDisplay display);
@ -117,6 +120,7 @@ protected:
void DoSetMinimized( bool minimized ) override; void DoSetMinimized( bool minimized ) override;
WaveTrackSubViewPlacements mPlacements; WaveTrackSubViewPlacements mPlacements;
mutable wxCoord mLastHeight{};
}; };
// Helper for drawing routines // Helper for drawing routines