#include "SplitPanel.h" #include "DockPanel.h" #include #include using namespace split_frame; using namespace split_panel; using namespace Config; DragSplitter::DragSplitter(split_frame::SplitType split, split_frame::ViewRes *parent) : QFrame(parent->widget()){ this->setFrameShape(QFrame::Shape::WinPanel); this->setFrameShadow(QFrame::Shadow::Raised); switch (split) { case split_frame::SplitType::SPLIT_H_LFIRST: case split_frame::SplitType::SPLIT_H_RFIRST: this->setCursor(Qt::CursorShape::SplitHCursor); break; default: this->setCursor(Qt::CursorShape::SizeVerCursor); } } void DragSplitter::mouseMoveEvent(QMouseEvent *event) { QFrame::mouseMoveEvent(event); emit this->adjustRequest(mapToParent(event->pos())); } //===================================================== SplitPanel::SplitPanel(ResManager *mgr, SplitType split) : QWidget(nullptr), manager_inst(mgr), parent_inst(nullptr), splitter_inst(new DragSplitter(split, this)) { connect(this->splitter_inst, &DragSplitter::adjustRequest, this, &SplitPanel::splitter_adjust); this->split_info = std::make_tuple(split, 0.5, 8); } #include SplitPanel::~SplitPanel() { } void SplitPanel::resizeEvent(QResizeEvent *e) { QWidget::resizeEvent(e); this->sync_status(); } ResManager *SplitPanel::splitManager() const { return this->manager_inst; } SplitView *SplitPanel::parentRes() const { return parent_inst; } void SplitPanel::setParentRes(SplitView *inst) { this->parent_inst = inst; if(inst){ this->setParent(inst->widget()); } else{ this->setParent(nullptr); } } qulonglong SplitPanel::hashCode() const { return (qulonglong)this; } void SplitPanel::setVisible(bool state) { QWidget::setVisible(state); } bool SplitPanel::isVisible() const { return QWidget::isVisible(); } void SplitPanel::initViews(ViewRes *a, ViewRes *b) { a->setParentRes(this); manager_inst->appendPresentView(dynamic_cast(a)); b->setParentRes(this); manager_inst->appendPresentView(dynamic_cast(b)); this->split_member = std::make_pair(a, b); } QWidget *SplitPanel::widget() const { return const_cast(this); } QSizeF SplitPanel::stiffSize() const { auto size_a = split_member.first->stiffSize(); auto size_b = split_member.second->stiffSize(); switch (this->splitType()) { case SplitType::SPLIT_H_LFIRST: case SplitType::SPLIT_H_RFIRST: return QSizeF(size_a.width() + size_b.width() + std::get<2>(split_info), std::max(size_a.height(), size_b.height())); default: return QSizeF(std::max(size_a.width(), size_b.width()), size_a.height() + size_b.height() + std::get<2>(split_info)); } } QRectF SplitPanel::outlineRect() const { return this->rect(); } void SplitPanel::setOutline(const QRectF &outline) { if(outline != this->outlineRect()){ this->setGeometry(outline.toRect()); this->sync_status(); } } std::pair SplitPanel::except(ViewRes *inst) const { if(!contains(inst)) throw new SimpleException("运行异常", "传入的视图实例不属于本组件"); if(split_member.first == inst) return std::make_pair(split_member.second, 1); return std::make_pair(split_member.first, 0); } bool SplitPanel::contains(ViewRes *inst) const { return split_member.first == inst || split_member.second == inst; } void SplitPanel::replaceView(ViewRes *_new, ViewRes *_old) { if(!contains(_old)){ throw new SimpleException("运行异常", "指定替换的视图不属于本组件"); } auto elsev = except(_old); _new->setParentRes(this); switch (elsev.second) { case 0: this->split_member = std::make_pair(elsev.first, _new); break; default: this->split_member = std::make_pair(_new, elsev.first); } _old->setParentRes(nullptr); sync_status(); this->update(); } float SplitPanel::splitterWidth() const { return std::get<2>(split_info); } float SplitPanel::splitterPos() const { return std::get<1>(split_info); } SplitType SplitPanel::splitType() const { return std::get<0>(split_info); } void SplitPanel::setSplitInfo(float pos, float width) { this->split_info = std::make_tuple(std::get<0>(split_info), pos, width); this->sync_status(); this->update(); } void SplitPanel::sync_status() { auto total_w = this->width(); auto total_h = this->height(); switch (std::get<0>(split_info)) { case SplitType::SPLIT_H_LFIRST: case SplitType::SPLIT_H_RFIRST: { auto width_a = total_w * std::get<1>(split_info); auto width_b = total_w - width_a - std::get<2>(split_info); auto first = this->split_member.first; auto second = this->split_member.second; first->setOutline(QRectF(0, 0, width_a, total_h)); second->setOutline(QRectF(width_a + std::get<2>(split_info), 0, width_b, total_h)); this->splitter_inst->setGeometry(QRect(width_a, 0, std::get<2>(split_info), total_h)); } break; case SplitType::SPLIT_V_BFIRST: case SplitType::SPLIT_V_TFIRST: { auto height_a = total_h * std::get<1>(split_info); auto height_b = total_h - height_a - std::get<2>(split_info); auto first = this->split_member.first; auto second = this->split_member.second; first->setOutline(QRectF(0, 0, total_w, height_a)); second->setOutline(QRectF(0, height_a + std::get<2>(split_info) - 1, total_w, height_b + 1)); splitter_inst->setGeometry(QRect(0, height_a, total_w, std::get<2>(split_info))); } break; } split_member.first->setVisible(true); split_member.second->setVisible(true); } void SplitPanel::splitter_adjust(const QPoint &pos) { switch (std::get<0>(split_info)) { case SplitType::SPLIT_H_LFIRST: case SplitType::SPLIT_H_RFIRST:{ auto lwidth = split_member.first->stiffSize().width(); auto rwidth = split_member.second->stiffSize().width(); if(pos.x() >= lwidth && pos.x() <= this->width() - rwidth - std::get<2>(split_info)) this->split_info = std::make_tuple(std::get<0>(split_info), pos.x()/(float)this->width(), std::get<2>(split_info)); }break; case SplitType::SPLIT_V_BFIRST: case SplitType::SPLIT_V_TFIRST:{ auto theight = split_member.first->stiffSize().height(); auto bheight = split_member.second->stiffSize().height(); if(pos.y() >= theight && pos.y() <= this->height() - bheight - std::get<2>(split_info)) this->split_info = std::make_tuple(std::get<0>(split_info), pos.y()/(float)this->height(), std::get<2>(split_info)); }break; } this->sync_status(); }