229 lines
6.7 KiB
C++
229 lines
6.7 KiB
C++
#include "SplitPanel.h"
|
|
#include "DockPanel.h"
|
|
#include <QPainter>
|
|
#include <libConfig.h>
|
|
|
|
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 <QDebug>
|
|
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<ViewBase*>(a));
|
|
b->setParentRes(this);
|
|
manager_inst->appendPresentView(dynamic_cast<ViewBase*>(b));
|
|
this->split_member = std::make_pair(a, b);
|
|
}
|
|
|
|
QWidget *SplitPanel::widget() const { return const_cast<SplitPanel *>(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<ViewRes *, int> SplitPanel::except(ViewRes *inst) const
|
|
{
|
|
if(!contains(inst))
|
|
throw new SimpleException<QString>("运行异常", "传入的视图实例不属于本组件");
|
|
|
|
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<QString>("运行异常", "指定替换的视图不属于本组件");
|
|
}
|
|
|
|
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();
|
|
}
|