LCOV - code coverage report
Current view: top level - src - MultiHandleSliderLogic.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 95.2 % 84 80
Test Date: 2026-03-03 00:31:37 Functions: 100.0 % 10 10

            Line data    Source code
       1              : #include "MultiHandleSliderLogic.h"
       2              : #include "RangeSliderLogic.h"
       3              : #include <algorithm>
       4              : #include <cmath>
       5              : 
       6           56 : MultiHandleSliderLogic::MultiHandleSliderLogic(double maxValue)
       7              :     : loopEnd_(std::max(0.0, maxValue)),
       8           28 :       maxValue_(std::max(0.0, maxValue)) {
       9           28 : }
      10              : 
      11           18 : void MultiHandleSliderLogic::setLoopStart(double v) {
      12           18 :     loopStart_ = std::clamp(v, 0.0, loopEnd_);
      13           18 : }
      14              : 
      15           10 : void MultiHandleSliderLogic::setPlayhead(double v) {
      16           10 :     playhead_ = std::clamp(v, 0.0, maxValue_);
      17           10 : }
      18              : 
      19           18 : void MultiHandleSliderLogic::setLoopEnd(double v) {
      20           18 :     loopEnd_ = std::clamp(v, loopStart_, maxValue_);
      21           18 : }
      22              : 
      23            3 : void MultiHandleSliderLogic::setMaxValue(double v) {
      24            3 :     const double oldMax = maxValue_;
      25            3 :     maxValue_ = std::max(0.0, v);
      26              :     // When transitioning from uninitialized (0) to a real duration,
      27              :     // expand loopEnd to cover the full range.
      28            3 :     if (oldMax <= 0.0 && maxValue_ > 0.0)
      29            1 :         loopEnd_ = maxValue_;
      30            3 :     loopEnd_ = std::min(loopEnd_, maxValue_);
      31            3 :     loopStart_ = std::min(loopStart_, loopEnd_);
      32            3 :     playhead_ = std::min(playhead_, maxValue_);
      33            3 : }
      34              : 
      35              : MultiHandleSliderLogic::HandleType
      36            5 : MultiHandleSliderLogic::hitTest(float mouseX,
      37              :                                 float trackStart, float trackWidth,
      38              :                                 float thumbRadius) const {
      39            5 :     if (maxValue_ <= 0.0)
      40            0 :         return HandleType::None;
      41              : 
      42           10 :     const float lsPx = RangeSliderLogic::valueToPixel(loopStart_, 0.0, maxValue_,
      43            5 :                                                       trackStart, trackWidth);
      44           10 :     const float phPx = RangeSliderLogic::valueToPixel(playhead_, 0.0, maxValue_,
      45            5 :                                                       trackStart, trackWidth);
      46           10 :     const float lePx = RangeSliderLogic::valueToPixel(loopEnd_, 0.0, maxValue_,
      47            5 :                                                       trackStart, trackWidth);
      48              : 
      49            5 :     const float dLS = std::abs(mouseX - lsPx);
      50            5 :     const float dPH = std::abs(mouseX - phPx);
      51            5 :     const float dLE = std::abs(mouseX - lePx);
      52              : 
      53              :     // Find the closest handle within thumbRadius
      54            5 :     float bestDist = thumbRadius + 1.0f;
      55            5 :     HandleType best = HandleType::None;
      56              : 
      57            5 :     if (dLS <= thumbRadius && dLS < bestDist) {
      58            1 :         bestDist = dLS;
      59            1 :         best = HandleType::LoopStart;
      60            1 :     }
      61            5 :     if (dPH <= thumbRadius && dPH < bestDist) {
      62            1 :         bestDist = dPH;
      63            1 :         best = HandleType::Playhead;
      64            1 :     }
      65            5 :     if (dLE <= thumbRadius && dLE < bestDist) {
      66            1 :         bestDist = dLE;
      67            1 :         best = HandleType::LoopEnd;
      68            1 :     }
      69              : 
      70            5 :     if (best != HandleType::None)
      71            3 :         return best;
      72              : 
      73              :     // Check middle zone between loop handles
      74            4 :     if (RangeSliderLogic::isInMiddleZone(mouseX, loopStart_, loopEnd_,
      75            2 :                                          0.0, maxValue_, trackStart, trackWidth,
      76            2 :                                          thumbRadius))
      77            1 :         return HandleType::MiddleZone;
      78              : 
      79            1 :     return HandleType::None;
      80            5 : }
      81              : 
      82            6 : void MultiHandleSliderLogic::dragHandle(HandleType handle, float mouseX,
      83              :                                         float trackStart, float trackWidth) {
      84            6 :     if (maxValue_ <= 0.0)
      85            0 :         return;
      86              : 
      87           12 :     const double val = RangeSliderLogic::pixelToValue(mouseX, 0.0, maxValue_, trackStart,
      88            6 :                                                       trackWidth);
      89              : 
      90            6 :     switch (handle) {
      91              :     case HandleType::LoopStart:
      92            2 :         loopStart_ = std::clamp(val, 0.0, loopEnd_);
      93            2 :         break;
      94              :     case HandleType::Playhead:
      95            2 :         playhead_ = std::clamp(val, 0.0, maxValue_);
      96            2 :         break;
      97              :     case HandleType::LoopEnd:
      98            2 :         loopEnd_ = std::clamp(val, loopStart_, maxValue_);
      99            2 :         break;
     100              :     default:
     101            0 :         break;
     102              :     }
     103            6 : }
     104              : 
     105            3 : void MultiHandleSliderLogic::dragMiddleZone(double initialLoopStart,
     106              :                                             double initialLoopEnd,
     107              :                                             float deltaPixels,
     108              :                                             float trackStart, float trackWidth) {
     109            6 :     auto [newStart, newEnd] = RangeSliderLogic::applyDrag(
     110            3 :         initialLoopStart, initialLoopEnd, 0.0, maxValue_, deltaPixels, trackStart,
     111            3 :         trackWidth);
     112            3 :     loopStart_ = newStart;
     113            3 :     loopEnd_ = newEnd;
     114            3 : }
     115              : 
     116            4 : std::string MultiHandleSliderLogic::formatTime(double seconds) {
     117            4 :     if (seconds < 0.0)
     118            0 :         seconds = 0.0;
     119            4 :     const int totalSec = static_cast<int>(seconds);
     120            4 :     const int mins = totalSec / 60;
     121            4 :     const int secs = totalSec % 60;
     122              : 
     123              :     char buf[16];
     124            4 :     std::snprintf(buf, sizeof (buf), "%d:%02d", mins, secs);
     125            4 :     return buf;
     126              : }
        

Generated by: LCOV version 2.4-0