#include "QViewportPane.h" #include #include #include #include #include #include #include #include #include #include #include "PropertyWidgets.h" #include QViewportPane::QViewportPane(QWidget* parent) : QWidget(parent), m_viewport(nullptr) { m_layout = new QVBoxLayout(this); m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setSpacing(0); // Title bar setup m_titleBar = new QWidget(this); m_titleBar->setObjectName("PaneTitleBar"); m_titleBar->setFixedHeight(22); auto* titleLayout = new QHBoxLayout(m_titleBar); titleLayout->setContentsMargins(5, 0, 0, 0); m_titleLabel = new QLabel("Viewport", m_titleBar); m_titleLabel->setObjectName("TitleLabel"); m_toggleBtn = new QPushButton("Display", m_titleBar); m_toggleBtn->setCheckable(true); m_toggleBtn->setFixedSize(60, 18); m_toggleBtn->setObjectName("DisplayToggleBtn"); auto* closeBtn = new QToolButton(m_titleBar); closeBtn->setObjectName("PaneCloseButton"); closeBtn->setText("X"); closeBtn->setFixedSize(18, 18); titleLayout->addWidget(m_titleLabel); titleLayout->addStretch(); titleLayout->addWidget(m_toggleBtn); titleLayout->addSpacing(5); titleLayout->addWidget(closeBtn); m_layout->addWidget(m_titleBar); // Main horizontal container for viewport and display panel QWidget* mainArea = new QWidget(this); QHBoxLayout* hLayout = new QHBoxLayout(mainArea); hLayout->setContentsMargins(0, 0, 0, 0); hLayout->setSpacing(0); m_layout->addWidget(mainArea); // Viewport will be added here via setViewport m_viewport = new uLib::Vtk::QViewport(mainArea); hLayout->addWidget(m_viewport); // Display Panel (Overlay/Slide-out) m_displayPanel = new QFrame(mainArea); m_displayPanel->setObjectName("DisplayPropertiesPanel"); m_displayPanel->setFixedWidth(250); m_displayPanel->hide(); QVBoxLayout* panelLayout = new QVBoxLayout(m_displayPanel); panelLayout->setContentsMargins(5, 5, 5, 5); QLabel* panelHeader = new QLabel("Display Properties", m_displayPanel); panelHeader->setStyleSheet("font-weight: bold; padding: 5px;"); panelLayout->addWidget(panelHeader); m_displayEditor = new uLib::Qt::PropertyEditor(m_displayPanel); panelLayout->addWidget(m_displayEditor); hLayout->addWidget(m_displayPanel); connect(m_toggleBtn, &QPushButton::toggled, this, &QViewportPane::toggleDisplayPanel); connect(m_titleBar, &QWidget::customContextMenuRequested, this, &QViewportPane::showContextMenu); connect(closeBtn, &QToolButton::clicked, this, &QViewportPane::onCloseRequested); m_titleBar->setContextMenuPolicy(Qt::CustomContextMenu); } void QViewportPane::toggleDisplayPanel() { m_displayPanel->setVisible(m_toggleBtn->isChecked()); } void QViewportPane::setObject(uLib::Object* obj) { m_displayEditor->setObject(obj, true); // Auto-show panel if it's a prop3d and we want to highlight this feature? // User asked for "hiding panel", so maybe we don't auto-show. } void QViewportPane::setViewport(QWidget* viewport, const QString& title) { if (m_viewport) { m_viewport->parentWidget()->layout()->removeWidget(m_viewport); delete m_viewport; } m_viewport = viewport; m_titleLabel->setText(title); m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); auto* mainAreaLayout = static_cast(m_displayPanel->parentWidget()->layout()); mainAreaLayout->insertWidget(0, m_viewport); } QViewportPane::~QViewportPane() {} void QViewportPane::setViewport(QWidget* viewport, const QString& title) { if (m_viewport) { m_layout->removeWidget(m_viewport); delete m_viewport; } m_viewport = viewport; m_titleLabel->setText(title); m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_layout->addWidget(m_viewport); } void QViewportPane::addVtkViewport() { auto* viewport = new uLib::Vtk::QViewport(this); setViewport(viewport, "VTK Viewport"); } void QViewportPane::addRootCanvas() { auto* canvas = new uLib::Root::QCanvas(this); setViewport(canvas, "ROOT Canvas"); } void QViewportPane::onCloseRequested() { QSplitter* parentSplitter = qobject_cast(parentWidget()); if (parentSplitter && parentSplitter->count() > 1) { deleteLater(); } else { // Can't close the last viewport in the splitter safely. Re-initialize to default VTK canvas. addVtkViewport(); } } void QViewportPane::showContextMenu(const QPoint& pos) { QMenu menu(this); QAction* hSplit = menu.addAction("H split"); QAction* vSplit = menu.addAction("V split"); menu.addSeparator(); bool isVtk = (qobject_cast(m_viewport) != nullptr); QAction* changeType = menu.addAction(isVtk ? "Change to ROOT Canvas" : "Change to VTK Viewport"); QAction* selected = menu.exec(m_titleBar->mapToGlobal(pos)); if (selected == hSplit) { AttemptSplit(Qt::Horizontal); } else if (selected == vSplit) { AttemptSplit(Qt::Vertical); } else if (selected == changeType) { if (isVtk) { addRootCanvas(); } else { addVtkViewport(); } } } void QViewportPane::AttemptSplit(Qt::Orientation orientation) { QWidget* p = parentWidget(); if (!p) return; QSplitter* parentSplitter = qobject_cast(p); if (!parentSplitter) return; QViewportPane* newPane = new QViewportPane(); // 1. Synchronize viewport content and camera (VTK Viewport only for now) auto* currentVtk = qobject_cast(m_viewport); if (currentVtk) { auto* newVtk = qobject_cast(newPane->currentViewport()); if (newVtk) { // Copy prop3ds for (auto* prop3d : currentVtk->getProp3Ds()) { newVtk->AddProp3D(*prop3d); } // Copy camera if (currentVtk->GetRenderer() && newVtk->GetRenderer()) { vtkCamera* currentCam = currentVtk->GetRenderer()->GetActiveCamera(); vtkCamera* newCam = newVtk->GetRenderer()->GetActiveCamera(); if (currentCam && newCam) { newCam->DeepCopy(currentCam); } } // Sync grid visible and axis newVtk->SetGridVisible(currentVtk->GetGridVisible()); newVtk->SetGridAxis(currentVtk->GetGridAxis()); } } // 2. Adjust for ROOT Canvas if that was the active view bool isRoot = (qobject_cast(m_viewport) != nullptr); if (isRoot) { newPane->addRootCanvas(); } if (parentSplitter->orientation() == orientation) { int index = parentSplitter->indexOf(this); QList sizes = parentSplitter->sizes(); int currentSize = sizes.value(index, 0); int half = currentSize / 2; sizes[index] = half; sizes.insert(index + 1, currentSize - half); parentSplitter->insertWidget(index + 1, newPane); parentSplitter->setSizes(sizes); } else { int index = parentSplitter->indexOf(this); QList parentSizes = parentSplitter->sizes(); QSplitter* newSplitter = new QSplitter(orientation); newSplitter->addWidget(this); newSplitter->addWidget(newPane); QList subSizes; subSizes << 500 << 500; newSplitter->setSizes(subSizes); parentSplitter->insertWidget(index, newSplitter); parentSplitter->setSizes(parentSizes); } }