26 #include <QPaintEvent>
27 #include <QResizeEvent>
30 #include <QGridLayout>
50 struct DockOverlayPrivate
54 CDockOverlayCross*
Cross;
58 CDockOverlay::eMode
Mode = CDockOverlay::ModeDockAreaOverlay;
72 CDockOverlayCross*
_this;
73 CDockOverlay::eMode
Mode = CDockOverlay::ModeDockAreaOverlay;
99 QPalette pal =
_this->palette();
102 case CDockOverlayCross::FrameColor:
return pal.color(QPalette::Active, QPalette::Highlight);
103 case CDockOverlayCross::WindowBackgroundColor:
return pal.color(QPalette::Active, QPalette::Base);
104 case CDockOverlayCross::OverlayColor:
106 QColor Color = pal.color(QPalette::Active, QPalette::Highlight);
112 case CDockOverlayCross::ArrowColor:
return pal.color(QPalette::Active, QPalette::Base);
113 case CDockOverlayCross::ShadowColor:
return QColor(0, 0, 0, 64);
124 QColor
iconColor(CDockOverlayCross::eIconColor ColorIndex)
127 if (!Color.isValid())
146 return static_cast<qreal
>(l->fontMetrics().height()) * 3.
f;
153 CDockOverlay::eMode
Mode)
155 QLabel* l =
new QLabel();
156 l->setObjectName(
"DockWidgetAreaLabel");
159 const QSizeF
size(metric, metric);
162 l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
163 l->setAttribute(Qt::WA_TranslucentBackground);
171 QLabel* l = qobject_cast<QLabel*>(DropIndicatorWidget);
173 const QSizeF
size(metric, metric);
175 int Area = l->property(
"dockWidgetArea").toInt();
181 CDockOverlay::eMode
Mode)
183 QColor borderColor =
iconColor(CDockOverlayCross::FrameColor);
184 QColor backgroundColor =
iconColor(CDockOverlayCross::WindowBackgroundColor);
186 #if QT_VERSION >= 0x050600
187 double DevicePixelRatio =
_this->window()->devicePixelRatioF();
189 double DevicePixelRatio =
_this->window()->devicePixelRatio();
191 QSizeF PixmapSize =
size * DevicePixelRatio;
192 QPixmap pm(PixmapSize.toSize());
193 pm.fill(QColor(0, 0, 0, 0));
197 QRectF ShadowRect(pm.rect());
199 baseRect.setSize(ShadowRect.size() * 0.7);
200 baseRect.moveCenter(ShadowRect.center());
203 QColor ShadowColor =
iconColor(CDockOverlayCross::ShadowColor);
204 if (ShadowColor.alpha() == 255)
206 ShadowColor.setAlpha(64);
208 p.fillRect(ShadowRect, ShadowColor);
218 areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
219 nonAreaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
220 areaLine = QLineF(areaRect.bottomLeft(), areaRect.bottomRight());
223 areaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
224 nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
225 areaLine = QLineF(areaRect.topLeft(), areaRect.bottomLeft());
228 areaRect = QRectF(baseRect.x(), ShadowRect.height() * .5f, baseRect.width(), baseRect.height() * .5f);
229 nonAreaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width(), baseRect.height() * .5f);
230 areaLine = QLineF(areaRect.topLeft(), areaRect.topRight());
233 areaRect = QRectF(baseRect.x(), baseRect.y(), baseRect.width() * .5f, baseRect.height());
234 nonAreaRect = QRectF(ShadowRect.width() * .5f, baseRect.y(), baseRect.width() * .5f, baseRect.height());
235 areaLine = QLineF(areaRect.topRight(), areaRect.bottomRight());
241 QSizeF baseSize = baseRect.size();
247 p.fillRect(baseRect, backgroundColor);
248 if (areaRect.isValid())
251 pen.setColor(borderColor);
252 QColor Color =
iconColor(CDockOverlayCross::OverlayColor);
253 if (Color.alpha() == 255)
259 p.drawRect(areaRect);
263 pen.setColor(borderColor);
264 pen.setStyle(Qt::DashLine);
266 p.drawLine(areaLine);
273 pen.setColor(borderColor);
275 p.setBrush(Qt::NoBrush);
277 p.drawRect(baseRect);
280 p.setBrush(borderColor);
281 QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10));
282 p.drawRect(FrameRect);
289 ArrowRect.setSize(baseSize);
290 ArrowRect.setWidth(ArrowRect.width() / 4.6);
291 ArrowRect.setHeight(ArrowRect.height() / 2);
292 ArrowRect.moveCenter(QPointF(0, 0));
294 Arrow << ArrowRect.topLeft()
295 << QPointF( ArrowRect.right(), ArrowRect.center().y())
296 << ArrowRect.bottomLeft();
298 p.setBrush(
iconColor(CDockOverlayCross::ArrowColor));
299 p.setRenderHint(QPainter::Antialiasing,
true);
300 p.translate(nonAreaRect.center().x(), nonAreaRect.center().y());
319 p.drawPolygon(Arrow);
322 pm.setDevicePixelRatio(DevicePixelRatio);
330 CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) :
332 d(new DockOverlayPrivate(this))
335 d->Cross =
new CDockOverlayCross(
this);
337 setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
339 setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
342 setWindowTitle(
"DockOverlay");
343 setAttribute(Qt::WA_NoSystemBackground);
344 setAttribute(Qt::WA_TranslucentBackground);
346 d->Cross->setVisible(
false);
352 CDockOverlay::~CDockOverlay()
359 void CDockOverlay::setAllowedAreas(DockWidgetAreas areas)
361 if (areas ==
d->AllowedAreas)
363 d->AllowedAreas = areas;
369 DockWidgetAreas CDockOverlay::allowedAreas()
const
371 return d->AllowedAreas;
384 CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(
d->TargetWidget.data());
391 && !DockArea->titleBar()->isHidden()
392 && DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(QCursor::pos())))
404 if (isHidden() || !
d->DropPreviewEnabled)
410 return dropAreaUnderCursor();
418 if (
d->TargetWidget == target)
422 if (da !=
d->LastLocation)
425 d->LastLocation = da;
430 d->TargetWidget = target;
434 resize(target->size());
435 QPoint TopLeft = target->mapToGlobal(target->rect().topLeft());
438 d->Cross->updatePosition();
439 d->Cross->updateOverlayIcons();
440 return dropAreaUnderCursor();
445 void CDockOverlay::hideOverlay()
448 d->TargetWidget.clear();
450 d->DropAreaRect = QRect();
455 void CDockOverlay::enableDropPreview(
bool Enable)
457 d->DropPreviewEnabled = Enable;
463 bool CDockOverlay::dropPreviewEnabled()
const
465 return d->DropPreviewEnabled;
470 void CDockOverlay::paintEvent(QPaintEvent* event)
474 if (!
d->DropPreviewEnabled)
476 d->DropAreaRect = QRect();
482 double Factor = (CDockOverlay::ModeContainerOverlay ==
d->Mode) ?
494 QPainter painter(
this);
495 QColor Color = palette().color(QPalette::Active, QPalette::Highlight);
496 QPen Pen = painter.pen();
497 Pen.setColor(Color.darker(120));
498 Pen.setStyle(Qt::SolidLine);
500 Pen.setCosmetic(
true);
502 Color = Color.lighter(130);
504 painter.setBrush(Color);
505 painter.drawRect(r.adjusted(0, 0, -1, -1));
511 QRect CDockOverlay::dropOverlayRect()
const
513 return d->DropAreaRect;
518 void CDockOverlay::showEvent(QShowEvent* e)
521 QFrame::showEvent(e);
526 void CDockOverlay::hideEvent(QHideEvent* e)
529 QFrame::hideEvent(e);
534 bool CDockOverlay::event(QEvent *e)
536 bool Result = Super::event(e);
537 if (e->type() == QEvent::Polish)
539 d->Cross->setupOverlayCross(
d->Mode);
555 default:
return Qt::AlignCenter;
564 if (CDockOverlay::ModeDockAreaOverlay ==
Mode)
573 default:
return QPoint();
585 default:
return QPoint();
592 CDockOverlayCross::CDockOverlayCross(CDockOverlay* overlay) :
593 QWidget(overlay->parentWidget()),
594 d(new DockOverlayCrossPrivate(this))
596 d->DockOverlay = overlay;
598 setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
600 setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
602 setWindowTitle(
"DockOverlayCross");
603 setAttribute(Qt::WA_TranslucentBackground);
605 d->GridLayout =
new QGridLayout();
606 d->GridLayout->setSpacing(0);
607 setLayout(
d->GridLayout);
612 CDockOverlayCross::~CDockOverlayCross()
619 void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
623 QHash<DockWidgetArea, QWidget*> areaWidgets;
629 #if QT_VERSION >= 0x050600
630 d->LastDevicePixelRatio = devicePixelRatioF();
632 d->LastDevicePixelRatio = devicePixelRatio();
634 setAreaWidgets(areaWidgets);
635 d->UpdateRequired =
false;
640 void CDockOverlayCross::updateOverlayIcons()
642 if (windowHandle()->devicePixelRatio() ==
d->LastDevicePixelRatio)
647 for (
auto Widget :
d->DropIndicatorWidgets)
649 d->updateDropIndicatorIcon(Widget);
651 #if QT_VERSION >= 0x050600
652 d->LastDevicePixelRatio = devicePixelRatioF();
654 d->LastDevicePixelRatio = devicePixelRatio();
660 void CDockOverlayCross::setIconColor(eIconColor ColorIndex,
const QColor& Color)
662 d->IconColors[ColorIndex] = Color;
663 d->UpdateRequired =
true;
668 QColor CDockOverlayCross::iconColor(eIconColor ColorIndex)
const
670 return d->IconColors[ColorIndex];
675 void CDockOverlayCross::setAreaWidgets(
const QHash<DockWidgetArea, QWidget*>& widgets)
678 QMutableHashIterator<DockWidgetArea, QWidget*> i(
d->DropIndicatorWidgets);
682 QWidget* widget = i.value();
683 d->GridLayout->removeWidget(widget);
689 d->DropIndicatorWidgets = widgets;
690 QHashIterator<DockWidgetArea, QWidget*> i2(
d->DropIndicatorWidgets);
695 QWidget* widget = i2.value();
696 QPoint p =
d->areaGridPosition(area);
697 d->GridLayout->addWidget(widget, p.x(), p.y(), (Qt::Alignment)
areaAlignment(area));
700 if (CDockOverlay::ModeDockAreaOverlay ==
d->Mode)
702 d->GridLayout->setContentsMargins(0, 0, 0, 0);
703 d->GridLayout->setRowStretch(0, 1);
704 d->GridLayout->setRowStretch(1, 0);
705 d->GridLayout->setRowStretch(2, 0);
706 d->GridLayout->setRowStretch(3, 0);
707 d->GridLayout->setRowStretch(4, 1);
709 d->GridLayout->setColumnStretch(0, 1);
710 d->GridLayout->setColumnStretch(1, 0);
711 d->GridLayout->setColumnStretch(2, 0);
712 d->GridLayout->setColumnStretch(3, 0);
713 d->GridLayout->setColumnStretch(4, 1);
717 d->GridLayout->setContentsMargins(4, 4, 4, 4);
718 d->GridLayout->setRowStretch(0, 0);
719 d->GridLayout->setRowStretch(1, 1);
720 d->GridLayout->setRowStretch(2, 1);
721 d->GridLayout->setRowStretch(3, 1);
722 d->GridLayout->setRowStretch(4, 0);
724 d->GridLayout->setColumnStretch(0, 0);
725 d->GridLayout->setColumnStretch(1, 1);
726 d->GridLayout->setColumnStretch(2, 1);
727 d->GridLayout->setColumnStretch(3, 1);
728 d->GridLayout->setColumnStretch(4, 0);
737 const QPoint pos = mapFromGlobal(QCursor::pos());
738 QHashIterator<DockWidgetArea, QWidget*> i(
d->DropIndicatorWidgets);
742 if (
d->DockOverlay->allowedAreas().testFlag(i.key())
744 && i.value()->isVisible()
745 && i.value()->geometry().contains(pos))
755 void CDockOverlayCross::showEvent(QShowEvent*)
757 if (
d->UpdateRequired)
759 setupOverlayCross(
d->Mode);
761 this->updatePosition();
766 void CDockOverlayCross::updatePosition()
768 resize(
d->DockOverlay->size());
769 QPoint TopLeft =
d->DockOverlay->pos();
770 QPoint Offest((this->
width() -
d->DockOverlay->width()) / 2,
771 (this->height() -
d->DockOverlay->height()) / 2);
772 QPoint CrossTopLeft = TopLeft - Offest;
783 const DockWidgetAreas allowedAreas =
d->DockOverlay->allowedAreas();
786 for (
int i = 0; i < allAreas.count(); ++i)
788 QPoint p =
d->areaGridPosition(allAreas.at(i));
789 QLayoutItem* item =
d->GridLayout->itemAtPosition(p.x(), p.y());
790 QWidget* w =
nullptr;
791 if (item && (w = item->widget()) !=
nullptr)
793 w->setVisible(allowedAreas.testFlag(allAreas.at(i)));
800 void CDockOverlayCross::setIconColors(
const QString& Colors)
803 {
"Frame", CDockOverlayCross::FrameColor},
804 {
"Background", CDockOverlayCross::WindowBackgroundColor},
805 {
"Overlay", CDockOverlayCross::OverlayColor},
806 {
"Arrow", CDockOverlayCross::ArrowColor},
807 {
"Shadow", CDockOverlayCross::ShadowColor}};
810 for (
const auto& ColorListEntry : ColorList)
813 int Component = ColorCompenentStringMap.value(ComponentColor[0], -1);
818 d->IconColors[Component] = QColor(ComponentColor[1]);
821 d->UpdateRequired =
true;
825 QString CDockOverlayCross::iconColors()
const