1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-04-29 23:29:41 +02:00

Own resizing area added to stereo wave tracks view and affordance view

(cherry picked from audacity commit 7949a0dc86b6e473ffa7fd41d4fe9ddad1e6ba51)

Signed-off-by: akleja <storspov@gmail.com>
This commit is contained in:
Vitaly Sverchinsky 2021-08-12 21:28:09 +03:00 committed by akleja
parent 607e60ab4d
commit e9d6aa2c5c
4 changed files with 118 additions and 31 deletions

View File

@ -16,6 +16,7 @@
#include "../../../../TrackPanelMouseEvent.h"
#include "../../../../TrackArtist.h"
#include "../../../../TrackPanelDrawingContext.h"
#include "../../../../TrackPanelResizeHandle.h"
#include "../../../../ViewInfo.h"
#include "../../../../WaveTrack.h"
#include "../../../../WaveClip.h"
@ -34,14 +35,29 @@ std::vector<UIHandlePtr> WaveTrackAffordanceControls::HitTest(const TrackPanelMo
std::vector<UIHandlePtr> results;
const auto track = FindTrack();
const auto waveTrack = std::static_pointer_cast<WaveTrack>(track->SubstitutePendingChangedTrack());
auto px = state.state.m_x;
auto py = state.state.m_y;
const auto rect = state.rect;
auto px = state.state.m_x;
auto py = state.state.m_y;
const auto track = FindTrack();
auto trackList = track->GetOwner();
if ((std::abs(rect.GetTop() - py) <= WaveTrackView::kChannelSeparatorThickness / 2)
&& trackList
&& !track->IsLeader())
{
//given that track is not a leader there always should be
//another track before this one
auto prev = --trackList->Find(track.get());
auto result = std::static_pointer_cast<UIHandle>(
std::make_shared<TrackPanelResizeHandle>((*prev)->shared_from_this(), py)
);
result = AssignUIHandlePtr(mResizeHandle, result);
results.push_back(result);
}
const auto waveTrack = std::static_pointer_cast<WaveTrack>(track->SubstitutePendingChangedTrack());
auto& zoomInfo = ViewInfo::Get(*pProject);
for (const auto& clip : waveTrack->GetClips())

View File

@ -19,6 +19,7 @@ class TENACITY_DLL_API WaveTrackAffordanceControls : public CommonTrackCell
{
std::weak_ptr<WaveClip> mFocusClip;
std::weak_ptr<AffordanceHandle> mAffordanceHandle;
std::weak_ptr<UIHandle> mResizeHandle;
public:
WaveTrackAffordanceControls(const std::shared_ptr<Track>& pTrack);

View File

@ -31,6 +31,7 @@ Paul Licameli split from TrackPanel.cpp
#include "../../../../TrackArtist.h"
#include "../../../../TrackPanelDrawingContext.h"
#include "../../../../TrackPanelMouseEvent.h"
#include "../../../../TrackPanelResizeHandle.h"
#include "../../../../ViewInfo.h"
#include "../../../../prefs/TracksPrefs.h"
@ -703,6 +704,49 @@ std::pair<
mCloseHandle,
*pWaveTrackView, *this, state ) )
results.second.push_back( pHandle );
auto channels = TrackList::Channels(wt.get());
if(channels.size() > 1) {
// Only one cell is tested and we need to know
// which one and it's relative location to the border.
auto subviews = pWaveTrackView->GetSubViews();
auto currentSubview = std::find_if(subviews.begin(), subviews.end(),
[self = shared_from_this()](const auto& p){
return self == p.second;
});
if (currentSubview != subviews.end())
{
auto currentSubviewIndex = std::distance(subviews.begin(), currentSubview);
const auto py = state.state.GetY();
const auto topBorderHit = std::abs(py - state.rect.GetTop())
<= WaveTrackView::kChannelSeparatorThickness / 2;
const auto bottomBorderHit = std::abs(py - state.rect.GetBottom())
<= WaveTrackView::kChannelSeparatorThickness / 2;
auto currentChannel = channels.find(wt.get());
auto currentChannelIndex = std::distance(channels.begin(), currentChannel);
if (//for not-last-view check the bottom border hit
((currentChannelIndex != channels.size() - 1)
&& (currentSubviewIndex == static_cast<int>(subviews.size()) - 1)
&& bottomBorderHit)
||
//or for not-first-view check the top border hit
((currentChannelIndex != 0) && currentSubviewIndex == 0 && topBorderHit))
{
//depending on which border hit test succeeded on we
//need to choose a proper target for resizing
auto it = bottomBorderHit ? currentChannel : currentChannel.advance(-1);
auto result = std::static_pointer_cast<UIHandle>(
std::make_shared<TrackPanelResizeHandle>((*it)->shared_from_this(), py)
);
result = AssignUIHandlePtr(mResizeHandle, result);
results.second.push_back(result);
}
}
}
if ( auto pHandle = SubViewAdjustHandle::HitTest(
mAdjustHandle,
*pWaveTrackView, *this, state ) )
@ -964,6 +1008,11 @@ void WaveTrackView::DoSetDisplay(Display display, bool exclusive)
}
auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement
{
return GetSubViews(&rect);
}
auto WaveTrackView::GetSubViews(const wxRect* rect) -> Refinement
{
BuildSubViews();
@ -974,41 +1023,51 @@ auto WaveTrackView::GetSubViews( const wxRect &rect ) -> Refinement
std::vector< Item > items;
size_t ii = 0;
float total = 0;
WaveTrackSubViews::ForEach( [&]( WaveTrackSubView &subView ){
auto &placement = mPlacements[ii];
WaveTrackSubViews::ForEach([&](WaveTrackSubView& subView) {
auto& placement = mPlacements[ii];
auto index = placement.index;
auto fraction = placement.fraction;
if ( index >= 0 && fraction > 0.0 )
if (index >= 0 && fraction > 0.0)
total += fraction,
items.push_back( { index, fraction, subView.shared_from_this() } );
items.push_back({ index, fraction, subView.shared_from_this() });
++ii;
} );
std::sort( items.begin(), items.end(), [](const Item &a, const Item &b){
});
std::sort(items.begin(), items.end(), [](const Item& a, const Item& b) {
return a.index < b.index;
} );
});
// Remove views we don't need
auto begin = items.begin(), end = items.end(),
newEnd = std::remove_if( begin, end,
[]( const Item &item ){ return !item.pView; } );
items.erase( newEnd, end );
newEnd = std::remove_if(begin, end,
[](const Item& item) { return !item.pView; });
items.erase(newEnd, end);
// Assign coordinates, redenominating to the total height,
// storing integer values
Refinement results;
results.reserve( items.size() );
const auto top = rect.GetTop();
const auto height = rect.GetHeight();
float partial = 0;
wxCoord lastCoord = 0;
for ( const auto &item : items ) {
wxCoord newCoord = top + (partial / total) * height;
results.emplace_back( newCoord, item.pView );
partial += item.fraction;
}
// Cache for the use of sub-view dragging
mLastHeight = height;
if (rect != nullptr)
{
// Assign coordinates, redenominating to the total height,
// storing integer values
results.reserve(items.size());
const auto top = rect->GetTop();
const auto height = rect->GetHeight();
float partial = 0;
wxCoord lastCoord = 0;
for (const auto& item : items) {
wxCoord newCoord = top + (partial / total) * height;
results.emplace_back(newCoord, item.pView);
partial += item.fraction;
}
// Cache for the use of sub-view dragging
mLastHeight = height;
}
else
{
std::transform(items.begin(), items.end(), std::back_inserter(results), [](const auto& item) {
return std::make_pair(0, item.pView);
});
}
return results;
}

View File

@ -52,6 +52,7 @@ protected:
private:
std::weak_ptr<UIHandle> mCloseHandle;
std::weak_ptr<UIHandle> mResizeHandle;
std::weak_ptr<UIHandle> mAdjustHandle;
std::weak_ptr<UIHandle> mRearrangeHandle;
std::weak_ptr<CutlineHandle> mCutlineHandle;
@ -77,6 +78,8 @@ class TENACITY_DLL_API WaveTrackView final
WaveTrackView &operator=( const WaveTrackView& ) = delete;
public:
static constexpr int kChannelSeparatorThickness{ 8 };
using Display = WaveTrackViewConstants::Display;
static WaveTrackView &Get( WaveTrack &track );
@ -128,6 +131,15 @@ public:
std::weak_ptr<WaveClip> GetSelectedClip();
// Returns a visible subset of subviews, sorted in the same
// order as they are supposed to be displayed
// Get the visible sub-views,
// if rect is provided then result will contain
// y coordinate for each subview within this rect
Refinement GetSubViews(const wxRect* rect = nullptr);
private:
void BuildSubViews() const;
void DoSetDisplay(Display display, bool exclusive = true);
@ -143,8 +155,7 @@ private:
override;
// TrackView implementation
// Get the visible sub-views with top y coordinates
Refinement GetSubViews( const wxRect &rect ) override;
Refinement GetSubViews(const wxRect& rect) override;
protected:
std::shared_ptr<CommonTrackCell> DoGetAffordanceControls() override;