diff --git a/sources/cellruler.cpp b/sources/cellruler.cpp index 299d70eb8..61fa98399 100644 --- a/sources/cellruler.cpp +++ b/sources/cellruler.cpp @@ -73,7 +73,7 @@ void CellRuler::paintEvent(QPaintEvent *event) Q_UNUSED(event) QPainter painter(this); - painter.fillRect(rect(), palette().color(QPalette::Button)); + painter.fillRect(rect(), background()); const bool horizontal = m_orientation == Qt::Horizontal; const int length = horizontal ? width() : height(); @@ -165,6 +165,25 @@ void CellRuler::paintEvent(QPaintEvent *event) if (m_leading_space > 0) { painter.fillRect(horizontal ? QRect(0, 0, m_leading_space, depth - 1) : QRect(0, 0, depth - 1, m_leading_space), - palette().color(QPalette::Button)); + background()); } } + +/** + @brief CellRuler::background + @return the button colour laid over the window colour, always opaque. + The Windows 11 style gives buttons a translucent colour; filled with it + as is, a ruler (painted with Qt::WA_OpaquePaintEvent, so never cleared + first) would let every previous frame show through, and zooming would + leave a shadow of the old labels behind the new ones. +*/ +QColor CellRuler::background() const +{ + const QColor window = palette().color(QPalette::Window); + const QColor button = palette().color(QPalette::Button); + const qreal alpha = button.alphaF(); + return QColor::fromRgbF( + button.redF() * alpha + window.redF() * (1 - alpha), + button.greenF() * alpha + window.greenF() * (1 - alpha), + button.blueF() * alpha + window.blueF() * (1 - alpha)); +} diff --git a/sources/cellruler.h b/sources/cellruler.h index 619b2d52e..586918210 100644 --- a/sources/cellruler.h +++ b/sources/cellruler.h @@ -44,6 +44,8 @@ class CellRuler : public QWidget void paintEvent(QPaintEvent *event) override; private: + QColor background() const; + Qt::Orientation m_orientation; DiagramView *m_view; /// Pixels before the viewport starts, left empty: the corner the diff --git a/sources/diagramview.cpp b/sources/diagramview.cpp index 918b6bbbf..b2677d04d 100644 --- a/sources/diagramview.cpp +++ b/sources/diagramview.cpp @@ -1210,17 +1210,24 @@ void DiagramView::setCellRulersShown(bool shown) /** @brief DiagramView::updateCellRulers - Show each ruler when the rulers are wanted and the folio shows the - matching header, and give it room in the margins of the view. The - part of the folio in sight stays in sight when the viewport resizes. + Show each ruler when the rulers are wanted, the folio shows the + matching header and that header is not already wholly in sight, and + give it room in the margins of the view. The drawing does not move on + screen when a ruler comes or goes: the ruler covers or uncovers the + edge of the viewport, as if it lay over it. */ void DiagramView::updateCellRulers() { const BorderTitleBlock &border = m_diagram->border_and_titleblock; + const QRectF in_sight = mapToScene(viewport()->rect()).boundingRect(); + const QRectF columns = border.columnsRect(); + const QRectF rows = border.rowsRect(); const bool top = m_cell_rulers_shown - && border.borderIsDisplayed() && border.columnsAreDisplayed(); + && border.borderIsDisplayed() && border.columnsAreDisplayed() + && (columns.top() < in_sight.top() || columns.bottom() > in_sight.bottom()); const bool side = m_cell_rulers_shown - && border.borderIsDisplayed() && border.rowsAreDisplayed(); + && border.borderIsDisplayed() && border.rowsAreDisplayed() + && (rows.left() < in_sight.left() || rows.right() > in_sight.right()); const int thickness = m_top_ruler->thickness(); m_top_ruler->setVisible(top); @@ -1229,9 +1236,12 @@ void DiagramView::updateCellRulers() const QMargins margins(side ? thickness : 0, top ? thickness : 0, 0, 0); if (margins != viewportMargins()) { - const QPointF centre = mapToScene(viewport()->rect().center()); + const QPointF origin = mapToScene(viewport()->rect().center()); + const QPoint before = viewport()->mapToGlobal(mapFromScene(origin)); setViewportMargins(margins); - centerOn(centre); + const QPoint moved = viewport()->mapToGlobal(mapFromScene(origin)) - before; + horizontalScrollBar()->setValue(horizontalScrollBar()->value() + moved.x()); + verticalScrollBar()->setValue(verticalScrollBar()->value() + moved.y()); } placeCellRulers(); m_top_ruler->update(); @@ -1281,11 +1291,17 @@ void DiagramView::paintEvent(QPaintEvent *event) { PaletteGraphicsView::paintEvent(event); - //Scrolling and zooming both repaint the viewport: follow them + //Scrolling and zooming both repaint the viewport: follow them. + //Showing or hiding a ruler resizes the viewport, which cannot be + //done while it paints. if (viewportTransform() != m_rulers_transform) { m_rulers_transform = viewportTransform(); m_top_ruler->update(); m_side_ruler->update(); + if (m_cell_rulers_shown) { + QMetaObject::invokeMethod(this, &DiagramView::updateCellRulers, + Qt::QueuedConnection); + } } if (m_free_rubberbanding && m_free_rubberband.count() >= 3)