mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-07 15:22:34 +02:00
Wave track affordances
This commit is contained in:
parent
cfacf2fa09
commit
70a7238ee6
@ -825,6 +825,8 @@ list( APPEND SOURCES
|
||||
tracks/playabletrack/wavetrack/ui/SpectrumVZoomHandle.h
|
||||
tracks/playabletrack/wavetrack/ui/SpectrumView.cpp
|
||||
tracks/playabletrack/wavetrack/ui/SpectrumView.h
|
||||
tracks/playabletrack/wavetrack/ui/WaveTrackAffordanceControls.cpp
|
||||
tracks/playabletrack/wavetrack/ui/WaveTrackAffordanceControls.h
|
||||
tracks/playabletrack/wavetrack/ui/WaveTrackControls.cpp
|
||||
tracks/playabletrack/wavetrack/ui/WaveTrackControls.h
|
||||
tracks/playabletrack/wavetrack/ui/WaveTrackShifter.cpp
|
||||
|
@ -172,7 +172,8 @@ ChooseColorSet( float bin0, float bin1, float selBinLo,
|
||||
void DrawClipSpectrum(TrackPanelDrawingContext &context,
|
||||
WaveTrackCache &waveTrackCache,
|
||||
const WaveClip *clip,
|
||||
const wxRect & rect)
|
||||
const wxRect & rect,
|
||||
bool selected)
|
||||
{
|
||||
auto &dc = context.dc;
|
||||
const auto artist = TrackArtist::Get( context );
|
||||
@ -608,13 +609,19 @@ void DrawClipSpectrum(TrackPanelDrawingContext &context,
|
||||
|
||||
// Draw clip edges, as also in waveform view, which improves the appearance
|
||||
// of split views
|
||||
params.DrawClipEdges( dc, rect );
|
||||
{
|
||||
//increase virtual view size by px to hide edges that should not be visible
|
||||
auto clipRect = ClipParameters::GetClipRect(*clip, zoomInfo, rect.Inflate(1, 0), 1);
|
||||
if (!clipRect.IsEmpty())
|
||||
TrackArt::DrawClipEdges(dc, clipRect, selected);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SpectrumView::DoDraw( TrackPanelDrawingContext &context,
|
||||
const WaveTrack *track,
|
||||
void SpectrumView::DoDraw(TrackPanelDrawingContext& context,
|
||||
const WaveTrack* track,
|
||||
const WaveClip* selectedClip,
|
||||
const wxRect & rect )
|
||||
{
|
||||
const auto artist = TrackArtist::Get( context );
|
||||
@ -625,7 +632,7 @@ void SpectrumView::DoDraw( TrackPanelDrawingContext &context,
|
||||
|
||||
WaveTrackCache cache(track->SharedPointer<const WaveTrack>());
|
||||
for (const auto &clip: track->GetClips())
|
||||
DrawClipSpectrum( context, cache, clip.get(), rect );
|
||||
DrawClipSpectrum( context, cache, clip.get(), rect, clip.get() == selectedClip );
|
||||
|
||||
DrawBoldBoundaries( context, track, rect );
|
||||
}
|
||||
@ -653,14 +660,18 @@ void SpectrumView::Draw(
|
||||
wxAntialiasMode aamode = dc.GetGraphicsContext()->GetAntialiasMode();
|
||||
dc.GetGraphicsContext()->SetAntialiasMode(wxANTIALIAS_NONE);
|
||||
#endif
|
||||
|
||||
auto waveTrackView = GetWaveTrackView().lock();
|
||||
wxASSERT(waveTrackView.use_count());
|
||||
|
||||
DoDraw( context, wt.get(), rect );
|
||||
auto seletedClip = waveTrackView->GetSelectedClip().lock();
|
||||
DoDraw( context, wt.get(), seletedClip.get(), rect );
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
dc.GetGraphicsContext()->SetAntialiasMode(aamode);
|
||||
#endif
|
||||
}
|
||||
CommonTrackView::Draw( context, rect, iPass );
|
||||
WaveTrackSubView::Draw( context, rect, iPass );
|
||||
}
|
||||
|
||||
static const WaveTrackSubViews::RegisteredFactory key{
|
||||
|
@ -38,6 +38,7 @@ private:
|
||||
|
||||
static void DoDraw( TrackPanelDrawingContext &context,
|
||||
const WaveTrack *track,
|
||||
const WaveClip* selectedClip,
|
||||
const wxRect & rect );
|
||||
|
||||
std::vector<UIHandlePtr> DetailedHitTest(
|
||||
|
@ -0,0 +1,105 @@
|
||||
/*!********************************************************************
|
||||
*
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
WaveTrackAffordanceControls.cpp
|
||||
|
||||
Vitaly Sverchinsky
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "WaveTrackAffordanceControls.h"
|
||||
|
||||
#include <wx/dc.h>
|
||||
|
||||
#include "../../../../AllThemeResources.h"
|
||||
#include "../../../../TrackPanelMouseEvent.h"
|
||||
#include "../../../../TrackArtist.h"
|
||||
#include "../../../../TrackPanelDrawingContext.h"
|
||||
#include "../../../../ViewInfo.h"
|
||||
#include "../../../../WaveTrack.h"
|
||||
#include "../../../../WaveClip.h"
|
||||
#include "../../../ui/AffordanceHandle.h"
|
||||
#include "WaveTrackView.h"//need only ClipParameters
|
||||
|
||||
|
||||
WaveTrackAffordanceControls::WaveTrackAffordanceControls(const std::shared_ptr<Track>& pTrack)
|
||||
: CommonTrackCell(pTrack)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<UIHandlePtr> WaveTrackAffordanceControls::HitTest(const TrackPanelMouseState& state, const AudacityProject* pProject)
|
||||
{
|
||||
mFocusClip.reset();
|
||||
|
||||
std::vector<UIHandlePtr> results;
|
||||
|
||||
const auto track = FindTrack();
|
||||
|
||||
const auto waveTrack = std::static_pointer_cast<WaveTrack>(track->SubstitutePendingChangedTrack());
|
||||
|
||||
const auto rect = state.rect;
|
||||
|
||||
auto px = state.state.m_x;
|
||||
auto py = state.state.m_y;
|
||||
|
||||
auto& zoomInfo = ViewInfo::Get(*pProject);
|
||||
for (const auto& clip : waveTrack->GetClips())
|
||||
{
|
||||
auto affordanceRect = ClipParameters::GetClipRect(*clip.get(), zoomInfo, rect);
|
||||
|
||||
if (affordanceRect.Contains(px, py))
|
||||
{
|
||||
results.push_back(AffordanceHandle::HitAnywhere(mAffordanceHandle, track));
|
||||
mFocusClip = clip;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
void WaveTrackAffordanceControls::Draw(TrackPanelDrawingContext& context, const wxRect& rect, unsigned iPass)
|
||||
{
|
||||
if (iPass == TrackArtist::PassBackground) {
|
||||
auto track = FindTrack();
|
||||
const auto artist = TrackArtist::Get(context);
|
||||
|
||||
TrackArt::DrawBackgroundWithSelection(context, rect, track.get(), artist->blankSelectedBrush, artist->blankBrush);
|
||||
|
||||
const auto waveTrack = std::static_pointer_cast<WaveTrack>(track->SubstitutePendingChangedTrack());
|
||||
const auto& zoomInfo = *artist->pZoomInfo;
|
||||
|
||||
context.dc.SetClippingRegion(rect);
|
||||
|
||||
auto px = context.lastState.m_x;
|
||||
auto py = context.lastState.m_y;
|
||||
|
||||
for (const auto& clip : waveTrack->GetClips())
|
||||
{
|
||||
auto affordanceRect = ClipParameters::GetClipRect(
|
||||
*clip.get(),
|
||||
zoomInfo,
|
||||
rect.Inflate(TrackArt::ClipFrameRadius, 0),
|
||||
TrackArt::ClipFrameRadius
|
||||
);
|
||||
if (affordanceRect.IsEmpty())
|
||||
continue;
|
||||
|
||||
auto selected = GetSelectedClip().lock() == clip;
|
||||
auto highlight = selected || affordanceRect.Contains(px, py);
|
||||
TrackArt::DrawClipAffordance(context.dc, affordanceRect, highlight, selected);
|
||||
|
||||
}
|
||||
context.dc.DestroyClippingRegion();
|
||||
}
|
||||
}
|
||||
|
||||
std::weak_ptr<WaveClip> WaveTrackAffordanceControls::GetSelectedClip() const
|
||||
{
|
||||
if (auto handle = mAffordanceHandle.lock())
|
||||
{
|
||||
return handle->Clicked() ? mFocusClip : std::weak_ptr<WaveClip>();
|
||||
}
|
||||
return {};
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*!********************************************************************
|
||||
*
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
WaveTrackAffordanceControls.h
|
||||
|
||||
Vitaly Sverchinsky
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../../ui/CommonTrackPanelCell.h"
|
||||
|
||||
class AffordanceHandle;
|
||||
class WaveClip;
|
||||
|
||||
class AUDACITY_DLL_API WaveTrackAffordanceControls : public CommonTrackCell
|
||||
{
|
||||
std::weak_ptr<WaveClip> mFocusClip;
|
||||
std::weak_ptr<AffordanceHandle> mAffordanceHandle;
|
||||
public:
|
||||
WaveTrackAffordanceControls(const std::shared_ptr<Track>& pTrack);
|
||||
|
||||
std::vector<UIHandlePtr> HitTest(const TrackPanelMouseState& state, const AudacityProject* pProject) override;
|
||||
|
||||
void Draw(TrackPanelDrawingContext& context, const wxRect& rect, unsigned iPass) override;
|
||||
|
||||
std::weak_ptr<WaveClip> GetSelectedClip() const;
|
||||
};
|
@ -38,8 +38,11 @@ Paul Licameli split from TrackPanel.cpp
|
||||
#include "../../../ui/ButtonHandle.h"
|
||||
#include "../../../../TrackInfo.h"
|
||||
|
||||
#include "WaveTrackAffordanceControls.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
using WaveTrackSubViewPtrs = std::vector< std::shared_ptr< WaveTrackSubView > >;
|
||||
|
||||
// Structure that collects and modifies information on sub-view positions
|
||||
@ -760,6 +763,11 @@ void WaveTrackSubView::DrawBoldBoundaries(
|
||||
}
|
||||
}
|
||||
|
||||
std::weak_ptr<WaveTrackView> WaveTrackSubView::GetWaveTrackView() const
|
||||
{
|
||||
return mwWaveTrackView;
|
||||
}
|
||||
|
||||
WaveTrackView &WaveTrackView::Get( WaveTrack &track )
|
||||
{
|
||||
return static_cast< WaveTrackView& >( TrackView::Get( track ) );
|
||||
@ -1018,6 +1026,11 @@ WaveTrackView::GetAllSubViews()
|
||||
return results;
|
||||
}
|
||||
|
||||
std::shared_ptr<CommonTrackCell> WaveTrackView::DoGetAffordanceControls()
|
||||
{
|
||||
return std::make_shared<WaveTrackAffordanceControls>(FindTrack());
|
||||
}
|
||||
|
||||
void WaveTrackView::DoSetMinimized( bool minimized )
|
||||
{
|
||||
BuildSubViews();
|
||||
@ -1229,20 +1242,23 @@ ClipParameters::ClipParameters
|
||||
}
|
||||
}
|
||||
|
||||
void ClipParameters::DrawClipEdges( wxDC &dc, const wxRect &rect ) const
|
||||
wxRect ClipParameters::GetClipRect(const WaveClip& clip, const ZoomInfo& zoomInfo, const wxRect& viewRect, int clipOffsetX)
|
||||
{
|
||||
// Draw clip edges
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
if (tpre < 0) {
|
||||
AColor::Line(dc,
|
||||
mid.x - 1, mid.y,
|
||||
mid.x - 1, mid.y + rect.height);
|
||||
}
|
||||
if (tpost > t1) {
|
||||
AColor::Line(dc,
|
||||
mid.x + mid.width, mid.y,
|
||||
mid.x + mid.width, mid.y + rect.height);
|
||||
}
|
||||
auto srs = 1. / static_cast<double>(clip.GetRate());
|
||||
//to prevent overlap left and right most samples with frame border
|
||||
auto margin = .25 * srs;
|
||||
auto edgeLeft = static_cast<wxInt64>(viewRect.GetLeft());
|
||||
auto edgeRight = static_cast<wxInt64>(viewRect.GetRight());
|
||||
auto left = std::clamp(zoomInfo.TimeToPosition(clip.GetOffset() - margin, viewRect.x + clipOffsetX, true), edgeLeft, edgeRight);
|
||||
auto right = std::clamp(zoomInfo.TimeToPosition(clip.GetEndTime() - srs + margin, viewRect.x + clipOffsetX, true), edgeLeft, edgeRight);
|
||||
if (right - left > 0)
|
||||
{
|
||||
//after clamping we can expect that left and right
|
||||
//are small enough to be put into int
|
||||
return wxRect(static_cast<int>(left), viewRect.y, static_cast<int>(right - left), viewRect.height);
|
||||
}
|
||||
//off the screen
|
||||
return wxRect();
|
||||
}
|
||||
|
||||
void WaveTrackView::Reparent( const std::shared_ptr<Track> &parent )
|
||||
@ -1252,6 +1268,17 @@ void WaveTrackView::Reparent( const std::shared_ptr<Track> &parent )
|
||||
WaveTrackSubViews::ForEach( [&parent](WaveTrackSubView &subView){
|
||||
subView.Reparent( parent );
|
||||
} );
|
||||
if (mpAffordanceCellControl)
|
||||
mpAffordanceCellControl->Reparent(parent);
|
||||
}
|
||||
|
||||
std::weak_ptr<WaveClip> WaveTrackView::GetSelectedClip()
|
||||
{
|
||||
if (auto affordance = std::dynamic_pointer_cast<WaveTrackAffordanceControls>(GetAffordanceControls()))
|
||||
{
|
||||
return affordance->GetSelectedClip();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void WaveTrackView::BuildSubViews() const
|
||||
|
@ -21,6 +21,7 @@ class CutlineHandle;
|
||||
class TranslatableString;
|
||||
class WaveTrack;
|
||||
class WaveTrackView;
|
||||
class WaveClip;
|
||||
|
||||
class AUDACITY_DLL_API WaveTrackSubView : public CommonTrackView
|
||||
{
|
||||
@ -47,6 +48,8 @@ protected:
|
||||
TrackPanelDrawingContext &context, const WaveTrack *track,
|
||||
const wxRect &rect );
|
||||
|
||||
std::weak_ptr<WaveTrackView> GetWaveTrackView() const;
|
||||
|
||||
private:
|
||||
std::weak_ptr<UIHandle> mCloseHandle;
|
||||
std::weak_ptr<UIHandle> mAdjustHandle;
|
||||
@ -122,6 +125,9 @@ public:
|
||||
bool GetMultiView() const { return mMultiView; }
|
||||
void SetMultiView( bool value ) { mMultiView = value; }
|
||||
|
||||
|
||||
std::weak_ptr<WaveClip> GetSelectedClip();
|
||||
|
||||
private:
|
||||
void BuildSubViews() const;
|
||||
void DoSetDisplay(Display display, bool exclusive = true);
|
||||
@ -141,6 +147,8 @@ private:
|
||||
Refinement GetSubViews( const wxRect &rect ) override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<CommonTrackCell> DoGetAffordanceControls() override;
|
||||
|
||||
void DoSetMinimized( bool minimized ) override;
|
||||
|
||||
// Placements are in correspondence with the array of sub-views
|
||||
@ -188,7 +196,9 @@ struct AUDACITY_DLL_API ClipParameters
|
||||
wxRect mid;
|
||||
int leftOffset;
|
||||
|
||||
void DrawClipEdges( wxDC &dc, const wxRect &rect ) const;
|
||||
// returns a clip rectangle restricted by viewRect,
|
||||
// and with clipOffsetX - clip horizontal origin offset within view rect
|
||||
static wxRect GetClipRect(const WaveClip& clip, const ZoomInfo& zoomInfo, const wxRect& viewRect, int clipOffsetX = 0);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -670,7 +670,8 @@ void DrawClipWaveform(TrackPanelDrawingContext &context,
|
||||
const WaveClip *clip,
|
||||
const wxRect & rect,
|
||||
bool dB,
|
||||
bool muted)
|
||||
bool muted,
|
||||
bool selected)
|
||||
{
|
||||
auto &dc = context.dc;
|
||||
const auto artist = TrackArtist::Get( context );
|
||||
@ -900,7 +901,12 @@ void DrawClipWaveform(TrackPanelDrawingContext &context,
|
||||
if (h == 0.0 && tOffset < 0.0) {
|
||||
TrackArt::DrawNegativeOffsetTrackArrows( context, rect );
|
||||
}
|
||||
params.DrawClipEdges( dc, rect );
|
||||
{
|
||||
//increase virtual view size by px to hide edges that should not be visible
|
||||
auto clipRect = ClipParameters::GetClipRect(*clip, zoomInfo, rect.Inflate(1, 0), 1);
|
||||
if (!clipRect.IsEmpty())
|
||||
TrackArt::DrawClipEdges(dc, clipRect, selected);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTimeSlider( TrackPanelDrawingContext &context,
|
||||
@ -967,7 +973,8 @@ void DrawTimeSlider( TrackPanelDrawingContext &context,
|
||||
//#include "tracks/ui/TimeShiftHandle.h"
|
||||
void WaveformView::DoDraw(TrackPanelDrawingContext &context,
|
||||
const WaveTrack *track,
|
||||
const wxRect & rect,
|
||||
const WaveClip* selectedClip,
|
||||
const wxRect& rect,
|
||||
bool muted)
|
||||
{
|
||||
auto &dc = context.dc;
|
||||
@ -988,10 +995,11 @@ void WaveformView::DoDraw(TrackPanelDrawingContext &context,
|
||||
TrackArt::DrawBackgroundWithSelection(
|
||||
context, rect, track, blankSelectedBrush, blankBrush );
|
||||
|
||||
for (const auto &clip: track->GetClips())
|
||||
for (const auto& clip : track->GetClips())
|
||||
{
|
||||
DrawClipWaveform(context, track, clip.get(), rect,
|
||||
dB, muted);
|
||||
|
||||
dB, muted, clip.get() == selectedClip);
|
||||
}
|
||||
DrawBoldBoundaries( context, track, rect );
|
||||
|
||||
const auto drawSliders = artist->drawSliders;
|
||||
@ -1028,13 +1036,17 @@ void WaveformView::Draw(
|
||||
dc.GetGraphicsContext()->SetAntialiasMode(wxANTIALIAS_NONE);
|
||||
#endif
|
||||
|
||||
DoDraw(context, wt.get(), rect, muted);
|
||||
auto waveTrackView = GetWaveTrackView().lock();
|
||||
wxASSERT(waveTrackView.use_count());
|
||||
|
||||
auto selectedClip = waveTrackView->GetSelectedClip().lock();
|
||||
DoDraw(context, wt.get(), selectedClip.get(), rect, muted);
|
||||
|
||||
#if defined(__WXMAC__)
|
||||
dc.GetGraphicsContext()->SetAntialiasMode(aamode);
|
||||
#endif
|
||||
}
|
||||
CommonTrackView::Draw( context, rect, iPass );
|
||||
WaveTrackSubView::Draw( context, rect, iPass );
|
||||
}
|
||||
|
||||
static const WaveTrackSubViews::RegisteredFactory key{
|
||||
|
@ -38,6 +38,7 @@ private:
|
||||
const wxRect &rect, unsigned iPass ) override;
|
||||
static void DoDraw(TrackPanelDrawingContext &context,
|
||||
const WaveTrack *track,
|
||||
const WaveClip* selectedClip,
|
||||
const wxRect & rect,
|
||||
bool muted);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user