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;
338 if (!newvstate && viewInfo.vpos != 0) {
344 if (!newhstate &&
sbarH != 0) {
358 wxInt64 maxScrollbarRange = (wxInt64)(2147483647 * 0.999);
373 scaledSbarH + offset, scaledSbarScreen, scaledSbarTotal,
374 scaledSbarScreen,
true);
383 rescroll = (rescroll &&
384 (viewInfo.GetScreenEndTime() - viewInfo.hpos) <
total);
385 Publish({ (refresh || rescroll),
386 (oldhstate != newhstate || oldvstate != newvstate),
false });
392 if (
auto This = wthis.lock()) {
393 This->UpdateScrollbarsForTracks();
394 This->Publish({ false, false, true });
423 auto width = viewInfo.GetTracksUsableWidth();
424 const auto zoom = viewInfo.GetZoom();
425 viewInfo.hpos = std::clamp(
sbarH / zoom, lowerBound, std::max(lowerBound,
total - width / zoom));
436 Publish({
true,
false,
false });
447 pTrack = *
tracks.Selected().begin();
463 trackTop += trackHeight;
472 auto [width, height] =
size;
474 if (trackTop < viewInfo.vpos) {
475 height = viewInfo.vpos - trackTop +
scrollStep;
479 else if (trackTop + trackHeight > viewInfo.vpos + height) {
480 height = (trackTop + trackHeight) - (viewInfo.vpos + height);
489 Publish({
true,
false,
false });
497 viewInfo.SetZoom(pixelsPerSecond);
501 float t0 = viewInfo.selectedRegion.t0();
502 float t1 = viewInfo.selectedRegion.t1();
503 float tAvailable = viewInfo.GetScreenEndTime() - viewInfo.hpos;
504 float tOnLeft = (tAvailable - t0 + t1)/2.0;
515 viewInfo.ZoomBy(multiplier);
523 viewInfo.selectedRegion.setT0(0,
false);
525 viewInfo.selectedRegion.setT1(0);
542 double len =
tracks.GetEndTime();
544 viewInfo.selectedRegion.setT1(len,
false);
546 viewInfo.selectedRegion.setT0(len);
558 auto range =
tracks.Any();
560 const auto getHeight = [
this](
auto pTrack){
563 if (!range.empty()) {
564 trackHeight = getHeight(*range.rbegin());
568 range.sum(getHeight);
571 const auto [width, height] =
size;
573 const int delta = ((trackTop + trackHeight - height) - viewInfo.vpos
576 Publish({
true,
false,
false });
588 const double endTime = viewInfo.GetScreenEndTime();
589 const double duration = endTime - viewInfo.hpos;
591 bool selectionIsOnscreen =
592 (viewInfo.selectedRegion.t0() < endTime) &&
593 (viewInfo.selectedRegion.t1() >= viewInfo.hpos);
595 bool selectionFillsScreen =
596 (viewInfo.selectedRegion.t0() < viewInfo.hpos) &&
597 (viewInfo.selectedRegion.t1() > endTime);
599 if (selectionIsOnscreen && !selectionFillsScreen) {
601 double selCenter = (viewInfo.selectedRegion.t0() +
602 viewInfo.selectedRegion.t1()) / 2;
606 if (selCenter < viewInfo.hpos)
607 selCenter = viewInfo.hpos +
608 (viewInfo.selectedRegion.t1() - viewInfo.hpos) / 2;
609 if (selCenter > endTime)
610 selCenter = endTime -
611 (endTime - viewInfo.selectedRegion.t0()) / 2;
615 const double newDuration =
616 viewInfo.GetScreenEndTime() - viewInfo.hpos;
624 double origLeft = viewInfo.hpos;
625 double origWidth = duration;
628 const double newDuration =
629 viewInfo.GetScreenEndTime() - viewInfo.hpos;
630 double newh = origLeft + (origWidth - newDuration) / 2;
654 const double origLeft = viewInfo.hpos;
655 const double origWidth = viewInfo.GetScreenEndTime() - origLeft;
658 const double newWidth = viewInfo.GetScreenEndTime() - viewInfo.hpos;
660 const double newh = origLeft + (origWidth - newWidth) / 2;
672 const double start = 0;
673 const double len =
end - start;
676 return viewInfo.GetZoom();
678 auto w = viewInfo.GetTracksUsableWidth();
689 const double start = 0;
706 - [
this](
const Track *pTrack){
713 auto height = viewInfo.GetHeight();
717 const auto fn = [
this](
const Track *pTrack){
720 height -=
tracks.Any().sum(
fn) - range.sum(
fn);
722 height = std::max<int>(
mpCallbacks->MinimumTrackHeight(), height);
754 if (
auto This = wthis.lock()) {
755 This->UpdateScrollbarsForTracks();
756 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