#include "ViewportPane.h" #include #include #include #include #include #include #include #include #include #include #include "PropertyWidgets.h" #include ViewportPane::ViewportPane(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, &ViewportPane::toggleDisplayPanel); connect(m_titleBar, &QWidget::customContextMenuRequested, this, &ViewportPane::showContextMenu); connect(closeBtn, &QToolButton::clicked, this, &ViewportPane::onCloseRequested); m_titleBar->setContextMenuPolicy(Qt::CustomContextMenu); } ViewportPane::~ViewportPane() {} void ViewportPane::toggleDisplayPanel() { m_displayPanel->setVisible(m_toggleBtn->isChecked()); } void ViewportPane::setObject(uLib::Object* obj) { m_displayEditor->setObject(obj, true); // Check if the object is a Puppet (meaning it has display properties) bool isPuppet = (dynamic_cast<::uLib::Vtk::Puppet*>(obj) != nullptr); // Only show the "Display" toggle button if it's a puppet m_toggleBtn->setVisible(isPuppet); // If it's a puppet, we might want to keep the panel state if it was already open, // or if it's NOT a puppet, definitely hide the toggle and panel. if (!isPuppet) { m_toggleBtn->setChecked(false); m_displayPanel->hide(); } } void ViewportPane::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); } void ViewportPane::addVtkViewport() { auto* viewport = new uLib::Vtk::QViewport(this); setViewport(viewport, "VTK Viewport"); } void ViewportPane::addRootCanvas() { auto* canvas = new uLib::Root::QCanvas(this); setViewport(canvas, "ROOT Canvas"); } void ViewportPane::onCloseRequested() { QSplitter* parentSplitter = qobject_cast(parentWidget()); if (parentSplitter && parentSplitter->count() > 1) { deleteLater(); } else { addVtkViewport(); } } void ViewportPane::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) isVtk ? addRootCanvas() : addVtkViewport(); } void ViewportPane::AttemptSplit(Qt::Orientation orientation) { QWidget* p = parentWidget(); if (!p) return; QSplitter* parentSplitter = qobject_cast(p); if (!parentSplitter) return; ViewportPane* newPane = new ViewportPane(); 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); } }