LCOV - code coverage report
Current view: top level - src - OptionsPanelLayout.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 69.4 % 124 86
Test Date: 2026-03-03 00:31:37 Functions: 46.9 % 32 15

            Line data    Source code
       1              : #include "OptionsPanelLayout.h"
       2              : 
       3              : #include <algorithm>
       4              : 
       5              : // ── Fold state ───────────────────────────────────────────────────────────────
       6              : 
       7           12 : void OptionsPanelLayout::setFolded(Section s, bool folded) {
       8           12 :     if (s >= 0 && s < SectionCount) {
       9           12 :         folded_[s] = folded;
      10           12 :         clampScroll();
      11           12 :     }
      12           12 : }
      13              : 
      14            3 : bool OptionsPanelLayout::isFolded(Section s) const {
      15            3 :     return s >= 0 && s < SectionCount && folded_[s];
      16              : }
      17              : 
      18            2 : void OptionsPanelLayout::toggleFolded(Section s) {
      19            2 :     if (s >= 0 && s < SectionCount) {
      20            2 :         folded_[s] = !folded_[s];
      21            2 :         clampScroll();
      22            2 :     }
      23            2 : }
      24              : 
      25              : // ── Scroll state ─────────────────────────────────────────────────────────────
      26              : 
      27            3 : void OptionsPanelLayout::setScrollOffset(int offset) {
      28            3 :     scrollOffset_ = offset;
      29            3 :     clampScroll();
      30            3 : }
      31              : 
      32            7 : int OptionsPanelLayout::scrollOffset() const {
      33            7 :     return scrollOffset_;
      34              : }
      35              : 
      36            2 : void OptionsPanelLayout::scrollBy(int delta) {
      37            2 :     scrollOffset_ += delta;
      38            2 :     clampScroll();
      39            2 : }
      40              : 
      41              : // ── Viewport ─────────────────────────────────────────────────────────────────
      42              : 
      43            5 : void OptionsPanelLayout::setViewportHeight(int h) {
      44            5 :     viewportHeight_ = h;
      45            5 :     clampScroll();
      46            5 : }
      47              : 
      48            0 : int OptionsPanelLayout::viewportHeight() const {
      49            0 :     return viewportHeight_;
      50              : }
      51              : 
      52              : // ── Computed values ──────────────────────────────────────────────────────────
      53              : 
      54           33 : int OptionsPanelLayout::contentHeight() const {
      55              :     // Walk sections to compute total height
      56           33 :     int y = kFirstSectionY;
      57          165 :     for (int s = 0; s < SectionCount; ++s) {
      58          132 :         y += kHeaderH + kSectionGap; // header + gap before next section
      59          132 :         if (!folded_[s]) {
      60           99 :             switch (static_cast<Section>(s)) {
      61           20 :                 case MidiRouting: y += kMidiRoutingContentH; break;
      62           24 :                 case Video:       y += kVideoContentH; break;
      63           27 :                 case Circles:     y += kCirclesContentH; break;
      64           28 :                 case Animation:   y += kAnimationContentH; break;
      65            0 :                 default: break;
      66              :             }
      67           99 :         }
      68          132 :     }
      69           33 :     y += kButtonsH; // save/load buttons always visible
      70           33 :     return y;
      71              : }
      72              : 
      73           30 : int OptionsPanelLayout::maxScrollOffset() const {
      74           30 :     return std::max(0, contentHeight() - viewportHeight_);
      75              : }
      76              : 
      77              : // ── Y positions ──────────────────────────────────────────────────────────────
      78              : 
      79           28 : int OptionsPanelLayout::sectionHeaderY(Section s) const {
      80           28 :     int y = kFirstSectionY;
      81           58 :     for (int i = 0; i < s; ++i) {
      82           30 :         y += kHeaderH + kSectionGap;
      83           30 :         if (!folded_[i]) {
      84           26 :             switch (static_cast<Section>(i)) {
      85           15 :                 case MidiRouting: y += kMidiRoutingContentH; break;
      86            8 :                 case Video:       y += kVideoContentH; break;
      87            3 :                 case Circles:     y += kCirclesContentH; break;
      88            0 :                 case Animation:   y += kAnimationContentH; break;
      89            0 :                 default: break;
      90              :             }
      91           26 :         }
      92           30 :     }
      93           28 :     return y;
      94              : }
      95              : 
      96            2 : int OptionsPanelLayout::sectionContentY(Section s) const {
      97            2 :     return sectionHeaderY(s) + kHeaderH;
      98              : }
      99              : 
     100              : // MIDI ROUTING content: voice rows start 2px below header bottom (88 = 66 + 22)
     101            2 : int OptionsPanelLayout::midiRoutingFirstRowY() const {
     102            2 :     return sectionContentY(MidiRouting) + 2;
     103              : }
     104              : 
     105              : // VIDEO content offsets (relative to VIDEO header Y)
     106              : // Transport buttons (play/pause, stop, loop, eye, blur) on first line.
     107            0 : int OptionsPanelLayout::videoTransportY() const {
     108            0 :     return sectionHeaderY(Video) + 18;
     109              : }
     110              : 
     111              : // Seekbar on its own line below transport buttons.
     112            0 : int OptionsPanelLayout::videoSeekBarY() const {
     113            0 :     return sectionHeaderY(Video) + 46;
     114              : }
     115              : 
     116            0 : int OptionsPanelLayout::videoTimeLabelY() const {
     117            0 :     return sectionHeaderY(Video) + 96;
     118              : }
     119              : 
     120            0 : int OptionsPanelLayout::videoCtrlY() const {
     121            0 :     return sectionHeaderY(Video) + 114;
     122              : }
     123              : 
     124            0 : int OptionsPanelLayout::videoFilesY() const {
     125            0 :     return videoCtrlY() + 134;
     126              : }
     127              : 
     128            0 : int OptionsPanelLayout::videoFileListTopY() const {
     129            0 :     return videoFilesY() + 16;
     130              : }
     131              : 
     132              : // CIRCLES content offsets (relative to CIRCLES header Y)
     133            0 : int OptionsPanelLayout::circlesSizeRangeY() const {
     134            0 :     return sectionHeaderY(Circles) + 18;
     135              : }
     136              : 
     137            0 : int OptionsPanelLayout::circlesSliderY() const {
     138            0 :     return sectionHeaderY(Circles) + 34;
     139              : }
     140              : 
     141            0 : int OptionsPanelLayout::circlesHandleLabelsY() const {
     142            0 :     return sectionHeaderY(Circles) + 66;
     143              : }
     144              : 
     145              : // ANIMATION content offsets (relative to ANIMATION header Y)
     146            0 : int OptionsPanelLayout::animFloatToggleY() const {
     147            0 :     return sectionHeaderY(Animation) + 20;
     148              : }
     149              : 
     150            0 : int OptionsPanelLayout::animCollisionToggleY() const {
     151            0 :     return sectionHeaderY(Animation) + 46;
     152              : }
     153              : 
     154            0 : int OptionsPanelLayout::animClockToggleY() const {
     155            0 :     return sectionHeaderY(Animation) + 72;
     156              : }
     157              : 
     158            0 : int OptionsPanelLayout::animClockDivY() const {
     159            0 :     return sectionHeaderY(Animation) + 118;
     160              : }
     161              : 
     162            0 : int OptionsPanelLayout::animClockKickSliderY() const {
     163            0 :     return sectionHeaderY(Animation) + 168;
     164              : }
     165              : 
     166            0 : int OptionsPanelLayout::animFloatIntensitySliderY() const {
     167            0 :     return sectionHeaderY(Animation) + 218;
     168              : }
     169              : 
     170            0 : int OptionsPanelLayout::animFloatSpeedSliderY() const {
     171            0 :     return sectionHeaderY(Animation) + 268;
     172              : }
     173              : 
     174            2 : int OptionsPanelLayout::buttonsY() const {
     175            2 :     int y = kFirstSectionY;
     176           10 :     for (int i = 0; i < SectionCount; ++i) {
     177            8 :         y += kHeaderH + kSectionGap;
     178            8 :         if (!folded_[i]) {
     179            7 :             switch (static_cast<Section>(i)) {
     180            2 :                 case MidiRouting: y += kMidiRoutingContentH; break;
     181            2 :                 case Video:       y += kVideoContentH; break;
     182            2 :                 case Circles:     y += kCirclesContentH; break;
     183            1 :                 case Animation:   y += kAnimationContentH; break;
     184            0 :                 default: break;
     185              :             }
     186            7 :         }
     187            8 :     }
     188            2 :     return y;
     189              : }
     190              : 
     191              : // ── Hit-test ─────────────────────────────────────────────────────────────────
     192              : 
     193            6 : OptionsPanelLayout::Section OptionsPanelLayout::hitTestHeader(int contentY) const {
     194           16 :     for (int s = 0; s < SectionCount; ++s) {
     195           14 :         const int hy = sectionHeaderY(static_cast<Section>(s));
     196           14 :         if (contentY >= hy && contentY < hy + kHeaderH)
     197            4 :             return static_cast<Section>(s);
     198           10 :     }
     199            2 :     return SectionCount;
     200            6 : }
     201              : 
     202              : // ── Internal ─────────────────────────────────────────────────────────────────
     203              : 
     204           24 : void OptionsPanelLayout::clampScroll() {
     205           24 :     const int max = maxScrollOffset();
     206           24 :     if (scrollOffset_ < 0) scrollOffset_ = 0;
     207           24 :     if (scrollOffset_ > max) scrollOffset_ = max;
     208           24 : }
        

Generated by: LCOV version 2.4-0