mirror of
https://github.com/cookiengineer/audacity
synced 2025-07-25 17:08:07 +02:00
... ViewInfo should only be concerned with screen geometry. (And so it won't depend on AudioIO (even higher level) after stream time moves there.) PlaybackScroller receives the timer event directly (not from ViewInfo) and caches playback position instead. Then, as before, it propagates the event to PlayIndicatorOverlay.
249 lines
5.5 KiB
C++
249 lines
5.5 KiB
C++
/**********************************************************************
|
|
|
|
Audacity: A Digital Audio Editor
|
|
|
|
ViewInfo.cpp
|
|
|
|
Paul Licameli
|
|
|
|
**********************************************************************/
|
|
|
|
#include "ViewInfo.h"
|
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
#include "Prefs.h"
|
|
#include "Project.h"
|
|
#include "xml/XMLWriter.h"
|
|
#include "prefs/TracksBehaviorsPrefs.h"
|
|
#include "xml/XMLWriter.h"
|
|
|
|
wxDEFINE_EVENT( EVT_SELECTED_REGION_CHANGE, SelectedRegionEvent );
|
|
|
|
SelectedRegionEvent::SelectedRegionEvent(
|
|
wxEventType commandType, NotifyingSelectedRegion *pReg )
|
|
: wxEvent{ 0, commandType }
|
|
, pRegion{ pReg }
|
|
{}
|
|
|
|
wxEvent *SelectedRegionEvent::Clone() const
|
|
{
|
|
return safenew SelectedRegionEvent{ *this };
|
|
}
|
|
|
|
bool NotifyingSelectedRegion::HandleXMLAttribute
|
|
(const wxChar *attr, const wxChar *value,
|
|
const wxChar *legacyT0Name, const wxChar *legacyT1Name)
|
|
{
|
|
auto result = mRegion.HandleXMLAttribute(
|
|
attr, value, legacyT0Name, legacyT1Name );
|
|
if ( result )
|
|
Notify( true );
|
|
return result;
|
|
}
|
|
|
|
NotifyingSelectedRegion& NotifyingSelectedRegion::operator =
|
|
( const SelectedRegion &other )
|
|
{
|
|
if ( mRegion != other ) {
|
|
mRegion = other;
|
|
Notify();
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
bool NotifyingSelectedRegion::setTimes(double t0, double t1)
|
|
{
|
|
bool result = false;
|
|
if ( mRegion.t0() != t0 || mRegion.t1() != t1 ) {
|
|
result = mRegion.setTimes( t0, t1 );
|
|
Notify();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool NotifyingSelectedRegion::setT0(double t, bool maySwap)
|
|
{
|
|
bool result = false;
|
|
if ( mRegion.t0() != t ) {
|
|
result = mRegion.setT0( t, maySwap );
|
|
Notify();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool NotifyingSelectedRegion::setT1(double t, bool maySwap)
|
|
{
|
|
bool result = false;
|
|
if ( mRegion.t1() != t ) {
|
|
result = mRegion.setT1( t, maySwap );
|
|
Notify();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void NotifyingSelectedRegion::collapseToT0()
|
|
{
|
|
if ( mRegion.t0() != mRegion.t1() ) {
|
|
mRegion.collapseToT0();
|
|
Notify();
|
|
}
|
|
}
|
|
|
|
void NotifyingSelectedRegion::collapseToT1()
|
|
{
|
|
if ( mRegion.t0() != mRegion.t1() ) {
|
|
mRegion.collapseToT1();
|
|
Notify();
|
|
}
|
|
}
|
|
|
|
void NotifyingSelectedRegion::move(double delta)
|
|
{
|
|
if (delta != 0) {
|
|
mRegion.move( delta );
|
|
Notify();
|
|
}
|
|
}
|
|
|
|
bool NotifyingSelectedRegion::setFrequencies(double f0, double f1)
|
|
{
|
|
bool result = false;
|
|
if ( mRegion.f0() != f0 || mRegion.f1() != f1 ) {
|
|
result = mRegion.setFrequencies( f0, f1 );
|
|
Notify();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool NotifyingSelectedRegion::setF0(double f, bool maySwap)
|
|
{
|
|
bool result = false;
|
|
if ( mRegion.f0() != f ) {
|
|
result = mRegion.setF0( f, maySwap );
|
|
Notify();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool NotifyingSelectedRegion::setF1(double f, bool maySwap)
|
|
{
|
|
bool result = false;
|
|
if ( mRegion.f1() != f ) {
|
|
result = mRegion.setF1( f, maySwap );
|
|
Notify();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void NotifyingSelectedRegion::Notify( bool delayed )
|
|
{
|
|
SelectedRegionEvent evt{ EVT_SELECTED_REGION_CHANGE, this };
|
|
if ( delayed )
|
|
QueueEvent( evt.Clone() );
|
|
else
|
|
ProcessEvent( evt );
|
|
}
|
|
|
|
static const AudacityProject::AttachedObjects::RegisteredFactory key{
|
|
[]( AudacityProject &project ) {
|
|
return std::make_unique<ViewInfo>(0.0, 1.0, ZoomInfo::GetDefaultZoom());
|
|
}
|
|
};
|
|
|
|
ViewInfo &ViewInfo::Get( AudacityProject &project )
|
|
{
|
|
return project.AttachedObjects::Get< ViewInfo >( key );
|
|
}
|
|
|
|
const ViewInfo &ViewInfo::Get( const AudacityProject &project )
|
|
{
|
|
return Get( const_cast< AudacityProject & >( project ) );
|
|
}
|
|
|
|
ViewInfo::ViewInfo(double start, double screenDuration, double pixelsPerSecond)
|
|
: ZoomInfo(start, pixelsPerSecond)
|
|
, selectedRegion()
|
|
, total(screenDuration)
|
|
, sbarH(0)
|
|
, sbarScreen(1)
|
|
, sbarTotal(1)
|
|
, sbarScale(1.0)
|
|
, scrollStep(16)
|
|
, bUpdateTrackIndicator(true)
|
|
, bScrollBeyondZero(false)
|
|
{
|
|
UpdatePrefs();
|
|
}
|
|
|
|
void ViewInfo::UpdateSelectedPrefs( int id )
|
|
{
|
|
if (id == UpdateScrollPrefsID())
|
|
gPrefs->Read(wxT("/GUI/AutoScroll"), &bUpdateTrackIndicator,
|
|
true);
|
|
ZoomInfo::UpdateSelectedPrefs( id );
|
|
}
|
|
|
|
void ViewInfo::UpdatePrefs()
|
|
{
|
|
ZoomInfo::UpdatePrefs();
|
|
#ifdef EXPERIMENTAL_SCROLLING_LIMITS
|
|
gPrefs->Read(TracksBehaviorsPrefs::ScrollingPreferenceKey(), &bScrollBeyondZero,
|
|
TracksBehaviorsPrefs::ScrollingPreferenceDefault());
|
|
#endif
|
|
gPrefs->Read(wxT("/GUI/AdjustSelectionEdges"), &bAdjustSelectionEdges,
|
|
true);
|
|
|
|
UpdateSelectedPrefs( UpdateScrollPrefsID() );
|
|
}
|
|
|
|
void ViewInfo::SetBeforeScreenWidth(wxInt64 beforeWidth, wxInt64 screenWidth, double lowerBoundTime)
|
|
{
|
|
h =
|
|
std::max(lowerBoundTime,
|
|
std::min(total - screenWidth / zoom,
|
|
beforeWidth / zoom));
|
|
}
|
|
|
|
void ViewInfo::WriteXMLAttributes(XMLWriter &xmlFile) const
|
|
// may throw
|
|
{
|
|
selectedRegion.WriteXMLAttributes(xmlFile, wxT("sel0"), wxT("sel1"));
|
|
xmlFile.WriteAttr(wxT("vpos"), vpos);
|
|
xmlFile.WriteAttr(wxT("h"), h, 10);
|
|
xmlFile.WriteAttr(wxT("zoom"), zoom, 10);
|
|
}
|
|
|
|
bool ViewInfo::ReadXMLAttribute(const wxChar *attr, const wxChar *value)
|
|
{
|
|
if (selectedRegion.HandleXMLAttribute(attr, value, wxT("sel0"), wxT("sel1")))
|
|
return true;
|
|
|
|
if (!wxStrcmp(attr, wxT("vpos"))) {
|
|
long longVpos;
|
|
wxString(value).ToLong(&longVpos);
|
|
vpos = (int)(longVpos);
|
|
return true;
|
|
}
|
|
|
|
if (!wxStrcmp(attr, wxT("h"))) {
|
|
Internat::CompatibleToDouble(value, &h);
|
|
return true;
|
|
}
|
|
|
|
if (!wxStrcmp(attr, wxT("zoom"))) {
|
|
Internat::CompatibleToDouble(value, &zoom);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
int ViewInfo::UpdateScrollPrefsID()
|
|
{
|
|
static int value = wxNewId();
|
|
return value;
|
|
}
|