#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 area with splitter for viewport and display panel m_areaSplitter = new QSplitter(Qt::Horizontal, this); m_areaSplitter->setObjectName("ViewportAreaSplitter"); m_layout->addWidget(m_areaSplitter, 1); // Viewport will be added here via setViewport m_viewport = new uLib::Vtk::QViewport(m_areaSplitter); m_areaSplitter->addWidget(m_viewport); // Display Panel (Overlay/Slide-out) m_displayPanel = new QFrame(m_areaSplitter); m_displayPanel->setObjectName("DisplayPropertiesPanel"); m_displayPanel->setMinimumWidth(150); m_displayPanel->hide(); m_areaSplitter->addWidget(m_displayPanel); m_areaSplitter->setStretchFactor(0, 1); m_areaSplitter->setStretchFactor(1, 0); 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); 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() { bool visible = m_toggleBtn->isChecked(); m_displayPanel->setVisible(visible); if (visible && m_areaSplitter->sizes().value(1, 0) == 0) { QList sizes = m_areaSplitter->sizes(); int total = sizes[0] + sizes[1]; sizes[1] = 250; sizes[0] = total - 250; m_areaSplitter->setSizes(sizes); } } void ViewportPane::setObject(uLib::Object* obj) { m_displayEditor->setObject(obj, true); // Check if the object is a Prop3D (meaning it has display properties) bool isProp3D = (dynamic_cast<::uLib::Vtk::Prop3D*>(obj) != nullptr); // Only show the "Display" toggle button if it's a prop3d m_toggleBtn->setVisible(isProp3D); // If it's a prop3d, we might want to keep the panel state if it was already open, // or if it's NOT a prop3d, definitely hide the toggle and panel. if (!isProp3D) { m_toggleBtn->setChecked(false); m_displayPanel->hide(); } } void ViewportPane::setContext(uLib::ObjectsContext* context) { m_displayEditor->setContext(context); } void ViewportPane::setViewport(QWidget* viewport, const QString& title) { if (m_viewport) { delete m_viewport; } m_viewport = viewport; m_titleLabel->setText(title); m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); m_areaSplitter->insertWidget(0, m_viewport); m_areaSplitter->setStretchFactor(0, 1); } uLib::Vtk::Viewport* ViewportPane::viewport() const { return dynamic_cast(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); } }