28 auto result = std::make_shared<Viewport>(
project);
45 , mSnappingChangedSubscription{
49 switch (message.
type) {
50 case UndoRedoMessage::Pushed:
51 case UndoRedoMessage::Modified:
52 return OnUndoPushedModified();
53 case UndoRedoMessage::UndoOrRedo:
55 case UndoRedoMessage::Reset:
88 auto w = viewInfo.GetTracksUsableWidth();
90 int pixel = viewInfo.TimeToPosition(pos);
91 if (pixel < 0 || pixel >= w) {
93 Publish({
true,
false,
false });
101 ScrollIntoView(viewInfo.PositionToTime(x, viewInfo.GetLeftOffset()));
108 const auto prevPos = pos;
111 pos = std::max<wxInt64>(pos, 0);
116 mpCallbacks->SetHorizontalThumbPosition(
static_cast<int>(pos));
125 const auto prevPos = pos;
139 mpCallbacks->SetHorizontalThumbPosition(
static_cast<int>(pos));
148 const auto prevPos = pos;
151 pos = std::max<wxInt64>(pos, 0);
156 mpCallbacks->SetHorizontalThumbPosition(
static_cast<int>(pos));
165 const auto prevPos = pos;
179 mpCallbacks->SetHorizontalThumbPosition(
static_cast<int>(pos));
198 viewInfo.TimeRangeToPixelWidth(scrollto - lowerBound);
207 const int max = std::max(
210 const int pos = std::clamp<int>(floor(0.5 + unscaled *
sbarScale), 0, max);
213 sbarH = std::clamp<wxInt64>(
224 int pos = oldPos + delta;
257 bool refresh =
false;
258 bool rescroll =
false;
261 const int totalHeight =
271 const auto panelWidth = std::max(0, viewInfo.GetTracksUsableWidth());
272 const auto panelHeight = std::max(0, viewInfo.GetHeight());
275 const bool oldhstate = (viewInfo.GetScreenEndTime() - viewInfo.hpos) <
total;
276 const bool oldvstate = panelHeight < totalHeight;
279 const auto LastTime = std::accumulate(
tracks.begin(),
tracks.end(),
280 viewInfo.selectedRegion.t1(),
281 [&pendingTracks](
double acc,
const Track *track){
283 track = &pendingTracks.SubstitutePendingChangedTrack(*track);
284 return std::max(acc, track->GetEndTime());
287 const double screen = viewInfo.GetScreenEndTime() - viewInfo.hpos;
288 const double halfScreen = screen / 2.0;
291 const double additional = screen / 4.0;
293 total = LastTime + additional;
296 total = std::max(
total, viewInfo.hpos + screen);
299 if (viewInfo.hpos < lowerBound) {
300 viewInfo.hpos = lowerBound;
306 sbarScreen =
static_cast<wxInt64
>(panelWidth);
307 sbarH =
static_cast<wxInt64
>(viewInfo.GetBeforeScreenWidth());
322 viewInfo.vpos = std::clamp(viewInfo.vpos, 0, totalHeight - 1);
327 (viewInfo.GetScreenEndTime() - viewInfo.hpos) <
total;
328 bool newvstate = panelHeight < totalHeight;
340 if (!newvstate && viewInfo.vpos != 0) {
346 if (!newhstate &&
sbarH != 0) {
360 wxInt64 maxScrollbarRange = (wxInt64)(2147483647 * 0.999);
375 scaledSbarH + offset, scaledSbarScreen, scaledSbarTotal,
376 scaledSbarScreen,
true);
388 rescroll = (viewInfo.GetScreenEndTime() - viewInfo.hpos) <
total;
389 Publish({ (refresh || rescroll),
390 (oldhstate != newhstate || oldvstate != newvstate),
false });
396 if (
auto This = wthis.lock()) {
397 This->UpdateScrollbarsForTracks();
398 This->Publish({ false, false, true });
427 auto width = viewInfo.GetTracksUsableWidth();
428 const auto zoom = viewInfo.GetZoom();
429 viewInfo.hpos = std::clamp(
sbarH / zoom, lowerBound, std::max(lowerBound,
total - width / zoom));
440 Publish({
true,
false,
false });
451 pTrack = *
tracks.Selected().begin();
467 trackTop += trackHeight;
476 auto [width, height] =
size;
478 if (trackTop < viewInfo.vpos) {
479 height = viewInfo.vpos - trackTop +
scrollStep;
483 else if (trackTop + trackHeight > viewInfo.vpos + height) {
484 height = (trackTop + trackHeight) - (viewInfo.vpos + height);
493 Publish({
true,
false,
false });
501 viewInfo.SetZoom(pixelsPerSecond);
505 float t0 = viewInfo.selectedRegion.t0();
506 float t1 = viewInfo.selectedRegion.t1();
507 float tAvailable = viewInfo.GetScreenEndTime() - viewInfo.hpos;
508 float tOnLeft = (tAvailable - t0 + t1)/2.0;
519 viewInfo.ZoomBy(multiplier);
527 viewInfo.selectedRegion.setT0(0,
false);
529 viewInfo.selectedRegion.setT1(0);
546 double len =
tracks.GetEndTime();
548 viewInfo.selectedRegion.setT1(len,
false);
550 viewInfo.selectedRegion.setT0(len);
562 auto range =
tracks.Any();
564 const auto getHeight = [
this](
auto pTrack){
567 if (!range.empty()) {
568 trackHeight = getHeight(*range.rbegin());
572 range.sum(getHeight);
575 const auto [width, height] =
size;
577 const int delta = ((trackTop + trackHeight - height) - viewInfo.vpos
580 Publish({
true,
false,
false });
592 const double endTime = viewInfo.GetScreenEndTime();
593 const double duration = endTime - viewInfo.hpos;
595 bool selectionIsOnscreen =
596 (viewInfo.selectedRegion.t0() < endTime) &&
597 (viewInfo.selectedRegion.t1() >= viewInfo.hpos);
599 bool selectionFillsScreen =
600 (viewInfo.selectedRegion.t0() < viewInfo.hpos) &&
601 (viewInfo.selectedRegion.t1() > endTime);
603 if (selectionIsOnscreen && !selectionFillsScreen) {
605 double selCenter = (viewInfo.selectedRegion.t0() +
606 viewInfo.selectedRegion.t1()) / 2;
610 if (selCenter < viewInfo.hpos)
611 selCenter = viewInfo.hpos +
612 (viewInfo.selectedRegion.t1() - viewInfo.hpos) / 2;
613 if (selCenter > endTime)
614 selCenter = endTime -
615 (endTime - viewInfo.selectedRegion.t0()) / 2;
619 const double newDuration =
620 viewInfo.GetScreenEndTime() - viewInfo.hpos;
628 double origLeft = viewInfo.hpos;
629 double origWidth = duration;
632 const double newDuration =
633 viewInfo.GetScreenEndTime() - viewInfo.hpos;
634 double newh = origLeft + (origWidth - newDuration) / 2;
658 const double origLeft = viewInfo.hpos;
659 const double origWidth = viewInfo.GetScreenEndTime() - origLeft;
662 const double newWidth = viewInfo.GetScreenEndTime() - viewInfo.hpos;
664 const double newh = origLeft + (origWidth - newWidth) / 2;
676 const double start = 0;
677 const double len =
end - start;
680 return viewInfo.GetZoom();
682 auto w = viewInfo.GetTracksUsableWidth();
693 const double start = 0;
710 - [
this](
const Track *pTrack){
717 auto height = viewInfo.GetHeight();
721 const auto fn = [
this](
const Track *pTrack){
724 height -=
tracks.Any().sum(
fn) - range.sum(
fn);
726 height = std::max<int>(
mpCallbacks->MinimumTrackHeight(), height);
758 if (
auto This = wthis.lock()) {
759 This->UpdateScrollbarsForTracks();
760 This->Publish({ true, false, false });
Toolkit-neutral facade for basic user interface services.
Extends Track with notions of mute and solo setting.
static const AudacityProject::AttachedObjects::RegisteredFactory sKey
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
Track subclass holding data representing sound (as notes, or samples, or ...)
virtual size_t NChannels() const =0
Report the number of channels.
Client code makes static instance from a factory of attachments; passes it to Get or Find as a retrie...
Subscription Subscribe(Callback callback)
Connect a callback to the Publisher; later-connected are called earlier.
CallbackReturn Publish(const ViewportMessage &message)
Send a message to connected callbacks.
static PendingTracks & Get(AudacityProject &project)
Project snapping settings.
Abstract base class for an object holding data associated with points on a time axis.
static TrackList & Get(AudacityProject &project)
static UndoManager & Get(AudacityProject &project)
static ViewInfo & Get(AudacityProject &project)
virtual ~ViewportCallbacks()
void OnScrollLeftButton()
void ZoomAboutSelection(double multiplier)
void SetCallbacks(std::unique_ptr< ViewportCallbacks > pCallbacks)
void UpdateScrollbarsForTracks()
AudacityProject & mProject
std::unique_ptr< ViewportCallbacks > mpCallbacks
void Zoom(double pixelsPerSecond)
Set timeline magnification; unchanged left edge time.
bool mbInitializingScrollbar
Viewport(AudacityProject &project)
void ShowTrack(const Track &track)
void ZoomFitHorizontally()
void OnScrollRightButton()
void ScrollToEnd(bool extend)
void SetToDefaultSize()
Send a message to the main window PARENT of the viewport, to resize.
void ZoomBy(double multiplier)
Multiply the magnification; unchanged left edge time.
void SetHorizontalThumb(double scrollto, bool doScroll=true)
void ZoomFitHorizontallyAndShowTrack(Track *pTrack)
void ScrollToStart(bool extend)
void DoScroll()
Cause refresh of viewport contents after setting scrolling or zooming.
static Viewport & Get(AudacityProject &project)
void ZoomAboutCenter(double multiplier)
Multiply timeline magnification, conserving the midpoint time if possible.
void ScrollIntoView(double pos)
Center view horizontally at the given time, if it was not in bounds.
void OnUndoPushedModified()
bool ScrollUpDown(int delta)
double ScrollingLowerBoundTime() const
double PixelWidthBeforeTime(double scrollto) const
double GetZoomOfToFit() const
Find pixels-per-second that would fit all tracks on the timeline.
void CallAfter(Action action)
Schedule an action to be done later, and in the main thread.
Services * Get()
Fetch the global instance, or nullptr if none is yet installed.
void Yield()
Dispatch waiting events, including actions enqueued by CallAfter.
const char * end(const char *str) noexcept
Type of message published by UndoManager.
enum UndoRedoMessage::Type type