8.4 KiB
Bug Fix Specification: Resolving Layout Overlaps & Synchronized Scroll Management (Scroll & Overlap Fix)
This document defines the technical solution to completely eliminate two critical layout overlap defects occurring during timeline scrolling operations, based on the real-world visual analysis.
1. Visual Overlap Analysis
Based on the graphical evidence, the system is experiencing user interface overlap (clipping) defects at two positions indicated by the red arrows:
1.1. Defect Index 1: Playhead and Grid Lines Overflowing Over the TCP
- Symptom: The red playback cursor (Playhead) and the vertical time grid markers (Ruler/Grid lines) render on top of the left Track Control Panel (TCP) during horizontal scrolling.
- Root Cause: The Timeline bounding container lacks an independent visual clipping boundary (
overflow: hidden) relative to the TCP column. Alternatively, the TCP lacks a sufficient rendering layer tier (z-index) and a solid background color, which allows absolute-positioned elements from the Timeline to float over the TCP stack.
1.2. Defect Index 2: Horizontal Scrollbar Overflowing Underneath the TCP Base
- Symptom: The global horizontal scrollbar at the bottom of the viewport extends across the lower quadrant of the TCP all the way to the far left edge of the screen.
- Root Cause: The absolute outermost parent container wrapping both the TCP and the Timeline has been assigned horizontal scrolling properties, or the Timeline column is not physically isolated (as adjacent flex columns) from the TCP section.
2. Structural Architecture: Synchronized Dual-Column Viewports (Split-Container Sync)
To permanently resolve these defects, the workspace must completely isolate the two main columns into distinct physical viewports while linking their vertical scroll movements using JavaScript or UI event signals:
[ MASTER WORKSPACE - flex h-full overflow-hidden ]
┌──────────────────────────────┬──────────────────────────────────────────────┐
│ [LEFT COLUMN - TCP PANEL] │ [RIGHT COLUMN - TIMELINE SCROLL VIEWPORT] │
│ - Width: 300px (Fixed) │ - flex-1 │
│ - overflow: hidden │ - overflow-x: auto (Isolated Horiz. Scroll) │
│ - z-index: 20 (Layer Top) │ - overflow-y: auto (Isolated Vert. Scroll) │
│ - bg: #262626 (Solid Solid) │ - z-index: 10 │
│ │ │
│ ┌──────────────────────────┐ │ ┌──────────────────────────────────────────┐ │
│ │ TCP Track 01 │ │ │ Waveform Track 01 │ │
│ ├──────────────────────────┤ │ ├──────────────────────────────────────────┤ │
│ │ TCP Track 02 │ │ │ Waveform Track 02 │ │
│ └──────────────────────────┘ │ └──────────────────────────────────────────┘ │
└──────────────────────────────┴──────────────────────────────────────────────┘
▲ │
│ [JS Vertical Scroll Sync Link] │
└──────────────────────────────────────▼
tcpContainer.scrollTop = timelineContainer.scrollTop
2.1. Rendering Priority and Containment Rules
- TCP Panel: Configured with
position: relative,z-index: 20, and a solidbackground-color: #262626. Consequently, when the Timeline viewport scrolls horizontally to the left, all waveform vectors and the absolute playhead path automatically scroll beneath the TCP panel layer, masking them perfectly from view. - Timeline Wrapper: Positioned immediately adjacent to the TCP column, utilizing
overflow-x: autoandoverflow-y: auto. The horizontal scrollbar will strictly begin rendering at coordinatex = 300\text{ px}stretching rightward, preventing it from clipping the bottom area of the TCP.
3. Mouse Wheel Interaction Mechanics
The translation of scrolling gestures across the timeline canvas depends on the following hardware modifier key bindings:
A. Standard Mouse Wheel Rotation (Vertical Scroll)
- User Action: The user rotates the mouse wheel up or down while hovering over the Timeline area.
- Result: The layout executes native vertical scrolling. The browser triggers the
onScrollevent listener loop, and the synchronization script immediately maps the offset values:
\text{scrollTop}_{\text{TCP}} = \text{scrollTop}_{\text{Timeline}}
This forces both columns to move up and down in absolute physical alignment.
B. Shift + Mouse Wheel Rotation (Horizontal Scroll)
- User Action: The user holds down the
Shiftkey while rotating the mouse wheel up or down. - Result: The system intercepts the input and cross-routes vertical scrolling vectors into the horizontal scroll register:
\text{scrollLeft}_{\text{Timeline}} \mathrel{+}= \Delta y
The Timeline viewport shifts horizontally left or right, letting the editor browse across different segments of the arrangement timeline.
4. Porting Guidelines for Python Docker Applications (PyQt6 / PySide6)
When porting this split-container layout blueprint to a containerized Python desktop application, instantiate two independent QScrollArea nodes positioned side by side within a horizontal layout (QHBoxLayout), then connect their vertical scrollbar signals (verticalScrollBar):
from PyQt6.QtWidgets import QWidget, QHBoxLayout, QScrollArea, QVBoxLayout
from PyQt6.QtCore import Qt
class SyncedDAWWorkspace(QWidget):
def __init__(self):
super().__init__()
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
# 1. Initialize the Left TCP Scroll Area (Enforce absolute scrollbar concealment)
self.tcp_scroll = QScrollArea()
self.tcp_scroll.setFixedWidth(300)
self.tcp_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.tcp_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
self.tcp_scroll.setWidgetResizable(True)
# 2. Initialize the Right Timeline Scroll Area (Enable bidirection scroll mapping)
self.timeline_scroll = QScrollArea()
self.timeline_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
self.timeline_scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn)
self.timeline_scroll.setWidgetResizable(True)
layout.addWidget(self.tcp_scroll)
layout.addWidget(self.timeline_scroll)
# 3. VERTICAL SYNC BINDING: Redirect Timeline scrolling directly to the TCP axis
self.timeline_scroll.verticalScrollBar().valueChanged.connect(
self.tcp_scroll.verticalScrollBar().setValue
)
def eventFilter(self, obj, event):
"""
Intercepts WheelEvents on the Timeline view to handle Shift + Horizontal Scrolling.
"""
if obj == self.timeline_scroll.viewport() and event.type() == event.Type.Wheel:
if event.modifiers() & Qt.KeyboardModifier.ShiftModifier:
# Convert vertical wheel delta into horizontal scroll offset step increments
num_degrees = event.angleDelta().y() / 8
num_steps = num_degrees / 15
self.timeline_scroll.horizontalScrollBar().setValue(
self.timeline_scroll.horizontalScrollBar().value() - num_steps * 30
)
return True # Halt event propagation as it is now fully handled
return super().eventFilter(obj, event)